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