You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2015/06/11 02:28:04 UTC
[2/2] trafficserver git commit: TS-3542 Remove the reclaimable
freelist feature, it will be replaced with a buddy allocation scheme
TS-3542 Remove the reclaimable freelist feature, it will be replaced with a buddy allocation scheme
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/7142d326
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/7142d326
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/7142d326
Branch: refs/heads/master
Commit: 7142d326a5068f2423edf8ac4939bf2ee0289b29
Parents: 5dd6b20
Author: Leif Hedstrom <zw...@apache.org>
Authored: Thu Apr 30 11:02:58 2015 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Wed Jun 10 18:06:42 2015 -0600
----------------------------------------------------------------------
ci/jenkins/bin/in_tree.sh | 1 -
ci/jenkins/bin/out_of_tree.sh | 1 -
ci/tsqa/tests/test_regressions.py | 1 -
configure.ac | 20 -
iocore/eventsystem/I_IOBuffer.h | 4 -
iocore/eventsystem/I_ProxyAllocator.h | 16 +-
iocore/eventsystem/ProxyAllocator.cc | 10 +-
lib/ts/Makefile.am | 2 -
lib/ts/ink_config.h.in | 1 -
lib/ts/ink_queue.cc | 27 +-
lib/ts/ink_queue.h | 7 -
lib/ts/ink_queue_ext.cc | 660 -----------------------------
lib/ts/ink_queue_ext.h | 137 ------
proxy/http/HttpConfig.cc | 7 -
proxy/http/HttpConfig.h | 8 +-
15 files changed, 12 insertions(+), 890 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/ci/jenkins/bin/in_tree.sh
----------------------------------------------------------------------
diff --git a/ci/jenkins/bin/in_tree.sh b/ci/jenkins/bin/in_tree.sh
index f395835..1c78fbd 100755
--- a/ci/jenkins/bin/in_tree.sh
+++ b/ci/jenkins/bin/in_tree.sh
@@ -31,7 +31,6 @@ autoreconf -fi
--enable-experimental-plugins \
--enable-example-plugins \
--enable-test-tools \
- --enable-reclaimable-freelist \
--enable-wccp \
${enable_cppapi} \
CORES=2
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/ci/jenkins/bin/out_of_tree.sh
----------------------------------------------------------------------
diff --git a/ci/jenkins/bin/out_of_tree.sh b/ci/jenkins/bin/out_of_tree.sh
index 3f82106..f7e09c0 100755
--- a/ci/jenkins/bin/out_of_tree.sh
+++ b/ci/jenkins/bin/out_of_tree.sh
@@ -28,7 +28,6 @@ mkdir -p BUILDS && cd BUILDS
--enable-experimental-plugins \
--enable-example-plugins \
--enable-test-tools \
- --enable-reclaimable-freelist \
--enable-wccp \
CORES=2
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/ci/tsqa/tests/test_regressions.py
----------------------------------------------------------------------
diff --git a/ci/tsqa/tests/test_regressions.py b/ci/tsqa/tests/test_regressions.py
index e49aa74..64f1a81 100644
--- a/ci/tsqa/tests/test_regressions.py
+++ b/ci/tsqa/tests/test_regressions.py
@@ -52,7 +52,6 @@ class TestRegressions(helpers.EnvironmentCase):
cmd = [os.path.join(self.environment.layout.bindir, 'traffic_server'), '-R', '1']
tsqa.utils.run_sync_command(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-
class TestRegressionsLinuxNativeAIO(TestRegressions):
'''
Run the built-in traffic_server regression test suite with
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 3f130af..ee1182f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -368,26 +368,6 @@ TS_ARG_ENABLE_VAR([use], [freelist])
AC_SUBST(use_freelist)
#
-# The original InkFreeList memory pool could not reclaim itself
-# automatically. We can use '--enable-reclaimable-freelist' option
-# to enable the reclaiming feature. This option is effective only
-# when freelist is enable.
-#
-if test "x${enable_freelist}" = "xyes"; then
- AC_MSG_CHECKING([whether to enable reclaimable freelist])
- AC_ARG_ENABLE([reclaimable-freelist],
- [AS_HELP_STRING([--enable-reclaimable-freelist],
- [enable reclaimable freelist support (effective only when freelist is enabled)])],
- [],
- [enable_reclaimable_freelist="no"])
- AC_MSG_RESULT([$enable_reclaimable_freelist])
-else
- enable_reclaimable_freelist="no"
-fi
-TS_ARG_ENABLE_VAR([use], [reclaimable_freelist])
-AC_SUBST(use_reclaimable_freelist)
-
-#
# Options for SPDY
#
AC_MSG_CHECKING([whether to enable spdy])
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/iocore/eventsystem/I_IOBuffer.h
----------------------------------------------------------------------
diff --git a/iocore/eventsystem/I_IOBuffer.h b/iocore/eventsystem/I_IOBuffer.h
index c167bb4..6416e2b 100644
--- a/iocore/eventsystem/I_IOBuffer.h
+++ b/iocore/eventsystem/I_IOBuffer.h
@@ -68,11 +68,7 @@ enum AllocType {
CONSTANT,
};
-#if TS_USE_RECLAIMABLE_FREELIST
-#define DEFAULT_BUFFER_NUMBER 64
-#else
#define DEFAULT_BUFFER_NUMBER 128
-#endif
#define DEFAULT_HUGE_BUFFER_NUMBER 32
#define MAX_MIOBUFFER_READERS 5
#define DEFAULT_BUFFER_ALIGNMENT 8192 // should be disk/page size
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/iocore/eventsystem/I_ProxyAllocator.h
----------------------------------------------------------------------
diff --git a/iocore/eventsystem/I_ProxyAllocator.h b/iocore/eventsystem/I_ProxyAllocator.h
index 32fc72d..2e26fd5 100644
--- a/iocore/eventsystem/I_ProxyAllocator.h
+++ b/iocore/eventsystem/I_ProxyAllocator.h
@@ -49,7 +49,7 @@ template <class C>
inline C *
thread_alloc(ClassAllocator<C> &a, ProxyAllocator &l)
{
-#if TS_USE_FREELIST && !TS_USE_RECLAIMABLE_FREELIST
+#if TS_USE_FREELIST
if (l.freelist) {
C *v = (C *)l.freelist;
l.freelist = *(C **)l.freelist;
@@ -67,7 +67,7 @@ template <class C>
inline C *
thread_alloc_init(ClassAllocator<C> &a, ProxyAllocator &l)
{
-#if TS_USE_FREELIST && !TS_USE_RECLAIMABLE_FREELIST
+#if TS_USE_FREELIST
if (l.freelist) {
C *v = (C *)l.freelist;
l.freelist = *(C **)l.freelist;
@@ -98,9 +98,7 @@ template <class C>
inline void
thread_freeup(ClassAllocator<C> &a, ProxyAllocator &l)
{
-#if !TS_USE_RECLAIMABLE_FREELIST
C *head = (C *)l.freelist;
-#endif
C *tail = (C *)l.freelist;
size_t count = 0;
while (l.freelist && l.allocated > thread_freelist_low_watermark) {
@@ -108,11 +106,8 @@ thread_freeup(ClassAllocator<C> &a, ProxyAllocator &l)
l.freelist = *(C **)l.freelist;
--(l.allocated);
++count;
-#if TS_USE_RECLAIMABLE_FREELIST
- a.free(tail);
-#endif
}
-#if !TS_USE_RECLAIMABLE_FREELIST
+
if (unlikely(count == 1)) {
a.free(tail);
} else if (count > 0) {
@@ -120,7 +115,6 @@ thread_freeup(ClassAllocator<C> &a, ProxyAllocator &l)
}
ink_assert(l.allocated >= thread_freelist_low_watermark);
-#endif
}
void *thread_alloc(Allocator &a, ProxyAllocator &l);
@@ -128,7 +122,7 @@ void thread_freeup(Allocator &a, ProxyAllocator &l);
#define THREAD_ALLOC(_a, _t) thread_alloc(::_a, _t->_a)
#define THREAD_ALLOC_INIT(_a, _t) thread_alloc_init(::_a, _t->_a)
-#if TS_USE_FREELIST && !TS_USE_RECLAIMABLE_FREELIST
+#if TS_USE_FREELIST
#define THREAD_FREE(_p, _a, _t) \
do { \
*(char **)_p = (char *)_t->_a.freelist; \
@@ -137,7 +131,7 @@ void thread_freeup(Allocator &a, ProxyAllocator &l);
if (_t->_a.allocated > thread_freelist_high_watermark) \
thread_freeup(::_a, _t->_a); \
} while (0)
-#else /* !TS_USE_FREELIST || TS_USE_RECLAIMABLE_FREELIST */
+#else /* !TS_USE_FREELIST */
#define THREAD_FREE(_p, _a, _t) \
do { \
(void) _t; \
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/iocore/eventsystem/ProxyAllocator.cc
----------------------------------------------------------------------
diff --git a/iocore/eventsystem/ProxyAllocator.cc b/iocore/eventsystem/ProxyAllocator.cc
index 12a82cb..434921d 100644
--- a/iocore/eventsystem/ProxyAllocator.cc
+++ b/iocore/eventsystem/ProxyAllocator.cc
@@ -28,7 +28,7 @@ int thread_freelist_low_watermark = 32;
void *
thread_alloc(Allocator &a, ProxyAllocator &l)
{
-#if TS_USE_FREELIST && !TS_USE_RECLAIMABLE_FREELIST
+#if TS_USE_FREELIST
if (l.freelist) {
void *v = (void *)l.freelist;
l.freelist = *(void **)l.freelist;
@@ -44,9 +44,7 @@ thread_alloc(Allocator &a, ProxyAllocator &l)
void
thread_freeup(Allocator &a, ProxyAllocator &l)
{
-#if !TS_USE_RECLAIMABLE_FREELIST
void *head = (void *)l.freelist;
-#endif
void *tail = (void *)l.freelist;
size_t count = 0;
while (l.freelist && l.allocated > thread_freelist_low_watermark) {
@@ -54,11 +52,8 @@ thread_freeup(Allocator &a, ProxyAllocator &l)
l.freelist = *(void **)l.freelist;
--(l.allocated);
++count;
-#if TS_USE_RECLAIMABLE_FREELIST
- a.free_void(tail);
-#endif
}
-#if !TS_USE_RECLAIMABLE_FREELIST
+
if (unlikely(count == 1)) {
a.free_void(tail);
} else if (count > 0) {
@@ -66,5 +61,4 @@ thread_freeup(Allocator &a, ProxyAllocator &l)
}
ink_assert(l.allocated >= thread_freelist_low_watermark);
-#endif
}
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/lib/ts/Makefile.am
----------------------------------------------------------------------
diff --git a/lib/ts/Makefile.am b/lib/ts/Makefile.am
index 18c18cf..f30ac9c 100644
--- a/lib/ts/Makefile.am
+++ b/lib/ts/Makefile.am
@@ -148,8 +148,6 @@ libtsutil_la_SOURCES = \
ink_platform.h \
ink_queue.cc \
ink_queue.h \
- ink_queue_ext.cc \
- ink_queue_ext.h \
ink_queue_utils.cc \
ink_rand.cc \
ink_rand.h \
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/lib/ts/ink_config.h.in
----------------------------------------------------------------------
diff --git a/lib/ts/ink_config.h.in b/lib/ts/ink_config.h.in
index 0d51b4e..25cc250 100644
--- a/lib/ts/ink_config.h.in
+++ b/lib/ts/ink_config.h.in
@@ -70,7 +70,6 @@
#define TS_HAS_IP_TOS @has_ip_tos@
#define TS_USE_HWLOC @use_hwloc@
#define TS_USE_FREELIST @use_freelist@
-#define TS_USE_RECLAIMABLE_FREELIST @use_reclaimable_freelist@
#define TS_USE_TLS_NPN @use_tls_npn@
#define TS_USE_TLS_ALPN @use_tls_alpn@
#define TS_USE_TLS_SNI @use_tls_sni@
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/lib/ts/ink_queue.cc
----------------------------------------------------------------------
diff --git a/lib/ts/ink_queue.cc b/lib/ts/ink_queue.cc
index 0f14b68..38eaae6 100644
--- a/lib/ts/ink_queue.cc
+++ b/lib/ts/ink_queue.cc
@@ -48,7 +48,6 @@
#include "ink_memory.h"
#include "ink_error.h"
#include "ink_assert.h"
-#include "ink_queue_ext.h"
#include "ink_align.h"
#include "hugepages.h"
@@ -83,9 +82,6 @@ inkcoreapi volatile int64_t freelist_allocated_mem = 0;
void
ink_freelist_init(InkFreeList **fl, const char *name, uint32_t type_size, uint32_t chunk_size, uint32_t alignment)
{
-#if TS_USE_RECLAIMABLE_FREELIST
- return reclaimable_freelist_init(fl, name, type_size, chunk_size, alignment);
-#else
InkFreeList *f;
ink_freelist_list *fll;
@@ -116,7 +112,6 @@ ink_freelist_init(InkFreeList **fl, const char *name, uint32_t type_size, uint32
f->used_base = 0;
f->advice = 0;
*fl = f;
-#endif
}
void
@@ -124,11 +119,7 @@ ink_freelist_madvise_init(InkFreeList **fl, const char *name, uint32_t type_size
int advice)
{
ink_freelist_init(fl, name, type_size, chunk_size, alignment);
-#if TS_USE_RECLAIMABLE_FREELIST
- (void)advice;
-#else
(*fl)->advice = advice;
-#endif
}
InkFreeList *
@@ -151,9 +142,6 @@ void *
ink_freelist_new(InkFreeList *f)
{
#if TS_USE_FREELIST
-#if TS_USE_RECLAIMABLE_FREELIST
- return reclaimable_freelist_new(f);
-#else
head_p item;
head_p next;
int result = 0;
@@ -244,8 +232,7 @@ ink_freelist_new(InkFreeList *f)
ink_atomic_increment(&fastalloc_mem_in_use, (int64_t)f->type_size);
return TO_PTR(FREELIST_POINTER(item));
-#endif /* TS_USE_RECLAIMABLE_FREELIST */
-#else // ! TS_USE_FREELIST
+#else // ! TS_USE_FREELIST
void *newp = NULL;
if (f->alignment)
@@ -261,9 +248,6 @@ void
ink_freelist_free(InkFreeList *f, void *item)
{
#if TS_USE_FREELIST
-#if TS_USE_RECLAIMABLE_FREELIST
- return reclaimable_freelist_free(f, item);
-#else
volatile void **adr_of_next = (volatile void **)ADDRESS_OF_NEXT(item, 0);
head_p h;
head_p item_pair;
@@ -303,7 +287,6 @@ ink_freelist_free(InkFreeList *f, void *item)
ink_atomic_increment((int *)&f->used, -1);
ink_atomic_increment(&fastalloc_mem_in_use, -(int64_t)f->type_size);
-#endif /* TS_USE_RECLAIMABLE_FREELIST */
#else
if (f->alignment)
ats_memalign_free(item);
@@ -316,7 +299,6 @@ void
ink_freelist_free_bulk(InkFreeList *f, void *head, void *tail, size_t num_item)
{
#if TS_USE_FREELIST
-#if !TS_USE_RECLAIMABLE_FREELIST
volatile void **adr_of_next = (volatile void **)ADDRESS_OF_NEXT(tail, 0);
head_p h;
head_p item_pair;
@@ -361,13 +343,6 @@ ink_freelist_free_bulk(InkFreeList *f, void *head, void *tail, size_t num_item)
ink_atomic_increment((int *)&f->used, -1 * num_item);
ink_atomic_increment(&fastalloc_mem_in_use, -(int64_t)f->type_size * num_item);
-#else /* TS_USE_RECLAIMABLE_FREELIST */
- // Avoid compiler warnings
- (void)f;
- (void)head;
- (void)tail;
- (void)num_item;
-#endif /* !TS_USE_RECLAIMABLE_FREELIST */
#else /* !TS_USE_FREELIST */
void *item = head;
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/lib/ts/ink_queue.h
----------------------------------------------------------------------
diff --git a/lib/ts/ink_queue.h b/lib/ts/ink_queue.h
index 8570d47..f830111 100644
--- a/lib/ts/ink_queue.h
+++ b/lib/ts/ink_queue.h
@@ -144,12 +144,6 @@ typedef union {
#error "unsupported processor"
#endif
-#if TS_USE_RECLAIMABLE_FREELIST
-extern float cfg_reclaim_factor;
-extern int64_t cfg_max_overage;
-extern int64_t cfg_enable_reclaim;
-extern int64_t cfg_debug_filter;
-#else
struct _InkFreeList {
volatile head_p head;
const char *name;
@@ -161,7 +155,6 @@ struct _InkFreeList {
inkcoreapi extern volatile int64_t fastalloc_mem_in_use;
inkcoreapi extern volatile int64_t fastalloc_mem_total;
inkcoreapi extern volatile int64_t freelist_allocated_mem;
-#endif
typedef struct _InkFreeList InkFreeList, *PInkFreeList;
typedef struct _ink_freelist_list {
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/lib/ts/ink_queue_ext.cc
----------------------------------------------------------------------
diff --git a/lib/ts/ink_queue_ext.cc b/lib/ts/ink_queue_ext.cc
deleted file mode 100644
index 9687a74..0000000
--- a/lib/ts/ink_queue_ext.cc
+++ /dev/null
@@ -1,660 +0,0 @@
-/** @file
-
- A brief file description
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-/***********************************************************************
-
- Reclaimable freelist Implementation
-
-***********************************************************************/
-
-#include "ink_config.h"
-#include <assert.h>
-#include <memory.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include "ink_thread.h"
-#include "ink_atomic.h"
-#include "ink_queue.h"
-#include "ink_memory.h"
-#include "ink_error.h"
-#include "ink_assert.h"
-#include "ink_stack_trace.h"
-#include "ink_queue_ext.h"
-
-#if TS_USE_RECLAIMABLE_FREELIST
-
-#define CEIL(x, y) (((x) + (y)-1L) / (y))
-#define ROUND(x, l) (((x) + ((l)-1L)) & ~((l)-1L))
-#define ITEM_MAGIC 0xFF
-
-#define MAX_NUM_FREELIST 1024
-
-/*
- * Configurable Variables
- */
-float cfg_reclaim_factor = 0.3;
-int64_t cfg_max_overage = 10;
-int64_t cfg_enable_reclaim = 0;
-/*
- * Debug filter bit mask:
- * bit 0: reclaim in ink_freelist_new
- * bit 1: reclaim in ink_freelist_free
- * bit 2: fetch memory from thread cache
- */
-int64_t cfg_debug_filter;
-
-static uint32_t nr_freelist;
-static uint64_t total_mem_in_byte;
-static __thread InkThreadCache *ThreadCaches[MAX_NUM_FREELIST];
-
-#define MAX_CHUNK_BYTE_SIZE (ats_pagesize() << 8)
-
-/*
- * For debug
- */
-#define show_info(tag, f, pCache) __show_info(stdout, __FILE__, __LINE__, tag, f, pCache)
-#define error_info(tag, f, pCache) __show_info(stderr, __FILE__, __LINE__, tag, f, pCache)
-
-static inline void
-__show_info(FILE *fp, const char *file, int line, const char *tag, InkFreeList *f, InkThreadCache *pCache)
-{
- fprintf(fp, "[%lx:%02u][%s:%05d][%s] %6.2fM t:%-8uf:%-4u m:%-4u avg:%-6.1f"
- " M:%-4u csbase:%-4u csize:%-4u tsize:%-6u cbsize:%u\n",
- (long)ink_thread_self(), f->thread_cache_idx, file, line, tag, ((double)total_mem_in_byte / 1024 / 1024),
- pCache->nr_total, pCache->nr_free, pCache->nr_min, pCache->nr_average, pCache->nr_malloc, f->chunk_size_base,
- f->chunk_size, f->type_size, f->chunk_byte_size);
-}
-
-static inline void
-memory_alignment_init(InkFreeList *f, uint32_t type_size, uint32_t chunk_size, uint32_t alignment)
-{
- uint32_t chunk_byte_size, user_alignment, user_type_size;
-
- f->chunk_size_base = chunk_size;
- user_alignment = alignment;
- user_type_size = type_size;
- chunk_size = 1;
-
-#ifdef DEBUG
- /*
- * enlarge type_size to hold a item_magic
- */
- type_size += sizeof(unsigned char);
-#endif
-
- /*
- * limit the size of each chunk and resize alignment.
- * 1) when size of chunk > MAX_CHUNK_BYTE_SIZE:
- * alignment = page_size;
- * 2) when size of chunk <= MAX_CHUNK_BYTE_SIZE:
- * alignment = (2^N * page_size),
- * alignment should not larger than MAX_CHUNK_BYTE_SIZE
- */
- alignment = ats_pagesize();
- chunk_byte_size = ROUND(type_size + sizeof(InkChunkInfo), ats_pagesize());
- if (chunk_byte_size <= MAX_CHUNK_BYTE_SIZE) {
- chunk_byte_size = ROUND(type_size * f->chunk_size_base + sizeof(InkChunkInfo), ats_pagesize());
-
- if (chunk_byte_size > MAX_CHUNK_BYTE_SIZE) {
- chunk_size = (MAX_CHUNK_BYTE_SIZE - sizeof(InkChunkInfo)) / type_size;
- chunk_byte_size = ROUND(type_size * chunk_size + sizeof(InkChunkInfo), ats_pagesize());
- } else
- chunk_size = (chunk_byte_size - sizeof(InkChunkInfo)) / type_size;
-
- if (chunk_size > 1) {
- /* make alignment to be (2^N * page_size),
- * but not larger than MAX_CHUNK_BYTE_SIZE */
- while (alignment < chunk_byte_size)
- alignment <<= 1;
- }
- }
-
- if (user_alignment > alignment) {
- alignment = ats_pagesize();
- while (alignment < user_alignment)
- alignment <<= 1;
- }
- ink_release_assert(alignment <= MAX_CHUNK_BYTE_SIZE);
-
- f->alignment = alignment;
- f->type_size = user_type_size;
- f->chunk_size = chunk_size;
- f->chunk_addr_mask = ~((uintptr_t)(alignment - 1));
- f->chunk_byte_size = chunk_byte_size;
-
- return;
-}
-
-/*
- * mmap_align allocates _size_ bytes and returns a pointer to the
- * allocated memory, which address will be a multiple of _alignment_.
- * 1)the _size_ must be a multiple of page_size;
- * 2)the _alignment_ must be a power of page_size;
- */
-static void *
-mmap_align(size_t size, size_t alignment)
-{
- uintptr_t ptr;
- size_t adjust, extra = 0;
-
- ink_assert(size % ats_pagesize() == 0);
-
- /* ask for extra memory if alignment > page_size */
- if (alignment > ats_pagesize()) {
- extra = alignment - ats_pagesize();
- }
- void *result = mmap(NULL, size + extra, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
- if (result == MAP_FAILED) {
- ink_stack_trace_dump();
- const char *err_str = "Out of memory, or the process's maximum number of "
- "mappings would have been exceeded(if so, you can "
- "enlarge 'vm.max_map_count' by sysctl in linux).";
- ink_fatal("Failed to mmap %zu bytes, %s", size, (errno == ENOMEM) ? err_str : strerror(errno));
- }
-
- /* adjust the return memory so it is aligned */
- adjust = 0;
- ptr = (uintptr_t)result;
- if ((ptr & (alignment - 1)) != 0) {
- adjust = alignment - (ptr & (alignment - 1));
- }
-
- /* return the unused memory to the system */
- if (adjust > 0) {
- munmap((void *)ptr, adjust);
- }
- if (adjust < extra) {
- munmap((void *)(ptr + adjust + size), extra - adjust);
- }
-
- ptr += adjust;
- ink_assert((ptr & (alignment - 1)) == 0);
- return (void *)ptr;
-}
-
-#ifdef DEBUG
-static inline uint32_t
-get_chunk_item_magic_idx(InkFreeList *f, void *item, InkChunkInfo **ppChunk, bool do_check = false)
-{
- uint32_t idx;
- uintptr_t chunk_addr;
-
- if (f->chunk_size > 1)
- chunk_addr = (uintptr_t)item & f->chunk_addr_mask;
- else
- chunk_addr = (uintptr_t)item;
-
- if (*ppChunk == NULL)
- *ppChunk = (InkChunkInfo *)(chunk_addr + f->type_size * f->chunk_size);
-
- idx = ((uintptr_t)item - chunk_addr) / f->type_size;
-
- if (do_check && (idx >= f->chunk_size || ((uintptr_t)item - chunk_addr) % f->type_size)) {
- ink_stack_trace_dump();
- ink_fatal("Invalid address:%p, chunk_addr:%p, type_size:%d, chunk_size:%u, idx:%u", item, (void *)chunk_addr, f->type_size,
- f->chunk_size, idx);
- }
-
- return idx;
-}
-
-static inline void
-set_chunk_item_magic(InkFreeList *f, InkChunkInfo *pChunk, void *item)
-{
- uint32_t idx;
-
- idx = get_chunk_item_magic_idx(f, item, &pChunk);
-
- ink_release_assert(pChunk->item_magic[idx] == 0);
-
- pChunk->item_magic[idx] = ITEM_MAGIC;
-}
-
-static inline void
-clear_chunk_item_magic(InkFreeList *f, InkChunkInfo *pChunk, void *item)
-{
- uint32_t idx;
-
- idx = get_chunk_item_magic_idx(f, item, &pChunk, true);
-
- ink_release_assert(pChunk->item_magic[idx] == ITEM_MAGIC);
-
- pChunk->item_magic[idx] = 0;
-}
-#else
-#define set_chunk_item_magic(a, b, c)
-#define clear_chunk_item_magic(a, b, c)
-#endif
-
-static inline InkChunkInfo *
-get_chunk_info_addr(InkFreeList *f, void *item)
-{
- uintptr_t chunk_addr;
-
- if (f->chunk_size > 1)
- chunk_addr = (uintptr_t)item & f->chunk_addr_mask;
- else
- chunk_addr = (uintptr_t)item;
-
- return (InkChunkInfo *)(chunk_addr + f->type_size * f->chunk_size);
-}
-
-static inline InkChunkInfo *
-ink_chunk_create(InkFreeList *f, InkThreadCache *pCache)
-{
- uint32_t i;
- uint32_t type_size, chunk_size;
- void *chunk_addr, *curr, *next;
- InkChunkInfo *pChunk;
-
- chunk_addr = mmap_align(f->chunk_byte_size, f->alignment);
- pChunk = (InkChunkInfo *)((char *)chunk_addr + f->type_size * f->chunk_size);
-
- type_size = f->type_size;
- chunk_size = f->chunk_size;
-
- pChunk->tid = ink_thread_self();
- pChunk->head = chunk_addr;
- pChunk->type_size = type_size;
- pChunk->chunk_size = chunk_size;
- pChunk->length = f->chunk_byte_size;
- pChunk->allocated = 0;
- pChunk->pThreadCache = pCache;
- pChunk->link = Link<InkChunkInfo>();
-
-#ifdef DEBUG
-/*
- * The content will be initialized to zero when
- * calls mmap() with MAP_ANONYMOUS flag on linux
- * platform.
- */
-#if !defined(linux)
- memset(pChunk->item_magic, 0, chunk_size * sizeof(unsigned char));
-#endif
-#endif
-
- curr = pChunk->head;
- pChunk->inner_free_list = curr;
- for (i = 1; i < chunk_size; i++) {
- next = (void *)((char *)curr + type_size);
- *(void **)curr = next;
- curr = next;
- }
- *(void **)curr = NULL;
-
- ink_atomic_increment(&f->allocated, chunk_size);
- ink_atomic_increment(&total_mem_in_byte, f->chunk_byte_size);
-
- pCache->free_chunk_list.push(pChunk);
- pCache->nr_free_chunks++;
- return pChunk;
-}
-
-static inline void
-ink_chunk_delete(InkFreeList *f, InkThreadCache *pCache, InkChunkInfo *pChunk)
-{
- void *chunk_addr = pChunk->head;
-
- ink_assert(pChunk->allocated == 0);
-
- pCache->free_chunk_list.remove(pChunk);
- pCache->nr_free_chunks--;
-
- if (unlikely(munmap(chunk_addr, f->chunk_byte_size))) {
- ink_stack_trace_dump();
- ink_fatal("Failed to munmap %u bytes, %s", f->chunk_byte_size, strerror(errno));
- }
-
- ink_atomic_increment((int *)&f->allocated, -f->chunk_size);
-
- /*
- * TODO: I had used ink_atomic_increment() here, but it would
- * lead to incorrect value in linux OS, I don't know why:
- * ink_atomic_increment((int64_t *)&total_mem_in_byte, -f->chunk_byte_size);
- *
- * So I create a new wrap, ink_atomic_decrement(), in ink_atomic.h,
- * it works well. But we should create the same wrap for other OS.
- */
- ink_atomic_decrement(&total_mem_in_byte, f->chunk_byte_size);
-}
-
-static inline void *
-malloc_whole_chunk(InkFreeList *f, InkThreadCache *pCache, InkChunkInfo *pChunk)
-{
- uint32_t i;
- uint32_t type_size, chunk_size;
- void *next, *item;
-
- ink_assert(pChunk->allocated == 0);
-
- type_size = f->type_size;
- chunk_size = f->chunk_size;
-
- item = pChunk->head;
- for (i = 1; i < chunk_size; i++) {
- next = (void *)((char *)item + i * type_size);
- ink_atomic_increment(&pCache->nr_free, 1);
- ink_atomiclist_push(&pCache->outer_free_list, next);
- }
-
- pChunk->allocated += chunk_size;
- pChunk->inner_free_list = NULL;
- pCache->nr_total += chunk_size;
-
- return item;
-}
-
-static inline void *
-malloc_from_chunk(InkFreeList * /* f ATS_UNUSED */, InkThreadCache *pCache, InkChunkInfo *pChunk)
-{
- void *item;
-
- if ((item = pChunk->inner_free_list)) {
- pChunk->inner_free_list = *(void **)item;
- pChunk->allocated++;
- pCache->nr_total++;
- }
-
- return item;
-}
-
-static inline void
-free_to_chunk(InkFreeList *f, InkThreadCache *pCache, void *item)
-{
- InkChunkInfo *pChunk;
-
- pChunk = get_chunk_info_addr(f, item);
- pChunk->allocated--;
- pCache->nr_total--;
-
- *(void **)item = pChunk->inner_free_list;
- pChunk->inner_free_list = item;
-
- if (pChunk->allocated == 0)
- ink_chunk_delete(f, pCache, pChunk);
-}
-
-static inline void *
-malloc_from_cache(InkFreeList *f, InkThreadCache *pCache, uint32_t nr)
-{
- void *item;
- InkChunkInfo *pChunk;
-
- pChunk = pCache->free_chunk_list.head;
- while (pChunk) {
- while ((item = malloc_from_chunk(f, pCache, pChunk))) {
- if (--nr == 0)
- return item;
-
- ink_atomic_increment(&pCache->nr_free, 1);
- ink_atomiclist_push(&pCache->outer_free_list, item);
- }
- pChunk = pChunk->link.next;
- }
-
- pChunk = ink_chunk_create(f, pCache);
- if (nr == f->chunk_size)
- return malloc_whole_chunk(f, pCache, pChunk);
-
- while ((item = malloc_from_chunk(f, pCache, pChunk))) {
- if (--nr == 0)
- return item;
-
- ink_atomic_increment(&pCache->nr_free, 1);
- ink_atomiclist_push(&pCache->outer_free_list, item);
- }
-
- ink_assert(0);
- return NULL;
-}
-
-static inline void
-free_to_cache(InkFreeList *f, InkThreadCache *pCache, void *item, uint32_t nr)
-{
- uint32_t n = nr;
-
- if (item)
- free_to_chunk(f, pCache, item);
-
- while (n && (item = ink_atomiclist_pop(&pCache->outer_free_list))) {
- free_to_chunk(f, pCache, item);
- n--;
- }
- ink_atomic_increment((int *)&pCache->nr_free, -(nr - n));
-}
-
-static inline void
-refresh_average_info(InkThreadCache *pCache)
-{
- uint32_t nr_free;
- float nr_average;
-
- nr_free = pCache->nr_free;
- nr_average = pCache->nr_average;
-
- if (pCache->status == 1 || nr_free < pCache->nr_min)
- pCache->nr_min = nr_free;
-
- pCache->nr_average = (nr_average * (1 - cfg_reclaim_factor)) + (nr_free * cfg_reclaim_factor);
-}
-
-static inline bool
-need_to_reclaim(InkFreeList *f, InkThreadCache *pCache)
-{
- if (!cfg_enable_reclaim)
- return false;
-
- if (pCache->nr_free >= pCache->nr_average && pCache->nr_total > f->chunk_size_base) {
- if (pCache->nr_overage++ >= cfg_max_overage) {
- pCache->nr_overage = 0;
- return true;
- }
- return false;
- }
-
- pCache->nr_overage = 0;
- return false;
-}
-
-void
-reclaimable_freelist_init(InkFreeList **fl, const char *name, uint32_t type_size, uint32_t chunk_size, uint32_t alignment)
-{
- InkFreeList *f;
- ink_freelist_list *fll = freelists;
-
- /* quick test for power of 2 */
- ink_assert(!(alignment & (alignment - 1)));
-
- /* NOTE: it's safe to operate on this global list because
- * ink_freelist_init() is only called from single-threaded
- * initialization code. */
- while (fll) {
- /* Reuse InkFreeList if it has the same type_size. */
- if (fll->fl->type_size == type_size) {
- fll->fl->refcnt++;
- *fl = fll->fl;
- return;
- }
- fll = fll->next;
- }
-
- f = (InkFreeList *)ats_memalign(alignment, sizeof(InkFreeList));
- fll = (ink_freelist_list *)ats_memalign(alignment, sizeof(ink_freelist_list));
- fll->fl = f;
- fll->next = freelists;
- freelists = fll;
-
- f->name = name;
- f->used = 0;
- f->allocated = 0;
- f->allocated_base = 0;
- f->used_base = 0;
-
- memory_alignment_init(f, type_size, chunk_size, alignment);
-
- f->refcnt = 1;
- f->pThreadCache = NULL;
- f->nr_thread_cache = 0;
- f->thread_cache_idx = nr_freelist++;
- ink_assert(f->thread_cache_idx < MAX_NUM_FREELIST);
- ink_mutex_init(&f->lock, "InkFreeList Lock");
-
- *fl = f;
-}
-
-void *
-reclaimable_freelist_new(InkFreeList *f)
-{
- void *ptr;
- uint32_t i, nr;
- uint32_t old_value;
- uint32_t num_to_move;
- InkChunkInfo *pChunk = NULL;
- InkThreadCache *pCache, *pNextCache;
-
- ink_atomic_increment(&f->used, 1);
-
- /* no thread cache, create it */
- if (unlikely((pCache = ThreadCaches[f->thread_cache_idx]) == NULL)) {
- pCache = (InkThreadCache *)ats_calloc(1, sizeof(InkThreadCache));
-
- pCache->f = f;
- pCache->free_chunk_list = DLL<InkChunkInfo>();
-
- /* this lock will only be accessed when initializing
- * thread cache, so it won't damage performance */
- ink_mutex_acquire(&f->lock);
- ink_atomiclist_init(&pCache->outer_free_list, f->name, 0);
-
- nr = CEIL(f->chunk_size_base, f->chunk_size);
- for (i = 0; i < nr; i++) {
- pChunk = ink_chunk_create(f, pCache);
- }
-
- pCache->nr_malloc = 1;
-
- ThreadCaches[f->thread_cache_idx] = pCache;
-
- if (f->pThreadCache) {
- /* we will loop pCache.next without lock, following
- * statement's sequence is important for us. */
- pCache->next = f->pThreadCache;
- pCache->prev = f->pThreadCache->prev;
- pCache->next->prev = pCache;
- pCache->prev->next = pCache;
- } else {
- pCache->next = pCache;
- pCache->prev = pCache;
- }
-
- f->pThreadCache = pCache;
- f->nr_thread_cache++;
-
- ink_mutex_release(&f->lock);
-
- ptr = malloc_whole_chunk(f, pCache, pChunk);
- set_chunk_item_magic(f, pChunk, ptr);
- return ptr;
- }
-
- pCache->status = 0;
-
- /* priority to fetch memory from outer_free_list */
- if ((ptr = ink_atomiclist_pop(&pCache->outer_free_list))) {
- old_value = ink_atomic_increment((int *)&pCache->nr_free, -1);
- ink_release_assert(old_value > 0);
- ink_atomic_increment(&pCache->nr_malloc, 1);
- set_chunk_item_magic(f, NULL, ptr);
- return ptr;
- }
-
- /* try to steal memory from other thread's outer_free_list */
- pNextCache = pCache->next;
- while (pNextCache != pCache) {
- if ((ptr = ink_atomiclist_pop(&pNextCache->outer_free_list))) {
- old_value = ink_atomic_increment((int *)&pNextCache->nr_free, -1);
- ink_release_assert(old_value > 0);
- ink_atomic_increment(&pNextCache->nr_malloc, 1);
- set_chunk_item_magic(f, NULL, ptr);
- return ptr;
- }
- pNextCache = pNextCache->next;
- }
-
- /* try to reclaim memory from all caches in the same thread */
- for (i = 0; i < nr_freelist; i++) {
- if ((pNextCache = ThreadCaches[i]) == NULL)
- continue;
-
- if (need_to_reclaim(pNextCache->f, pNextCache)) {
- if (cfg_debug_filter & 0x1)
- show_info("F", pNextCache->f, pNextCache);
-
- num_to_move = MIN(pNextCache->nr_average, pNextCache->nr_free);
-
- free_to_cache(pNextCache->f, pNextCache, NULL, num_to_move);
-
- if (cfg_debug_filter & 0x1)
- show_info("-", pNextCache->f, pNextCache);
-
- refresh_average_info(pNextCache);
- }
- }
-
- /* finally, fetch from thread local cache */
- if (cfg_debug_filter & 0x2)
- show_info("M", f, pCache);
- ptr = malloc_from_cache(f, pCache, f->chunk_size);
- if (cfg_debug_filter & 0x2)
- show_info("+", f, pCache);
-
- refresh_average_info(pCache);
- ink_atomic_increment(&pCache->nr_malloc, 1);
- set_chunk_item_magic(f, NULL, ptr);
- return ptr;
-}
-
-void
-reclaimable_freelist_free(InkFreeList *f, void *item)
-{
- InkChunkInfo *pChunk;
- InkThreadCache *pCache;
-
- if (item == NULL)
- return;
-
- pChunk = get_chunk_info_addr(f, item);
- clear_chunk_item_magic(f, pChunk, item);
- pCache = pChunk->pThreadCache;
-
- ink_atomic_increment((int *)&pCache->nr_malloc, -1);
- if (ink_atomic_cas((int *)&pCache->status, 0, 1))
- refresh_average_info(pCache);
-
- ink_atomic_increment(&pCache->nr_free, 1);
- ink_atomiclist_push(&pCache->outer_free_list, item);
- ink_atomic_increment(&f->used, -1);
-}
-#endif
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/lib/ts/ink_queue_ext.h
----------------------------------------------------------------------
diff --git a/lib/ts/ink_queue_ext.h b/lib/ts/ink_queue_ext.h
deleted file mode 100644
index 4ff8402..0000000
--- a/lib/ts/ink_queue_ext.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/** @file
-
- A brief file description
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#ifndef _ink_queue_ext_h_
-#define _ink_queue_ext_h_
-
-/***********************************************************************
-
- Head file of Reclaimable freelist
-
-***********************************************************************/
-
-#include "List.h"
-#include "ink_queue.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-#if TS_USE_RECLAIMABLE_FREELIST
-struct _InkThreadCache;
-struct _InkFreeList;
-
-typedef struct _InkChunkInfo {
- pthread_t tid;
-
- uint32_t type_size;
- uint32_t chunk_size;
- uint32_t allocated;
- uint32_t length;
-
- /*
- * inner free list will only be
- * accessed by creator-thread
- */
- void *inner_free_list;
- void *head;
-
- struct _InkThreadCache *pThreadCache;
-
- LINK(_InkChunkInfo, link);
-
-#ifdef DEBUG
- /*
- * magic code for each item,
- * it's used to check double-free issue.
- */
- unsigned char item_magic[0];
-#endif
-} InkChunkInfo;
-
-typedef struct _InkThreadCache {
- struct _InkFreeList *f;
-
- /* outer free list will be accessed by:
- * - creator-thread, asa producer-thread
- * - consumer-thread
- * - neighbor-thread
- */
- InkAtomicList outer_free_list;
-
- /* using for memory reclaim algorithm */
- float nr_average;
- uint32_t nr_total;
- uint32_t nr_free;
- uint32_t nr_min;
- uint32_t nr_overage;
- uint32_t nr_malloc;
-
- /* represent the status(state) of allocator: Malloc-ing(0) or Free-ing(1),
- * I use it as an simple state machine - calculating the minimum of free
- * memory only when the status change from Malloc-ing to Free-ing.
- */
- uint32_t status;
-
- uint32_t nr_free_chunks;
- DLL<InkChunkInfo> free_chunk_list;
-
- _InkThreadCache *prev, *next;
-} InkThreadCache;
-
-typedef struct _InkFreeList {
- uint32_t thread_cache_idx;
-
- uint32_t refcnt;
- const char *name;
-
- uint32_t type_size;
- uint32_t alignment;
-
- /* number of elements in one chunk */
- uint32_t chunk_size;
- /* total byte size of one chuck */
- uint32_t chunk_byte_size;
- /* chunk_addr = (uintptr_t)ptr & chunk_addr_mask */
- uintptr_t chunk_addr_mask;
-
- uint32_t used;
- uint32_t allocated;
- uint32_t allocated_base;
- uint32_t used_base;
- uint32_t chunk_size_base;
-
- uint32_t nr_thread_cache;
- InkThreadCache *pThreadCache;
- ink_mutex lock;
-} InkFreeList, *PInkFreeList;
-
-/* reclaimable freelist API */
-void reclaimable_freelist_init(InkFreeList **fl, const char *name, uint32_t type_size, uint32_t chunk_size, uint32_t alignment);
-void *reclaimable_freelist_new(InkFreeList *f);
-void reclaimable_freelist_free(InkFreeList *f, void *item);
-#endif /* END OF TS_USE_RECLAIMABLE_FREELIST */
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* _ink_queue_ext_h_ */
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/proxy/http/HttpConfig.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpConfig.cc b/proxy/http/HttpConfig.cc
index b598111..aadd312 100644
--- a/proxy/http/HttpConfig.cc
+++ b/proxy/http/HttpConfig.cc
@@ -926,13 +926,6 @@ HttpConfig::startup()
RecHttpLoadIp("proxy.local.incoming_ip_to_bind", c.inbound_ip4, c.inbound_ip6);
RecHttpLoadIp("proxy.local.outgoing_ip_to_bind", c.outbound_ip4, c.outbound_ip6);
-#if TS_USE_RECLAIMABLE_FREELIST
- HttpEstablishStaticConfigLongLong(cfg_debug_filter, "proxy.config.allocator.debug_filter");
- HttpEstablishStaticConfigLongLong(cfg_enable_reclaim, "proxy.config.allocator.enable_reclaim");
- HttpEstablishStaticConfigLongLong(cfg_max_overage, "proxy.config.allocator.max_overage");
- HttpEstablishStaticConfigFloat(cfg_reclaim_factor, "proxy.config.allocator.reclaim_factor");
-#endif
-
HttpEstablishStaticConfigLongLong(c.server_max_connections, "proxy.config.http.server_max_connections");
HttpEstablishStaticConfigLongLong(c.max_websocket_connections, "proxy.config.http.websocket.max_number_of_connections");
HttpEstablishStaticConfigLongLong(c.oride.server_tcp_init_cwnd, "proxy.config.http.server_tcp_init_cwnd");
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7142d326/proxy/http/HttpConfig.h
----------------------------------------------------------------------
diff --git a/proxy/http/HttpConfig.h b/proxy/http/HttpConfig.h
index 07b2a4c..812d2c8 100644
--- a/proxy/http/HttpConfig.h
+++ b/proxy/http/HttpConfig.h
@@ -840,10 +840,10 @@ extern volatile int32_t icp_dynamic_enabled;
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
inline HttpConfigParams::HttpConfigParams()
- : proxy_hostname(NULL), proxy_hostname_len(0), server_max_connections(0), origin_min_keep_alive_connections(0), max_websocket_connections(-1),
- parent_proxy_routing_enable(0), disable_ssl_parenting(0), enable_url_expandomatic(0), no_dns_forward_to_parent(0),
- uncacheable_requests_bypass_parent(1), no_origin_server_dns(0), use_client_target_addr(0), use_client_source_port(0),
- proxy_request_via_string(NULL), proxy_request_via_string_len(0), proxy_response_via_string(NULL),
+ : proxy_hostname(NULL), proxy_hostname_len(0), server_max_connections(0), origin_min_keep_alive_connections(0),
+ max_websocket_connections(-1), parent_proxy_routing_enable(0), disable_ssl_parenting(0), enable_url_expandomatic(0),
+ no_dns_forward_to_parent(0), uncacheable_requests_bypass_parent(1), no_origin_server_dns(0), use_client_target_addr(0),
+ use_client_source_port(0), proxy_request_via_string(NULL), proxy_request_via_string_len(0), proxy_response_via_string(NULL),
proxy_response_via_string_len(0), url_expansions_string(NULL), url_expansions(NULL), num_url_expansions(0),
session_auth_cache_keep_alive_enabled(1), transaction_active_timeout_in(900), accept_no_activity_timeout(120),
parent_connect_attempts(4), per_parent_connect_attempts(2), parent_connect_timeout(30), anonymize_other_header_list(NULL),