static bool ctl_init(void) { bool ret; malloc_mutex_lock(&ctl_mtx); if (ctl_initialized == false) { #ifdef JEMALLOC_STATS unsigned i; #endif /* * Allocate space for one extra arena stats element, which * contains summed stats across all arenas. */ ctl_stats.arenas = (ctl_arena_stats_t *)base_alloc( (narenas + 1) * sizeof(ctl_arena_stats_t)); if (ctl_stats.arenas == NULL) { ret = true; goto RETURN; } memset(ctl_stats.arenas, 0, (narenas + 1) * sizeof(ctl_arena_stats_t)); /* * Initialize all stats structures, regardless of whether they * ever get used. Lazy initialization would allow errors to * cause inconsistent state to be viewable by the application. */ #ifdef JEMALLOC_STATS for (i = 0; i <= narenas; i++) { if (ctl_arena_init(&ctl_stats.arenas[i])) { ret = true; goto RETURN; } } #endif ctl_stats.arenas[narenas].initialized = true; ctl_epoch = 0; ctl_refresh(); ctl_initialized = true; } ret = false; RETURN: malloc_mutex_unlock(&ctl_mtx); return (ret); }
static bool ctl_init(void) { bool ret; malloc_mutex_lock(&ctl_mtx); if (ctl_initialized == false) { /* * Allocate space for one extra arena stats element, which * contains summed stats across all arenas. */ assert(narenas_auto == narenas_total_get()); ctl_stats.narenas = narenas_auto; ctl_stats.arenas = (ctl_arena_stats_t *)base_alloc( (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t)); if (ctl_stats.arenas == NULL) { ret = true; goto label_return; } memset(ctl_stats.arenas, 0, (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t)); /* * Initialize all stats structures, regardless of whether they * ever get used. Lazy initialization would allow errors to * cause inconsistent state to be viewable by the application. */ if (config_stats) { unsigned i; for (i = 0; i <= ctl_stats.narenas; i++) { if (ctl_arena_init(&ctl_stats.arenas[i])) { ret = true; goto label_return; } } } ctl_stats.arenas[ctl_stats.narenas].initialized = true; ctl_epoch = 0; ctl_refresh(); ctl_initialized = true; } ret = false; label_return: malloc_mutex_unlock(&ctl_mtx); return (ret); }
static bool ctl_grow(void) { ctl_arena_stats_t *astats; arena_t **tarenas; /* Allocate extended arena stats and arenas arrays. */ astats = (ctl_arena_stats_t *)imalloc((ctl_stats.narenas + 2) * sizeof(ctl_arena_stats_t)); if (astats == NULL) return (true); tarenas = (arena_t **)imalloc((ctl_stats.narenas + 1) * sizeof(arena_t *)); if (tarenas == NULL) { idalloc(astats); return (true); } /* Initialize the new astats element. */ memcpy(astats, ctl_stats.arenas, (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t)); memset(&astats[ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t)); if (ctl_arena_init(&astats[ctl_stats.narenas + 1])) { idalloc(tarenas); idalloc(astats); return (true); } /* Swap merged stats to their new location. */ { ctl_arena_stats_t tstats; memcpy(&tstats, &astats[ctl_stats.narenas], sizeof(ctl_arena_stats_t)); memcpy(&astats[ctl_stats.narenas], &astats[ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t)); memcpy(&astats[ctl_stats.narenas + 1], &tstats, sizeof(ctl_arena_stats_t)); } /* Initialize the new arenas element. */ tarenas[ctl_stats.narenas] = NULL; { arena_t **arenas_old = arenas; /* * Swap extended arenas array into place. Although ctl_mtx * protects this function from other threads extending the * array, it does not protect from other threads mutating it * (i.e. initializing arenas and setting array elements to * point to them). Therefore, array copying must happen under * the protection of arenas_lock. */ malloc_mutex_lock(&arenas_lock); arenas = tarenas; memcpy(arenas, arenas_old, ctl_stats.narenas * sizeof(arena_t *)); narenas_total++; arenas_extend(narenas_total - 1); malloc_mutex_unlock(&arenas_lock); /* * Deallocate arenas_old only if it came from imalloc() (not * base_alloc()). */ if (ctl_stats.narenas != narenas_auto) idalloc(arenas_old); } ctl_stats.arenas = astats; ctl_stats.narenas++; return (false); }