• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #define	JEMALLOC_C_
2 #include "jemalloc/internal/jemalloc_internal.h"
3 
4 /******************************************************************************/
5 /* Data. */
6 
7 /* Runtime configuration options. */
8 const char	*je_malloc_conf
9 #ifndef _WIN32
10     JEMALLOC_ATTR(weak)
11 #endif
12     ;
13 bool	opt_abort =
14 #ifdef JEMALLOC_DEBUG
15     true
16 #else
17     false
18 #endif
19     ;
20 const char	*opt_junk =
21 #if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))
22     "true"
23 #else
24     "false"
25 #endif
26     ;
27 bool	opt_junk_alloc =
28 #if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))
29     true
30 #else
31     false
32 #endif
33     ;
34 bool	opt_junk_free =
35 #if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))
36     true
37 #else
38     false
39 #endif
40     ;
41 
42 size_t	opt_quarantine = ZU(0);
43 bool	opt_redzone = false;
44 bool	opt_utrace = false;
45 bool	opt_xmalloc = false;
46 bool	opt_zero = false;
47 unsigned	opt_narenas = 0;
48 
49 /* Initialized to true if the process is running inside Valgrind. */
50 bool	in_valgrind;
51 
52 unsigned	ncpus;
53 
54 /* Protects arenas initialization. */
55 static malloc_mutex_t	arenas_lock;
56 /*
57  * Arenas that are used to service external requests.  Not all elements of the
58  * arenas array are necessarily used; arenas are created lazily as needed.
59  *
60  * arenas[0..narenas_auto) are used for automatic multiplexing of threads and
61  * arenas.  arenas[narenas_auto..narenas_total) are only used if the application
62  * takes some action to create them and allocate from them.
63  */
64 arena_t			**arenas;
65 static unsigned		narenas_total; /* Use narenas_total_*(). */
66 static arena_t		*a0; /* arenas[0]; read-only after initialization. */
67 unsigned		narenas_auto; /* Read-only after initialization. */
68 
69 typedef enum {
70 	malloc_init_uninitialized	= 3,
71 	malloc_init_a0_initialized	= 2,
72 	malloc_init_recursible		= 1,
73 	malloc_init_initialized		= 0 /* Common case --> jnz. */
74 } malloc_init_t;
75 static malloc_init_t	malloc_init_state = malloc_init_uninitialized;
76 
77 /* False should be the common case.  Set to true to trigger initialization. */
78 static bool	malloc_slow = true;
79 
80 /* When malloc_slow is true, set the corresponding bits for sanity check. */
81 enum {
82 	flag_opt_junk_alloc	= (1U),
83 	flag_opt_junk_free	= (1U << 1),
84 	flag_opt_quarantine	= (1U << 2),
85 	flag_opt_zero		= (1U << 3),
86 	flag_opt_utrace		= (1U << 4),
87 	flag_in_valgrind	= (1U << 5),
88 	flag_opt_xmalloc	= (1U << 6)
89 };
90 static uint8_t	malloc_slow_flags;
91 
92 JEMALLOC_ALIGNED(CACHELINE)
93 const size_t	pind2sz_tab[NPSIZES] = {
94 #define	PSZ_yes(lg_grp, ndelta, lg_delta)				\
95 	(((ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta))),
96 #define	PSZ_no(lg_grp, ndelta, lg_delta)
97 #define	SC(index, lg_grp, lg_delta, ndelta, psz, bin, lg_delta_lookup)	\
98 	PSZ_##psz(lg_grp, ndelta, lg_delta)
99 	SIZE_CLASSES
100 #undef PSZ_yes
101 #undef PSZ_no
102 #undef SC
103 };
104 
105 JEMALLOC_ALIGNED(CACHELINE)
106 const size_t	index2size_tab[NSIZES] = {
107 #define	SC(index, lg_grp, lg_delta, ndelta, psz, bin, lg_delta_lookup)	\
108 	((ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta)),
109 	SIZE_CLASSES
110 #undef SC
111 };
112 
113 JEMALLOC_ALIGNED(CACHELINE)
114 const uint8_t	size2index_tab[] = {
115 #if LG_TINY_MIN == 0
116 #warning "Dangerous LG_TINY_MIN"
117 #define	S2B_0(i)	i,
118 #elif LG_TINY_MIN == 1
119 #warning "Dangerous LG_TINY_MIN"
120 #define	S2B_1(i)	i,
121 #elif LG_TINY_MIN == 2
122 #warning "Dangerous LG_TINY_MIN"
123 #define	S2B_2(i)	i,
124 #elif LG_TINY_MIN == 3
125 #define	S2B_3(i)	i,
126 #elif LG_TINY_MIN == 4
127 #define	S2B_4(i)	i,
128 #elif LG_TINY_MIN == 5
129 #define	S2B_5(i)	i,
130 #elif LG_TINY_MIN == 6
131 #define	S2B_6(i)	i,
132 #elif LG_TINY_MIN == 7
133 #define	S2B_7(i)	i,
134 #elif LG_TINY_MIN == 8
135 #define	S2B_8(i)	i,
136 #elif LG_TINY_MIN == 9
137 #define	S2B_9(i)	i,
138 #elif LG_TINY_MIN == 10
139 #define	S2B_10(i)	i,
140 #elif LG_TINY_MIN == 11
141 #define	S2B_11(i)	i,
142 #else
143 #error "Unsupported LG_TINY_MIN"
144 #endif
145 #if LG_TINY_MIN < 1
146 #define	S2B_1(i)	S2B_0(i) S2B_0(i)
147 #endif
148 #if LG_TINY_MIN < 2
149 #define	S2B_2(i)	S2B_1(i) S2B_1(i)
150 #endif
151 #if LG_TINY_MIN < 3
152 #define	S2B_3(i)	S2B_2(i) S2B_2(i)
153 #endif
154 #if LG_TINY_MIN < 4
155 #define	S2B_4(i)	S2B_3(i) S2B_3(i)
156 #endif
157 #if LG_TINY_MIN < 5
158 #define	S2B_5(i)	S2B_4(i) S2B_4(i)
159 #endif
160 #if LG_TINY_MIN < 6
161 #define	S2B_6(i)	S2B_5(i) S2B_5(i)
162 #endif
163 #if LG_TINY_MIN < 7
164 #define	S2B_7(i)	S2B_6(i) S2B_6(i)
165 #endif
166 #if LG_TINY_MIN < 8
167 #define	S2B_8(i)	S2B_7(i) S2B_7(i)
168 #endif
169 #if LG_TINY_MIN < 9
170 #define	S2B_9(i)	S2B_8(i) S2B_8(i)
171 #endif
172 #if LG_TINY_MIN < 10
173 #define	S2B_10(i)	S2B_9(i) S2B_9(i)
174 #endif
175 #if LG_TINY_MIN < 11
176 #define	S2B_11(i)	S2B_10(i) S2B_10(i)
177 #endif
178 #define	S2B_no(i)
179 #define	SC(index, lg_grp, lg_delta, ndelta, psz, bin, lg_delta_lookup)	\
180 	S2B_##lg_delta_lookup(index)
181 	SIZE_CLASSES
182 #undef S2B_3
183 #undef S2B_4
184 #undef S2B_5
185 #undef S2B_6
186 #undef S2B_7
187 #undef S2B_8
188 #undef S2B_9
189 #undef S2B_10
190 #undef S2B_11
191 #undef S2B_no
192 #undef SC
193 };
194 
195 #ifdef JEMALLOC_THREADED_INIT
196 /* Used to let the initializing thread recursively allocate. */
197 #  define NO_INITIALIZER	((unsigned long)0)
198 #  define INITIALIZER		pthread_self()
199 #  define IS_INITIALIZER	(malloc_initializer == pthread_self())
200 static pthread_t		malloc_initializer = NO_INITIALIZER;
201 #else
202 #  define NO_INITIALIZER	false
203 #  define INITIALIZER		true
204 #  define IS_INITIALIZER	malloc_initializer
205 static bool			malloc_initializer = NO_INITIALIZER;
206 #endif
207 
208 /* Used to avoid initialization races. */
209 #ifdef _WIN32
210 #if _WIN32_WINNT >= 0x0600
211 static malloc_mutex_t	init_lock = SRWLOCK_INIT;
212 #else
213 static malloc_mutex_t	init_lock;
214 static bool init_lock_initialized = false;
215 
JEMALLOC_ATTR(constructor)216 JEMALLOC_ATTR(constructor)
217 static void WINAPI
218 _init_init_lock(void)
219 {
220 
221 	/* If another constructor in the same binary is using mallctl to
222 	 * e.g. setup chunk hooks, it may end up running before this one,
223 	 * and malloc_init_hard will crash trying to lock the uninitialized
224 	 * lock. So we force an initialization of the lock in
225 	 * malloc_init_hard as well. We don't try to care about atomicity
226 	 * of the accessed to the init_lock_initialized boolean, since it
227 	 * really only matters early in the process creation, before any
228 	 * separate thread normally starts doing anything. */
229 	if (!init_lock_initialized)
230 		malloc_mutex_init(&init_lock, "init", WITNESS_RANK_INIT);
231 	init_lock_initialized = true;
232 }
233 
234 #ifdef _MSC_VER
235 #  pragma section(".CRT$XCU", read)
236 JEMALLOC_SECTION(".CRT$XCU") JEMALLOC_ATTR(used)
237 static const void (WINAPI *init_init_lock)(void) = _init_init_lock;
238 #endif
239 #endif
240 #else
241 static malloc_mutex_t	init_lock = MALLOC_MUTEX_INITIALIZER;
242 #endif
243 
244 typedef struct {
245 	void	*p;	/* Input pointer (as in realloc(p, s)). */
246 	size_t	s;	/* Request size. */
247 	void	*r;	/* Result pointer. */
248 } malloc_utrace_t;
249 
250 #ifdef JEMALLOC_UTRACE
251 #  define UTRACE(a, b, c) do {						\
252 	if (unlikely(opt_utrace)) {					\
253 		int utrace_serrno = errno;				\
254 		malloc_utrace_t ut;					\
255 		ut.p = (a);						\
256 		ut.s = (b);						\
257 		ut.r = (c);						\
258 		utrace(&ut, sizeof(ut));				\
259 		errno = utrace_serrno;					\
260 	}								\
261 } while (0)
262 #else
263 #  define UTRACE(a, b, c)
264 #endif
265 
266 /******************************************************************************/
267 /*
268  * Function prototypes for static functions that are referenced prior to
269  * definition.
270  */
271 
272 static bool	malloc_init_hard_a0(void);
273 static bool	malloc_init_hard(void);
274 
275 /******************************************************************************/
276 /*
277  * Begin miscellaneous support functions.
278  */
279 
280 JEMALLOC_ALWAYS_INLINE_C bool
malloc_initialized(void)281 malloc_initialized(void)
282 {
283 
284 	return (malloc_init_state == malloc_init_initialized);
285 }
286 
287 JEMALLOC_ALWAYS_INLINE_C void
malloc_thread_init(void)288 malloc_thread_init(void)
289 {
290 
291 	/*
292 	 * TSD initialization can't be safely done as a side effect of
293 	 * deallocation, because it is possible for a thread to do nothing but
294 	 * deallocate its TLS data via free(), in which case writing to TLS
295 	 * would cause write-after-free memory corruption.  The quarantine
296 	 * facility *only* gets used as a side effect of deallocation, so make
297 	 * a best effort attempt at initializing its TSD by hooking all
298 	 * allocation events.
299 	 */
300 	if (config_fill && unlikely(opt_quarantine))
301 		quarantine_alloc_hook();
302 }
303 
304 JEMALLOC_ALWAYS_INLINE_C bool
malloc_init_a0(void)305 malloc_init_a0(void)
306 {
307 
308 	if (unlikely(malloc_init_state == malloc_init_uninitialized))
309 		return (malloc_init_hard_a0());
310 	return (false);
311 }
312 
313 JEMALLOC_ALWAYS_INLINE_C bool
malloc_init(void)314 malloc_init(void)
315 {
316 
317 	if (unlikely(!malloc_initialized()) && malloc_init_hard())
318 		return (true);
319 	malloc_thread_init();
320 
321 	return (false);
322 }
323 
324 /*
325  * The a0*() functions are used instead of i{d,}alloc() in situations that
326  * cannot tolerate TLS variable access.
327  */
328 
329 static void *
a0ialloc(size_t size,bool zero,bool is_metadata)330 a0ialloc(size_t size, bool zero, bool is_metadata)
331 {
332 
333 	if (unlikely(malloc_init_a0()))
334 		return (NULL);
335 
336 	return (iallocztm(TSDN_NULL, size, size2index(size), zero, NULL,
337 	    is_metadata, arena_get(TSDN_NULL, 0, true), true));
338 }
339 
340 static void
a0idalloc(void * ptr,bool is_metadata)341 a0idalloc(void *ptr, bool is_metadata)
342 {
343 
344 	idalloctm(TSDN_NULL, ptr, false, is_metadata, true);
345 }
346 
347 arena_t *
a0get(void)348 a0get(void)
349 {
350 
351 	return (a0);
352 }
353 
354 void *
a0malloc(size_t size)355 a0malloc(size_t size)
356 {
357 
358 	return (a0ialloc(size, false, true));
359 }
360 
361 void
a0dalloc(void * ptr)362 a0dalloc(void *ptr)
363 {
364 
365 	a0idalloc(ptr, true);
366 }
367 
368 /*
369  * FreeBSD's libc uses the bootstrap_*() functions in bootstrap-senstive
370  * situations that cannot tolerate TLS variable access (TLS allocation and very
371  * early internal data structure initialization).
372  */
373 
374 void *
bootstrap_malloc(size_t size)375 bootstrap_malloc(size_t size)
376 {
377 
378 	if (unlikely(size == 0))
379 		size = 1;
380 
381 	return (a0ialloc(size, false, false));
382 }
383 
384 void *
bootstrap_calloc(size_t num,size_t size)385 bootstrap_calloc(size_t num, size_t size)
386 {
387 	size_t num_size;
388 
389 	num_size = num * size;
390 	if (unlikely(num_size == 0)) {
391 		assert(num == 0 || size == 0);
392 		num_size = 1;
393 	}
394 
395 	return (a0ialloc(num_size, true, false));
396 }
397 
398 void
bootstrap_free(void * ptr)399 bootstrap_free(void *ptr)
400 {
401 
402 	if (unlikely(ptr == NULL))
403 		return;
404 
405 	a0idalloc(ptr, false);
406 }
407 
408 static void
arena_set(unsigned ind,arena_t * arena)409 arena_set(unsigned ind, arena_t *arena)
410 {
411 
412 	atomic_write_p((void **)&arenas[ind], arena);
413 }
414 
415 static void
narenas_total_set(unsigned narenas)416 narenas_total_set(unsigned narenas)
417 {
418 
419 	atomic_write_u(&narenas_total, narenas);
420 }
421 
422 static void
narenas_total_inc(void)423 narenas_total_inc(void)
424 {
425 
426 	atomic_add_u(&narenas_total, 1);
427 }
428 
429 unsigned
narenas_total_get(void)430 narenas_total_get(void)
431 {
432 
433 	return (atomic_read_u(&narenas_total));
434 }
435 
436 /* Create a new arena and insert it into the arenas array at index ind. */
437 static arena_t *
arena_init_locked(tsdn_t * tsdn,unsigned ind)438 arena_init_locked(tsdn_t *tsdn, unsigned ind)
439 {
440 	arena_t *arena;
441 
442 	assert(ind <= narenas_total_get());
443 	if (ind > MALLOCX_ARENA_MAX)
444 		return (NULL);
445 	if (ind == narenas_total_get())
446 		narenas_total_inc();
447 
448 	/*
449 	 * Another thread may have already initialized arenas[ind] if it's an
450 	 * auto arena.
451 	 */
452 	arena = arena_get(tsdn, ind, false);
453 	if (arena != NULL) {
454 		assert(ind < narenas_auto);
455 		return (arena);
456 	}
457 
458 	/* Actually initialize the arena. */
459 	arena = arena_new(tsdn, ind);
460 	arena_set(ind, arena);
461 	return (arena);
462 }
463 
464 arena_t *
arena_init(tsdn_t * tsdn,unsigned ind)465 arena_init(tsdn_t *tsdn, unsigned ind)
466 {
467 	arena_t *arena;
468 
469 	malloc_mutex_lock(tsdn, &arenas_lock);
470 	arena = arena_init_locked(tsdn, ind);
471 	malloc_mutex_unlock(tsdn, &arenas_lock);
472 	return (arena);
473 }
474 
475 static void
arena_bind(tsd_t * tsd,unsigned ind,bool internal)476 arena_bind(tsd_t *tsd, unsigned ind, bool internal)
477 {
478 	arena_t *arena;
479 
480 	if (!tsd_nominal(tsd))
481 		return;
482 
483 	arena = arena_get(tsd_tsdn(tsd), ind, false);
484 	arena_nthreads_inc(arena, internal);
485 
486 	if (internal)
487 		tsd_iarena_set(tsd, arena);
488 	else
489 		tsd_arena_set(tsd, arena);
490 }
491 
492 void
arena_migrate(tsd_t * tsd,unsigned oldind,unsigned newind)493 arena_migrate(tsd_t *tsd, unsigned oldind, unsigned newind)
494 {
495 	arena_t *oldarena, *newarena;
496 
497 	oldarena = arena_get(tsd_tsdn(tsd), oldind, false);
498 	newarena = arena_get(tsd_tsdn(tsd), newind, false);
499 	arena_nthreads_dec(oldarena, false);
500 	arena_nthreads_inc(newarena, false);
501 	tsd_arena_set(tsd, newarena);
502 }
503 
504 static void
arena_unbind(tsd_t * tsd,unsigned ind,bool internal)505 arena_unbind(tsd_t *tsd, unsigned ind, bool internal)
506 {
507 	arena_t *arena;
508 
509 	arena = arena_get(tsd_tsdn(tsd), ind, false);
510 	arena_nthreads_dec(arena, internal);
511 	if (internal)
512 		tsd_iarena_set(tsd, NULL);
513 	else
514 		tsd_arena_set(tsd, NULL);
515 }
516 
517 arena_tdata_t *
arena_tdata_get_hard(tsd_t * tsd,unsigned ind)518 arena_tdata_get_hard(tsd_t *tsd, unsigned ind)
519 {
520 	arena_tdata_t *tdata, *arenas_tdata_old;
521 	arena_tdata_t *arenas_tdata = tsd_arenas_tdata_get(tsd);
522 	unsigned narenas_tdata_old, i;
523 	unsigned narenas_tdata = tsd_narenas_tdata_get(tsd);
524 	unsigned narenas_actual = narenas_total_get();
525 
526 	/*
527 	 * Dissociate old tdata array (and set up for deallocation upon return)
528 	 * if it's too small.
529 	 */
530 	if (arenas_tdata != NULL && narenas_tdata < narenas_actual) {
531 		arenas_tdata_old = arenas_tdata;
532 		narenas_tdata_old = narenas_tdata;
533 		arenas_tdata = NULL;
534 		narenas_tdata = 0;
535 		tsd_arenas_tdata_set(tsd, arenas_tdata);
536 		tsd_narenas_tdata_set(tsd, narenas_tdata);
537 	} else {
538 		arenas_tdata_old = NULL;
539 		narenas_tdata_old = 0;
540 	}
541 
542 	/* Allocate tdata array if it's missing. */
543 	if (arenas_tdata == NULL) {
544 		bool *arenas_tdata_bypassp = tsd_arenas_tdata_bypassp_get(tsd);
545 		narenas_tdata = (ind < narenas_actual) ? narenas_actual : ind+1;
546 
547 		if (tsd_nominal(tsd) && !*arenas_tdata_bypassp) {
548 			*arenas_tdata_bypassp = true;
549 			arenas_tdata = (arena_tdata_t *)a0malloc(
550 			    sizeof(arena_tdata_t) * narenas_tdata);
551 			*arenas_tdata_bypassp = false;
552 		}
553 		if (arenas_tdata == NULL) {
554 			tdata = NULL;
555 			goto label_return;
556 		}
557 		assert(tsd_nominal(tsd) && !*arenas_tdata_bypassp);
558 		tsd_arenas_tdata_set(tsd, arenas_tdata);
559 		tsd_narenas_tdata_set(tsd, narenas_tdata);
560 	}
561 
562 	/*
563 	 * Copy to tdata array.  It's possible that the actual number of arenas
564 	 * has increased since narenas_total_get() was called above, but that
565 	 * causes no correctness issues unless two threads concurrently execute
566 	 * the arenas.extend mallctl, which we trust mallctl synchronization to
567 	 * prevent.
568 	 */
569 
570 	/* Copy/initialize tickers. */
571 	for (i = 0; i < narenas_actual; i++) {
572 		if (i < narenas_tdata_old) {
573 			ticker_copy(&arenas_tdata[i].decay_ticker,
574 			    &arenas_tdata_old[i].decay_ticker);
575 		} else {
576 			ticker_init(&arenas_tdata[i].decay_ticker,
577 			    DECAY_NTICKS_PER_UPDATE);
578 		}
579 	}
580 	if (narenas_tdata > narenas_actual) {
581 		memset(&arenas_tdata[narenas_actual], 0, sizeof(arena_tdata_t)
582 		    * (narenas_tdata - narenas_actual));
583 	}
584 
585 	/* Read the refreshed tdata array. */
586 	tdata = &arenas_tdata[ind];
587 label_return:
588 	if (arenas_tdata_old != NULL)
589 		a0dalloc(arenas_tdata_old);
590 	return (tdata);
591 }
592 
593 /* Slow path, called only by arena_choose(). */
594 arena_t *
arena_choose_hard(tsd_t * tsd,bool internal)595 arena_choose_hard(tsd_t *tsd, bool internal)
596 {
597 	arena_t *ret JEMALLOC_CC_SILENCE_INIT(NULL);
598 
599 	if (narenas_auto > 1) {
600 		unsigned i, j, choose[2], first_null;
601 
602 		/*
603 		 * Determine binding for both non-internal and internal
604 		 * allocation.
605 		 *
606 		 *   choose[0]: For application allocation.
607 		 *   choose[1]: For internal metadata allocation.
608 		 */
609 
610 		for (j = 0; j < 2; j++)
611 			choose[j] = 0;
612 
613 		first_null = narenas_auto;
614 		malloc_mutex_lock(tsd_tsdn(tsd), &arenas_lock);
615 		assert(arena_get(tsd_tsdn(tsd), 0, false) != NULL);
616 		for (i = 1; i < narenas_auto; i++) {
617 			if (arena_get(tsd_tsdn(tsd), i, false) != NULL) {
618 				/*
619 				 * Choose the first arena that has the lowest
620 				 * number of threads assigned to it.
621 				 */
622 				for (j = 0; j < 2; j++) {
623 					if (arena_nthreads_get(arena_get(
624 					    tsd_tsdn(tsd), i, false), !!j) <
625 					    arena_nthreads_get(arena_get(
626 					    tsd_tsdn(tsd), choose[j], false),
627 					    !!j))
628 						choose[j] = i;
629 				}
630 			} else if (first_null == narenas_auto) {
631 				/*
632 				 * Record the index of the first uninitialized
633 				 * arena, in case all extant arenas are in use.
634 				 *
635 				 * NB: It is possible for there to be
636 				 * discontinuities in terms of initialized
637 				 * versus uninitialized arenas, due to the
638 				 * "thread.arena" mallctl.
639 				 */
640 				first_null = i;
641 			}
642 		}
643 
644 		for (j = 0; j < 2; j++) {
645 			if (arena_nthreads_get(arena_get(tsd_tsdn(tsd),
646 			    choose[j], false), !!j) == 0 || first_null ==
647 			    narenas_auto) {
648 				/*
649 				 * Use an unloaded arena, or the least loaded
650 				 * arena if all arenas are already initialized.
651 				 */
652 				if (!!j == internal) {
653 					ret = arena_get(tsd_tsdn(tsd),
654 					    choose[j], false);
655 				}
656 			} else {
657 				arena_t *arena;
658 
659 				/* Initialize a new arena. */
660 				choose[j] = first_null;
661 				arena = arena_init_locked(tsd_tsdn(tsd),
662 				    choose[j]);
663 				if (arena == NULL) {
664 					malloc_mutex_unlock(tsd_tsdn(tsd),
665 					    &arenas_lock);
666 					return (NULL);
667 				}
668 				if (!!j == internal)
669 					ret = arena;
670 			}
671 			arena_bind(tsd, choose[j], !!j);
672 		}
673 		malloc_mutex_unlock(tsd_tsdn(tsd), &arenas_lock);
674 	} else {
675 		ret = arena_get(tsd_tsdn(tsd), 0, false);
676 		arena_bind(tsd, 0, false);
677 		arena_bind(tsd, 0, true);
678 	}
679 
680 	return (ret);
681 }
682 
683 void
thread_allocated_cleanup(tsd_t * tsd)684 thread_allocated_cleanup(tsd_t *tsd)
685 {
686 
687 	/* Do nothing. */
688 }
689 
690 void
thread_deallocated_cleanup(tsd_t * tsd)691 thread_deallocated_cleanup(tsd_t *tsd)
692 {
693 
694 	/* Do nothing. */
695 }
696 
697 void
iarena_cleanup(tsd_t * tsd)698 iarena_cleanup(tsd_t *tsd)
699 {
700 	arena_t *iarena;
701 
702 	iarena = tsd_iarena_get(tsd);
703 	if (iarena != NULL)
704 		arena_unbind(tsd, iarena->ind, true);
705 }
706 
707 void
arena_cleanup(tsd_t * tsd)708 arena_cleanup(tsd_t *tsd)
709 {
710 	arena_t *arena;
711 
712 	arena = tsd_arena_get(tsd);
713 	if (arena != NULL)
714 		arena_unbind(tsd, arena->ind, false);
715 }
716 
717 void
arenas_tdata_cleanup(tsd_t * tsd)718 arenas_tdata_cleanup(tsd_t *tsd)
719 {
720 	arena_tdata_t *arenas_tdata;
721 
722 	/* Prevent tsd->arenas_tdata from being (re)created. */
723 	*tsd_arenas_tdata_bypassp_get(tsd) = true;
724 
725 	arenas_tdata = tsd_arenas_tdata_get(tsd);
726 	if (arenas_tdata != NULL) {
727 		tsd_arenas_tdata_set(tsd, NULL);
728 		a0dalloc(arenas_tdata);
729 	}
730 }
731 
732 void
narenas_tdata_cleanup(tsd_t * tsd)733 narenas_tdata_cleanup(tsd_t *tsd)
734 {
735 
736 	/* Do nothing. */
737 }
738 
739 void
arenas_tdata_bypass_cleanup(tsd_t * tsd)740 arenas_tdata_bypass_cleanup(tsd_t *tsd)
741 {
742 
743 	/* Do nothing. */
744 }
745 
746 static void
stats_print_atexit(void)747 stats_print_atexit(void)
748 {
749 
750 	if (config_tcache && config_stats) {
751 		tsdn_t *tsdn;
752 		unsigned narenas, i;
753 
754 		tsdn = tsdn_fetch();
755 
756 		/*
757 		 * Merge stats from extant threads.  This is racy, since
758 		 * individual threads do not lock when recording tcache stats
759 		 * events.  As a consequence, the final stats may be slightly
760 		 * out of date by the time they are reported, if other threads
761 		 * continue to allocate.
762 		 */
763 		for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
764 			arena_t *arena = arena_get(tsdn, i, false);
765 			if (arena != NULL) {
766 				tcache_t *tcache;
767 
768 				/*
769 				 * tcache_stats_merge() locks bins, so if any
770 				 * code is introduced that acquires both arena
771 				 * and bin locks in the opposite order,
772 				 * deadlocks may result.
773 				 */
774 				malloc_mutex_lock(tsdn, &arena->lock);
775 				ql_foreach(tcache, &arena->tcache_ql, link) {
776 					tcache_stats_merge(tsdn, tcache, arena);
777 				}
778 				malloc_mutex_unlock(tsdn, &arena->lock);
779 			}
780 		}
781 	}
782 	je_malloc_stats_print(NULL, NULL, NULL);
783 }
784 
785 /*
786  * End miscellaneous support functions.
787  */
788 /******************************************************************************/
789 /*
790  * Begin initialization functions.
791  */
792 
793 #ifndef JEMALLOC_HAVE_SECURE_GETENV
794 static char *
secure_getenv(const char * name)795 secure_getenv(const char *name)
796 {
797 
798 #  ifdef JEMALLOC_HAVE_ISSETUGID
799 	if (issetugid() != 0)
800 		return (NULL);
801 #  endif
802 	return (getenv(name));
803 }
804 #endif
805 
806 static unsigned
malloc_ncpus(void)807 malloc_ncpus(void)
808 {
809 	long result;
810 
811 #ifdef _WIN32
812 	SYSTEM_INFO si;
813 	GetSystemInfo(&si);
814 	result = si.dwNumberOfProcessors;
815 #elif defined(JEMALLOC_GLIBC_MALLOC_HOOK) && defined(CPU_COUNT)
816 	/*
817 	 * glibc >= 2.6 has the CPU_COUNT macro.
818 	 *
819 	 * glibc's sysconf() uses isspace().  glibc allocates for the first time
820 	 * *before* setting up the isspace tables.  Therefore we need a
821 	 * different method to get the number of CPUs.
822 	 */
823 	{
824 		cpu_set_t set;
825 
826 		pthread_getaffinity_np(pthread_self(), sizeof(set), &set);
827 		result = CPU_COUNT(&set);
828 	}
829 #else
830 	result = sysconf(_SC_NPROCESSORS_ONLN);
831 #endif
832 	return ((result == -1) ? 1 : (unsigned)result);
833 }
834 
835 static bool
malloc_conf_next(char const ** opts_p,char const ** k_p,size_t * klen_p,char const ** v_p,size_t * vlen_p)836 malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p,
837     char const **v_p, size_t *vlen_p)
838 {
839 	bool accept;
840 	const char *opts = *opts_p;
841 
842 	*k_p = opts;
843 
844 	for (accept = false; !accept;) {
845 		switch (*opts) {
846 		case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
847 		case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
848 		case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
849 		case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
850 		case 'Y': case 'Z':
851 		case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
852 		case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
853 		case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
854 		case 's': case 't': case 'u': case 'v': case 'w': case 'x':
855 		case 'y': case 'z':
856 		case '0': case '1': case '2': case '3': case '4': case '5':
857 		case '6': case '7': case '8': case '9':
858 		case '_':
859 			opts++;
860 			break;
861 		case ':':
862 			opts++;
863 			*klen_p = (uintptr_t)opts - 1 - (uintptr_t)*k_p;
864 			*v_p = opts;
865 			accept = true;
866 			break;
867 		case '\0':
868 			if (opts != *opts_p) {
869 				malloc_write("<jemalloc>: Conf string ends "
870 				    "with key\n");
871 			}
872 			return (true);
873 		default:
874 			malloc_write("<jemalloc>: Malformed conf string\n");
875 			return (true);
876 		}
877 	}
878 
879 	for (accept = false; !accept;) {
880 		switch (*opts) {
881 		case ',':
882 			opts++;
883 			/*
884 			 * Look ahead one character here, because the next time
885 			 * this function is called, it will assume that end of
886 			 * input has been cleanly reached if no input remains,
887 			 * but we have optimistically already consumed the
888 			 * comma if one exists.
889 			 */
890 			if (*opts == '\0') {
891 				malloc_write("<jemalloc>: Conf string ends "
892 				    "with comma\n");
893 			}
894 			*vlen_p = (uintptr_t)opts - 1 - (uintptr_t)*v_p;
895 			accept = true;
896 			break;
897 		case '\0':
898 			*vlen_p = (uintptr_t)opts - (uintptr_t)*v_p;
899 			accept = true;
900 			break;
901 		default:
902 			opts++;
903 			break;
904 		}
905 	}
906 
907 	*opts_p = opts;
908 	return (false);
909 }
910 
911 static void
malloc_conf_error(const char * msg,const char * k,size_t klen,const char * v,size_t vlen)912 malloc_conf_error(const char *msg, const char *k, size_t klen, const char *v,
913     size_t vlen)
914 {
915 
916 	malloc_printf("<jemalloc>: %s: %.*s:%.*s\n", msg, (int)klen, k,
917 	    (int)vlen, v);
918 }
919 
920 static void
malloc_slow_flag_init(void)921 malloc_slow_flag_init(void)
922 {
923 	/*
924 	 * Combine the runtime options into malloc_slow for fast path.  Called
925 	 * after processing all the options.
926 	 */
927 	malloc_slow_flags |= (opt_junk_alloc ? flag_opt_junk_alloc : 0)
928 	    | (opt_junk_free ? flag_opt_junk_free : 0)
929 	    | (opt_quarantine ? flag_opt_quarantine : 0)
930 	    | (opt_zero ? flag_opt_zero : 0)
931 	    | (opt_utrace ? flag_opt_utrace : 0)
932 	    | (opt_xmalloc ? flag_opt_xmalloc : 0);
933 
934 	if (config_valgrind)
935 		malloc_slow_flags |= (in_valgrind ? flag_in_valgrind : 0);
936 
937 	malloc_slow = (malloc_slow_flags != 0);
938 }
939 
940 static void
malloc_conf_init(void)941 malloc_conf_init(void)
942 {
943 	unsigned i;
944 	char buf[PATH_MAX + 1];
945 	const char *opts, *k, *v;
946 	size_t klen, vlen;
947 
948 	/*
949 	 * Automatically configure valgrind before processing options.  The
950 	 * valgrind option remains in jemalloc 3.x for compatibility reasons.
951 	 */
952 	if (config_valgrind) {
953 		in_valgrind = (RUNNING_ON_VALGRIND != 0) ? true : false;
954 		if (config_fill && unlikely(in_valgrind)) {
955 			opt_junk = "false";
956 			opt_junk_alloc = false;
957 			opt_junk_free = false;
958 			assert(!opt_zero);
959 			opt_quarantine = JEMALLOC_VALGRIND_QUARANTINE_DEFAULT;
960 			opt_redzone = true;
961 		}
962 		if (config_tcache && unlikely(in_valgrind))
963 			opt_tcache = false;
964 	}
965 
966 #if defined(__ANDROID__)
967 	for (i = 0; i < 2; i++) {
968 #else
969 	for (i = 0; i < 4; i++) {
970 #endif
971 		/* Get runtime configuration. */
972 		switch (i) {
973 		case 0:
974 			opts = config_malloc_conf;
975 			break;
976 		case 1:
977 			if (je_malloc_conf != NULL) {
978 				/*
979 				 * Use options that were compiled into the
980 				 * program.
981 				 */
982 				opts = je_malloc_conf;
983 			} else {
984 				/* No configuration specified. */
985 				buf[0] = '\0';
986 				opts = buf;
987 			}
988 			break;
989 		case 2: {
990 			ssize_t linklen = 0;
991 #ifndef _WIN32
992 			int saved_errno = errno;
993 			const char *linkname =
994 #  ifdef JEMALLOC_PREFIX
995 			    "/etc/"JEMALLOC_PREFIX"malloc.conf"
996 #  else
997 			    "/etc/malloc.conf"
998 #  endif
999 			    ;
1000 
1001 			/*
1002 			 * Try to use the contents of the "/etc/malloc.conf"
1003 			 * symbolic link's name.
1004 			 */
1005 			linklen = readlink(linkname, buf, sizeof(buf) - 1);
1006 			if (linklen == -1) {
1007 				/* No configuration specified. */
1008 				linklen = 0;
1009 				/* Restore errno. */
1010 				set_errno(saved_errno);
1011 			}
1012 #endif
1013 			buf[linklen] = '\0';
1014 			opts = buf;
1015 			break;
1016 		} case 3: {
1017 			const char *envname =
1018 #ifdef JEMALLOC_PREFIX
1019 			    JEMALLOC_CPREFIX"MALLOC_CONF"
1020 #else
1021 			    "MALLOC_CONF"
1022 #endif
1023 			    ;
1024 
1025 			if ((opts = secure_getenv(envname)) != NULL) {
1026 				/*
1027 				 * Do nothing; opts is already initialized to
1028 				 * the value of the MALLOC_CONF environment
1029 				 * variable.
1030 				 */
1031 			} else {
1032 				/* No configuration specified. */
1033 				buf[0] = '\0';
1034 				opts = buf;
1035 			}
1036 			break;
1037 		} default:
1038 			not_reached();
1039 			buf[0] = '\0';
1040 			opts = buf;
1041 		}
1042 
1043 		while (*opts != '\0' && !malloc_conf_next(&opts, &k, &klen, &v,
1044 		    &vlen)) {
1045 #define	CONF_MATCH(n)							\
1046 	(sizeof(n)-1 == klen && strncmp(n, k, klen) == 0)
1047 #define	CONF_MATCH_VALUE(n)						\
1048 	(sizeof(n)-1 == vlen && strncmp(n, v, vlen) == 0)
1049 #define	CONF_HANDLE_BOOL(o, n, cont)					\
1050 			if (CONF_MATCH(n)) {				\
1051 				if (CONF_MATCH_VALUE("true"))		\
1052 					o = true;			\
1053 				else if (CONF_MATCH_VALUE("false"))	\
1054 					o = false;			\
1055 				else {					\
1056 					malloc_conf_error(		\
1057 					    "Invalid conf value",	\
1058 					    k, klen, v, vlen);		\
1059 				}					\
1060 				if (cont)				\
1061 					continue;			\
1062 			}
1063 #define	CONF_MIN_no(um, min)	false
1064 #define	CONF_MIN_yes(um, min)	((um) < (min))
1065 #define	CONF_MAX_no(um, max)	false
1066 #define	CONF_MAX_yes(um, max)	((um) > (max))
1067 #define	CONF_HANDLE_T_U(t, o, n, min, max, check_min, check_max, clip)	\
1068 			if (CONF_MATCH(n)) {				\
1069 				uintmax_t um;				\
1070 				char *end;				\
1071 									\
1072 				set_errno(0);				\
1073 				um = malloc_strtoumax(v, &end, 0);	\
1074 				if (get_errno() != 0 || (uintptr_t)end -\
1075 				    (uintptr_t)v != vlen) {		\
1076 					malloc_conf_error(		\
1077 					    "Invalid conf value",	\
1078 					    k, klen, v, vlen);		\
1079 				} else if (clip) {			\
1080 					if (CONF_MIN_##check_min(um,	\
1081 					    (min)))			\
1082 						o = (t)(min);		\
1083 					else if (CONF_MAX_##check_max(	\
1084 					    um, (max)))			\
1085 						o = (t)(max);		\
1086 					else				\
1087 						o = (t)um;		\
1088 				} else {				\
1089 					if (CONF_MIN_##check_min(um,	\
1090 					    (min)) ||			\
1091 					    CONF_MAX_##check_max(um,	\
1092 					    (max))) {			\
1093 						malloc_conf_error(	\
1094 						    "Out-of-range "	\
1095 						    "conf value",	\
1096 						    k, klen, v, vlen);	\
1097 					} else				\
1098 						o = (t)um;		\
1099 				}					\
1100 				continue;				\
1101 			}
1102 #define	CONF_HANDLE_UNSIGNED(o, n, min, max, check_min, check_max,	\
1103     clip)								\
1104 			CONF_HANDLE_T_U(unsigned, o, n, min, max,	\
1105 			    check_min, check_max, clip)
1106 #define	CONF_HANDLE_SIZE_T(o, n, min, max, check_min, check_max, clip)	\
1107 			CONF_HANDLE_T_U(size_t, o, n, min, max,		\
1108 			    check_min, check_max, clip)
1109 #define	CONF_HANDLE_SSIZE_T(o, n, min, max)				\
1110 			if (CONF_MATCH(n)) {				\
1111 				long l;					\
1112 				char *end;				\
1113 									\
1114 				set_errno(0);				\
1115 				l = strtol(v, &end, 0);			\
1116 				if (get_errno() != 0 || (uintptr_t)end -\
1117 				    (uintptr_t)v != vlen) {		\
1118 					malloc_conf_error(		\
1119 					    "Invalid conf value",	\
1120 					    k, klen, v, vlen);		\
1121 				} else if (l < (ssize_t)(min) || l >	\
1122 				    (ssize_t)(max)) {			\
1123 					malloc_conf_error(		\
1124 					    "Out-of-range conf value",	\
1125 					    k, klen, v, vlen);		\
1126 				} else					\
1127 					o = l;				\
1128 				continue;				\
1129 			}
1130 #define	CONF_HANDLE_CHAR_P(o, n, d)					\
1131 			if (CONF_MATCH(n)) {				\
1132 				size_t cpylen = (vlen <=		\
1133 				    sizeof(o)-1) ? vlen :		\
1134 				    sizeof(o)-1;			\
1135 				strncpy(o, v, cpylen);			\
1136 				o[cpylen] = '\0';			\
1137 				continue;				\
1138 			}
1139 
1140 			CONF_HANDLE_BOOL(opt_abort, "abort", true)
1141 			/*
1142 			 * Chunks always require at least one header page,
1143 			 * as many as 2^(LG_SIZE_CLASS_GROUP+1) data pages, and
1144 			 * possibly an additional page in the presence of
1145 			 * redzones.  In order to simplify options processing,
1146 			 * use a conservative bound that accommodates all these
1147 			 * constraints.
1148 			 */
1149 			CONF_HANDLE_SIZE_T(opt_lg_chunk, "lg_chunk", LG_PAGE +
1150 			    LG_SIZE_CLASS_GROUP + (config_fill ? 2 : 1),
1151 			    (sizeof(size_t) << 3) - 1, yes, yes, true)
1152 			if (strncmp("dss", k, klen) == 0) {
1153 				int i;
1154 				bool match = false;
1155 				for (i = 0; i < dss_prec_limit; i++) {
1156 					if (strncmp(dss_prec_names[i], v, vlen)
1157 					    == 0) {
1158 						if (chunk_dss_prec_set(i)) {
1159 							malloc_conf_error(
1160 							    "Error setting dss",
1161 							    k, klen, v, vlen);
1162 						} else {
1163 							opt_dss =
1164 							    dss_prec_names[i];
1165 							match = true;
1166 							break;
1167 						}
1168 					}
1169 				}
1170 				if (!match) {
1171 					malloc_conf_error("Invalid conf value",
1172 					    k, klen, v, vlen);
1173 				}
1174 				continue;
1175 			}
1176 			CONF_HANDLE_UNSIGNED(opt_narenas, "narenas", 1,
1177 			    UINT_MAX, yes, no, false)
1178 			if (strncmp("purge", k, klen) == 0) {
1179 				int i;
1180 				bool match = false;
1181 				for (i = 0; i < purge_mode_limit; i++) {
1182 					if (strncmp(purge_mode_names[i], v,
1183 					    vlen) == 0) {
1184 						opt_purge = (purge_mode_t)i;
1185 						match = true;
1186 						break;
1187 					}
1188 				}
1189 				if (!match) {
1190 					malloc_conf_error("Invalid conf value",
1191 					    k, klen, v, vlen);
1192 				}
1193 				continue;
1194 			}
1195 			CONF_HANDLE_SSIZE_T(opt_lg_dirty_mult, "lg_dirty_mult",
1196 			    -1, (sizeof(size_t) << 3) - 1)
1197 			CONF_HANDLE_SSIZE_T(opt_decay_time, "decay_time", -1,
1198 			    NSTIME_SEC_MAX);
1199 			CONF_HANDLE_BOOL(opt_stats_print, "stats_print", true)
1200 			if (config_fill) {
1201 				if (CONF_MATCH("junk")) {
1202 					if (CONF_MATCH_VALUE("true")) {
1203 						if (config_valgrind &&
1204 						    unlikely(in_valgrind)) {
1205 							malloc_conf_error(
1206 							"Deallocation-time "
1207 							"junk filling cannot "
1208 							"be enabled while "
1209 							"running inside "
1210 							"Valgrind", k, klen, v,
1211 							vlen);
1212 						} else {
1213 							opt_junk = "true";
1214 							opt_junk_alloc = true;
1215 							opt_junk_free = true;
1216 						}
1217 					} else if (CONF_MATCH_VALUE("false")) {
1218 						opt_junk = "false";
1219 						opt_junk_alloc = opt_junk_free =
1220 						    false;
1221 					} else if (CONF_MATCH_VALUE("alloc")) {
1222 						opt_junk = "alloc";
1223 						opt_junk_alloc = true;
1224 						opt_junk_free = false;
1225 					} else if (CONF_MATCH_VALUE("free")) {
1226 						if (config_valgrind &&
1227 						    unlikely(in_valgrind)) {
1228 							malloc_conf_error(
1229 							"Deallocation-time "
1230 							"junk filling cannot "
1231 							"be enabled while "
1232 							"running inside "
1233 							"Valgrind", k, klen, v,
1234 							vlen);
1235 						} else {
1236 							opt_junk = "free";
1237 							opt_junk_alloc = false;
1238 							opt_junk_free = true;
1239 						}
1240 					} else {
1241 						malloc_conf_error(
1242 						    "Invalid conf value", k,
1243 						    klen, v, vlen);
1244 					}
1245 					continue;
1246 				}
1247 				CONF_HANDLE_SIZE_T(opt_quarantine, "quarantine",
1248 				    0, SIZE_T_MAX, no, no, false)
1249 				CONF_HANDLE_BOOL(opt_redzone, "redzone", true)
1250 				CONF_HANDLE_BOOL(opt_zero, "zero", true)
1251 			}
1252 			if (config_utrace) {
1253 				CONF_HANDLE_BOOL(opt_utrace, "utrace", true)
1254 			}
1255 			if (config_xmalloc) {
1256 				CONF_HANDLE_BOOL(opt_xmalloc, "xmalloc", true)
1257 			}
1258 			if (config_tcache) {
1259 				CONF_HANDLE_BOOL(opt_tcache, "tcache",
1260 				    !config_valgrind || !in_valgrind)
1261 				if (CONF_MATCH("tcache")) {
1262 					assert(config_valgrind && in_valgrind);
1263 					if (opt_tcache) {
1264 						opt_tcache = false;
1265 						malloc_conf_error(
1266 						"tcache cannot be enabled "
1267 						"while running inside Valgrind",
1268 						k, klen, v, vlen);
1269 					}
1270 					continue;
1271 				}
1272 				CONF_HANDLE_SSIZE_T(opt_lg_tcache_max,
1273 				    "lg_tcache_max", -1,
1274 				    (sizeof(size_t) << 3) - 1)
1275 			}
1276 			if (config_prof) {
1277 				CONF_HANDLE_BOOL(opt_prof, "prof", true)
1278 				CONF_HANDLE_CHAR_P(opt_prof_prefix,
1279 				    "prof_prefix", "jeprof")
1280 				CONF_HANDLE_BOOL(opt_prof_active, "prof_active",
1281 				    true)
1282 				CONF_HANDLE_BOOL(opt_prof_thread_active_init,
1283 				    "prof_thread_active_init", true)
1284 				CONF_HANDLE_SIZE_T(opt_lg_prof_sample,
1285 				    "lg_prof_sample", 0, (sizeof(uint64_t) << 3)
1286 				    - 1, no, yes, true)
1287 				CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum",
1288 				    true)
1289 				CONF_HANDLE_SSIZE_T(opt_lg_prof_interval,
1290 				    "lg_prof_interval", -1,
1291 				    (sizeof(uint64_t) << 3) - 1)
1292 				CONF_HANDLE_BOOL(opt_prof_gdump, "prof_gdump",
1293 				    true)
1294 				CONF_HANDLE_BOOL(opt_prof_final, "prof_final",
1295 				    true)
1296 				CONF_HANDLE_BOOL(opt_prof_leak, "prof_leak",
1297 				    true)
1298 			}
1299 			malloc_conf_error("Invalid conf pair", k, klen, v,
1300 			    vlen);
1301 #undef CONF_MATCH
1302 #undef CONF_MATCH_VALUE
1303 #undef CONF_HANDLE_BOOL
1304 #undef CONF_MIN_no
1305 #undef CONF_MIN_yes
1306 #undef CONF_MAX_no
1307 #undef CONF_MAX_yes
1308 #undef CONF_HANDLE_T_U
1309 #undef CONF_HANDLE_UNSIGNED
1310 #undef CONF_HANDLE_SIZE_T
1311 #undef CONF_HANDLE_SSIZE_T
1312 #undef CONF_HANDLE_CHAR_P
1313 		}
1314 	}
1315 }
1316 
1317 static bool
1318 malloc_init_hard_needed(void)
1319 {
1320 
1321 	if (malloc_initialized() || (IS_INITIALIZER && malloc_init_state ==
1322 	    malloc_init_recursible)) {
1323 		/*
1324 		 * Another thread initialized the allocator before this one
1325 		 * acquired init_lock, or this thread is the initializing
1326 		 * thread, and it is recursively allocating.
1327 		 */
1328 		return (false);
1329 	}
1330 #ifdef JEMALLOC_THREADED_INIT
1331 	if (malloc_initializer != NO_INITIALIZER && !IS_INITIALIZER) {
1332 		spin_t spinner;
1333 
1334 		/* Busy-wait until the initializing thread completes. */
1335 		spin_init(&spinner);
1336 		do {
1337 			malloc_mutex_unlock(TSDN_NULL, &init_lock);
1338 			spin_adaptive(&spinner);
1339 			malloc_mutex_lock(TSDN_NULL, &init_lock);
1340 		} while (!malloc_initialized());
1341 		return (false);
1342 	}
1343 #endif
1344 	return (true);
1345 }
1346 
1347 static bool
1348 malloc_init_hard_a0_locked()
1349 {
1350 
1351 	malloc_initializer = INITIALIZER;
1352 
1353 	if (config_prof)
1354 		prof_boot0();
1355 	malloc_conf_init();
1356 	if (opt_stats_print) {
1357 		/* Print statistics at exit. */
1358 		if (atexit(stats_print_atexit) != 0) {
1359 			malloc_write("<jemalloc>: Error in atexit()\n");
1360 			if (opt_abort)
1361 				abort();
1362 		}
1363 	}
1364 	pages_boot();
1365 	if (base_boot())
1366 		return (true);
1367 	if (chunk_boot())
1368 		return (true);
1369 	if (ctl_boot())
1370 		return (true);
1371 	if (config_prof)
1372 		prof_boot1();
1373 	arena_boot();
1374 	if (config_tcache && tcache_boot(TSDN_NULL))
1375 		return (true);
1376 	if (malloc_mutex_init(&arenas_lock, "arenas", WITNESS_RANK_ARENAS))
1377 		return (true);
1378 	/*
1379 	 * Create enough scaffolding to allow recursive allocation in
1380 	 * malloc_ncpus().
1381 	 */
1382 	narenas_auto = 1;
1383 	narenas_total_set(narenas_auto);
1384 	arenas = &a0;
1385 	memset(arenas, 0, sizeof(arena_t *) * narenas_auto);
1386 	/*
1387 	 * Initialize one arena here.  The rest are lazily created in
1388 	 * arena_choose_hard().
1389 	 */
1390 	if (arena_init(TSDN_NULL, 0) == NULL)
1391 		return (true);
1392 
1393 	malloc_init_state = malloc_init_a0_initialized;
1394 
1395 	return (false);
1396 }
1397 
1398 static bool
1399 malloc_init_hard_a0(void)
1400 {
1401 	bool ret;
1402 
1403 	malloc_mutex_lock(TSDN_NULL, &init_lock);
1404 	ret = malloc_init_hard_a0_locked();
1405 	malloc_mutex_unlock(TSDN_NULL, &init_lock);
1406 	return (ret);
1407 }
1408 
1409 /* Initialize data structures which may trigger recursive allocation. */
1410 static bool
1411 malloc_init_hard_recursible(void)
1412 {
1413 
1414 	malloc_init_state = malloc_init_recursible;
1415 
1416 	ncpus = malloc_ncpus();
1417 
1418 #if (defined(JEMALLOC_HAVE_PTHREAD_ATFORK) && !defined(JEMALLOC_MUTEX_INIT_CB) \
1419     && !defined(JEMALLOC_ZONE) && !defined(_WIN32) && \
1420     !defined(__native_client__))
1421 	/* LinuxThreads' pthread_atfork() allocates. */
1422 	if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent,
1423 	    jemalloc_postfork_child) != 0) {
1424 		malloc_write("<jemalloc>: Error in pthread_atfork()\n");
1425 		if (opt_abort)
1426 			abort();
1427 		return (true);
1428 	}
1429 #endif
1430 
1431 	return (false);
1432 }
1433 
1434 static bool
1435 malloc_init_hard_finish(tsdn_t *tsdn)
1436 {
1437 
1438 	if (malloc_mutex_boot())
1439 		return (true);
1440 
1441 	if (opt_narenas == 0) {
1442 		/*
1443 		 * For SMP systems, create more than one arena per CPU by
1444 		 * default.
1445 		 */
1446 		if (ncpus > 1)
1447 			opt_narenas = ncpus << 2;
1448 		else
1449 			opt_narenas = 1;
1450 	}
1451 #if defined(ANDROID_MAX_ARENAS)
1452 	/* Never create more than MAX_ARENAS arenas regardless of num_cpus.
1453 	 * Extra arenas use more PSS and are not very useful unless
1454 	 * lots of threads are allocing/freeing at the same time.
1455 	 */
1456 	if (opt_narenas > ANDROID_MAX_ARENAS)
1457 		opt_narenas = ANDROID_MAX_ARENAS;
1458 #endif
1459 	narenas_auto = opt_narenas;
1460 	/*
1461 	 * Limit the number of arenas to the indexing range of MALLOCX_ARENA().
1462 	 */
1463 	if (narenas_auto > MALLOCX_ARENA_MAX) {
1464 		narenas_auto = MALLOCX_ARENA_MAX;
1465 		malloc_printf("<jemalloc>: Reducing narenas to limit (%d)\n",
1466 		    narenas_auto);
1467 	}
1468 	narenas_total_set(narenas_auto);
1469 
1470 	/* Allocate and initialize arenas. */
1471 	arenas = (arena_t **)base_alloc(tsdn, sizeof(arena_t *) *
1472 	    (MALLOCX_ARENA_MAX+1));
1473 	if (arenas == NULL)
1474 		return (true);
1475 	/* Copy the pointer to the one arena that was already initialized. */
1476 	arena_set(0, a0);
1477 
1478 	malloc_init_state = malloc_init_initialized;
1479 	malloc_slow_flag_init();
1480 
1481 	return (false);
1482 }
1483 
1484 static bool
1485 malloc_init_hard(void)
1486 {
1487 	tsd_t *tsd;
1488 
1489 #if defined(_WIN32) && _WIN32_WINNT < 0x0600
1490 	_init_init_lock();
1491 #endif
1492 	malloc_mutex_lock(TSDN_NULL, &init_lock);
1493 	if (!malloc_init_hard_needed()) {
1494 		malloc_mutex_unlock(TSDN_NULL, &init_lock);
1495 		return (false);
1496 	}
1497 
1498 	if (malloc_init_state != malloc_init_a0_initialized &&
1499 	    malloc_init_hard_a0_locked()) {
1500 		malloc_mutex_unlock(TSDN_NULL, &init_lock);
1501 		return (true);
1502 	}
1503 
1504 	malloc_mutex_unlock(TSDN_NULL, &init_lock);
1505 	/* Recursive allocation relies on functional tsd. */
1506 	tsd = malloc_tsd_boot0();
1507 	if (tsd == NULL)
1508 		return (true);
1509 	if (malloc_init_hard_recursible())
1510 		return (true);
1511 	malloc_mutex_lock(tsd_tsdn(tsd), &init_lock);
1512 
1513 	if (config_prof && prof_boot2(tsd)) {
1514 		malloc_mutex_unlock(tsd_tsdn(tsd), &init_lock);
1515 		return (true);
1516 	}
1517 
1518 	if (malloc_init_hard_finish(tsd_tsdn(tsd))) {
1519 		malloc_mutex_unlock(tsd_tsdn(tsd), &init_lock);
1520 		return (true);
1521 	}
1522 
1523 	malloc_mutex_unlock(tsd_tsdn(tsd), &init_lock);
1524 	malloc_tsd_boot1();
1525 	return (false);
1526 }
1527 
1528 /*
1529  * End initialization functions.
1530  */
1531 /******************************************************************************/
1532 /*
1533  * Begin malloc(3)-compatible functions.
1534  */
1535 
1536 static void *
1537 ialloc_prof_sample(tsd_t *tsd, size_t usize, szind_t ind, bool zero,
1538     prof_tctx_t *tctx, bool slow_path)
1539 {
1540 	void *p;
1541 
1542 	if (tctx == NULL)
1543 		return (NULL);
1544 	if (usize <= SMALL_MAXCLASS) {
1545 		szind_t ind_large = size2index(LARGE_MINCLASS);
1546 		p = ialloc(tsd, LARGE_MINCLASS, ind_large, zero, slow_path);
1547 		if (p == NULL)
1548 			return (NULL);
1549 		arena_prof_promoted(tsd_tsdn(tsd), p, usize);
1550 	} else
1551 		p = ialloc(tsd, usize, ind, zero, slow_path);
1552 
1553 	return (p);
1554 }
1555 
1556 JEMALLOC_ALWAYS_INLINE_C void *
1557 ialloc_prof(tsd_t *tsd, size_t usize, szind_t ind, bool zero, bool slow_path)
1558 {
1559 	void *p;
1560 	prof_tctx_t *tctx;
1561 
1562 	tctx = prof_alloc_prep(tsd, usize, prof_active_get_unlocked(), true);
1563 	if (unlikely((uintptr_t)tctx != (uintptr_t)1U))
1564 		p = ialloc_prof_sample(tsd, usize, ind, zero, tctx, slow_path);
1565 	else
1566 		p = ialloc(tsd, usize, ind, zero, slow_path);
1567 	if (unlikely(p == NULL)) {
1568 		prof_alloc_rollback(tsd, tctx, true);
1569 		return (NULL);
1570 	}
1571 	prof_malloc(tsd_tsdn(tsd), p, usize, tctx);
1572 
1573 	return (p);
1574 }
1575 
1576 /*
1577  * ialloc_body() is inlined so that fast and slow paths are generated separately
1578  * with statically known slow_path.
1579  *
1580  * This function guarantees that *tsdn is non-NULL on success.
1581  */
1582 JEMALLOC_ALWAYS_INLINE_C void *
1583 ialloc_body(size_t size, bool zero, tsdn_t **tsdn, size_t *usize,
1584     bool slow_path)
1585 {
1586 	tsd_t *tsd;
1587 	szind_t ind;
1588 
1589 	if (slow_path && unlikely(malloc_init())) {
1590 		*tsdn = NULL;
1591 		return (NULL);
1592 	}
1593 
1594 	tsd = tsd_fetch();
1595 	*tsdn = tsd_tsdn(tsd);
1596 	witness_assert_lockless(tsd_tsdn(tsd));
1597 
1598 	ind = size2index(size);
1599 	if (unlikely(ind >= NSIZES))
1600 		return (NULL);
1601 
1602 	if (config_stats || (config_prof && opt_prof) || (slow_path &&
1603 	    config_valgrind && unlikely(in_valgrind))) {
1604 		*usize = index2size(ind);
1605 		assert(*usize > 0 && *usize <= HUGE_MAXCLASS);
1606 	}
1607 
1608 	if (config_prof && opt_prof)
1609 		return (ialloc_prof(tsd, *usize, ind, zero, slow_path));
1610 
1611 	return (ialloc(tsd, size, ind, zero, slow_path));
1612 }
1613 
1614 JEMALLOC_ALWAYS_INLINE_C void
1615 ialloc_post_check(void *ret, tsdn_t *tsdn, size_t usize, const char *func,
1616     bool update_errno, bool slow_path)
1617 {
1618 
1619 	assert(!tsdn_null(tsdn) || ret == NULL);
1620 
1621 	if (unlikely(ret == NULL)) {
1622 		if (slow_path && config_xmalloc && unlikely(opt_xmalloc)) {
1623 			malloc_printf("<jemalloc>: Error in %s(): out of "
1624 			    "memory\n", func);
1625 			abort();
1626 		}
1627 		if (update_errno)
1628 			set_errno(ENOMEM);
1629 	}
1630 	if (config_stats && likely(ret != NULL)) {
1631 		assert(usize == isalloc(tsdn, ret, config_prof));
1632 		*tsd_thread_allocatedp_get(tsdn_tsd(tsdn)) += usize;
1633 	}
1634 	witness_assert_lockless(tsdn);
1635 }
1636 
1637 JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
1638 void JEMALLOC_NOTHROW *
1639 JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1)
1640 je_malloc(size_t size)
1641 {
1642 	void *ret;
1643 	tsdn_t *tsdn;
1644 	size_t usize JEMALLOC_CC_SILENCE_INIT(0);
1645 
1646 	if (size == 0)
1647 		size = 1;
1648 
1649 	if (likely(!malloc_slow)) {
1650 		ret = ialloc_body(size, false, &tsdn, &usize, false);
1651 		ialloc_post_check(ret, tsdn, usize, "malloc", true, false);
1652 	} else {
1653 		ret = ialloc_body(size, false, &tsdn, &usize, true);
1654 		ialloc_post_check(ret, tsdn, usize, "malloc", true, true);
1655 		UTRACE(0, size, ret);
1656 		JEMALLOC_VALGRIND_MALLOC(ret != NULL, tsdn, ret, usize, false);
1657 	}
1658 
1659 	return (ret);
1660 }
1661 
1662 static void *
1663 imemalign_prof_sample(tsd_t *tsd, size_t alignment, size_t usize,
1664     prof_tctx_t *tctx)
1665 {
1666 	void *p;
1667 
1668 	if (tctx == NULL)
1669 		return (NULL);
1670 	if (usize <= SMALL_MAXCLASS) {
1671 		assert(sa2u(LARGE_MINCLASS, alignment) == LARGE_MINCLASS);
1672 		p = ipalloc(tsd, LARGE_MINCLASS, alignment, false);
1673 		if (p == NULL)
1674 			return (NULL);
1675 		arena_prof_promoted(tsd_tsdn(tsd), p, usize);
1676 	} else
1677 		p = ipalloc(tsd, usize, alignment, false);
1678 
1679 	return (p);
1680 }
1681 
1682 JEMALLOC_ALWAYS_INLINE_C void *
1683 imemalign_prof(tsd_t *tsd, size_t alignment, size_t usize)
1684 {
1685 	void *p;
1686 	prof_tctx_t *tctx;
1687 
1688 	tctx = prof_alloc_prep(tsd, usize, prof_active_get_unlocked(), true);
1689 	if (unlikely((uintptr_t)tctx != (uintptr_t)1U))
1690 		p = imemalign_prof_sample(tsd, alignment, usize, tctx);
1691 	else
1692 		p = ipalloc(tsd, usize, alignment, false);
1693 	if (unlikely(p == NULL)) {
1694 		prof_alloc_rollback(tsd, tctx, true);
1695 		return (NULL);
1696 	}
1697 	prof_malloc(tsd_tsdn(tsd), p, usize, tctx);
1698 
1699 	return (p);
1700 }
1701 
1702 JEMALLOC_ATTR(nonnull(1))
1703 static int
1704 imemalign(void **memptr, size_t alignment, size_t size, size_t min_alignment)
1705 {
1706 	int ret;
1707 	tsd_t *tsd;
1708 	size_t usize;
1709 	void *result;
1710 
1711 	assert(min_alignment != 0);
1712 
1713 	if (unlikely(malloc_init())) {
1714 		tsd = NULL;
1715 		result = NULL;
1716 		goto label_oom;
1717 	}
1718 	tsd = tsd_fetch();
1719 	witness_assert_lockless(tsd_tsdn(tsd));
1720 	if (size == 0)
1721 		size = 1;
1722 
1723 	/* Make sure that alignment is a large enough power of 2. */
1724 	if (unlikely(((alignment - 1) & alignment) != 0
1725 	    || (alignment < min_alignment))) {
1726 		if (config_xmalloc && unlikely(opt_xmalloc)) {
1727 			malloc_write("<jemalloc>: Error allocating "
1728 			    "aligned memory: invalid alignment\n");
1729 			abort();
1730 		}
1731 		result = NULL;
1732 		ret = EINVAL;
1733 		goto label_return;
1734 	}
1735 
1736 	usize = sa2u(size, alignment);
1737 	if (unlikely(usize == 0 || usize > HUGE_MAXCLASS)) {
1738 		result = NULL;
1739 		goto label_oom;
1740 	}
1741 
1742 	if (config_prof && opt_prof)
1743 		result = imemalign_prof(tsd, alignment, usize);
1744 	else
1745 		result = ipalloc(tsd, usize, alignment, false);
1746 	if (unlikely(result == NULL))
1747 		goto label_oom;
1748 	assert(((uintptr_t)result & (alignment - 1)) == ZU(0));
1749 
1750 	*memptr = result;
1751 	ret = 0;
1752 label_return:
1753 	if (config_stats && likely(result != NULL)) {
1754 		assert(usize == isalloc(tsd_tsdn(tsd), result, config_prof));
1755 		*tsd_thread_allocatedp_get(tsd) += usize;
1756 	}
1757 	UTRACE(0, size, result);
1758 	JEMALLOC_VALGRIND_MALLOC(result != NULL, tsd_tsdn(tsd), result, usize,
1759 	    false);
1760 	witness_assert_lockless(tsd_tsdn(tsd));
1761 	return (ret);
1762 label_oom:
1763 	assert(result == NULL);
1764 	if (config_xmalloc && unlikely(opt_xmalloc)) {
1765 		malloc_write("<jemalloc>: Error allocating aligned memory: "
1766 		    "out of memory\n");
1767 		abort();
1768 	}
1769 	ret = ENOMEM;
1770 	witness_assert_lockless(tsd_tsdn(tsd));
1771 	goto label_return;
1772 }
1773 
1774 JEMALLOC_EXPORT int JEMALLOC_NOTHROW
1775 JEMALLOC_ATTR(nonnull(1))
1776 je_posix_memalign(void **memptr, size_t alignment, size_t size)
1777 {
1778 	int ret;
1779 
1780 	ret = imemalign(memptr, alignment, size, sizeof(void *));
1781 
1782 	return (ret);
1783 }
1784 
1785 JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
1786 void JEMALLOC_NOTHROW *
1787 JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(2)
1788 je_aligned_alloc(size_t alignment, size_t size)
1789 {
1790 	void *ret;
1791 	int err;
1792 
1793 	if (unlikely((err = imemalign(&ret, alignment, size, 1)) != 0)) {
1794 		ret = NULL;
1795 		set_errno(err);
1796 	}
1797 
1798 	return (ret);
1799 }
1800 
1801 JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
1802 void JEMALLOC_NOTHROW *
1803 JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2)
1804 je_calloc(size_t num, size_t size)
1805 {
1806 	void *ret;
1807 	tsdn_t *tsdn;
1808 	size_t num_size;
1809 	size_t usize JEMALLOC_CC_SILENCE_INIT(0);
1810 
1811 	num_size = num * size;
1812 	if (unlikely(num_size == 0)) {
1813 		if (num == 0 || size == 0)
1814 			num_size = 1;
1815 		else
1816 			num_size = HUGE_MAXCLASS + 1; /* Trigger OOM. */
1817 	/*
1818 	 * Try to avoid division here.  We know that it isn't possible to
1819 	 * overflow during multiplication if neither operand uses any of the
1820 	 * most significant half of the bits in a size_t.
1821 	 */
1822 	} else if (unlikely(((num | size) & (SIZE_T_MAX << (sizeof(size_t) <<
1823 	    2))) && (num_size / size != num)))
1824 		num_size = HUGE_MAXCLASS + 1; /* size_t overflow. */
1825 
1826 	if (likely(!malloc_slow)) {
1827 		ret = ialloc_body(num_size, true, &tsdn, &usize, false);
1828 		ialloc_post_check(ret, tsdn, usize, "calloc", true, false);
1829 	} else {
1830 		ret = ialloc_body(num_size, true, &tsdn, &usize, true);
1831 		ialloc_post_check(ret, tsdn, usize, "calloc", true, true);
1832 		UTRACE(0, num_size, ret);
1833 		JEMALLOC_VALGRIND_MALLOC(ret != NULL, tsdn, ret, usize, true);
1834 	}
1835 
1836 	return (ret);
1837 }
1838 
1839 static void *
1840 irealloc_prof_sample(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize,
1841     prof_tctx_t *tctx)
1842 {
1843 	void *p;
1844 
1845 	if (tctx == NULL)
1846 		return (NULL);
1847 	if (usize <= SMALL_MAXCLASS) {
1848 		p = iralloc(tsd, old_ptr, old_usize, LARGE_MINCLASS, 0, false);
1849 		if (p == NULL)
1850 			return (NULL);
1851 		arena_prof_promoted(tsd_tsdn(tsd), p, usize);
1852 	} else
1853 		p = iralloc(tsd, old_ptr, old_usize, usize, 0, false);
1854 
1855 	return (p);
1856 }
1857 
1858 JEMALLOC_ALWAYS_INLINE_C void *
1859 irealloc_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize)
1860 {
1861 	void *p;
1862 	bool prof_active;
1863 	prof_tctx_t *old_tctx, *tctx;
1864 
1865 	prof_active = prof_active_get_unlocked();
1866 	old_tctx = prof_tctx_get(tsd_tsdn(tsd), old_ptr);
1867 	tctx = prof_alloc_prep(tsd, usize, prof_active, true);
1868 	if (unlikely((uintptr_t)tctx != (uintptr_t)1U))
1869 		p = irealloc_prof_sample(tsd, old_ptr, old_usize, usize, tctx);
1870 	else
1871 		p = iralloc(tsd, old_ptr, old_usize, usize, 0, false);
1872 	if (unlikely(p == NULL)) {
1873 		prof_alloc_rollback(tsd, tctx, true);
1874 		return (NULL);
1875 	}
1876 	prof_realloc(tsd, p, usize, tctx, prof_active, true, old_ptr, old_usize,
1877 	    old_tctx);
1878 
1879 	return (p);
1880 }
1881 
1882 JEMALLOC_INLINE_C void
1883 ifree(tsd_t *tsd, void *ptr, tcache_t *tcache, bool slow_path)
1884 {
1885 	size_t usize;
1886 	UNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);
1887 
1888 	witness_assert_lockless(tsd_tsdn(tsd));
1889 
1890 	assert(ptr != NULL);
1891 	assert(malloc_initialized() || IS_INITIALIZER);
1892 
1893 	if (config_prof && opt_prof) {
1894 		usize = isalloc(tsd_tsdn(tsd), ptr, config_prof);
1895 		prof_free(tsd, ptr, usize);
1896 	} else if (config_stats || config_valgrind)
1897 		usize = isalloc(tsd_tsdn(tsd), ptr, config_prof);
1898 	if (config_stats)
1899 		*tsd_thread_deallocatedp_get(tsd) += usize;
1900 
1901 	if (likely(!slow_path))
1902 		iqalloc(tsd, ptr, tcache, false);
1903 	else {
1904 		if (config_valgrind && unlikely(in_valgrind))
1905 			rzsize = p2rz(tsd_tsdn(tsd), ptr);
1906 		iqalloc(tsd, ptr, tcache, true);
1907 		JEMALLOC_VALGRIND_FREE(ptr, rzsize);
1908 	}
1909 }
1910 
1911 JEMALLOC_INLINE_C void
1912 isfree(tsd_t *tsd, void *ptr, size_t usize, tcache_t *tcache, bool slow_path)
1913 {
1914 	UNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);
1915 
1916 	witness_assert_lockless(tsd_tsdn(tsd));
1917 
1918 	assert(ptr != NULL);
1919 	assert(malloc_initialized() || IS_INITIALIZER);
1920 
1921 	if (config_prof && opt_prof)
1922 		prof_free(tsd, ptr, usize);
1923 	if (config_stats)
1924 		*tsd_thread_deallocatedp_get(tsd) += usize;
1925 	if (config_valgrind && unlikely(in_valgrind))
1926 		rzsize = p2rz(tsd_tsdn(tsd), ptr);
1927 	isqalloc(tsd, ptr, usize, tcache, slow_path);
1928 	JEMALLOC_VALGRIND_FREE(ptr, rzsize);
1929 }
1930 
1931 JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
1932 void JEMALLOC_NOTHROW *
1933 JEMALLOC_ALLOC_SIZE(2)
1934 je_realloc(void *ptr, size_t size)
1935 {
1936 	void *ret;
1937 	tsdn_t *tsdn JEMALLOC_CC_SILENCE_INIT(NULL);
1938 	size_t usize JEMALLOC_CC_SILENCE_INIT(0);
1939 	size_t old_usize = 0;
1940 	UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);
1941 
1942 	if (unlikely(size == 0)) {
1943 		if (ptr != NULL) {
1944 			tsd_t *tsd;
1945 
1946 			/* realloc(ptr, 0) is equivalent to free(ptr). */
1947 			UTRACE(ptr, 0, 0);
1948 			tsd = tsd_fetch();
1949 			ifree(tsd, ptr, tcache_get(tsd, false), true);
1950 			return (NULL);
1951 		}
1952 		size = 1;
1953 	}
1954 
1955 	if (likely(ptr != NULL)) {
1956 		tsd_t *tsd;
1957 
1958 		assert(malloc_initialized() || IS_INITIALIZER);
1959 		malloc_thread_init();
1960 		tsd = tsd_fetch();
1961 
1962 		witness_assert_lockless(tsd_tsdn(tsd));
1963 
1964 		old_usize = isalloc(tsd_tsdn(tsd), ptr, config_prof);
1965 		if (config_valgrind && unlikely(in_valgrind)) {
1966 			old_rzsize = config_prof ? p2rz(tsd_tsdn(tsd), ptr) :
1967 			    u2rz(old_usize);
1968 		}
1969 
1970 		if (config_prof && opt_prof) {
1971 			usize = s2u(size);
1972 			ret = unlikely(usize == 0 || usize > HUGE_MAXCLASS) ?
1973 			    NULL : irealloc_prof(tsd, ptr, old_usize, usize);
1974 		} else {
1975 			if (config_stats || (config_valgrind &&
1976 			    unlikely(in_valgrind)))
1977 				usize = s2u(size);
1978 			ret = iralloc(tsd, ptr, old_usize, size, 0, false);
1979 		}
1980 		tsdn = tsd_tsdn(tsd);
1981 	} else {
1982 		/* realloc(NULL, size) is equivalent to malloc(size). */
1983 		if (likely(!malloc_slow))
1984 			ret = ialloc_body(size, false, &tsdn, &usize, false);
1985 		else
1986 			ret = ialloc_body(size, false, &tsdn, &usize, true);
1987 		assert(!tsdn_null(tsdn) || ret == NULL);
1988 	}
1989 
1990 	if (unlikely(ret == NULL)) {
1991 		if (config_xmalloc && unlikely(opt_xmalloc)) {
1992 			malloc_write("<jemalloc>: Error in realloc(): "
1993 			    "out of memory\n");
1994 			abort();
1995 		}
1996 		set_errno(ENOMEM);
1997 	}
1998 	if (config_stats && likely(ret != NULL)) {
1999 		tsd_t *tsd;
2000 
2001 		assert(usize == isalloc(tsdn, ret, config_prof));
2002 		tsd = tsdn_tsd(tsdn);
2003 		*tsd_thread_allocatedp_get(tsd) += usize;
2004 		*tsd_thread_deallocatedp_get(tsd) += old_usize;
2005 	}
2006 	UTRACE(ptr, size, ret);
2007 	JEMALLOC_VALGRIND_REALLOC(maybe, tsdn, ret, usize, maybe, ptr,
2008 	    old_usize, old_rzsize, maybe, false);
2009 	witness_assert_lockless(tsdn);
2010 	return (ret);
2011 }
2012 
2013 JEMALLOC_EXPORT void JEMALLOC_NOTHROW
2014 je_free(void *ptr)
2015 {
2016 
2017 	UTRACE(ptr, 0, 0);
2018 	if (likely(ptr != NULL)) {
2019 		tsd_t *tsd = tsd_fetch();
2020 		witness_assert_lockless(tsd_tsdn(tsd));
2021 		if (likely(!malloc_slow))
2022 			ifree(tsd, ptr, tcache_get(tsd, false), false);
2023 		else
2024 			ifree(tsd, ptr, tcache_get(tsd, false), true);
2025 		witness_assert_lockless(tsd_tsdn(tsd));
2026 	}
2027 }
2028 
2029 /*
2030  * End malloc(3)-compatible functions.
2031  */
2032 /******************************************************************************/
2033 /*
2034  * Begin non-standard override functions.
2035  */
2036 
2037 #ifdef JEMALLOC_OVERRIDE_MEMALIGN
2038 JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
2039 void JEMALLOC_NOTHROW *
2040 JEMALLOC_ATTR(malloc)
2041 je_memalign(size_t alignment, size_t size)
2042 {
2043 	void *ret JEMALLOC_CC_SILENCE_INIT(NULL);
2044 	if (unlikely(imemalign(&ret, alignment, size, 1) != 0))
2045 		ret = NULL;
2046 	return (ret);
2047 }
2048 #endif
2049 
2050 #ifdef JEMALLOC_OVERRIDE_VALLOC
2051 JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
2052 void JEMALLOC_NOTHROW *
2053 JEMALLOC_ATTR(malloc)
2054 je_valloc(size_t size)
2055 {
2056 	void *ret JEMALLOC_CC_SILENCE_INIT(NULL);
2057 	if (unlikely(imemalign(&ret, PAGE, size, 1) != 0))
2058 		ret = NULL;
2059 	return (ret);
2060 }
2061 #endif
2062 
2063 /*
2064  * is_malloc(je_malloc) is some macro magic to detect if jemalloc_defs.h has
2065  * #define je_malloc malloc
2066  */
2067 #define	malloc_is_malloc 1
2068 #define	is_malloc_(a) malloc_is_ ## a
2069 #define	is_malloc(a) is_malloc_(a)
2070 
2071 #if ((is_malloc(je_malloc) == 1) && defined(JEMALLOC_GLIBC_MALLOC_HOOK))
2072 /*
2073  * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible
2074  * to inconsistently reference libc's malloc(3)-compatible functions
2075  * (https://bugzilla.mozilla.org/show_bug.cgi?id=493541).
2076  *
2077  * These definitions interpose hooks in glibc.  The functions are actually
2078  * passed an extra argument for the caller return address, which will be
2079  * ignored.
2080  */
2081 JEMALLOC_EXPORT void (*__free_hook)(void *ptr) = je_free;
2082 JEMALLOC_EXPORT void *(*__malloc_hook)(size_t size) = je_malloc;
2083 JEMALLOC_EXPORT void *(*__realloc_hook)(void *ptr, size_t size) = je_realloc;
2084 # ifdef JEMALLOC_GLIBC_MEMALIGN_HOOK
2085 JEMALLOC_EXPORT void *(*__memalign_hook)(size_t alignment, size_t size) =
2086     je_memalign;
2087 # endif
2088 
2089 #ifdef CPU_COUNT
2090 /*
2091  * To enable static linking with glibc, the libc specific malloc interface must
2092  * be implemented also, so none of glibc's malloc.o functions are added to the
2093  * link.
2094  */
2095 #define	ALIAS(je_fn)	__attribute__((alias (#je_fn), used))
2096 /* To force macro expansion of je_ prefix before stringification. */
2097 #define	PREALIAS(je_fn)  ALIAS(je_fn)
2098 void	*__libc_malloc(size_t size) PREALIAS(je_malloc);
2099 void	__libc_free(void* ptr) PREALIAS(je_free);
2100 void	*__libc_realloc(void* ptr, size_t size) PREALIAS(je_realloc);
2101 void	*__libc_calloc(size_t n, size_t size) PREALIAS(je_calloc);
2102 void	*__libc_memalign(size_t align, size_t s) PREALIAS(je_memalign);
2103 void	*__libc_valloc(size_t size) PREALIAS(je_valloc);
2104 int	__posix_memalign(void** r, size_t a, size_t s)
2105     PREALIAS(je_posix_memalign);
2106 #undef PREALIAS
2107 #undef ALIAS
2108 
2109 #endif
2110 
2111 #endif
2112 
2113 /*
2114  * End non-standard override functions.
2115  */
2116 /******************************************************************************/
2117 /*
2118  * Begin non-standard functions.
2119  */
2120 
2121 JEMALLOC_ALWAYS_INLINE_C bool
2122 imallocx_flags_decode(tsd_t *tsd, size_t size, int flags, size_t *usize,
2123     size_t *alignment, bool *zero, tcache_t **tcache, arena_t **arena)
2124 {
2125 
2126 	if ((flags & MALLOCX_LG_ALIGN_MASK) == 0) {
2127 		*alignment = 0;
2128 		*usize = s2u(size);
2129 	} else {
2130 		*alignment = MALLOCX_ALIGN_GET_SPECIFIED(flags);
2131 		*usize = sa2u(size, *alignment);
2132 	}
2133 	if (unlikely(*usize == 0 || *usize > HUGE_MAXCLASS))
2134 		return (true);
2135 	*zero = MALLOCX_ZERO_GET(flags);
2136 	if ((flags & MALLOCX_TCACHE_MASK) != 0) {
2137 		if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE)
2138 			*tcache = NULL;
2139 		else
2140 			*tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));
2141 	} else
2142 		*tcache = tcache_get(tsd, true);
2143 	if ((flags & MALLOCX_ARENA_MASK) != 0) {
2144 		unsigned arena_ind = MALLOCX_ARENA_GET(flags);
2145 		*arena = arena_get(tsd_tsdn(tsd), arena_ind, true);
2146 		if (unlikely(*arena == NULL))
2147 			return (true);
2148 	} else
2149 		*arena = NULL;
2150 	return (false);
2151 }
2152 
2153 JEMALLOC_ALWAYS_INLINE_C void *
2154 imallocx_flags(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero,
2155     tcache_t *tcache, arena_t *arena, bool slow_path)
2156 {
2157 	szind_t ind;
2158 
2159 	if (unlikely(alignment != 0))
2160 		return (ipalloct(tsdn, usize, alignment, zero, tcache, arena));
2161 	ind = size2index(usize);
2162 	assert(ind < NSIZES);
2163 	return (iallocztm(tsdn, usize, ind, zero, tcache, false, arena,
2164 	    slow_path));
2165 }
2166 
2167 static void *
2168 imallocx_prof_sample(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero,
2169     tcache_t *tcache, arena_t *arena, bool slow_path)
2170 {
2171 	void *p;
2172 
2173 	if (usize <= SMALL_MAXCLASS) {
2174 		assert(((alignment == 0) ? s2u(LARGE_MINCLASS) :
2175 		    sa2u(LARGE_MINCLASS, alignment)) == LARGE_MINCLASS);
2176 		p = imallocx_flags(tsdn, LARGE_MINCLASS, alignment, zero,
2177 		    tcache, arena, slow_path);
2178 		if (p == NULL)
2179 			return (NULL);
2180 		arena_prof_promoted(tsdn, p, usize);
2181 	} else {
2182 		p = imallocx_flags(tsdn, usize, alignment, zero, tcache, arena,
2183 		    slow_path);
2184 	}
2185 
2186 	return (p);
2187 }
2188 
2189 JEMALLOC_ALWAYS_INLINE_C void *
2190 imallocx_prof(tsd_t *tsd, size_t size, int flags, size_t *usize, bool slow_path)
2191 {
2192 	void *p;
2193 	size_t alignment;
2194 	bool zero;
2195 	tcache_t *tcache;
2196 	arena_t *arena;
2197 	prof_tctx_t *tctx;
2198 
2199 	if (unlikely(imallocx_flags_decode(tsd, size, flags, usize, &alignment,
2200 	    &zero, &tcache, &arena)))
2201 		return (NULL);
2202 	tctx = prof_alloc_prep(tsd, *usize, prof_active_get_unlocked(), true);
2203 	if (likely((uintptr_t)tctx == (uintptr_t)1U)) {
2204 		p = imallocx_flags(tsd_tsdn(tsd), *usize, alignment, zero,
2205 		    tcache, arena, slow_path);
2206 	} else if ((uintptr_t)tctx > (uintptr_t)1U) {
2207 		p = imallocx_prof_sample(tsd_tsdn(tsd), *usize, alignment, zero,
2208 		    tcache, arena, slow_path);
2209 	} else
2210 		p = NULL;
2211 	if (unlikely(p == NULL)) {
2212 		prof_alloc_rollback(tsd, tctx, true);
2213 		return (NULL);
2214 	}
2215 	prof_malloc(tsd_tsdn(tsd), p, *usize, tctx);
2216 
2217 	assert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0));
2218 	return (p);
2219 }
2220 
2221 JEMALLOC_ALWAYS_INLINE_C void *
2222 imallocx_no_prof(tsd_t *tsd, size_t size, int flags, size_t *usize,
2223     bool slow_path)
2224 {
2225 	void *p;
2226 	size_t alignment;
2227 	bool zero;
2228 	tcache_t *tcache;
2229 	arena_t *arena;
2230 
2231 	if (unlikely(imallocx_flags_decode(tsd, size, flags, usize, &alignment,
2232 	    &zero, &tcache, &arena)))
2233 		return (NULL);
2234 	p = imallocx_flags(tsd_tsdn(tsd), *usize, alignment, zero, tcache,
2235 	    arena, slow_path);
2236 	assert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0));
2237 	return (p);
2238 }
2239 
2240 /* This function guarantees that *tsdn is non-NULL on success. */
2241 JEMALLOC_ALWAYS_INLINE_C void *
2242 imallocx_body(size_t size, int flags, tsdn_t **tsdn, size_t *usize,
2243     bool slow_path)
2244 {
2245 	tsd_t *tsd;
2246 
2247 	if (slow_path && unlikely(malloc_init())) {
2248 		*tsdn = NULL;
2249 		return (NULL);
2250 	}
2251 
2252 	tsd = tsd_fetch();
2253 	*tsdn = tsd_tsdn(tsd);
2254 	witness_assert_lockless(tsd_tsdn(tsd));
2255 
2256 	if (likely(flags == 0)) {
2257 		szind_t ind = size2index(size);
2258 		if (unlikely(ind >= NSIZES))
2259 			return (NULL);
2260 		if (config_stats || (config_prof && opt_prof) || (slow_path &&
2261 		    config_valgrind && unlikely(in_valgrind))) {
2262 			*usize = index2size(ind);
2263 			assert(*usize > 0 && *usize <= HUGE_MAXCLASS);
2264 		}
2265 
2266 		if (config_prof && opt_prof) {
2267 			return (ialloc_prof(tsd, *usize, ind, false,
2268 			    slow_path));
2269 		}
2270 
2271 		return (ialloc(tsd, size, ind, false, slow_path));
2272 	}
2273 
2274 	if (config_prof && opt_prof)
2275 		return (imallocx_prof(tsd, size, flags, usize, slow_path));
2276 
2277 	return (imallocx_no_prof(tsd, size, flags, usize, slow_path));
2278 }
2279 
2280 JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
2281 void JEMALLOC_NOTHROW *
2282 JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1)
2283 je_mallocx(size_t size, int flags)
2284 {
2285 	tsdn_t *tsdn;
2286 	void *p;
2287 	size_t usize;
2288 
2289 	assert(size != 0);
2290 
2291 	if (likely(!malloc_slow)) {
2292 		p = imallocx_body(size, flags, &tsdn, &usize, false);
2293 		ialloc_post_check(p, tsdn, usize, "mallocx", false, false);
2294 	} else {
2295 		p = imallocx_body(size, flags, &tsdn, &usize, true);
2296 		ialloc_post_check(p, tsdn, usize, "mallocx", false, true);
2297 		UTRACE(0, size, p);
2298 		JEMALLOC_VALGRIND_MALLOC(p != NULL, tsdn, p, usize,
2299 		    MALLOCX_ZERO_GET(flags));
2300 	}
2301 
2302 	return (p);
2303 }
2304 
2305 static void *
2306 irallocx_prof_sample(tsd_t *tsd, void *old_ptr, size_t old_usize,
2307     size_t usize, size_t alignment, bool zero, tcache_t *tcache, arena_t *arena,
2308     prof_tctx_t *tctx)
2309 {
2310 	void *p;
2311 
2312 	if (tctx == NULL)
2313 		return (NULL);
2314 	if (usize <= SMALL_MAXCLASS) {
2315 		p = iralloct(tsd, old_ptr, old_usize, LARGE_MINCLASS, alignment,
2316 		    zero, tcache, arena);
2317 		if (p == NULL)
2318 			return (NULL);
2319 		arena_prof_promoted(tsd_tsdn(tsd), p, usize);
2320 	} else {
2321 		p = iralloct(tsd, old_ptr, old_usize, usize, alignment, zero,
2322 		    tcache, arena);
2323 	}
2324 
2325 	return (p);
2326 }
2327 
2328 JEMALLOC_ALWAYS_INLINE_C void *
2329 irallocx_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t size,
2330     size_t alignment, size_t *usize, bool zero, tcache_t *tcache,
2331     arena_t *arena)
2332 {
2333 	void *p;
2334 	bool prof_active;
2335 	prof_tctx_t *old_tctx, *tctx;
2336 
2337 	prof_active = prof_active_get_unlocked();
2338 	old_tctx = prof_tctx_get(tsd_tsdn(tsd), old_ptr);
2339 	tctx = prof_alloc_prep(tsd, *usize, prof_active, false);
2340 	if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) {
2341 		p = irallocx_prof_sample(tsd, old_ptr, old_usize, *usize,
2342 		    alignment, zero, tcache, arena, tctx);
2343 	} else {
2344 		p = iralloct(tsd, old_ptr, old_usize, size, alignment, zero,
2345 		    tcache, arena);
2346 	}
2347 	if (unlikely(p == NULL)) {
2348 		prof_alloc_rollback(tsd, tctx, false);
2349 		return (NULL);
2350 	}
2351 
2352 	if (p == old_ptr && alignment != 0) {
2353 		/*
2354 		 * The allocation did not move, so it is possible that the size
2355 		 * class is smaller than would guarantee the requested
2356 		 * alignment, and that the alignment constraint was
2357 		 * serendipitously satisfied.  Additionally, old_usize may not
2358 		 * be the same as the current usize because of in-place large
2359 		 * reallocation.  Therefore, query the actual value of usize.
2360 		 */
2361 		*usize = isalloc(tsd_tsdn(tsd), p, config_prof);
2362 	}
2363 	prof_realloc(tsd, p, *usize, tctx, prof_active, false, old_ptr,
2364 	    old_usize, old_tctx);
2365 
2366 	return (p);
2367 }
2368 
2369 JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
2370 void JEMALLOC_NOTHROW *
2371 JEMALLOC_ALLOC_SIZE(2)
2372 je_rallocx(void *ptr, size_t size, int flags)
2373 {
2374 	void *p;
2375 	tsd_t *tsd;
2376 	size_t usize;
2377 	size_t old_usize;
2378 	UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);
2379 	size_t alignment = MALLOCX_ALIGN_GET(flags);
2380 	bool zero = flags & MALLOCX_ZERO;
2381 	arena_t *arena;
2382 	tcache_t *tcache;
2383 
2384 	assert(ptr != NULL);
2385 	assert(size != 0);
2386 	assert(malloc_initialized() || IS_INITIALIZER);
2387 	malloc_thread_init();
2388 	tsd = tsd_fetch();
2389 	witness_assert_lockless(tsd_tsdn(tsd));
2390 
2391 	if (unlikely((flags & MALLOCX_ARENA_MASK) != 0)) {
2392 		unsigned arena_ind = MALLOCX_ARENA_GET(flags);
2393 		arena = arena_get(tsd_tsdn(tsd), arena_ind, true);
2394 		if (unlikely(arena == NULL))
2395 			goto label_oom;
2396 	} else
2397 		arena = NULL;
2398 
2399 	if (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) {
2400 		if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE)
2401 			tcache = NULL;
2402 		else
2403 			tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));
2404 	} else
2405 		tcache = tcache_get(tsd, true);
2406 
2407 	old_usize = isalloc(tsd_tsdn(tsd), ptr, config_prof);
2408 	if (config_valgrind && unlikely(in_valgrind))
2409 		old_rzsize = u2rz(old_usize);
2410 
2411 	if (config_prof && opt_prof) {
2412 		usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);
2413 		if (unlikely(usize == 0 || usize > HUGE_MAXCLASS))
2414 			goto label_oom;
2415 		p = irallocx_prof(tsd, ptr, old_usize, size, alignment, &usize,
2416 		    zero, tcache, arena);
2417 		if (unlikely(p == NULL))
2418 			goto label_oom;
2419 	} else {
2420 		p = iralloct(tsd, ptr, old_usize, size, alignment, zero,
2421 		     tcache, arena);
2422 		if (unlikely(p == NULL))
2423 			goto label_oom;
2424 		if (config_stats || (config_valgrind && unlikely(in_valgrind)))
2425 			usize = isalloc(tsd_tsdn(tsd), p, config_prof);
2426 	}
2427 	assert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0));
2428 
2429 	if (config_stats) {
2430 		*tsd_thread_allocatedp_get(tsd) += usize;
2431 		*tsd_thread_deallocatedp_get(tsd) += old_usize;
2432 	}
2433 	UTRACE(ptr, size, p);
2434 	JEMALLOC_VALGRIND_REALLOC(maybe, tsd_tsdn(tsd), p, usize, no, ptr,
2435 	    old_usize, old_rzsize, no, zero);
2436 	witness_assert_lockless(tsd_tsdn(tsd));
2437 	return (p);
2438 label_oom:
2439 	if (config_xmalloc && unlikely(opt_xmalloc)) {
2440 		malloc_write("<jemalloc>: Error in rallocx(): out of memory\n");
2441 		abort();
2442 	}
2443 	UTRACE(ptr, size, 0);
2444 	witness_assert_lockless(tsd_tsdn(tsd));
2445 	return (NULL);
2446 }
2447 
2448 JEMALLOC_ALWAYS_INLINE_C size_t
2449 ixallocx_helper(tsdn_t *tsdn, void *ptr, size_t old_usize, size_t size,
2450     size_t extra, size_t alignment, bool zero)
2451 {
2452 	size_t usize;
2453 
2454 	if (ixalloc(tsdn, ptr, old_usize, size, extra, alignment, zero))
2455 		return (old_usize);
2456 	usize = isalloc(tsdn, ptr, config_prof);
2457 
2458 	return (usize);
2459 }
2460 
2461 static size_t
2462 ixallocx_prof_sample(tsdn_t *tsdn, void *ptr, size_t old_usize, size_t size,
2463     size_t extra, size_t alignment, bool zero, prof_tctx_t *tctx)
2464 {
2465 	size_t usize;
2466 
2467 	if (tctx == NULL)
2468 		return (old_usize);
2469 	usize = ixallocx_helper(tsdn, ptr, old_usize, size, extra, alignment,
2470 	    zero);
2471 
2472 	return (usize);
2473 }
2474 
2475 JEMALLOC_ALWAYS_INLINE_C size_t
2476 ixallocx_prof(tsd_t *tsd, void *ptr, size_t old_usize, size_t size,
2477     size_t extra, size_t alignment, bool zero)
2478 {
2479 	size_t usize_max, usize;
2480 	bool prof_active;
2481 	prof_tctx_t *old_tctx, *tctx;
2482 
2483 	prof_active = prof_active_get_unlocked();
2484 	old_tctx = prof_tctx_get(tsd_tsdn(tsd), ptr);
2485 	/*
2486 	 * usize isn't knowable before ixalloc() returns when extra is non-zero.
2487 	 * Therefore, compute its maximum possible value and use that in
2488 	 * prof_alloc_prep() to decide whether to capture a backtrace.
2489 	 * prof_realloc() will use the actual usize to decide whether to sample.
2490 	 */
2491 	if (alignment == 0) {
2492 		usize_max = s2u(size+extra);
2493 		assert(usize_max > 0 && usize_max <= HUGE_MAXCLASS);
2494 	} else {
2495 		usize_max = sa2u(size+extra, alignment);
2496 		if (unlikely(usize_max == 0 || usize_max > HUGE_MAXCLASS)) {
2497 			/*
2498 			 * usize_max is out of range, and chances are that
2499 			 * allocation will fail, but use the maximum possible
2500 			 * value and carry on with prof_alloc_prep(), just in
2501 			 * case allocation succeeds.
2502 			 */
2503 			usize_max = HUGE_MAXCLASS;
2504 		}
2505 	}
2506 	tctx = prof_alloc_prep(tsd, usize_max, prof_active, false);
2507 
2508 	if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) {
2509 		usize = ixallocx_prof_sample(tsd_tsdn(tsd), ptr, old_usize,
2510 		    size, extra, alignment, zero, tctx);
2511 	} else {
2512 		usize = ixallocx_helper(tsd_tsdn(tsd), ptr, old_usize, size,
2513 		    extra, alignment, zero);
2514 	}
2515 	if (usize == old_usize) {
2516 		prof_alloc_rollback(tsd, tctx, false);
2517 		return (usize);
2518 	}
2519 	prof_realloc(tsd, ptr, usize, tctx, prof_active, false, ptr, old_usize,
2520 	    old_tctx);
2521 
2522 	return (usize);
2523 }
2524 
2525 JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW
2526 je_xallocx(void *ptr, size_t size, size_t extra, int flags)
2527 {
2528 	tsd_t *tsd;
2529 	size_t usize, old_usize;
2530 	UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);
2531 	size_t alignment = MALLOCX_ALIGN_GET(flags);
2532 	bool zero = flags & MALLOCX_ZERO;
2533 
2534 	assert(ptr != NULL);
2535 	assert(size != 0);
2536 	assert(SIZE_T_MAX - size >= extra);
2537 	assert(malloc_initialized() || IS_INITIALIZER);
2538 	malloc_thread_init();
2539 	tsd = tsd_fetch();
2540 	witness_assert_lockless(tsd_tsdn(tsd));
2541 
2542 	old_usize = isalloc(tsd_tsdn(tsd), ptr, config_prof);
2543 
2544 	/*
2545 	 * The API explicitly absolves itself of protecting against (size +
2546 	 * extra) numerical overflow, but we may need to clamp extra to avoid
2547 	 * exceeding HUGE_MAXCLASS.
2548 	 *
2549 	 * Ordinarily, size limit checking is handled deeper down, but here we
2550 	 * have to check as part of (size + extra) clamping, since we need the
2551 	 * clamped value in the above helper functions.
2552 	 */
2553 	if (unlikely(size > HUGE_MAXCLASS)) {
2554 		usize = old_usize;
2555 		goto label_not_resized;
2556 	}
2557 	if (unlikely(HUGE_MAXCLASS - size < extra))
2558 		extra = HUGE_MAXCLASS - size;
2559 
2560 	if (config_valgrind && unlikely(in_valgrind))
2561 		old_rzsize = u2rz(old_usize);
2562 
2563 	if (config_prof && opt_prof) {
2564 		usize = ixallocx_prof(tsd, ptr, old_usize, size, extra,
2565 		    alignment, zero);
2566 	} else {
2567 		usize = ixallocx_helper(tsd_tsdn(tsd), ptr, old_usize, size,
2568 		    extra, alignment, zero);
2569 	}
2570 	if (unlikely(usize == old_usize))
2571 		goto label_not_resized;
2572 
2573 	if (config_stats) {
2574 		*tsd_thread_allocatedp_get(tsd) += usize;
2575 		*tsd_thread_deallocatedp_get(tsd) += old_usize;
2576 	}
2577 	JEMALLOC_VALGRIND_REALLOC(no, tsd_tsdn(tsd), ptr, usize, no, ptr,
2578 	    old_usize, old_rzsize, no, zero);
2579 label_not_resized:
2580 	UTRACE(ptr, size, ptr);
2581 	witness_assert_lockless(tsd_tsdn(tsd));
2582 	return (usize);
2583 }
2584 
2585 JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW
2586 JEMALLOC_ATTR(pure)
2587 je_sallocx(const void *ptr, int flags)
2588 {
2589 	size_t usize;
2590 	tsdn_t *tsdn;
2591 
2592 	assert(malloc_initialized() || IS_INITIALIZER);
2593 	malloc_thread_init();
2594 
2595 	tsdn = tsdn_fetch();
2596 	witness_assert_lockless(tsdn);
2597 
2598 	if (config_ivsalloc)
2599 		usize = ivsalloc(tsdn, ptr, config_prof);
2600 	else
2601 		usize = isalloc(tsdn, ptr, config_prof);
2602 
2603 	witness_assert_lockless(tsdn);
2604 	return (usize);
2605 }
2606 
2607 JEMALLOC_EXPORT void JEMALLOC_NOTHROW
2608 je_dallocx(void *ptr, int flags)
2609 {
2610 	tsd_t *tsd;
2611 	tcache_t *tcache;
2612 
2613 	assert(ptr != NULL);
2614 	assert(malloc_initialized() || IS_INITIALIZER);
2615 
2616 	tsd = tsd_fetch();
2617 	witness_assert_lockless(tsd_tsdn(tsd));
2618 	if (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) {
2619 		if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE)
2620 			tcache = NULL;
2621 		else
2622 			tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));
2623 	} else
2624 		tcache = tcache_get(tsd, false);
2625 
2626 	UTRACE(ptr, 0, 0);
2627 	if (likely(!malloc_slow))
2628 		ifree(tsd, ptr, tcache, false);
2629 	else
2630 		ifree(tsd, ptr, tcache, true);
2631 	witness_assert_lockless(tsd_tsdn(tsd));
2632 }
2633 
2634 JEMALLOC_ALWAYS_INLINE_C size_t
2635 inallocx(tsdn_t *tsdn, size_t size, int flags)
2636 {
2637 	size_t usize;
2638 
2639 	witness_assert_lockless(tsdn);
2640 
2641 	if (likely((flags & MALLOCX_LG_ALIGN_MASK) == 0))
2642 		usize = s2u(size);
2643 	else
2644 		usize = sa2u(size, MALLOCX_ALIGN_GET_SPECIFIED(flags));
2645 	witness_assert_lockless(tsdn);
2646 	return (usize);
2647 }
2648 
2649 JEMALLOC_EXPORT void JEMALLOC_NOTHROW
2650 je_sdallocx(void *ptr, size_t size, int flags)
2651 {
2652 	tsd_t *tsd;
2653 	tcache_t *tcache;
2654 	size_t usize;
2655 
2656 	assert(ptr != NULL);
2657 	assert(malloc_initialized() || IS_INITIALIZER);
2658 	tsd = tsd_fetch();
2659 	usize = inallocx(tsd_tsdn(tsd), size, flags);
2660 	assert(usize == isalloc(tsd_tsdn(tsd), ptr, config_prof));
2661 
2662 	witness_assert_lockless(tsd_tsdn(tsd));
2663 	if (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) {
2664 		if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE)
2665 			tcache = NULL;
2666 		else
2667 			tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));
2668 	} else
2669 		tcache = tcache_get(tsd, false);
2670 
2671 	UTRACE(ptr, 0, 0);
2672 	if (likely(!malloc_slow))
2673 		isfree(tsd, ptr, usize, tcache, false);
2674 	else
2675 		isfree(tsd, ptr, usize, tcache, true);
2676 	witness_assert_lockless(tsd_tsdn(tsd));
2677 }
2678 
2679 JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW
2680 JEMALLOC_ATTR(pure)
2681 je_nallocx(size_t size, int flags)
2682 {
2683 	size_t usize;
2684 	tsdn_t *tsdn;
2685 
2686 	assert(size != 0);
2687 
2688 	if (unlikely(malloc_init()))
2689 		return (0);
2690 
2691 	tsdn = tsdn_fetch();
2692 	witness_assert_lockless(tsdn);
2693 
2694 	usize = inallocx(tsdn, size, flags);
2695 	if (unlikely(usize > HUGE_MAXCLASS))
2696 		return (0);
2697 
2698 	witness_assert_lockless(tsdn);
2699 	return (usize);
2700 }
2701 
2702 JEMALLOC_EXPORT int JEMALLOC_NOTHROW
2703 je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp,
2704     size_t newlen)
2705 {
2706 	int ret;
2707 	tsd_t *tsd;
2708 
2709 	if (unlikely(malloc_init()))
2710 		return (EAGAIN);
2711 
2712 	tsd = tsd_fetch();
2713 	witness_assert_lockless(tsd_tsdn(tsd));
2714 	ret = ctl_byname(tsd, name, oldp, oldlenp, newp, newlen);
2715 	witness_assert_lockless(tsd_tsdn(tsd));
2716 	return (ret);
2717 }
2718 
2719 JEMALLOC_EXPORT int JEMALLOC_NOTHROW
2720 je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp)
2721 {
2722 	int ret;
2723 	tsdn_t *tsdn;
2724 
2725 	if (unlikely(malloc_init()))
2726 		return (EAGAIN);
2727 
2728 	tsdn = tsdn_fetch();
2729 	witness_assert_lockless(tsdn);
2730 	ret = ctl_nametomib(tsdn, name, mibp, miblenp);
2731 	witness_assert_lockless(tsdn);
2732 	return (ret);
2733 }
2734 
2735 JEMALLOC_EXPORT int JEMALLOC_NOTHROW
2736 je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
2737   void *newp, size_t newlen)
2738 {
2739 	int ret;
2740 	tsd_t *tsd;
2741 
2742 	if (unlikely(malloc_init()))
2743 		return (EAGAIN);
2744 
2745 	tsd = tsd_fetch();
2746 	witness_assert_lockless(tsd_tsdn(tsd));
2747 	ret = ctl_bymib(tsd, mib, miblen, oldp, oldlenp, newp, newlen);
2748 	witness_assert_lockless(tsd_tsdn(tsd));
2749 	return (ret);
2750 }
2751 
2752 JEMALLOC_EXPORT void JEMALLOC_NOTHROW
2753 je_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
2754     const char *opts)
2755 {
2756 	tsdn_t *tsdn;
2757 
2758 	tsdn = tsdn_fetch();
2759 	witness_assert_lockless(tsdn);
2760 	stats_print(write_cb, cbopaque, opts);
2761 	witness_assert_lockless(tsdn);
2762 }
2763 
2764 JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW
2765 je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)
2766 {
2767 	size_t ret;
2768 	tsdn_t *tsdn;
2769 
2770 	assert(malloc_initialized() || IS_INITIALIZER);
2771 	malloc_thread_init();
2772 
2773 	tsdn = tsdn_fetch();
2774 	witness_assert_lockless(tsdn);
2775 
2776 	if (config_ivsalloc)
2777 		ret = ivsalloc(tsdn, ptr, config_prof);
2778 	else
2779 		ret = (ptr == NULL) ? 0 : isalloc(tsdn, ptr, config_prof);
2780 
2781 	witness_assert_lockless(tsdn);
2782 	return (ret);
2783 }
2784 
2785 /*
2786  * End non-standard functions.
2787  */
2788 /******************************************************************************/
2789 /*
2790  * The following functions are used by threading libraries for protection of
2791  * malloc during fork().
2792  */
2793 
2794 /*
2795  * If an application creates a thread before doing any allocation in the main
2796  * thread, then calls fork(2) in the main thread followed by memory allocation
2797  * in the child process, a race can occur that results in deadlock within the
2798  * child: the main thread may have forked while the created thread had
2799  * partially initialized the allocator.  Ordinarily jemalloc prevents
2800  * fork/malloc races via the following functions it registers during
2801  * initialization using pthread_atfork(), but of course that does no good if
2802  * the allocator isn't fully initialized at fork time.  The following library
2803  * constructor is a partial solution to this problem.  It may still be possible
2804  * to trigger the deadlock described above, but doing so would involve forking
2805  * via a library constructor that runs before jemalloc's runs.
2806  */
2807 #ifndef JEMALLOC_JET
2808 JEMALLOC_ATTR(constructor)
2809 static void
2810 jemalloc_constructor(void)
2811 {
2812 
2813 	malloc_init();
2814 }
2815 #endif
2816 
2817 #ifndef JEMALLOC_MUTEX_INIT_CB
2818 void
2819 jemalloc_prefork(void)
2820 #else
2821 JEMALLOC_EXPORT void
2822 _malloc_prefork(void)
2823 #endif
2824 {
2825 	tsd_t *tsd;
2826 	unsigned i, j, narenas;
2827 	arena_t *arena;
2828 
2829 #ifdef JEMALLOC_MUTEX_INIT_CB
2830 	if (!malloc_initialized())
2831 		return;
2832 #endif
2833 	assert(malloc_initialized());
2834 
2835 	tsd = tsd_fetch();
2836 
2837 	narenas = narenas_total_get();
2838 
2839 	witness_prefork(tsd);
2840 	/* Acquire all mutexes in a safe order. */
2841 	ctl_prefork(tsd_tsdn(tsd));
2842 	tcache_prefork(tsd_tsdn(tsd));
2843 	malloc_mutex_prefork(tsd_tsdn(tsd), &arenas_lock);
2844 	prof_prefork0(tsd_tsdn(tsd));
2845 	for (i = 0; i < 3; i++) {
2846 		for (j = 0; j < narenas; j++) {
2847 			if ((arena = arena_get(tsd_tsdn(tsd), j, false)) !=
2848 			    NULL) {
2849 				switch (i) {
2850 				case 0:
2851 					arena_prefork0(tsd_tsdn(tsd), arena);
2852 					break;
2853 				case 1:
2854 					arena_prefork1(tsd_tsdn(tsd), arena);
2855 					break;
2856 				case 2:
2857 					arena_prefork2(tsd_tsdn(tsd), arena);
2858 					break;
2859 				default: not_reached();
2860 				}
2861 			}
2862 		}
2863 	}
2864 	base_prefork(tsd_tsdn(tsd));
2865 	for (i = 0; i < narenas; i++) {
2866 		if ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL)
2867 			arena_prefork3(tsd_tsdn(tsd), arena);
2868 	}
2869 	prof_prefork1(tsd_tsdn(tsd));
2870 }
2871 
2872 #ifndef JEMALLOC_MUTEX_INIT_CB
2873 void
2874 jemalloc_postfork_parent(void)
2875 #else
2876 JEMALLOC_EXPORT void
2877 _malloc_postfork(void)
2878 #endif
2879 {
2880 	tsd_t *tsd;
2881 	unsigned i, narenas;
2882 
2883 #ifdef JEMALLOC_MUTEX_INIT_CB
2884 	if (!malloc_initialized())
2885 		return;
2886 #endif
2887 	assert(malloc_initialized());
2888 
2889 	tsd = tsd_fetch();
2890 
2891 	witness_postfork_parent(tsd);
2892 	/* Release all mutexes, now that fork() has completed. */
2893 	base_postfork_parent(tsd_tsdn(tsd));
2894 	for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
2895 		arena_t *arena;
2896 
2897 		if ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL)
2898 			arena_postfork_parent(tsd_tsdn(tsd), arena);
2899 	}
2900 	prof_postfork_parent(tsd_tsdn(tsd));
2901 	malloc_mutex_postfork_parent(tsd_tsdn(tsd), &arenas_lock);
2902 	tcache_postfork_parent(tsd_tsdn(tsd));
2903 	ctl_postfork_parent(tsd_tsdn(tsd));
2904 }
2905 
2906 void
2907 jemalloc_postfork_child(void)
2908 {
2909 	tsd_t *tsd;
2910 	unsigned i, narenas;
2911 
2912 	assert(malloc_initialized());
2913 
2914 	tsd = tsd_fetch();
2915 
2916 	witness_postfork_child(tsd);
2917 	/* Release all mutexes, now that fork() has completed. */
2918 	base_postfork_child(tsd_tsdn(tsd));
2919 	for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
2920 		arena_t *arena;
2921 
2922 		if ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL)
2923 			arena_postfork_child(tsd_tsdn(tsd), arena);
2924 	}
2925 	prof_postfork_child(tsd_tsdn(tsd));
2926 	malloc_mutex_postfork_child(tsd_tsdn(tsd), &arenas_lock);
2927 	tcache_postfork_child(tsd_tsdn(tsd));
2928 	ctl_postfork_child(tsd_tsdn(tsd));
2929 }
2930 
2931 /******************************************************************************/
2932 
2933 /* ANDROID extension */
2934 #include "android_je_iterate.c"
2935 #include "android_je_mallinfo.c"
2936 /* End ANDROID extension */
2937