Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:11.4
glibc.i686
glibc-malloc-arena-max.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File glibc-malloc-arena-max.diff of Package glibc.i686
Allow M_ARENA_MAX / MALLOC_ARENA_MAX limit even with PER_THREAD disabled With the new PER_THREAD compile-time option, the allocator also offers a way to limit the total number of arenas using MALLOC_ARENA_MAX environment variable or mallopt(M_ARENA_MAX). In principle, this feature is not tied to the PER_THREAD option. This patch makes it possible to use it even with the default compilation settings. One motivation to limit the number of arenas may be libhugetlbfs users that rely on its __morecore hook providing hugetlbfs-backed memory for the allocator - this can work only with a single arena and multi-threaded programs wishing to use this feature need a way to limit the allocator to a single arena. Another motivation is avoiding pathological behavior in extremely thread-intensive applications. 2011-02-04 Petr Baudis <pasky@suse.cz> * malloc/arena.c: Define and manage narenas even ifndef PER_THREAD. * malloc/arena.c (ptmalloc_init_minimal): Likewise. * malloc/arena.c (_int_new_arena): Likewise. * malloc/arena.c (ptmalloc_init): Implement MALLOC_ARENA_MAX even ifndef PER_THREAD. * malloc/arena.c (reused_arena): Split off get_narenas_limit(), define even ifndef PER_THREAD. * malloc/arena.c (arena_get2): Adjust for get_narenas_limit() split, call reused_arena even ifndef PER_THREAD. * malloc/hooks.c (public_gET_STATe): Set arena_max, narenas even ifndef PER_THREAD. * malloc/hooks.c (public_sET_STATe): Likewise. * malloc/malloc.c (malloc_par): Define arena_max even ifndef PER_THREAD. * malloc/malloc.c (mALLOPt): Implement M_ARENA_MAX even ifndef PER_THREAD. * malloc/malloc.c: Remove redundant M_* defines. diff --git a/malloc/arena.c b/malloc/arena.c index 4d0deef..ea80724 100644 --- a/malloc/arena.c +++ b/malloc/arena.c @@ -78,8 +78,8 @@ extern int sanity_check_heap_info_alignment[(sizeof (heap_info) static tsd_key_t arena_key; static mutex_t list_lock; -#ifdef PER_THREAD static size_t narenas; +#ifdef PER_THREAD static mstate free_list; #endif @@ -416,8 +416,8 @@ ptmalloc_init_minimal (void) #ifdef PER_THREAD # define NARENAS_FROM_NCORES(n) ((n) * (sizeof(long) == 4 ? 2 : 8)) mp_.arena_test = NARENAS_FROM_NCORES (1); - narenas = 1; #endif + narenas = 1; } @@ -574,10 +574,8 @@ ptmalloc_init (void) { if (memcmp (envline, "MMAP_MAX_", 9) == 0) mALLOPt(M_MMAP_MAX, atoi(&envline[10])); -#ifdef PER_THREAD else if (memcmp (envline, "ARENA_MAX", 9) == 0) mALLOPt(M_ARENA_MAX, atoi(&envline[10])); -#endif } break; #ifdef PER_THREAD @@ -946,9 +944,9 @@ _int_new_arena(size_t size) atomic_write_barrier (); main_arena.next = a; -#ifdef PER_THREAD ++narenas; +#ifdef PER_THREAD (void)mutex_unlock(&list_lock); #endif @@ -982,13 +980,9 @@ get_free_list (void) return result; } - -static mstate -reused_arena (void) +static int +get_narenas_limit (void) __attribute__((pure)) { - if (narenas <= mp_.arena_test) - return NULL; - static int narenas_limit; if (narenas_limit == 0) { @@ -1006,10 +1000,16 @@ reused_arena (void) narenas_limit = NARENAS_FROM_NCORES (2); } } + return narenas_limit; +} +#endif - if (narenas < narenas_limit) - return NULL; +/* Reuse and return one of the existing arenas; if all arenas are busy, + * pick one in a round-robin fashion and block until it becomes available. */ +static mstate +reused_arena (void) +{ mstate result; static mstate next_to_use; if (next_to_use == NULL) @@ -1035,7 +1035,6 @@ reused_arena (void) return result; } -#endif static mstate internal_function @@ -1048,10 +1047,15 @@ arena_get2(a_tsd, size) mstate a_tsd; size_t size; mstate a; #ifdef PER_THREAD - if ((a = get_free_list ()) == NULL - && (a = reused_arena ()) == NULL) - /* Nothing immediately available, so generate a new arena. */ - a = _int_new_arena(size); + if ((a = get_free_list ()) == NULL) + { + if (narenas > mp_.arena_test && narenas >= get_narenas_limit()) + a = reused_arena (); + else + /* Nothing immediately available, but we can still generate more + * arenas, so get a new one. */ + a = _int_new_arena(size); + } #else if(!a_tsd) a = a_tsd = &main_arena; @@ -1093,8 +1097,14 @@ arena_get2(a_tsd, size) mstate a_tsd; size_t size; goto repeat; } - /* Nothing immediately available, so generate a new arena. */ - a = _int_new_arena(size); + if (__builtin_expect(mp_.arena_max > 0, 0) && narenas >= mp_.arena_max) + /* Try again, this time blocking in case we are still unable to find + * a free arena. */ + a = reused_arena(); + else + /* Nothing immediately available, so generate a new arena. */ + a = _int_new_arena(size); + (void)mutex_unlock(&list_lock); #endif diff --git a/malloc/hooks.c b/malloc/hooks.c index 28845ee..e938492 100644 --- a/malloc/hooks.c +++ b/malloc/hooks.c @@ -579,9 +579,9 @@ public_gET_STATe(void) ms->max_fast = get_max_fast(); #ifdef PER_THREAD ms->arena_test = mp_.arena_test; +#endif ms->arena_max = mp_.arena_max; ms->narenas = narenas; -#endif (void)mutex_unlock(&main_arena.mutex); return (Void_t*)ms; } @@ -683,9 +683,9 @@ public_sET_STATe(Void_t* msptr) if (ms->version >= 4) { #ifdef PER_THREAD mp_.arena_test = ms->arena_test; +#endif mp_.arena_max = ms->arena_max; narenas = ms->narenas; -#endif } check_malloc_state(&main_arena); diff --git a/malloc/malloc.c b/malloc/malloc.c index b1d43c6..8dbadfa 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -2406,9 +2406,10 @@ struct malloc_par { INTERNAL_SIZE_T top_pad; INTERNAL_SIZE_T mmap_threshold; #ifdef PER_THREAD + /* Lower bound for arena_max. */ INTERNAL_SIZE_T arena_test; - INTERNAL_SIZE_T arena_max; #endif + INTERNAL_SIZE_T arena_max; /* Memory map support */ int n_mmaps; @@ -2446,13 +2447,6 @@ static struct malloc_state main_arena; static struct malloc_par mp_; -#ifdef PER_THREAD -/* Non public mallopt parameters. */ -#define M_ARENA_TEST -7 -#define M_ARENA_MAX -8 -#endif - - /* Maximum size of memory handled in fastbins. */ static INTERNAL_SIZE_T global_max_fast; @@ -6095,12 +6089,12 @@ int mALLOPt(param_number, value) int param_number; int value; if (value > 0) mp_.arena_test = value; break; +#endif case M_ARENA_MAX: if (value > 0) mp_.arena_max = value; break; -#endif } (void)mutex_unlock(&av->mutex); return res;
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor