Merge branch 'dev'

This commit is contained in:
Jason Evans 2011-01-31 20:12:32 -08:00
commit a73ebd946a
12 changed files with 97 additions and 89 deletions

View File

@ -6,6 +6,14 @@ found in the git revision history:
http://www.canonware.com/cgi-bin/gitweb.cgi?p=jemalloc.git http://www.canonware.com/cgi-bin/gitweb.cgi?p=jemalloc.git
git://canonware.com/jemalloc.git git://canonware.com/jemalloc.git
* 2.1.1
Bug Fixes:
- Fix aligned huge reallocation (affected allocm()).
- Fix the ALLOCM_LG_ALIGN macro definition.
- Fix a heap dumping deadlock.
- Fix a "thread.arena" mallctl bug.
* 2.1.0 * 2.1.0
This version incorporates some optimizations that can't quite be considered This version incorporates some optimizations that can't quite be considered
@ -27,7 +35,7 @@ found in the git revision history:
Bug fixes: Bug fixes:
- Fix a race condition in heap profiling that could cause undefined behavior - Fix a race condition in heap profiling that could cause undefined behavior
if opt.prof_accum were disabled. if "opt.prof_accum" were disabled.
- Add missing mutex unlocks for some OOM error paths in the heap profiling - Add missing mutex unlocks for some OOM error paths in the heap profiling
code. code.
- Fix a compilation error for non-C99 builds. - Fix a compilation error for non-C99 builds.

View File

@ -28,7 +28,7 @@ any of the following arguments (not a definitive list) to 'configure':
--with-jemalloc-prefix=<prefix> --with-jemalloc-prefix=<prefix>
Prefix all public APIs with <prefix>. For example, if <prefix> is Prefix all public APIs with <prefix>. For example, if <prefix> is
"prefix_", the API changes like the following occur: "prefix_", API changes like the following occur:
malloc() --> prefix_malloc() malloc() --> prefix_malloc()
malloc_conf --> prefix_malloc_conf malloc_conf --> prefix_malloc_conf
@ -48,9 +48,9 @@ any of the following arguments (not a definitive list) to 'configure':
example, libjemalloc.so.0 becomes libjemalloc<suffix>.so.0. example, libjemalloc.so.0 becomes libjemalloc<suffix>.so.0.
--enable-cc-silence --enable-cc-silence
Enable code that silences unuseful compiler warnings. This is helpful when Enable code that silences non-useful compiler warnings. This is helpful
trying to tell serious warnings from those due to compiler limitations, but when trying to tell serious warnings from those due to compiler
it potentially incurs a performance penalty. limitations, but it potentially incurs a performance penalty.
--enable-debug --enable-debug
Enable assertions and validation code. This incurs a substantial Enable assertions and validation code. This incurs a substantial
@ -62,7 +62,7 @@ any of the following arguments (not a definitive list) to 'configure':
--enable-prof --enable-prof
Enable heap profiling and leak detection functionality. See the "opt.prof" Enable heap profiling and leak detection functionality. See the "opt.prof"
option documention for usage details. option documentation for usage details.
--disable-prof-libgcc --disable-prof-libgcc
Disable the use of libgcc's backtracing functionality. Ordinarily, libgcc's Disable the use of libgcc's backtracing functionality. Ordinarily, libgcc's
@ -89,7 +89,7 @@ any of the following arguments (not a definitive list) to 'configure':
--disable-tcache --disable-tcache
Disable thread-specific caches for small objects. Objects are cached and Disable thread-specific caches for small objects. Objects are cached and
released in bulk, thus reducing the total number of mutex operations. See released in bulk, thus reducing the total number of mutex operations. See
the "opt.tcache" option for suage details. the "opt.tcache" option for usage details.
--enable-swap --enable-swap
Enable mmap()ed swap file support. When this feature is built in, it is Enable mmap()ed swap file support. When this feature is built in, it is
@ -198,8 +198,8 @@ MANDIR="?"
Use this as the installation prefix for man pages. Use this as the installation prefix for man pages.
DESTDIR="?" DESTDIR="?"
Prepend DESTDIR to INCLUDEDIR, LIBDIR, and MANDIR. This is useful when Prepend DESTDIR to INCLUDEDIR, LIBDIR, DATADIR, and MANDIR. This is useful
installing to a different path than was specified via --prefix. when installing to a different path than was specified via --prefix.
CC="?" CC="?"
Use this to invoke the C compiler. Use this to invoke the C compiler.

View File

@ -45,9 +45,10 @@
* point is implicitly RUN_BFP bits to the left. * point is implicitly RUN_BFP bits to the left.
* *
* Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be * Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be
* honored for some/all object sizes, since there is one bit of header overhead * honored for some/all object sizes, since when heap profiling is enabled
* per object (plus a constant). This constraint is relaxed (ignored) for runs * there is one pointer of header overhead per object (plus a constant). This
* that are so small that the per-region overhead is greater than: * constraint is relaxed (ignored) for runs that are so small that the
* per-region overhead is greater than:
* *
* (RUN_MAX_OVRHD / (reg_size << (3+RUN_BFP)) * (RUN_MAX_OVRHD / (reg_size << (3+RUN_BFP))
*/ */
@ -105,7 +106,7 @@ struct arena_chunk_map_s {
* Run address (or size) and various flags are stored together. The bit * Run address (or size) and various flags are stored together. The bit
* layout looks like (assuming 32-bit system): * layout looks like (assuming 32-bit system):
* *
* ???????? ???????? ????---- ----dzla * ???????? ???????? ????---- ----dula
* *
* ? : Unallocated: Run address for first/last pages, unset for internal * ? : Unallocated: Run address for first/last pages, unset for internal
* pages. * pages.
@ -113,7 +114,7 @@ struct arena_chunk_map_s {
* Large: Run size for first page, unset for trailing pages. * Large: Run size for first page, unset for trailing pages.
* - : Unused. * - : Unused.
* d : dirty? * d : dirty?
* z : zeroed? * u : unzeroed?
* l : large? * l : large?
* a : allocated? * a : allocated?
* *
@ -129,30 +130,30 @@ struct arena_chunk_map_s {
* [dula] : bit unset * [dula] : bit unset
* *
* Unallocated (clean): * Unallocated (clean):
* ssssssss ssssssss ssss---- ----du-- * ssssssss ssssssss ssss---- ----du-a
* xxxxxxxx xxxxxxxx xxxx---- -----Uxx * xxxxxxxx xxxxxxxx xxxx---- -----Uxx
* ssssssss ssssssss ssss---- ----dU-- * ssssssss ssssssss ssss---- ----dU-a
* *
* Unallocated (dirty): * Unallocated (dirty):
* ssssssss ssssssss ssss---- ----D--- * ssssssss ssssssss ssss---- ----D--a
* xxxxxxxx xxxxxxxx xxxx---- ----xxxx * xxxxxxxx xxxxxxxx xxxx---- ----xxxx
* ssssssss ssssssss ssss---- ----D--- * ssssssss ssssssss ssss---- ----D--a
* *
* Small: * Small:
* pppppppp pppppppp pppp---- ----d--a * pppppppp pppppppp pppp---- ----d--A
* pppppppp pppppppp pppp---- -------a * pppppppp pppppppp pppp---- -------A
* pppppppp pppppppp pppp---- ----d--a * pppppppp pppppppp pppp---- ----d--A
* *
* Large: * Large:
* ssssssss ssssssss ssss---- ----D-la * ssssssss ssssssss ssss---- ----D-LA
* xxxxxxxx xxxxxxxx xxxx---- ----xxxx * xxxxxxxx xxxxxxxx xxxx---- ----xxxx
* -------- -------- -------- ----D-la * -------- -------- -------- ----D-LA
* *
* Large (sampled, size <= PAGE_SIZE): * Large (sampled, size <= PAGE_SIZE):
* ssssssss ssssssss sssscccc ccccD-la * ssssssss ssssssss sssscccc ccccD-LA
* *
* Large (not sampled, size == PAGE_SIZE): * Large (not sampled, size == PAGE_SIZE):
* ssssssss ssssssss ssss---- ----D-la * ssssssss ssssssss ssss---- ----D-LA
*/ */
size_t bits; size_t bits;
#ifdef JEMALLOC_PROF #ifdef JEMALLOC_PROF
@ -347,45 +348,35 @@ struct arena_s {
/* /*
* bins is used to store trees of free regions of the following sizes, * bins is used to store trees of free regions of the following sizes,
* assuming a 16-byte quantum, 4 KiB page size, and default * assuming a 64-bit system with 16-byte quantum, 4 KiB page size, and
* JEMALLOC_OPTIONS. * default MALLOC_CONF.
* *
* bins[i] | size | * bins[i] | size |
* --------+--------+ * --------+--------+
* 0 | 2 | * 0 | 8 |
* 1 | 4 |
* 2 | 8 |
* --------+--------+ * --------+--------+
* 3 | 16 | * 1 | 16 |
* 4 | 32 | * 2 | 32 |
* 5 | 48 | * 3 | 48 |
* : : * : :
* 8 | 96 | * 6 | 96 |
* 9 | 112 | * 7 | 112 |
* 10 | 128 | * 8 | 128 |
* --------+--------+ * --------+--------+
* 11 | 192 | * 9 | 192 |
* 12 | 256 | * 10 | 256 |
* 13 | 320 | * 11 | 320 |
* 14 | 384 | * 12 | 384 |
* 15 | 448 | * 13 | 448 |
* 16 | 512 | * 14 | 512 |
* --------+--------+ * --------+--------+
* 17 | 768 | * 15 | 768 |
* 18 | 1024 | * 16 | 1024 |
* 19 | 1280 | * 17 | 1280 |
* : : * : :
* 27 | 3328 | * 25 | 3328 |
* 28 | 3584 | * 26 | 3584 |
* 29 | 3840 | * 27 | 3840 |
* --------+--------+
* 30 | 4 KiB |
* 31 | 6 KiB |
* 33 | 8 KiB |
* : :
* 43 | 28 KiB |
* 44 | 30 KiB |
* 45 | 32 KiB |
* --------+--------+ * --------+--------+
*/ */
arena_bin_t bins[1]; /* Dynamically sized. */ arena_bin_t bins[1]; /* Dynamically sized. */

View File

@ -31,7 +31,7 @@ struct ckhc_s {
struct ckh_s { struct ckh_s {
#ifdef JEMALLOC_DEBUG #ifdef JEMALLOC_DEBUG
#define CKH_MAGIG 0x3af2489d #define CKH_MAGIC 0x3af2489d
uint32_t magic; uint32_t magic;
#endif #endif

View File

@ -37,7 +37,6 @@ struct tcache_bin_s {
tcache_bin_stats_t tstats; tcache_bin_stats_t tstats;
# endif # endif
unsigned low_water; /* Min # cached since last GC. */ unsigned low_water; /* Min # cached since last GC. */
unsigned high_water; /* Max # cached since last GC. */
unsigned ncached; /* # of cached objects. */ unsigned ncached; /* # of cached objects. */
unsigned ncached_max; /* Upper limit on ncached. */ unsigned ncached_max; /* Upper limit on ncached. */
void *avail; /* Chain of available objects. */ void *avail; /* Chain of available objects. */
@ -194,7 +193,6 @@ tcache_event(tcache_t *tcache)
} }
} }
tbin->low_water = tbin->ncached; tbin->low_water = tbin->ncached;
tbin->high_water = tbin->ncached;
tcache->next_gc_bin++; tcache->next_gc_bin++;
if (tcache->next_gc_bin == nhbins) if (tcache->next_gc_bin == nhbins)
@ -348,8 +346,6 @@ tcache_dalloc_small(tcache_t *tcache, void *ptr)
*(void **)ptr = tbin->avail; *(void **)ptr = tbin->avail;
tbin->avail = ptr; tbin->avail = ptr;
tbin->ncached++; tbin->ncached++;
if (tbin->ncached > tbin->high_water)
tbin->high_water = tbin->ncached;
tcache_event(tcache); tcache_event(tcache);
} }
@ -388,8 +384,6 @@ tcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size)
*(void **)ptr = tbin->avail; *(void **)ptr = tbin->avail;
tbin->avail = ptr; tbin->avail = ptr;
tbin->ncached++; tbin->ncached++;
if (tbin->ncached > tbin->high_water)
tbin->high_water = tbin->ncached;
tcache_event(tcache); tcache_event(tcache);
} }

View File

@ -19,7 +19,7 @@ extern "C" {
# define JEMALLOC_P(s) s # define JEMALLOC_P(s) s
#endif #endif
#define ALLOCM_LG_ALIGN ((int)0x3f) #define ALLOCM_LG_ALIGN(la) (la)
#if LG_SIZEOF_PTR == 2 #if LG_SIZEOF_PTR == 2
#define ALLOCM_ALIGN(a) (ffs(a)-1) #define ALLOCM_ALIGN(a) (ffs(a)-1)
#else #else

View File

@ -1358,8 +1358,6 @@ arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind
#endif #endif
malloc_mutex_unlock(&bin->lock); malloc_mutex_unlock(&bin->lock);
tbin->ncached = i; tbin->ncached = i;
if (tbin->ncached > tbin->high_water)
tbin->high_water = tbin->ncached;
} }
#endif #endif
@ -1369,7 +1367,6 @@ arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind
* *) bin->run_size >= min_run_size * *) bin->run_size >= min_run_size
* *) bin->run_size <= arena_maxclass * *) bin->run_size <= arena_maxclass
* *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed). * *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed).
* *) run header size < PAGE_SIZE
* *
* bin->nregs and bin->reg0_offset are also calculated here, since these * bin->nregs and bin->reg0_offset are also calculated here, since these
* settings are all interdependent. * settings are all interdependent.
@ -1455,8 +1452,7 @@ arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size)
} while (try_run_size <= arena_maxclass } while (try_run_size <= arena_maxclass
&& try_run_size <= arena_maxclass && try_run_size <= arena_maxclass
&& RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX && RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX
&& (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size && (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size);
&& try_hdr_size < PAGE_SIZE);
assert(good_hdr_size <= good_reg0_offset); assert(good_hdr_size <= good_reg0_offset);

View File

@ -73,7 +73,7 @@ ckh_isearch(ckh_t *ckh, const void *key)
size_t hash1, hash2, bucket, cell; size_t hash1, hash2, bucket, cell;
assert(ckh != NULL); assert(ckh != NULL);
assert(ckh->magic = CKH_MAGIG); assert(ckh->magic == CKH_MAGIC);
ckh->hash(key, ckh->lg_curbuckets, &hash1, &hash2); ckh->hash(key, ckh->lg_curbuckets, &hash1, &hash2);
@ -383,7 +383,7 @@ ckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash, ckh_keycomp_t *keycomp)
} }
#ifdef JEMALLOC_DEBUG #ifdef JEMALLOC_DEBUG
ckh->magic = CKH_MAGIG; ckh->magic = CKH_MAGIC;
#endif #endif
ret = false; ret = false;
@ -396,7 +396,7 @@ ckh_delete(ckh_t *ckh)
{ {
assert(ckh != NULL); assert(ckh != NULL);
assert(ckh->magic = CKH_MAGIG); assert(ckh->magic == CKH_MAGIC);
#ifdef CKH_VERBOSE #ifdef CKH_VERBOSE
malloc_printf( malloc_printf(
@ -421,7 +421,7 @@ ckh_count(ckh_t *ckh)
{ {
assert(ckh != NULL); assert(ckh != NULL);
assert(ckh->magic = CKH_MAGIG); assert(ckh->magic == CKH_MAGIC);
return (ckh->count); return (ckh->count);
} }
@ -452,7 +452,7 @@ ckh_insert(ckh_t *ckh, const void *key, const void *data)
bool ret; bool ret;
assert(ckh != NULL); assert(ckh != NULL);
assert(ckh->magic = CKH_MAGIG); assert(ckh->magic == CKH_MAGIC);
assert(ckh_search(ckh, key, NULL, NULL)); assert(ckh_search(ckh, key, NULL, NULL));
#ifdef CKH_COUNT #ifdef CKH_COUNT
@ -477,7 +477,7 @@ ckh_remove(ckh_t *ckh, const void *searchkey, void **key, void **data)
size_t cell; size_t cell;
assert(ckh != NULL); assert(ckh != NULL);
assert(ckh->magic = CKH_MAGIG); assert(ckh->magic == CKH_MAGIC);
cell = ckh_isearch(ckh, searchkey); cell = ckh_isearch(ckh, searchkey);
if (cell != SIZE_T_MAX) { if (cell != SIZE_T_MAX) {
@ -509,7 +509,7 @@ ckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data)
size_t cell; size_t cell;
assert(ckh != NULL); assert(ckh != NULL);
assert(ckh->magic = CKH_MAGIG); assert(ckh->magic == CKH_MAGIC);
cell = ckh_isearch(ckh, searchkey); cell = ckh_isearch(ckh, searchkey);
if (cell != SIZE_T_MAX) { if (cell != SIZE_T_MAX) {

View File

@ -1137,6 +1137,11 @@ thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
/* Set new arena association. */ /* Set new arena association. */
ARENA_SET(arena); ARENA_SET(arena);
{
tcache_t *tcache = TCACHE_GET();
if (tcache != NULL)
tcache->arena = arena;
}
} }
ret = 0; ret = 0;

View File

@ -83,7 +83,7 @@ huge_palloc(size_t size, size_t alignment, bool zero)
* alignment, in order to assure the alignment can be achieved, then * alignment, in order to assure the alignment can be achieved, then
* unmap leading and trailing chunks. * unmap leading and trailing chunks.
*/ */
assert(alignment >= chunksize); assert(alignment > chunksize);
chunk_size = CHUNK_CEILING(size); chunk_size = CHUNK_CEILING(size);
@ -192,7 +192,7 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
* different size class. In that case, fall back to allocating new * different size class. In that case, fall back to allocating new
* space and copying. * space and copying.
*/ */
if (alignment != 0) if (alignment > chunksize)
ret = huge_palloc(size + extra, alignment, zero); ret = huge_palloc(size + extra, alignment, zero);
else else
ret = huge_malloc(size + extra, zero); ret = huge_malloc(size + extra, zero);
@ -201,7 +201,7 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
if (extra == 0) if (extra == 0)
return (NULL); return (NULL);
/* Try again, this time without extra. */ /* Try again, this time without extra. */
if (alignment != 0) if (alignment > chunksize)
ret = huge_palloc(size, alignment, zero); ret = huge_palloc(size, alignment, zero);
else else
ret = huge_malloc(size, zero); ret = huge_malloc(size, zero);

View File

@ -421,8 +421,8 @@ malloc_conf_init(void)
if ((opts = getenv(envname)) != NULL) { if ((opts = getenv(envname)) != NULL) {
/* /*
* Do nothing; opts is already initialized to * Do nothing; opts is already initialized to
* the value of the JEMALLOC_OPTIONS * the value of the MALLOC_CONF environment
* environment variable. * variable.
*/ */
} else { } else {
/* No configuration specified. */ /* No configuration specified. */

View File

@ -432,6 +432,7 @@ prof_lookup(prof_bt_t *bt)
prof_ctx_t *p; prof_ctx_t *p;
void *v; void *v;
} ctx; } ctx;
bool new_ctx;
/* /*
* This thread's cache lacks bt. Look for it in the global * This thread's cache lacks bt. Look for it in the global
@ -468,12 +469,14 @@ prof_lookup(prof_bt_t *bt)
idalloc(ctx.v); idalloc(ctx.v);
return (NULL); return (NULL);
} }
}
/* /*
* Acquire ctx's lock before releasing bt2ctx_mtx, in order to * Artificially raise curobjs, in order to avoid a race
* avoid a race condition with prof_ctx_destroy(). * condition with prof_ctx_merge()/prof_ctx_destroy().
*/ */
malloc_mutex_lock(&ctx.p->lock); ctx.p->cnt_merged.curobjs++;
new_ctx = true;
} else
new_ctx = false;
prof_leave(); prof_leave();
/* Link a prof_thd_cnt_t into ctx for this thread. */ /* Link a prof_thd_cnt_t into ctx for this thread. */
@ -498,7 +501,11 @@ prof_lookup(prof_bt_t *bt)
/* Allocate and partially initialize a new cnt. */ /* Allocate and partially initialize a new cnt. */
ret.v = imalloc(sizeof(prof_thr_cnt_t)); ret.v = imalloc(sizeof(prof_thr_cnt_t));
if (ret.p == NULL) { if (ret.p == NULL) {
if (new_ctx) {
malloc_mutex_lock(&ctx.p->lock);
ctx.p->cnt_merged.curobjs--;
malloc_mutex_unlock(&ctx.p->lock); malloc_mutex_unlock(&ctx.p->lock);
}
return (NULL); return (NULL);
} }
ql_elm_new(ret.p, cnts_link); ql_elm_new(ret.p, cnts_link);
@ -509,12 +516,19 @@ prof_lookup(prof_bt_t *bt)
ret.p->epoch = 0; ret.p->epoch = 0;
memset(&ret.p->cnts, 0, sizeof(prof_cnt_t)); memset(&ret.p->cnts, 0, sizeof(prof_cnt_t));
if (ckh_insert(&prof_tdata->bt2cnt, btkey.v, ret.v)) { if (ckh_insert(&prof_tdata->bt2cnt, btkey.v, ret.v)) {
if (new_ctx) {
malloc_mutex_lock(&ctx.p->lock);
ctx.p->cnt_merged.curobjs--;
malloc_mutex_unlock(&ctx.p->lock); malloc_mutex_unlock(&ctx.p->lock);
}
idalloc(ret.v); idalloc(ret.v);
return (NULL); return (NULL);
} }
ql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link); ql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link);
malloc_mutex_lock(&ctx.p->lock);
ql_tail_insert(&ctx.p->cnts_ql, ret.p, cnts_link); ql_tail_insert(&ctx.p->cnts_ql, ret.p, cnts_link);
if (new_ctx)
ctx.p->cnt_merged.curobjs--;
malloc_mutex_unlock(&ctx.p->lock); malloc_mutex_unlock(&ctx.p->lock);
} else { } else {
/* Move ret to the front of the LRU. */ /* Move ret to the front of the LRU. */