version 1.17, 2008/03/08 13:17:13 |
version 1.24.6.2, 2012/04/23 23:40:40 |
Line 319 __strerror_r(int e, char *s, size_t l) |
|
Line 319 __strerror_r(int e, char *s, size_t l) |
|
#define SMALL_MAX_DEFAULT (1 << SMALL_MAX_2POW_DEFAULT) |
#define SMALL_MAX_DEFAULT (1 << SMALL_MAX_2POW_DEFAULT) |
|
|
/* |
/* |
* Maximum desired run header overhead. Runs are sized as small as possible |
* RUN_MAX_OVRHD indicates maximum desired run header overhead. Runs are sized |
* such that this setting is still honored, without violating other constraints. |
* as small as possible such that this setting is still honored, without |
* The goal is to make runs as small as possible without exceeding a per run |
* violating other constraints. The goal is to make runs as small as possible |
* external fragmentation threshold. |
* without exceeding a per run external fragmentation threshold. |
* |
* |
* Note that it is possible to set this low enough that it cannot be honored |
* We use binary fixed point math for overhead computations, where the binary |
* for some/all object sizes, since there is one bit of header overhead per |
* point is implicitly RUN_BFP bits to the left. |
* object (plus a constant). In such cases, this constraint is relaxed. |
|
* |
* |
* RUN_MAX_OVRHD_RELAX specifies the maximum number of bits per region of |
* Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be |
* overhead for which RUN_MAX_OVRHD is relaxed. |
* honored for some/all object sizes, since there is one bit of header overhead |
|
* per object (plus a constant). This 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)) |
*/ |
*/ |
#define RUN_MAX_OVRHD 0.015 |
#define RUN_BFP 12 |
#define RUN_MAX_OVRHD_RELAX 1.5 |
/* \/ Implicit binary fixed point. */ |
|
#define RUN_MAX_OVRHD 0x0000003dU |
|
#define RUN_MAX_OVRHD_RELAX 0x00001800U |
|
|
/* Put a cap on small object run size. This overrides RUN_MAX_OVRHD. */ |
/* Put a cap on small object run size. This overrides RUN_MAX_OVRHD. */ |
#define RUN_MAX_SMALL_2POW 15 |
#define RUN_MAX_SMALL_2POW 15 |
Line 1029 base_pages_alloc(size_t minsize) |
|
Line 1034 base_pages_alloc(size_t minsize) |
|
*/ |
*/ |
incr = (intptr_t)chunksize |
incr = (intptr_t)chunksize |
- (intptr_t)CHUNK_ADDR2OFFSET(brk_cur); |
- (intptr_t)CHUNK_ADDR2OFFSET(brk_cur); |
if (incr < minsize) |
assert(incr >= 0); |
|
if ((size_t)incr < minsize) |
incr += csize; |
incr += csize; |
|
|
brk_prev = sbrk(incr); |
brk_prev = sbrk(incr); |
Line 1364 chunk_alloc(size_t size) |
|
Line 1370 chunk_alloc(size_t size) |
|
*/ |
*/ |
incr = (intptr_t)size |
incr = (intptr_t)size |
- (intptr_t)CHUNK_ADDR2OFFSET(brk_cur); |
- (intptr_t)CHUNK_ADDR2OFFSET(brk_cur); |
if (incr == size) { |
if (incr == (intptr_t)size) { |
ret = brk_cur; |
ret = brk_cur; |
} else { |
} else { |
ret = (void *)((intptr_t)brk_cur + incr); |
ret = (void *)((intptr_t)brk_cur + incr); |
Line 1529 chunk_dealloc(void *chunk, size_t size) |
|
Line 1535 chunk_dealloc(void *chunk, size_t size) |
|
* amongst threads. To accomplish this, next_arena advances only in |
* amongst threads. To accomplish this, next_arena advances only in |
* ncpu steps. |
* ncpu steps. |
*/ |
*/ |
static inline arena_t * |
static __noinline arena_t * |
choose_arena(void) |
choose_arena_hard(void) |
{ |
{ |
unsigned i, curcpu; |
unsigned i, curcpu; |
arena_t **map; |
arena_t **map; |
|
|
map = get_arenas_map(); |
|
curcpu = thr_curcpu(); |
|
if (__predict_true(map != NULL && map[curcpu] != NULL)) |
|
return map[curcpu]; |
|
|
|
/* Initialize the current block of arenas and advance to next. */ |
/* Initialize the current block of arenas and advance to next. */ |
malloc_mutex_lock(&arenas_mtx); |
malloc_mutex_lock(&arenas_mtx); |
assert(next_arena % ncpus == 0); |
assert(next_arena % ncpus == 0); |
Line 1563 choose_arena(void) |
|
Line 1564 choose_arena(void) |
|
return arenas[0]; |
return arenas[0]; |
} |
} |
|
|
|
static inline arena_t * |
|
choose_arena(void) |
|
{ |
|
unsigned curcpu; |
|
arena_t **map; |
|
|
|
map = get_arenas_map(); |
|
curcpu = thr_curcpu(); |
|
if (__predict_true(map != NULL && map[curcpu] != NULL)) |
|
return map[curcpu]; |
|
|
|
return choose_arena_hard(); |
|
} |
|
|
#ifndef lint |
#ifndef lint |
static inline int |
static inline int |
arena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b) |
arena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b) |
Line 2133 arena_bin_run_size_calc(arena_bin_t *bin |
|
Line 2148 arena_bin_run_size_calc(arena_bin_t *bin |
|
size_t try_run_size, good_run_size; |
size_t try_run_size, good_run_size; |
unsigned good_nregs, good_mask_nelms, good_reg0_offset; |
unsigned good_nregs, good_mask_nelms, good_reg0_offset; |
unsigned try_nregs, try_mask_nelms, try_reg0_offset; |
unsigned try_nregs, try_mask_nelms, try_reg0_offset; |
float max_ovrhd = RUN_MAX_OVRHD; |
|
|
|
assert(min_run_size >= pagesize); |
assert(min_run_size >= pagesize); |
assert(min_run_size <= arena_maxclass); |
assert(min_run_size <= arena_maxclass); |
Line 2151 arena_bin_run_size_calc(arena_bin_t *bin |
|
Line 2165 arena_bin_run_size_calc(arena_bin_t *bin |
|
*/ |
*/ |
try_run_size = min_run_size; |
try_run_size = min_run_size; |
try_nregs = (unsigned)(((try_run_size - sizeof(arena_run_t)) / |
try_nregs = (unsigned)(((try_run_size - sizeof(arena_run_t)) / |
bin->reg_size) + 1); /* Counter-act the first line of the loop. */ |
bin->reg_size) + 1); /* Counter-act try_nregs-- in loop. */ |
do { |
do { |
try_nregs--; |
try_nregs--; |
try_mask_nelms = (try_nregs >> (SIZEOF_INT_2POW + 3)) + |
try_mask_nelms = (try_nregs >> (SIZEOF_INT_2POW + 3)) + |
Line 2185 arena_bin_run_size_calc(arena_bin_t *bin |
|
Line 2199 arena_bin_run_size_calc(arena_bin_t *bin |
|
} while (sizeof(arena_run_t) + (sizeof(unsigned) * |
} while (sizeof(arena_run_t) + (sizeof(unsigned) * |
(try_mask_nelms - 1)) > try_reg0_offset); |
(try_mask_nelms - 1)) > try_reg0_offset); |
} while (try_run_size <= arena_maxclass && try_run_size <= RUN_MAX_SMALL |
} while (try_run_size <= arena_maxclass && try_run_size <= RUN_MAX_SMALL |
&& max_ovrhd > RUN_MAX_OVRHD_RELAX / ((float)(bin->reg_size << 3)) |
&& RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX |
&& ((float)(try_reg0_offset)) / ((float)(try_run_size)) > |
&& (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size); |
max_ovrhd); |
|
|
|
assert(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1)) |
assert(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1)) |
<= good_reg0_offset); |
<= good_reg0_offset); |
Line 2846 huge_ralloc(void *ptr, size_t size, size |
|
Line 2859 huge_ralloc(void *ptr, size_t size, size |
|
/* size_t wrap-around */ |
/* size_t wrap-around */ |
return (NULL); |
return (NULL); |
} |
} |
|
|
|
/* |
|
* Remove the old region from the tree now. If mremap() |
|
* returns the region to the system, other thread may |
|
* map it for same huge allocation and insert it to the |
|
* tree before we acquire the mutex lock again. |
|
*/ |
|
malloc_mutex_lock(&chunks_mtx); |
|
key.chunk = __DECONST(void *, ptr); |
|
/* LINTED */ |
|
node = RB_FIND(chunk_tree_s, &huge, &key); |
|
assert(node != NULL); |
|
assert(node->chunk == ptr); |
|
assert(node->size == oldcsize); |
|
RB_REMOVE(chunk_tree_s, &huge, node); |
|
malloc_mutex_unlock(&chunks_mtx); |
|
|
newptr = mremap(ptr, oldcsize, NULL, newcsize, |
newptr = mremap(ptr, oldcsize, NULL, newcsize, |
MAP_ALIGNED(chunksize_2pow)); |
MAP_ALIGNED(chunksize_2pow)); |
if (newptr != MAP_FAILED) { |
if (newptr == MAP_FAILED) { |
|
/* We still own the old region. */ |
|
malloc_mutex_lock(&chunks_mtx); |
|
RB_INSERT(chunk_tree_s, &huge, node); |
|
malloc_mutex_unlock(&chunks_mtx); |
|
} else { |
assert(CHUNK_ADDR2BASE(newptr) == newptr); |
assert(CHUNK_ADDR2BASE(newptr) == newptr); |
|
|
/* update tree */ |
/* Insert new or resized old region. */ |
malloc_mutex_lock(&chunks_mtx); |
malloc_mutex_lock(&chunks_mtx); |
key.chunk = __DECONST(void *, ptr); |
|
/* LINTED */ |
|
node = RB_FIND(chunk_tree_s, &huge, &key); |
|
assert(node != NULL); |
|
assert(node->chunk == ptr); |
|
assert(node->size == oldcsize); |
|
node->size = newcsize; |
node->size = newcsize; |
if (ptr != newptr) { |
node->chunk = newptr; |
RB_REMOVE(chunk_tree_s, &huge, node); |
RB_INSERT(chunk_tree_s, &huge, node); |
node->chunk = newptr; |
|
RB_INSERT(chunk_tree_s, &huge, node); |
|
} |
|
#ifdef MALLOC_STATS |
#ifdef MALLOC_STATS |
huge_nralloc++; |
huge_nralloc++; |
huge_allocated += newcsize - oldcsize; |
huge_allocated += newcsize - oldcsize; |
Line 3299 malloc_init_hard(void) |
|
Line 3325 malloc_init_hard(void) |
|
ssize_t linklen; |
ssize_t linklen; |
char buf[PATH_MAX + 1]; |
char buf[PATH_MAX + 1]; |
const char *opts = ""; |
const char *opts = ""; |
|
int serrno; |
|
|
malloc_mutex_lock(&init_lock); |
malloc_mutex_lock(&init_lock); |
if (malloc_initialized) { |
if (malloc_initialized) { |
Line 3310 malloc_init_hard(void) |
|
Line 3337 malloc_init_hard(void) |
|
return (false); |
return (false); |
} |
} |
|
|
|
serrno = errno; |
/* Get number of CPUs. */ |
/* Get number of CPUs. */ |
{ |
{ |
int mib[2]; |
int mib[2]; |
Line 3360 malloc_init_hard(void) |
|
Line 3388 malloc_init_hard(void) |
|
} |
} |
break; |
break; |
case 1: |
case 1: |
if (issetugid() == 0 && (opts = |
if ((opts = getenv("MALLOC_OPTIONS")) != NULL && |
getenv("MALLOC_OPTIONS")) != NULL) { |
issetugid() == 0) { |
/* |
/* |
* Do nothing; opts is already initialized to |
* Do nothing; opts is already initialized to |
* the value of the MALLOC_OPTIONS environment |
* the value of the MALLOC_OPTIONS environment |
Line 3421 malloc_init_hard(void) |
|
Line 3449 malloc_init_hard(void) |
|
opt_chunk_2pow--; |
opt_chunk_2pow--; |
break; |
break; |
case 'K': |
case 'K': |
/* |
if (opt_chunk_2pow + 1 < |
* There must be fewer pages in a chunk than |
(int)(sizeof(size_t) << 3)) |
* can be recorded by the pos field of |
|
* arena_chunk_map_t, in order to make POS_FREE |
|
* special. |
|
*/ |
|
if (opt_chunk_2pow - pagesize_2pow |
|
< (sizeof(uint32_t) << 3) - 1) |
|
opt_chunk_2pow++; |
opt_chunk_2pow++; |
break; |
break; |
case 'n': |
case 'n': |
Line 3495 malloc_init_hard(void) |
|
Line 3517 malloc_init_hard(void) |
|
} |
} |
} |
} |
} |
} |
|
errno = serrno; |
|
|
/* Take care to call atexit() only once. */ |
/* Take care to call atexit() only once. */ |
if (opt_print_stats) { |
if (opt_print_stats) { |