xref: /aosp_15_r20/external/jemalloc_new/src/base.c (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
1*1208bc7eSAndroid Build Coastguard Worker #define JEMALLOC_BASE_C_
2*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_preamble.h"
3*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_internal_includes.h"
4*1208bc7eSAndroid Build Coastguard Worker 
5*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/assert.h"
6*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/extent_mmap.h"
7*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/mutex.h"
8*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/sz.h"
9*1208bc7eSAndroid Build Coastguard Worker 
10*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
11*1208bc7eSAndroid Build Coastguard Worker /* Data. */
12*1208bc7eSAndroid Build Coastguard Worker 
13*1208bc7eSAndroid Build Coastguard Worker static base_t *b0;
14*1208bc7eSAndroid Build Coastguard Worker 
15*1208bc7eSAndroid Build Coastguard Worker metadata_thp_mode_t opt_metadata_thp = METADATA_THP_DEFAULT;
16*1208bc7eSAndroid Build Coastguard Worker 
17*1208bc7eSAndroid Build Coastguard Worker const char *metadata_thp_mode_names[] = {
18*1208bc7eSAndroid Build Coastguard Worker 	"disabled",
19*1208bc7eSAndroid Build Coastguard Worker 	"auto",
20*1208bc7eSAndroid Build Coastguard Worker 	"always"
21*1208bc7eSAndroid Build Coastguard Worker };
22*1208bc7eSAndroid Build Coastguard Worker 
23*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
24*1208bc7eSAndroid Build Coastguard Worker 
25*1208bc7eSAndroid Build Coastguard Worker static inline bool
metadata_thp_madvise(void)26*1208bc7eSAndroid Build Coastguard Worker metadata_thp_madvise(void) {
27*1208bc7eSAndroid Build Coastguard Worker 	return (metadata_thp_enabled() &&
28*1208bc7eSAndroid Build Coastguard Worker 	    (init_system_thp_mode == thp_mode_default));
29*1208bc7eSAndroid Build Coastguard Worker }
30*1208bc7eSAndroid Build Coastguard Worker 
31*1208bc7eSAndroid Build Coastguard Worker static void *
base_map(tsdn_t * tsdn,extent_hooks_t * extent_hooks,unsigned ind,size_t size)32*1208bc7eSAndroid Build Coastguard Worker base_map(tsdn_t *tsdn, extent_hooks_t *extent_hooks, unsigned ind, size_t size) {
33*1208bc7eSAndroid Build Coastguard Worker 	void *addr;
34*1208bc7eSAndroid Build Coastguard Worker 	bool zero = true;
35*1208bc7eSAndroid Build Coastguard Worker 	bool commit = true;
36*1208bc7eSAndroid Build Coastguard Worker 
37*1208bc7eSAndroid Build Coastguard Worker 	/* Use huge page sizes and alignment regardless of opt_metadata_thp. */
38*1208bc7eSAndroid Build Coastguard Worker 	assert(size == HUGEPAGE_CEILING(size));
39*1208bc7eSAndroid Build Coastguard Worker 	size_t alignment = HUGEPAGE;
40*1208bc7eSAndroid Build Coastguard Worker 	if (extent_hooks == &extent_hooks_default) {
41*1208bc7eSAndroid Build Coastguard Worker 		addr = extent_alloc_mmap(NULL, size, alignment, &zero, &commit);
42*1208bc7eSAndroid Build Coastguard Worker 	} else {
43*1208bc7eSAndroid Build Coastguard Worker 		/* No arena context as we are creating new arenas. */
44*1208bc7eSAndroid Build Coastguard Worker 		tsd_t *tsd = tsdn_null(tsdn) ? tsd_fetch() : tsdn_tsd(tsdn);
45*1208bc7eSAndroid Build Coastguard Worker 		pre_reentrancy(tsd, NULL);
46*1208bc7eSAndroid Build Coastguard Worker 		addr = extent_hooks->alloc(extent_hooks, NULL, size, alignment,
47*1208bc7eSAndroid Build Coastguard Worker 		    &zero, &commit, ind);
48*1208bc7eSAndroid Build Coastguard Worker 		post_reentrancy(tsd);
49*1208bc7eSAndroid Build Coastguard Worker 	}
50*1208bc7eSAndroid Build Coastguard Worker 
51*1208bc7eSAndroid Build Coastguard Worker 	return addr;
52*1208bc7eSAndroid Build Coastguard Worker }
53*1208bc7eSAndroid Build Coastguard Worker 
54*1208bc7eSAndroid Build Coastguard Worker static void
base_unmap(tsdn_t * tsdn,extent_hooks_t * extent_hooks,unsigned ind,void * addr,size_t size)55*1208bc7eSAndroid Build Coastguard Worker base_unmap(tsdn_t *tsdn, extent_hooks_t *extent_hooks, unsigned ind, void *addr,
56*1208bc7eSAndroid Build Coastguard Worker     size_t size) {
57*1208bc7eSAndroid Build Coastguard Worker 	/*
58*1208bc7eSAndroid Build Coastguard Worker 	 * Cascade through dalloc, decommit, purge_forced, and purge_lazy,
59*1208bc7eSAndroid Build Coastguard Worker 	 * stopping at first success.  This cascade is performed for consistency
60*1208bc7eSAndroid Build Coastguard Worker 	 * with the cascade in extent_dalloc_wrapper() because an application's
61*1208bc7eSAndroid Build Coastguard Worker 	 * custom hooks may not support e.g. dalloc.  This function is only ever
62*1208bc7eSAndroid Build Coastguard Worker 	 * called as a side effect of arena destruction, so although it might
63*1208bc7eSAndroid Build Coastguard Worker 	 * seem pointless to do anything besides dalloc here, the application
64*1208bc7eSAndroid Build Coastguard Worker 	 * may in fact want the end state of all associated virtual memory to be
65*1208bc7eSAndroid Build Coastguard Worker 	 * in some consistent-but-allocated state.
66*1208bc7eSAndroid Build Coastguard Worker 	 */
67*1208bc7eSAndroid Build Coastguard Worker 	if (extent_hooks == &extent_hooks_default) {
68*1208bc7eSAndroid Build Coastguard Worker 		if (!extent_dalloc_mmap(addr, size)) {
69*1208bc7eSAndroid Build Coastguard Worker 			goto label_done;
70*1208bc7eSAndroid Build Coastguard Worker 		}
71*1208bc7eSAndroid Build Coastguard Worker 		if (!pages_decommit(addr, size)) {
72*1208bc7eSAndroid Build Coastguard Worker 			goto label_done;
73*1208bc7eSAndroid Build Coastguard Worker 		}
74*1208bc7eSAndroid Build Coastguard Worker 		if (!pages_purge_forced(addr, size)) {
75*1208bc7eSAndroid Build Coastguard Worker 			goto label_done;
76*1208bc7eSAndroid Build Coastguard Worker 		}
77*1208bc7eSAndroid Build Coastguard Worker 		if (!pages_purge_lazy(addr, size)) {
78*1208bc7eSAndroid Build Coastguard Worker 			goto label_done;
79*1208bc7eSAndroid Build Coastguard Worker 		}
80*1208bc7eSAndroid Build Coastguard Worker 		/* Nothing worked.  This should never happen. */
81*1208bc7eSAndroid Build Coastguard Worker 		not_reached();
82*1208bc7eSAndroid Build Coastguard Worker 	} else {
83*1208bc7eSAndroid Build Coastguard Worker 		tsd_t *tsd = tsdn_null(tsdn) ? tsd_fetch() : tsdn_tsd(tsdn);
84*1208bc7eSAndroid Build Coastguard Worker 		pre_reentrancy(tsd, NULL);
85*1208bc7eSAndroid Build Coastguard Worker 		if (extent_hooks->dalloc != NULL &&
86*1208bc7eSAndroid Build Coastguard Worker 		    !extent_hooks->dalloc(extent_hooks, addr, size, true,
87*1208bc7eSAndroid Build Coastguard Worker 		    ind)) {
88*1208bc7eSAndroid Build Coastguard Worker 			goto label_post_reentrancy;
89*1208bc7eSAndroid Build Coastguard Worker 		}
90*1208bc7eSAndroid Build Coastguard Worker 		if (extent_hooks->decommit != NULL &&
91*1208bc7eSAndroid Build Coastguard Worker 		    !extent_hooks->decommit(extent_hooks, addr, size, 0, size,
92*1208bc7eSAndroid Build Coastguard Worker 		    ind)) {
93*1208bc7eSAndroid Build Coastguard Worker 			goto label_post_reentrancy;
94*1208bc7eSAndroid Build Coastguard Worker 		}
95*1208bc7eSAndroid Build Coastguard Worker 		if (extent_hooks->purge_forced != NULL &&
96*1208bc7eSAndroid Build Coastguard Worker 		    !extent_hooks->purge_forced(extent_hooks, addr, size, 0,
97*1208bc7eSAndroid Build Coastguard Worker 		    size, ind)) {
98*1208bc7eSAndroid Build Coastguard Worker 			goto label_post_reentrancy;
99*1208bc7eSAndroid Build Coastguard Worker 		}
100*1208bc7eSAndroid Build Coastguard Worker 		if (extent_hooks->purge_lazy != NULL &&
101*1208bc7eSAndroid Build Coastguard Worker 		    !extent_hooks->purge_lazy(extent_hooks, addr, size, 0, size,
102*1208bc7eSAndroid Build Coastguard Worker 		    ind)) {
103*1208bc7eSAndroid Build Coastguard Worker 			goto label_post_reentrancy;
104*1208bc7eSAndroid Build Coastguard Worker 		}
105*1208bc7eSAndroid Build Coastguard Worker 		/* Nothing worked.  That's the application's problem. */
106*1208bc7eSAndroid Build Coastguard Worker 	label_post_reentrancy:
107*1208bc7eSAndroid Build Coastguard Worker 		post_reentrancy(tsd);
108*1208bc7eSAndroid Build Coastguard Worker 	}
109*1208bc7eSAndroid Build Coastguard Worker label_done:
110*1208bc7eSAndroid Build Coastguard Worker 	if (metadata_thp_madvise()) {
111*1208bc7eSAndroid Build Coastguard Worker 		/* Set NOHUGEPAGE after unmap to avoid kernel defrag. */
112*1208bc7eSAndroid Build Coastguard Worker 		assert(((uintptr_t)addr & HUGEPAGE_MASK) == 0 &&
113*1208bc7eSAndroid Build Coastguard Worker 		    (size & HUGEPAGE_MASK) == 0);
114*1208bc7eSAndroid Build Coastguard Worker 		pages_nohuge(addr, size);
115*1208bc7eSAndroid Build Coastguard Worker 	}
116*1208bc7eSAndroid Build Coastguard Worker }
117*1208bc7eSAndroid Build Coastguard Worker 
118*1208bc7eSAndroid Build Coastguard Worker static void
base_extent_init(size_t * extent_sn_next,extent_t * extent,void * addr,size_t size)119*1208bc7eSAndroid Build Coastguard Worker base_extent_init(size_t *extent_sn_next, extent_t *extent, void *addr,
120*1208bc7eSAndroid Build Coastguard Worker     size_t size) {
121*1208bc7eSAndroid Build Coastguard Worker 	size_t sn;
122*1208bc7eSAndroid Build Coastguard Worker 
123*1208bc7eSAndroid Build Coastguard Worker 	sn = *extent_sn_next;
124*1208bc7eSAndroid Build Coastguard Worker 	(*extent_sn_next)++;
125*1208bc7eSAndroid Build Coastguard Worker 
126*1208bc7eSAndroid Build Coastguard Worker 	extent_binit(extent, addr, size, sn);
127*1208bc7eSAndroid Build Coastguard Worker }
128*1208bc7eSAndroid Build Coastguard Worker 
129*1208bc7eSAndroid Build Coastguard Worker static size_t
base_get_num_blocks(base_t * base,bool with_new_block)130*1208bc7eSAndroid Build Coastguard Worker base_get_num_blocks(base_t *base, bool with_new_block) {
131*1208bc7eSAndroid Build Coastguard Worker 	base_block_t *b = base->blocks;
132*1208bc7eSAndroid Build Coastguard Worker 	assert(b != NULL);
133*1208bc7eSAndroid Build Coastguard Worker 
134*1208bc7eSAndroid Build Coastguard Worker 	size_t n_blocks = with_new_block ? 2 : 1;
135*1208bc7eSAndroid Build Coastguard Worker 	while (b->next != NULL) {
136*1208bc7eSAndroid Build Coastguard Worker 		n_blocks++;
137*1208bc7eSAndroid Build Coastguard Worker 		b = b->next;
138*1208bc7eSAndroid Build Coastguard Worker 	}
139*1208bc7eSAndroid Build Coastguard Worker 
140*1208bc7eSAndroid Build Coastguard Worker 	return n_blocks;
141*1208bc7eSAndroid Build Coastguard Worker }
142*1208bc7eSAndroid Build Coastguard Worker 
143*1208bc7eSAndroid Build Coastguard Worker static void
base_auto_thp_switch(tsdn_t * tsdn,base_t * base)144*1208bc7eSAndroid Build Coastguard Worker base_auto_thp_switch(tsdn_t *tsdn, base_t *base) {
145*1208bc7eSAndroid Build Coastguard Worker 	assert(opt_metadata_thp == metadata_thp_auto);
146*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_assert_owner(tsdn, &base->mtx);
147*1208bc7eSAndroid Build Coastguard Worker 	if (base->auto_thp_switched) {
148*1208bc7eSAndroid Build Coastguard Worker 		return;
149*1208bc7eSAndroid Build Coastguard Worker 	}
150*1208bc7eSAndroid Build Coastguard Worker 	/* Called when adding a new block. */
151*1208bc7eSAndroid Build Coastguard Worker 	bool should_switch;
152*1208bc7eSAndroid Build Coastguard Worker 	if (base_ind_get(base) != 0) {
153*1208bc7eSAndroid Build Coastguard Worker 		should_switch = (base_get_num_blocks(base, true) ==
154*1208bc7eSAndroid Build Coastguard Worker 		    BASE_AUTO_THP_THRESHOLD);
155*1208bc7eSAndroid Build Coastguard Worker 	} else {
156*1208bc7eSAndroid Build Coastguard Worker 		should_switch = (base_get_num_blocks(base, true) ==
157*1208bc7eSAndroid Build Coastguard Worker 		    BASE_AUTO_THP_THRESHOLD_A0);
158*1208bc7eSAndroid Build Coastguard Worker 	}
159*1208bc7eSAndroid Build Coastguard Worker 	if (!should_switch) {
160*1208bc7eSAndroid Build Coastguard Worker 		return;
161*1208bc7eSAndroid Build Coastguard Worker 	}
162*1208bc7eSAndroid Build Coastguard Worker 
163*1208bc7eSAndroid Build Coastguard Worker 	base->auto_thp_switched = true;
164*1208bc7eSAndroid Build Coastguard Worker 	assert(!config_stats || base->n_thp == 0);
165*1208bc7eSAndroid Build Coastguard Worker 	/* Make the initial blocks THP lazily. */
166*1208bc7eSAndroid Build Coastguard Worker 	base_block_t *block = base->blocks;
167*1208bc7eSAndroid Build Coastguard Worker 	while (block != NULL) {
168*1208bc7eSAndroid Build Coastguard Worker 		assert((block->size & HUGEPAGE_MASK) == 0);
169*1208bc7eSAndroid Build Coastguard Worker 		pages_huge(block, block->size);
170*1208bc7eSAndroid Build Coastguard Worker 		if (config_stats) {
171*1208bc7eSAndroid Build Coastguard Worker 			base->n_thp += HUGEPAGE_CEILING(block->size -
172*1208bc7eSAndroid Build Coastguard Worker 			    extent_bsize_get(&block->extent)) >> LG_HUGEPAGE;
173*1208bc7eSAndroid Build Coastguard Worker 		}
174*1208bc7eSAndroid Build Coastguard Worker 		block = block->next;
175*1208bc7eSAndroid Build Coastguard Worker 		assert(block == NULL || (base_ind_get(base) == 0));
176*1208bc7eSAndroid Build Coastguard Worker 	}
177*1208bc7eSAndroid Build Coastguard Worker }
178*1208bc7eSAndroid Build Coastguard Worker 
179*1208bc7eSAndroid Build Coastguard Worker static void *
base_extent_bump_alloc_helper(extent_t * extent,size_t * gap_size,size_t size,size_t alignment)180*1208bc7eSAndroid Build Coastguard Worker base_extent_bump_alloc_helper(extent_t *extent, size_t *gap_size, size_t size,
181*1208bc7eSAndroid Build Coastguard Worker     size_t alignment) {
182*1208bc7eSAndroid Build Coastguard Worker 	void *ret;
183*1208bc7eSAndroid Build Coastguard Worker 
184*1208bc7eSAndroid Build Coastguard Worker 	assert(alignment == ALIGNMENT_CEILING(alignment, QUANTUM));
185*1208bc7eSAndroid Build Coastguard Worker 	assert(size == ALIGNMENT_CEILING(size, alignment));
186*1208bc7eSAndroid Build Coastguard Worker 
187*1208bc7eSAndroid Build Coastguard Worker 	*gap_size = ALIGNMENT_CEILING((uintptr_t)extent_addr_get(extent),
188*1208bc7eSAndroid Build Coastguard Worker 	    alignment) - (uintptr_t)extent_addr_get(extent);
189*1208bc7eSAndroid Build Coastguard Worker 	ret = (void *)((uintptr_t)extent_addr_get(extent) + *gap_size);
190*1208bc7eSAndroid Build Coastguard Worker 	assert(extent_bsize_get(extent) >= *gap_size + size);
191*1208bc7eSAndroid Build Coastguard Worker 	extent_binit(extent, (void *)((uintptr_t)extent_addr_get(extent) +
192*1208bc7eSAndroid Build Coastguard Worker 	    *gap_size + size), extent_bsize_get(extent) - *gap_size - size,
193*1208bc7eSAndroid Build Coastguard Worker 	    extent_sn_get(extent));
194*1208bc7eSAndroid Build Coastguard Worker 	return ret;
195*1208bc7eSAndroid Build Coastguard Worker }
196*1208bc7eSAndroid Build Coastguard Worker 
197*1208bc7eSAndroid Build Coastguard Worker static void
base_extent_bump_alloc_post(base_t * base,extent_t * extent,size_t gap_size,void * addr,size_t size)198*1208bc7eSAndroid Build Coastguard Worker base_extent_bump_alloc_post(base_t *base, extent_t *extent, size_t gap_size,
199*1208bc7eSAndroid Build Coastguard Worker     void *addr, size_t size) {
200*1208bc7eSAndroid Build Coastguard Worker 	if (extent_bsize_get(extent) > 0) {
201*1208bc7eSAndroid Build Coastguard Worker 		/*
202*1208bc7eSAndroid Build Coastguard Worker 		 * Compute the index for the largest size class that does not
203*1208bc7eSAndroid Build Coastguard Worker 		 * exceed extent's size.
204*1208bc7eSAndroid Build Coastguard Worker 		 */
205*1208bc7eSAndroid Build Coastguard Worker 		szind_t index_floor =
206*1208bc7eSAndroid Build Coastguard Worker 		    sz_size2index(extent_bsize_get(extent) + 1) - 1;
207*1208bc7eSAndroid Build Coastguard Worker 		extent_heap_insert(&base->avail[index_floor], extent);
208*1208bc7eSAndroid Build Coastguard Worker 	}
209*1208bc7eSAndroid Build Coastguard Worker 
210*1208bc7eSAndroid Build Coastguard Worker 	if (config_stats) {
211*1208bc7eSAndroid Build Coastguard Worker 		base->allocated += size;
212*1208bc7eSAndroid Build Coastguard Worker 		/*
213*1208bc7eSAndroid Build Coastguard Worker 		 * Add one PAGE to base_resident for every page boundary that is
214*1208bc7eSAndroid Build Coastguard Worker 		 * crossed by the new allocation. Adjust n_thp similarly when
215*1208bc7eSAndroid Build Coastguard Worker 		 * metadata_thp is enabled.
216*1208bc7eSAndroid Build Coastguard Worker 		 */
217*1208bc7eSAndroid Build Coastguard Worker 		base->resident += PAGE_CEILING((uintptr_t)addr + size) -
218*1208bc7eSAndroid Build Coastguard Worker 		    PAGE_CEILING((uintptr_t)addr - gap_size);
219*1208bc7eSAndroid Build Coastguard Worker 		assert(base->allocated <= base->resident);
220*1208bc7eSAndroid Build Coastguard Worker 		assert(base->resident <= base->mapped);
221*1208bc7eSAndroid Build Coastguard Worker 		if (metadata_thp_madvise() && (opt_metadata_thp ==
222*1208bc7eSAndroid Build Coastguard Worker 		    metadata_thp_always || base->auto_thp_switched)) {
223*1208bc7eSAndroid Build Coastguard Worker 			base->n_thp += (HUGEPAGE_CEILING((uintptr_t)addr + size)
224*1208bc7eSAndroid Build Coastguard Worker 			    - HUGEPAGE_CEILING((uintptr_t)addr - gap_size)) >>
225*1208bc7eSAndroid Build Coastguard Worker 			    LG_HUGEPAGE;
226*1208bc7eSAndroid Build Coastguard Worker 			assert(base->mapped >= base->n_thp << LG_HUGEPAGE);
227*1208bc7eSAndroid Build Coastguard Worker 		}
228*1208bc7eSAndroid Build Coastguard Worker 	}
229*1208bc7eSAndroid Build Coastguard Worker }
230*1208bc7eSAndroid Build Coastguard Worker 
231*1208bc7eSAndroid Build Coastguard Worker static void *
base_extent_bump_alloc(base_t * base,extent_t * extent,size_t size,size_t alignment)232*1208bc7eSAndroid Build Coastguard Worker base_extent_bump_alloc(base_t *base, extent_t *extent, size_t size,
233*1208bc7eSAndroid Build Coastguard Worker     size_t alignment) {
234*1208bc7eSAndroid Build Coastguard Worker 	void *ret;
235*1208bc7eSAndroid Build Coastguard Worker 	size_t gap_size;
236*1208bc7eSAndroid Build Coastguard Worker 
237*1208bc7eSAndroid Build Coastguard Worker 	ret = base_extent_bump_alloc_helper(extent, &gap_size, size, alignment);
238*1208bc7eSAndroid Build Coastguard Worker 	base_extent_bump_alloc_post(base, extent, gap_size, ret, size);
239*1208bc7eSAndroid Build Coastguard Worker 	return ret;
240*1208bc7eSAndroid Build Coastguard Worker }
241*1208bc7eSAndroid Build Coastguard Worker 
242*1208bc7eSAndroid Build Coastguard Worker /*
243*1208bc7eSAndroid Build Coastguard Worker  * Allocate a block of virtual memory that is large enough to start with a
244*1208bc7eSAndroid Build Coastguard Worker  * base_block_t header, followed by an object of specified size and alignment.
245*1208bc7eSAndroid Build Coastguard Worker  * On success a pointer to the initialized base_block_t header is returned.
246*1208bc7eSAndroid Build Coastguard Worker  */
247*1208bc7eSAndroid Build Coastguard Worker static base_block_t *
base_block_alloc(tsdn_t * tsdn,base_t * base,extent_hooks_t * extent_hooks,unsigned ind,pszind_t * pind_last,size_t * extent_sn_next,size_t size,size_t alignment)248*1208bc7eSAndroid Build Coastguard Worker base_block_alloc(tsdn_t *tsdn, base_t *base, extent_hooks_t *extent_hooks,
249*1208bc7eSAndroid Build Coastguard Worker     unsigned ind, pszind_t *pind_last, size_t *extent_sn_next, size_t size,
250*1208bc7eSAndroid Build Coastguard Worker     size_t alignment) {
251*1208bc7eSAndroid Build Coastguard Worker 	alignment = ALIGNMENT_CEILING(alignment, QUANTUM);
252*1208bc7eSAndroid Build Coastguard Worker 	size_t usize = ALIGNMENT_CEILING(size, alignment);
253*1208bc7eSAndroid Build Coastguard Worker 	size_t header_size = sizeof(base_block_t);
254*1208bc7eSAndroid Build Coastguard Worker 	size_t gap_size = ALIGNMENT_CEILING(header_size, alignment) -
255*1208bc7eSAndroid Build Coastguard Worker 	    header_size;
256*1208bc7eSAndroid Build Coastguard Worker 	/*
257*1208bc7eSAndroid Build Coastguard Worker 	 * Create increasingly larger blocks in order to limit the total number
258*1208bc7eSAndroid Build Coastguard Worker 	 * of disjoint virtual memory ranges.  Choose the next size in the page
259*1208bc7eSAndroid Build Coastguard Worker 	 * size class series (skipping size classes that are not a multiple of
260*1208bc7eSAndroid Build Coastguard Worker 	 * HUGEPAGE), or a size large enough to satisfy the requested size and
261*1208bc7eSAndroid Build Coastguard Worker 	 * alignment, whichever is larger.
262*1208bc7eSAndroid Build Coastguard Worker 	 */
263*1208bc7eSAndroid Build Coastguard Worker 	size_t min_block_size = HUGEPAGE_CEILING(sz_psz2u(header_size + gap_size
264*1208bc7eSAndroid Build Coastguard Worker 	    + usize));
265*1208bc7eSAndroid Build Coastguard Worker 	pszind_t pind_next = (*pind_last + 1 < NPSIZES) ? *pind_last + 1 :
266*1208bc7eSAndroid Build Coastguard Worker 	    *pind_last;
267*1208bc7eSAndroid Build Coastguard Worker 	size_t next_block_size = HUGEPAGE_CEILING(sz_pind2sz(pind_next));
268*1208bc7eSAndroid Build Coastguard Worker 	size_t block_size = (min_block_size > next_block_size) ? min_block_size
269*1208bc7eSAndroid Build Coastguard Worker 	    : next_block_size;
270*1208bc7eSAndroid Build Coastguard Worker 	base_block_t *block = (base_block_t *)base_map(tsdn, extent_hooks, ind,
271*1208bc7eSAndroid Build Coastguard Worker 	    block_size);
272*1208bc7eSAndroid Build Coastguard Worker 	if (block == NULL) {
273*1208bc7eSAndroid Build Coastguard Worker 		return NULL;
274*1208bc7eSAndroid Build Coastguard Worker 	}
275*1208bc7eSAndroid Build Coastguard Worker 
276*1208bc7eSAndroid Build Coastguard Worker 	if (metadata_thp_madvise()) {
277*1208bc7eSAndroid Build Coastguard Worker 		void *addr = (void *)block;
278*1208bc7eSAndroid Build Coastguard Worker 		assert(((uintptr_t)addr & HUGEPAGE_MASK) == 0 &&
279*1208bc7eSAndroid Build Coastguard Worker 		    (block_size & HUGEPAGE_MASK) == 0);
280*1208bc7eSAndroid Build Coastguard Worker 		if (opt_metadata_thp == metadata_thp_always) {
281*1208bc7eSAndroid Build Coastguard Worker 			pages_huge(addr, block_size);
282*1208bc7eSAndroid Build Coastguard Worker 		} else if (opt_metadata_thp == metadata_thp_auto &&
283*1208bc7eSAndroid Build Coastguard Worker 		    base != NULL) {
284*1208bc7eSAndroid Build Coastguard Worker 			/* base != NULL indicates this is not a new base. */
285*1208bc7eSAndroid Build Coastguard Worker 			malloc_mutex_lock(tsdn, &base->mtx);
286*1208bc7eSAndroid Build Coastguard Worker 			base_auto_thp_switch(tsdn, base);
287*1208bc7eSAndroid Build Coastguard Worker 			if (base->auto_thp_switched) {
288*1208bc7eSAndroid Build Coastguard Worker 				pages_huge(addr, block_size);
289*1208bc7eSAndroid Build Coastguard Worker 			}
290*1208bc7eSAndroid Build Coastguard Worker 			malloc_mutex_unlock(tsdn, &base->mtx);
291*1208bc7eSAndroid Build Coastguard Worker 		}
292*1208bc7eSAndroid Build Coastguard Worker 	}
293*1208bc7eSAndroid Build Coastguard Worker 
294*1208bc7eSAndroid Build Coastguard Worker 	*pind_last = sz_psz2ind(block_size);
295*1208bc7eSAndroid Build Coastguard Worker 	block->size = block_size;
296*1208bc7eSAndroid Build Coastguard Worker 	block->next = NULL;
297*1208bc7eSAndroid Build Coastguard Worker 	assert(block_size >= header_size);
298*1208bc7eSAndroid Build Coastguard Worker 	base_extent_init(extent_sn_next, &block->extent,
299*1208bc7eSAndroid Build Coastguard Worker 	    (void *)((uintptr_t)block + header_size), block_size - header_size);
300*1208bc7eSAndroid Build Coastguard Worker 	return block;
301*1208bc7eSAndroid Build Coastguard Worker }
302*1208bc7eSAndroid Build Coastguard Worker 
303*1208bc7eSAndroid Build Coastguard Worker /*
304*1208bc7eSAndroid Build Coastguard Worker  * Allocate an extent that is at least as large as specified size, with
305*1208bc7eSAndroid Build Coastguard Worker  * specified alignment.
306*1208bc7eSAndroid Build Coastguard Worker  */
307*1208bc7eSAndroid Build Coastguard Worker static extent_t *
base_extent_alloc(tsdn_t * tsdn,base_t * base,size_t size,size_t alignment)308*1208bc7eSAndroid Build Coastguard Worker base_extent_alloc(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment) {
309*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_assert_owner(tsdn, &base->mtx);
310*1208bc7eSAndroid Build Coastguard Worker 
311*1208bc7eSAndroid Build Coastguard Worker 	extent_hooks_t *extent_hooks = base_extent_hooks_get(base);
312*1208bc7eSAndroid Build Coastguard Worker 	/*
313*1208bc7eSAndroid Build Coastguard Worker 	 * Drop mutex during base_block_alloc(), because an extent hook will be
314*1208bc7eSAndroid Build Coastguard Worker 	 * called.
315*1208bc7eSAndroid Build Coastguard Worker 	 */
316*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_unlock(tsdn, &base->mtx);
317*1208bc7eSAndroid Build Coastguard Worker 	base_block_t *block = base_block_alloc(tsdn, base, extent_hooks,
318*1208bc7eSAndroid Build Coastguard Worker 	    base_ind_get(base), &base->pind_last, &base->extent_sn_next, size,
319*1208bc7eSAndroid Build Coastguard Worker 	    alignment);
320*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_lock(tsdn, &base->mtx);
321*1208bc7eSAndroid Build Coastguard Worker 	if (block == NULL) {
322*1208bc7eSAndroid Build Coastguard Worker 		return NULL;
323*1208bc7eSAndroid Build Coastguard Worker 	}
324*1208bc7eSAndroid Build Coastguard Worker 	block->next = base->blocks;
325*1208bc7eSAndroid Build Coastguard Worker 	base->blocks = block;
326*1208bc7eSAndroid Build Coastguard Worker 	if (config_stats) {
327*1208bc7eSAndroid Build Coastguard Worker 		base->allocated += sizeof(base_block_t);
328*1208bc7eSAndroid Build Coastguard Worker 		base->resident += PAGE_CEILING(sizeof(base_block_t));
329*1208bc7eSAndroid Build Coastguard Worker 		base->mapped += block->size;
330*1208bc7eSAndroid Build Coastguard Worker 		if (metadata_thp_madvise() &&
331*1208bc7eSAndroid Build Coastguard Worker 		    !(opt_metadata_thp == metadata_thp_auto
332*1208bc7eSAndroid Build Coastguard Worker 		      && !base->auto_thp_switched)) {
333*1208bc7eSAndroid Build Coastguard Worker 			assert(base->n_thp > 0);
334*1208bc7eSAndroid Build Coastguard Worker 			base->n_thp += HUGEPAGE_CEILING(sizeof(base_block_t)) >>
335*1208bc7eSAndroid Build Coastguard Worker 			    LG_HUGEPAGE;
336*1208bc7eSAndroid Build Coastguard Worker 		}
337*1208bc7eSAndroid Build Coastguard Worker 		assert(base->allocated <= base->resident);
338*1208bc7eSAndroid Build Coastguard Worker 		assert(base->resident <= base->mapped);
339*1208bc7eSAndroid Build Coastguard Worker 		assert(base->n_thp << LG_HUGEPAGE <= base->mapped);
340*1208bc7eSAndroid Build Coastguard Worker 	}
341*1208bc7eSAndroid Build Coastguard Worker 	return &block->extent;
342*1208bc7eSAndroid Build Coastguard Worker }
343*1208bc7eSAndroid Build Coastguard Worker 
344*1208bc7eSAndroid Build Coastguard Worker base_t *
b0get(void)345*1208bc7eSAndroid Build Coastguard Worker b0get(void) {
346*1208bc7eSAndroid Build Coastguard Worker 	return b0;
347*1208bc7eSAndroid Build Coastguard Worker }
348*1208bc7eSAndroid Build Coastguard Worker 
349*1208bc7eSAndroid Build Coastguard Worker base_t *
base_new(tsdn_t * tsdn,unsigned ind,extent_hooks_t * extent_hooks)350*1208bc7eSAndroid Build Coastguard Worker base_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) {
351*1208bc7eSAndroid Build Coastguard Worker 	pszind_t pind_last = 0;
352*1208bc7eSAndroid Build Coastguard Worker 	size_t extent_sn_next = 0;
353*1208bc7eSAndroid Build Coastguard Worker 	base_block_t *block = base_block_alloc(tsdn, NULL, extent_hooks, ind,
354*1208bc7eSAndroid Build Coastguard Worker 	    &pind_last, &extent_sn_next, sizeof(base_t), QUANTUM);
355*1208bc7eSAndroid Build Coastguard Worker 	if (block == NULL) {
356*1208bc7eSAndroid Build Coastguard Worker 		return NULL;
357*1208bc7eSAndroid Build Coastguard Worker 	}
358*1208bc7eSAndroid Build Coastguard Worker 
359*1208bc7eSAndroid Build Coastguard Worker 	size_t gap_size;
360*1208bc7eSAndroid Build Coastguard Worker 	size_t base_alignment = CACHELINE;
361*1208bc7eSAndroid Build Coastguard Worker 	size_t base_size = ALIGNMENT_CEILING(sizeof(base_t), base_alignment);
362*1208bc7eSAndroid Build Coastguard Worker 	base_t *base = (base_t *)base_extent_bump_alloc_helper(&block->extent,
363*1208bc7eSAndroid Build Coastguard Worker 	    &gap_size, base_size, base_alignment);
364*1208bc7eSAndroid Build Coastguard Worker 	base->ind = ind;
365*1208bc7eSAndroid Build Coastguard Worker 	atomic_store_p(&base->extent_hooks, extent_hooks, ATOMIC_RELAXED);
366*1208bc7eSAndroid Build Coastguard Worker 	if (malloc_mutex_init(&base->mtx, "base", WITNESS_RANK_BASE,
367*1208bc7eSAndroid Build Coastguard Worker 	    malloc_mutex_rank_exclusive)) {
368*1208bc7eSAndroid Build Coastguard Worker 		base_unmap(tsdn, extent_hooks, ind, block, block->size);
369*1208bc7eSAndroid Build Coastguard Worker 		return NULL;
370*1208bc7eSAndroid Build Coastguard Worker 	}
371*1208bc7eSAndroid Build Coastguard Worker 	base->pind_last = pind_last;
372*1208bc7eSAndroid Build Coastguard Worker 	base->extent_sn_next = extent_sn_next;
373*1208bc7eSAndroid Build Coastguard Worker 	base->blocks = block;
374*1208bc7eSAndroid Build Coastguard Worker 	base->auto_thp_switched = false;
375*1208bc7eSAndroid Build Coastguard Worker 	for (szind_t i = 0; i < NSIZES; i++) {
376*1208bc7eSAndroid Build Coastguard Worker 		extent_heap_new(&base->avail[i]);
377*1208bc7eSAndroid Build Coastguard Worker 	}
378*1208bc7eSAndroid Build Coastguard Worker 	if (config_stats) {
379*1208bc7eSAndroid Build Coastguard Worker 		base->allocated = sizeof(base_block_t);
380*1208bc7eSAndroid Build Coastguard Worker 		base->resident = PAGE_CEILING(sizeof(base_block_t));
381*1208bc7eSAndroid Build Coastguard Worker 		base->mapped = block->size;
382*1208bc7eSAndroid Build Coastguard Worker 		base->n_thp = (opt_metadata_thp == metadata_thp_always) &&
383*1208bc7eSAndroid Build Coastguard Worker 		    metadata_thp_madvise() ? HUGEPAGE_CEILING(sizeof(base_block_t))
384*1208bc7eSAndroid Build Coastguard Worker 		    >> LG_HUGEPAGE : 0;
385*1208bc7eSAndroid Build Coastguard Worker 		assert(base->allocated <= base->resident);
386*1208bc7eSAndroid Build Coastguard Worker 		assert(base->resident <= base->mapped);
387*1208bc7eSAndroid Build Coastguard Worker 		assert(base->n_thp << LG_HUGEPAGE <= base->mapped);
388*1208bc7eSAndroid Build Coastguard Worker 	}
389*1208bc7eSAndroid Build Coastguard Worker 	base_extent_bump_alloc_post(base, &block->extent, gap_size, base,
390*1208bc7eSAndroid Build Coastguard Worker 	    base_size);
391*1208bc7eSAndroid Build Coastguard Worker 
392*1208bc7eSAndroid Build Coastguard Worker 	return base;
393*1208bc7eSAndroid Build Coastguard Worker }
394*1208bc7eSAndroid Build Coastguard Worker 
395*1208bc7eSAndroid Build Coastguard Worker void
base_delete(tsdn_t * tsdn,base_t * base)396*1208bc7eSAndroid Build Coastguard Worker base_delete(tsdn_t *tsdn, base_t *base) {
397*1208bc7eSAndroid Build Coastguard Worker 	extent_hooks_t *extent_hooks = base_extent_hooks_get(base);
398*1208bc7eSAndroid Build Coastguard Worker 	base_block_t *next = base->blocks;
399*1208bc7eSAndroid Build Coastguard Worker 	do {
400*1208bc7eSAndroid Build Coastguard Worker 		base_block_t *block = next;
401*1208bc7eSAndroid Build Coastguard Worker 		next = block->next;
402*1208bc7eSAndroid Build Coastguard Worker 		base_unmap(tsdn, extent_hooks, base_ind_get(base), block,
403*1208bc7eSAndroid Build Coastguard Worker 		    block->size);
404*1208bc7eSAndroid Build Coastguard Worker 	} while (next != NULL);
405*1208bc7eSAndroid Build Coastguard Worker }
406*1208bc7eSAndroid Build Coastguard Worker 
407*1208bc7eSAndroid Build Coastguard Worker extent_hooks_t *
base_extent_hooks_get(base_t * base)408*1208bc7eSAndroid Build Coastguard Worker base_extent_hooks_get(base_t *base) {
409*1208bc7eSAndroid Build Coastguard Worker 	return (extent_hooks_t *)atomic_load_p(&base->extent_hooks,
410*1208bc7eSAndroid Build Coastguard Worker 	    ATOMIC_ACQUIRE);
411*1208bc7eSAndroid Build Coastguard Worker }
412*1208bc7eSAndroid Build Coastguard Worker 
413*1208bc7eSAndroid Build Coastguard Worker extent_hooks_t *
base_extent_hooks_set(base_t * base,extent_hooks_t * extent_hooks)414*1208bc7eSAndroid Build Coastguard Worker base_extent_hooks_set(base_t *base, extent_hooks_t *extent_hooks) {
415*1208bc7eSAndroid Build Coastguard Worker 	extent_hooks_t *old_extent_hooks = base_extent_hooks_get(base);
416*1208bc7eSAndroid Build Coastguard Worker 	atomic_store_p(&base->extent_hooks, extent_hooks, ATOMIC_RELEASE);
417*1208bc7eSAndroid Build Coastguard Worker 	return old_extent_hooks;
418*1208bc7eSAndroid Build Coastguard Worker }
419*1208bc7eSAndroid Build Coastguard Worker 
420*1208bc7eSAndroid Build Coastguard Worker static void *
base_alloc_impl(tsdn_t * tsdn,base_t * base,size_t size,size_t alignment,size_t * esn)421*1208bc7eSAndroid Build Coastguard Worker base_alloc_impl(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment,
422*1208bc7eSAndroid Build Coastguard Worker     size_t *esn) {
423*1208bc7eSAndroid Build Coastguard Worker 	alignment = QUANTUM_CEILING(alignment);
424*1208bc7eSAndroid Build Coastguard Worker 	size_t usize = ALIGNMENT_CEILING(size, alignment);
425*1208bc7eSAndroid Build Coastguard Worker 	size_t asize = usize + alignment - QUANTUM;
426*1208bc7eSAndroid Build Coastguard Worker 
427*1208bc7eSAndroid Build Coastguard Worker 	extent_t *extent = NULL;
428*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_lock(tsdn, &base->mtx);
429*1208bc7eSAndroid Build Coastguard Worker 	for (szind_t i = sz_size2index(asize); i < NSIZES; i++) {
430*1208bc7eSAndroid Build Coastguard Worker 		extent = extent_heap_remove_first(&base->avail[i]);
431*1208bc7eSAndroid Build Coastguard Worker 		if (extent != NULL) {
432*1208bc7eSAndroid Build Coastguard Worker 			/* Use existing space. */
433*1208bc7eSAndroid Build Coastguard Worker 			break;
434*1208bc7eSAndroid Build Coastguard Worker 		}
435*1208bc7eSAndroid Build Coastguard Worker 	}
436*1208bc7eSAndroid Build Coastguard Worker 	if (extent == NULL) {
437*1208bc7eSAndroid Build Coastguard Worker 		/* Try to allocate more space. */
438*1208bc7eSAndroid Build Coastguard Worker 		extent = base_extent_alloc(tsdn, base, usize, alignment);
439*1208bc7eSAndroid Build Coastguard Worker 	}
440*1208bc7eSAndroid Build Coastguard Worker 	void *ret;
441*1208bc7eSAndroid Build Coastguard Worker 	if (extent == NULL) {
442*1208bc7eSAndroid Build Coastguard Worker 		ret = NULL;
443*1208bc7eSAndroid Build Coastguard Worker 		goto label_return;
444*1208bc7eSAndroid Build Coastguard Worker 	}
445*1208bc7eSAndroid Build Coastguard Worker 
446*1208bc7eSAndroid Build Coastguard Worker 	ret = base_extent_bump_alloc(base, extent, usize, alignment);
447*1208bc7eSAndroid Build Coastguard Worker 	if (esn != NULL) {
448*1208bc7eSAndroid Build Coastguard Worker 		*esn = extent_sn_get(extent);
449*1208bc7eSAndroid Build Coastguard Worker 	}
450*1208bc7eSAndroid Build Coastguard Worker label_return:
451*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_unlock(tsdn, &base->mtx);
452*1208bc7eSAndroid Build Coastguard Worker 	return ret;
453*1208bc7eSAndroid Build Coastguard Worker }
454*1208bc7eSAndroid Build Coastguard Worker 
455*1208bc7eSAndroid Build Coastguard Worker /*
456*1208bc7eSAndroid Build Coastguard Worker  * base_alloc() returns zeroed memory, which is always demand-zeroed for the
457*1208bc7eSAndroid Build Coastguard Worker  * auto arenas, in order to make multi-page sparse data structures such as radix
458*1208bc7eSAndroid Build Coastguard Worker  * tree nodes efficient with respect to physical memory usage.  Upon success a
459*1208bc7eSAndroid Build Coastguard Worker  * pointer to at least size bytes with specified alignment is returned.  Note
460*1208bc7eSAndroid Build Coastguard Worker  * that size is rounded up to the nearest multiple of alignment to avoid false
461*1208bc7eSAndroid Build Coastguard Worker  * sharing.
462*1208bc7eSAndroid Build Coastguard Worker  */
463*1208bc7eSAndroid Build Coastguard Worker void *
base_alloc(tsdn_t * tsdn,base_t * base,size_t size,size_t alignment)464*1208bc7eSAndroid Build Coastguard Worker base_alloc(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment) {
465*1208bc7eSAndroid Build Coastguard Worker 	return base_alloc_impl(tsdn, base, size, alignment, NULL);
466*1208bc7eSAndroid Build Coastguard Worker }
467*1208bc7eSAndroid Build Coastguard Worker 
468*1208bc7eSAndroid Build Coastguard Worker extent_t *
base_alloc_extent(tsdn_t * tsdn,base_t * base)469*1208bc7eSAndroid Build Coastguard Worker base_alloc_extent(tsdn_t *tsdn, base_t *base) {
470*1208bc7eSAndroid Build Coastguard Worker 	size_t esn;
471*1208bc7eSAndroid Build Coastguard Worker 	extent_t *extent = base_alloc_impl(tsdn, base, sizeof(extent_t),
472*1208bc7eSAndroid Build Coastguard Worker 	    CACHELINE, &esn);
473*1208bc7eSAndroid Build Coastguard Worker 	if (extent == NULL) {
474*1208bc7eSAndroid Build Coastguard Worker 		return NULL;
475*1208bc7eSAndroid Build Coastguard Worker 	}
476*1208bc7eSAndroid Build Coastguard Worker 	extent_esn_set(extent, esn);
477*1208bc7eSAndroid Build Coastguard Worker 	return extent;
478*1208bc7eSAndroid Build Coastguard Worker }
479*1208bc7eSAndroid Build Coastguard Worker 
480*1208bc7eSAndroid Build Coastguard Worker void
base_stats_get(tsdn_t * tsdn,base_t * base,size_t * allocated,size_t * resident,size_t * mapped,size_t * n_thp)481*1208bc7eSAndroid Build Coastguard Worker base_stats_get(tsdn_t *tsdn, base_t *base, size_t *allocated, size_t *resident,
482*1208bc7eSAndroid Build Coastguard Worker     size_t *mapped, size_t *n_thp) {
483*1208bc7eSAndroid Build Coastguard Worker 	cassert(config_stats);
484*1208bc7eSAndroid Build Coastguard Worker 
485*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_lock(tsdn, &base->mtx);
486*1208bc7eSAndroid Build Coastguard Worker 	assert(base->allocated <= base->resident);
487*1208bc7eSAndroid Build Coastguard Worker 	assert(base->resident <= base->mapped);
488*1208bc7eSAndroid Build Coastguard Worker 	*allocated = base->allocated;
489*1208bc7eSAndroid Build Coastguard Worker 	*resident = base->resident;
490*1208bc7eSAndroid Build Coastguard Worker 	*mapped = base->mapped;
491*1208bc7eSAndroid Build Coastguard Worker 	*n_thp = base->n_thp;
492*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_unlock(tsdn, &base->mtx);
493*1208bc7eSAndroid Build Coastguard Worker }
494*1208bc7eSAndroid Build Coastguard Worker 
495*1208bc7eSAndroid Build Coastguard Worker void
base_prefork(tsdn_t * tsdn,base_t * base)496*1208bc7eSAndroid Build Coastguard Worker base_prefork(tsdn_t *tsdn, base_t *base) {
497*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_prefork(tsdn, &base->mtx);
498*1208bc7eSAndroid Build Coastguard Worker }
499*1208bc7eSAndroid Build Coastguard Worker 
500*1208bc7eSAndroid Build Coastguard Worker void
base_postfork_parent(tsdn_t * tsdn,base_t * base)501*1208bc7eSAndroid Build Coastguard Worker base_postfork_parent(tsdn_t *tsdn, base_t *base) {
502*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_postfork_parent(tsdn, &base->mtx);
503*1208bc7eSAndroid Build Coastguard Worker }
504*1208bc7eSAndroid Build Coastguard Worker 
505*1208bc7eSAndroid Build Coastguard Worker void
base_postfork_child(tsdn_t * tsdn,base_t * base)506*1208bc7eSAndroid Build Coastguard Worker base_postfork_child(tsdn_t *tsdn, base_t *base) {
507*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_postfork_child(tsdn, &base->mtx);
508*1208bc7eSAndroid Build Coastguard Worker }
509*1208bc7eSAndroid Build Coastguard Worker 
510*1208bc7eSAndroid Build Coastguard Worker bool
base_boot(tsdn_t * tsdn)511*1208bc7eSAndroid Build Coastguard Worker base_boot(tsdn_t *tsdn) {
512*1208bc7eSAndroid Build Coastguard Worker 	b0 = base_new(tsdn, 0, (extent_hooks_t *)&extent_hooks_default);
513*1208bc7eSAndroid Build Coastguard Worker 	return (b0 == NULL);
514*1208bc7eSAndroid Build Coastguard Worker }
515