static mstate internal_function arena_get2 (mstate a_tsd, size_t size, mstate avoid_arena) { mstate a; static size_t narenas_limit; a = get_free_list (); if (a == NULL) { /* Nothing immediately available, so generate a new arena. */ if (narenas_limit == 0) { if (mp_.arena_max != 0) narenas_limit = mp_.arena_max; else if (narenas > mp_.arena_test) { int n = 2; /*__get_nprocs (); */ if (n >= 1) narenas_limit = NARENAS_FROM_NCORES (n); else /* We have no information about the system. Assume two cores. */ narenas_limit = NARENAS_FROM_NCORES (2); } } repeat:; size_t n = narenas; /* NB: the following depends on the fact that (size_t)0 - 1 is a very large number and that the underflow is OK. If arena_max is set the value of arena_test is irrelevant. If arena_test is set but narenas is not yet larger or equal to arena_test narenas_limit is 0. There is no possibility for narenas to be too big for the test to always fail since there is not enough address space to create that many arenas. */ if (__glibc_unlikely (n <= narenas_limit - 1)) { if (catomic_compare_and_exchange_bool_acq (&narenas, n + 1, n)) goto repeat; a = _int_new_arena (size); if (__glibc_unlikely (a == NULL)) catomic_decrement (&narenas); } else a = reused_arena (avoid_arena); } return a; }
/* Set up basic state so that _int_malloc et al can work. */ static void ptmalloc_init_minimal (void) { #if DEFAULT_TOP_PAD != 0 mp_.top_pad = DEFAULT_TOP_PAD; #endif mp_.n_mmaps_max = DEFAULT_MMAP_MAX; mp_.mmap_threshold = DEFAULT_MMAP_THRESHOLD; mp_.trim_threshold = DEFAULT_TRIM_THRESHOLD; mp_.pagesize = malloc_getpagesize; #ifdef PER_THREAD # define NARENAS_FROM_NCORES(n) ((n) * (sizeof(long) == 4 ? 2 : 8)) mp_.arena_test = NARENAS_FROM_NCORES (1); narenas = 1; #endif }
static mstate internal_function arena_get2(mstate a_tsd, size_t size, mstate avoid_arena) { mstate a; #ifdef PER_THREAD static size_t narenas_limit; a = get_free_list (); if (a == NULL) { /* Nothing immediately available, so generate a new arena. */ if (narenas_limit == 0) { if (mp_.arena_max != 0) narenas_limit = mp_.arena_max; else if (narenas > mp_.arena_test) { int n = __get_nprocs (); if (n >= 1) narenas_limit = NARENAS_FROM_NCORES (n); else /* We have no information about the system. Assume two cores. */ narenas_limit = NARENAS_FROM_NCORES (2); } } repeat:; size_t n = narenas; /* NB: the following depends on the fact that (size_t)0 - 1 is a very large number and that the underflow is OK. If arena_max is set the value of arena_test is irrelevant. If arena_test is set but narenas is not yet larger or equal to arena_test narenas_limit is 0. There is no possibility for narenas to be too big for the test to always fail since there is not enough address space to create that many arenas. */ if (__builtin_expect (n <= narenas_limit - 1, 0)) { if (catomic_compare_and_exchange_bool_acq (&narenas, n + 1, n)) goto repeat; a = _int_new_arena (size); if (__builtin_expect (a == NULL, 0)) catomic_decrement (&narenas); } else a = reused_arena (avoid_arena); } #else if(!a_tsd) a = a_tsd = &main_arena; else { a = a_tsd->next; if(!a) { /* This can only happen while initializing the new arena. */ (void)mutex_lock(&main_arena.mutex); THREAD_STAT(++(main_arena.stat_lock_wait)); return &main_arena; } } /* Check the global, circularly linked list for available arenas. */ bool retried = false; repeat: do { if(!mutex_trylock(&a->mutex)) { if (retried) (void)mutex_unlock(&list_lock); THREAD_STAT(++(a->stat_lock_loop)); tsd_setspecific(arena_key, (void *)a); return a; } a = a->next; } while(a != a_tsd); /* If not even the list_lock can be obtained, try again. This can happen during `atfork', or for example on systems where thread creation makes it temporarily impossible to obtain _any_ locks. */ if(!retried && mutex_trylock(&list_lock)) { /* We will block to not run in a busy loop. */ (void)mutex_lock(&list_lock); /* Since we blocked there might be an arena available now. */ retried = true; a = a_tsd; goto repeat; } /* Nothing immediately available, so generate a new arena. */ a = _int_new_arena(size); (void)mutex_unlock(&list_lock); #endif return a; }