jemalloc.c revision ecd3e59ca351d7111ec72a327fe0c009f2aa69a0
1#define	JEMALLOC_C_
2#include "jemalloc/internal/jemalloc_internal.h"
3
4/******************************************************************************/
5/* Data. */
6
7malloc_tsd_data(, arenas, arena_t *, NULL)
8malloc_tsd_data(, thread_allocated, thread_allocated_t,
9    THREAD_ALLOCATED_INITIALIZER)
10
11/* Runtime configuration options. */
12const char	*je_malloc_conf;
13bool	opt_abort =
14#ifdef JEMALLOC_DEBUG
15    true
16#else
17    false
18#endif
19    ;
20bool	opt_junk =
21#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))
22    true
23#else
24    false
25#endif
26    ;
27size_t	opt_quarantine = ZU(0);
28bool	opt_redzone = false;
29bool	opt_utrace = false;
30bool	opt_xmalloc = false;
31bool	opt_zero = false;
32size_t	opt_narenas = 0;
33
34/* Initialized to true if the process is running inside Valgrind. */
35bool	in_valgrind;
36
37unsigned	ncpus;
38
39malloc_mutex_t		arenas_lock;
40arena_t			**arenas;
41unsigned		narenas_total;
42unsigned		narenas_auto;
43
44/* Set to true once the allocator has been initialized. */
45static bool		malloc_initialized = false;
46
47#ifdef JEMALLOC_THREADED_INIT
48/* Used to let the initializing thread recursively allocate. */
49#  define NO_INITIALIZER	((unsigned long)0)
50#  define INITIALIZER		pthread_self()
51#  define IS_INITIALIZER	(malloc_initializer == pthread_self())
52static pthread_t		malloc_initializer = NO_INITIALIZER;
53#else
54#  define NO_INITIALIZER	false
55#  define INITIALIZER		true
56#  define IS_INITIALIZER	malloc_initializer
57static bool			malloc_initializer = NO_INITIALIZER;
58#endif
59
60/* Used to avoid initialization races. */
61#ifdef _WIN32
62static malloc_mutex_t	init_lock;
63
64JEMALLOC_ATTR(constructor)
65static void WINAPI
66_init_init_lock(void)
67{
68
69	malloc_mutex_init(&init_lock);
70}
71
72#ifdef _MSC_VER
73#  pragma section(".CRT$XCU", read)
74JEMALLOC_SECTION(".CRT$XCU") JEMALLOC_ATTR(used)
75static const void (WINAPI *init_init_lock)(void) = _init_init_lock;
76#endif
77
78#else
79static malloc_mutex_t	init_lock = MALLOC_MUTEX_INITIALIZER;
80#endif
81
82typedef struct {
83	void	*p;	/* Input pointer (as in realloc(p, s)). */
84	size_t	s;	/* Request size. */
85	void	*r;	/* Result pointer. */
86} malloc_utrace_t;
87
88#ifdef JEMALLOC_UTRACE
89#  define UTRACE(a, b, c) do {						\
90	if (opt_utrace) {						\
91		int utrace_serrno = errno;				\
92		malloc_utrace_t ut;					\
93		ut.p = (a);						\
94		ut.s = (b);						\
95		ut.r = (c);						\
96		utrace(&ut, sizeof(ut));				\
97		errno = utrace_serrno;					\
98	}								\
99} while (0)
100#else
101#  define UTRACE(a, b, c)
102#endif
103
104/******************************************************************************/
105/*
106 * Function prototypes for static functions that are referenced prior to
107 * definition.
108 */
109
110static bool	malloc_init_hard(void);
111
112/******************************************************************************/
113/*
114 * Begin miscellaneous support functions.
115 */
116
117/* Create a new arena and insert it into the arenas array at index ind. */
118arena_t *
119arenas_extend(unsigned ind)
120{
121	arena_t *ret;
122
123	ret = (arena_t *)base_alloc(sizeof(arena_t));
124	if (ret != NULL && arena_new(ret, ind) == false) {
125		arenas[ind] = ret;
126		return (ret);
127	}
128	/* Only reached if there is an OOM error. */
129
130	/*
131	 * OOM here is quite inconvenient to propagate, since dealing with it
132	 * would require a check for failure in the fast path.  Instead, punt
133	 * by using arenas[0].  In practice, this is an extremely unlikely
134	 * failure.
135	 */
136	malloc_write("<jemalloc>: Error initializing arena\n");
137	if (opt_abort)
138		abort();
139
140	return (arenas[0]);
141}
142
143/* Slow path, called only by choose_arena(). */
144arena_t *
145choose_arena_hard(void)
146{
147	arena_t *ret;
148
149	if (narenas_auto > 1) {
150		unsigned i, choose, first_null;
151
152		choose = 0;
153		first_null = narenas_auto;
154		malloc_mutex_lock(&arenas_lock);
155		assert(arenas[0] != NULL);
156		for (i = 1; i < narenas_auto; i++) {
157			if (arenas[i] != NULL) {
158				/*
159				 * Choose the first arena that has the lowest
160				 * number of threads assigned to it.
161				 */
162				if (arenas[i]->nthreads <
163				    arenas[choose]->nthreads)
164					choose = i;
165			} else if (first_null == narenas_auto) {
166				/*
167				 * Record the index of the first uninitialized
168				 * arena, in case all extant arenas are in use.
169				 *
170				 * NB: It is possible for there to be
171				 * discontinuities in terms of initialized
172				 * versus uninitialized arenas, due to the
173				 * "thread.arena" mallctl.
174				 */
175				first_null = i;
176			}
177		}
178
179		if (arenas[choose]->nthreads == 0
180		    || first_null == narenas_auto) {
181			/*
182			 * Use an unloaded arena, or the least loaded arena if
183			 * all arenas are already initialized.
184			 */
185			ret = arenas[choose];
186		} else {
187			/* Initialize a new arena. */
188			ret = arenas_extend(first_null);
189		}
190		ret->nthreads++;
191		malloc_mutex_unlock(&arenas_lock);
192	} else {
193		ret = arenas[0];
194		malloc_mutex_lock(&arenas_lock);
195		ret->nthreads++;
196		malloc_mutex_unlock(&arenas_lock);
197	}
198
199	arenas_tsd_set(&ret);
200
201	return (ret);
202}
203
204static void
205stats_print_atexit(void)
206{
207
208	if (config_tcache && config_stats) {
209		unsigned narenas, i;
210
211		/*
212		 * Merge stats from extant threads.  This is racy, since
213		 * individual threads do not lock when recording tcache stats
214		 * events.  As a consequence, the final stats may be slightly
215		 * out of date by the time they are reported, if other threads
216		 * continue to allocate.
217		 */
218		for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
219			arena_t *arena = arenas[i];
220			if (arena != NULL) {
221				tcache_t *tcache;
222
223				/*
224				 * tcache_stats_merge() locks bins, so if any
225				 * code is introduced that acquires both arena
226				 * and bin locks in the opposite order,
227				 * deadlocks may result.
228				 */
229				malloc_mutex_lock(&arena->lock);
230				ql_foreach(tcache, &arena->tcache_ql, link) {
231					tcache_stats_merge(tcache, arena);
232				}
233				malloc_mutex_unlock(&arena->lock);
234			}
235		}
236	}
237	je_malloc_stats_print(NULL, NULL, NULL);
238}
239
240/*
241 * End miscellaneous support functions.
242 */
243/******************************************************************************/
244/*
245 * Begin initialization functions.
246 */
247
248static unsigned
249malloc_ncpus(void)
250{
251	long result;
252
253#ifdef _WIN32
254	SYSTEM_INFO si;
255	GetSystemInfo(&si);
256	result = si.dwNumberOfProcessors;
257#else
258	result = sysconf(_SC_NPROCESSORS_ONLN);
259#endif
260	return ((result == -1) ? 1 : (unsigned)result);
261}
262
263void
264arenas_cleanup(void *arg)
265{
266	arena_t *arena = *(arena_t **)arg;
267
268	malloc_mutex_lock(&arenas_lock);
269	arena->nthreads--;
270	malloc_mutex_unlock(&arenas_lock);
271}
272
273JEMALLOC_ALWAYS_INLINE_C void
274malloc_thread_init(void)
275{
276
277	/*
278	 * TSD initialization can't be safely done as a side effect of
279	 * deallocation, because it is possible for a thread to do nothing but
280	 * deallocate its TLS data via free(), in which case writing to TLS
281	 * would cause write-after-free memory corruption.  The quarantine
282	 * facility *only* gets used as a side effect of deallocation, so make
283	 * a best effort attempt at initializing its TSD by hooking all
284	 * allocation events.
285	 */
286	if (config_fill && opt_quarantine)
287		quarantine_alloc_hook();
288}
289
290JEMALLOC_ALWAYS_INLINE_C bool
291malloc_init(void)
292{
293
294	if (malloc_initialized == false && malloc_init_hard())
295		return (true);
296	malloc_thread_init();
297
298	return (false);
299}
300
301static bool
302malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p,
303    char const **v_p, size_t *vlen_p)
304{
305	bool accept;
306	const char *opts = *opts_p;
307
308	*k_p = opts;
309
310	for (accept = false; accept == false;) {
311		switch (*opts) {
312		case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
313		case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
314		case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
315		case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
316		case 'Y': case 'Z':
317		case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
318		case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
319		case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
320		case 's': case 't': case 'u': case 'v': case 'w': case 'x':
321		case 'y': case 'z':
322		case '0': case '1': case '2': case '3': case '4': case '5':
323		case '6': case '7': case '8': case '9':
324		case '_':
325			opts++;
326			break;
327		case ':':
328			opts++;
329			*klen_p = (uintptr_t)opts - 1 - (uintptr_t)*k_p;
330			*v_p = opts;
331			accept = true;
332			break;
333		case '\0':
334			if (opts != *opts_p) {
335				malloc_write("<jemalloc>: Conf string ends "
336				    "with key\n");
337			}
338			return (true);
339		default:
340			malloc_write("<jemalloc>: Malformed conf string\n");
341			return (true);
342		}
343	}
344
345	for (accept = false; accept == false;) {
346		switch (*opts) {
347		case ',':
348			opts++;
349			/*
350			 * Look ahead one character here, because the next time
351			 * this function is called, it will assume that end of
352			 * input has been cleanly reached if no input remains,
353			 * but we have optimistically already consumed the
354			 * comma if one exists.
355			 */
356			if (*opts == '\0') {
357				malloc_write("<jemalloc>: Conf string ends "
358				    "with comma\n");
359			}
360			*vlen_p = (uintptr_t)opts - 1 - (uintptr_t)*v_p;
361			accept = true;
362			break;
363		case '\0':
364			*vlen_p = (uintptr_t)opts - (uintptr_t)*v_p;
365			accept = true;
366			break;
367		default:
368			opts++;
369			break;
370		}
371	}
372
373	*opts_p = opts;
374	return (false);
375}
376
377static void
378malloc_conf_error(const char *msg, const char *k, size_t klen, const char *v,
379    size_t vlen)
380{
381
382	malloc_printf("<jemalloc>: %s: %.*s:%.*s\n", msg, (int)klen, k,
383	    (int)vlen, v);
384}
385
386static void
387malloc_conf_init(void)
388{
389	unsigned i;
390	char buf[PATH_MAX + 1];
391	const char *opts, *k, *v;
392	size_t klen, vlen;
393
394	/*
395	 * Automatically configure valgrind before processing options.  The
396	 * valgrind option remains in jemalloc 3.x for compatibility reasons.
397	 */
398	if (config_valgrind) {
399		in_valgrind = (RUNNING_ON_VALGRIND != 0) ? true : false;
400		if (config_fill && in_valgrind) {
401			opt_junk = false;
402			assert(opt_zero == false);
403			opt_quarantine = JEMALLOC_VALGRIND_QUARANTINE_DEFAULT;
404			opt_redzone = true;
405		}
406		if (config_tcache && in_valgrind)
407			opt_tcache = false;
408	}
409
410	for (i = 0; i < 3; i++) {
411		/* Get runtime configuration. */
412		switch (i) {
413		case 0:
414			if (je_malloc_conf != NULL) {
415				/*
416				 * Use options that were compiled into the
417				 * program.
418				 */
419				opts = je_malloc_conf;
420			} else {
421				/* No configuration specified. */
422				buf[0] = '\0';
423				opts = buf;
424			}
425			break;
426		case 1: {
427			int linklen = 0;
428#ifndef _WIN32
429			int saved_errno = errno;
430			const char *linkname =
431#  ifdef JEMALLOC_PREFIX
432			    "/etc/"JEMALLOC_PREFIX"malloc.conf"
433#  else
434			    "/etc/malloc.conf"
435#  endif
436			    ;
437
438			/*
439			 * Try to use the contents of the "/etc/malloc.conf"
440			 * symbolic link's name.
441			 */
442			linklen = readlink(linkname, buf, sizeof(buf) - 1);
443			if (linklen == -1) {
444				/* No configuration specified. */
445				linklen = 0;
446				/* restore errno */
447				set_errno(saved_errno);
448			}
449#endif
450			buf[linklen] = '\0';
451			opts = buf;
452			break;
453		} case 2: {
454			const char *envname =
455#ifdef JEMALLOC_PREFIX
456			    JEMALLOC_CPREFIX"MALLOC_CONF"
457#else
458			    "MALLOC_CONF"
459#endif
460			    ;
461
462			if ((opts = getenv(envname)) != NULL) {
463				/*
464				 * Do nothing; opts is already initialized to
465				 * the value of the MALLOC_CONF environment
466				 * variable.
467				 */
468			} else {
469				/* No configuration specified. */
470				buf[0] = '\0';
471				opts = buf;
472			}
473			break;
474		} default:
475			not_reached();
476			buf[0] = '\0';
477			opts = buf;
478		}
479
480		while (*opts != '\0' && malloc_conf_next(&opts, &k, &klen, &v,
481		    &vlen) == false) {
482#define	CONF_HANDLE_BOOL(o, n)						\
483			if (sizeof(n)-1 == klen && strncmp(n, k,	\
484			    klen) == 0) {				\
485				if (strncmp("true", v, vlen) == 0 &&	\
486				    vlen == sizeof("true")-1)		\
487					o = true;			\
488				else if (strncmp("false", v, vlen) ==	\
489				    0 && vlen == sizeof("false")-1)	\
490					o = false;			\
491				else {					\
492					malloc_conf_error(		\
493					    "Invalid conf value",	\
494					    k, klen, v, vlen);		\
495				}					\
496				continue;				\
497			}
498#define	CONF_HANDLE_SIZE_T(o, n, min, max, clip)			\
499			if (sizeof(n)-1 == klen && strncmp(n, k,	\
500			    klen) == 0) {				\
501				uintmax_t um;				\
502				char *end;				\
503									\
504				set_errno(0);				\
505				um = malloc_strtoumax(v, &end, 0);	\
506				if (get_errno() != 0 || (uintptr_t)end -\
507				    (uintptr_t)v != vlen) {		\
508					malloc_conf_error(		\
509					    "Invalid conf value",	\
510					    k, klen, v, vlen);		\
511				} else if (clip) {			\
512					if (min != 0 && um < min)	\
513						o = min;		\
514					else if (um > max)		\
515						o = max;		\
516					else				\
517						o = um;			\
518				} else {				\
519					if ((min != 0 && um < min) ||	\
520					    um > max) {			\
521						malloc_conf_error(	\
522						    "Out-of-range "	\
523						    "conf value",	\
524						    k, klen, v, vlen);	\
525					} else				\
526						o = um;			\
527				}					\
528				continue;				\
529			}
530#define	CONF_HANDLE_SSIZE_T(o, n, min, max)				\
531			if (sizeof(n)-1 == klen && strncmp(n, k,	\
532			    klen) == 0) {				\
533				long l;					\
534				char *end;				\
535									\
536				set_errno(0);				\
537				l = strtol(v, &end, 0);			\
538				if (get_errno() != 0 || (uintptr_t)end -\
539				    (uintptr_t)v != vlen) {		\
540					malloc_conf_error(		\
541					    "Invalid conf value",	\
542					    k, klen, v, vlen);		\
543				} else if (l < (ssize_t)min || l >	\
544				    (ssize_t)max) {			\
545					malloc_conf_error(		\
546					    "Out-of-range conf value",	\
547					    k, klen, v, vlen);		\
548				} else					\
549					o = l;				\
550				continue;				\
551			}
552#define	CONF_HANDLE_CHAR_P(o, n, d)					\
553			if (sizeof(n)-1 == klen && strncmp(n, k,	\
554			    klen) == 0) {				\
555				size_t cpylen = (vlen <=		\
556				    sizeof(o)-1) ? vlen :		\
557				    sizeof(o)-1;			\
558				strncpy(o, v, cpylen);			\
559				o[cpylen] = '\0';			\
560				continue;				\
561			}
562
563			CONF_HANDLE_BOOL(opt_abort, "abort")
564			/*
565			 * Chunks always require at least one header page, plus
566			 * one data page in the absence of redzones, or three
567			 * pages in the presence of redzones.  In order to
568			 * simplify options processing, fix the limit based on
569			 * config_fill.
570			 */
571			CONF_HANDLE_SIZE_T(opt_lg_chunk, "lg_chunk", LG_PAGE +
572			    (config_fill ? 2 : 1), (sizeof(size_t) << 3) - 1,
573			    true)
574			if (strncmp("dss", k, klen) == 0) {
575				int i;
576				bool match = false;
577				for (i = 0; i < dss_prec_limit; i++) {
578					if (strncmp(dss_prec_names[i], v, vlen)
579					    == 0) {
580						if (chunk_dss_prec_set(i)) {
581							malloc_conf_error(
582							    "Error setting dss",
583							    k, klen, v, vlen);
584						} else {
585							opt_dss =
586							    dss_prec_names[i];
587							match = true;
588							break;
589						}
590					}
591				}
592				if (match == false) {
593					malloc_conf_error("Invalid conf value",
594					    k, klen, v, vlen);
595				}
596				continue;
597			}
598			CONF_HANDLE_SIZE_T(opt_narenas, "narenas", 1,
599			    SIZE_T_MAX, false)
600			CONF_HANDLE_SSIZE_T(opt_lg_dirty_mult, "lg_dirty_mult",
601			    -1, (sizeof(size_t) << 3) - 1)
602			CONF_HANDLE_BOOL(opt_stats_print, "stats_print")
603			if (config_fill) {
604				CONF_HANDLE_BOOL(opt_junk, "junk")
605				CONF_HANDLE_SIZE_T(opt_quarantine, "quarantine",
606				    0, SIZE_T_MAX, false)
607				CONF_HANDLE_BOOL(opt_redzone, "redzone")
608				CONF_HANDLE_BOOL(opt_zero, "zero")
609			}
610			if (config_utrace) {
611				CONF_HANDLE_BOOL(opt_utrace, "utrace")
612			}
613			if (config_xmalloc) {
614				CONF_HANDLE_BOOL(opt_xmalloc, "xmalloc")
615			}
616			if (config_tcache) {
617				CONF_HANDLE_BOOL(opt_tcache, "tcache")
618				CONF_HANDLE_SSIZE_T(opt_lg_tcache_max,
619				    "lg_tcache_max", -1,
620				    (sizeof(size_t) << 3) - 1)
621			}
622			if (config_prof) {
623				CONF_HANDLE_BOOL(opt_prof, "prof")
624				CONF_HANDLE_CHAR_P(opt_prof_prefix,
625				    "prof_prefix", "jeprof")
626				CONF_HANDLE_BOOL(opt_prof_active, "prof_active")
627				CONF_HANDLE_SSIZE_T(opt_lg_prof_sample,
628				    "lg_prof_sample", 0,
629				    (sizeof(uint64_t) << 3) - 1)
630				CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum")
631				CONF_HANDLE_SSIZE_T(opt_lg_prof_interval,
632				    "lg_prof_interval", -1,
633				    (sizeof(uint64_t) << 3) - 1)
634				CONF_HANDLE_BOOL(opt_prof_gdump, "prof_gdump")
635				CONF_HANDLE_BOOL(opt_prof_final, "prof_final")
636				CONF_HANDLE_BOOL(opt_prof_leak, "prof_leak")
637			}
638			malloc_conf_error("Invalid conf pair", k, klen, v,
639			    vlen);
640#undef CONF_HANDLE_BOOL
641#undef CONF_HANDLE_SIZE_T
642#undef CONF_HANDLE_SSIZE_T
643#undef CONF_HANDLE_CHAR_P
644		}
645	}
646}
647
648static bool
649malloc_init_hard(void)
650{
651	arena_t *init_arenas[1];
652
653	malloc_mutex_lock(&init_lock);
654	if (malloc_initialized || IS_INITIALIZER) {
655		/*
656		 * Another thread initialized the allocator before this one
657		 * acquired init_lock, or this thread is the initializing
658		 * thread, and it is recursively allocating.
659		 */
660		malloc_mutex_unlock(&init_lock);
661		return (false);
662	}
663#ifdef JEMALLOC_THREADED_INIT
664	if (malloc_initializer != NO_INITIALIZER && IS_INITIALIZER == false) {
665		/* Busy-wait until the initializing thread completes. */
666		do {
667			malloc_mutex_unlock(&init_lock);
668			CPU_SPINWAIT;
669			malloc_mutex_lock(&init_lock);
670		} while (malloc_initialized == false);
671		malloc_mutex_unlock(&init_lock);
672		return (false);
673	}
674#endif
675	malloc_initializer = INITIALIZER;
676
677	malloc_tsd_boot();
678	if (config_prof)
679		prof_boot0();
680
681	malloc_conf_init();
682
683	if (opt_stats_print) {
684		/* Print statistics at exit. */
685		if (atexit(stats_print_atexit) != 0) {
686			malloc_write("<jemalloc>: Error in atexit()\n");
687			if (opt_abort)
688				abort();
689		}
690	}
691
692	if (base_boot()) {
693		malloc_mutex_unlock(&init_lock);
694		return (true);
695	}
696
697	if (chunk_boot()) {
698		malloc_mutex_unlock(&init_lock);
699		return (true);
700	}
701
702	if (ctl_boot()) {
703		malloc_mutex_unlock(&init_lock);
704		return (true);
705	}
706
707	if (config_prof)
708		prof_boot1();
709
710	arena_boot();
711
712	if (config_tcache && tcache_boot0()) {
713		malloc_mutex_unlock(&init_lock);
714		return (true);
715	}
716
717	if (huge_boot()) {
718		malloc_mutex_unlock(&init_lock);
719		return (true);
720	}
721
722	if (malloc_mutex_init(&arenas_lock)) {
723		malloc_mutex_unlock(&init_lock);
724		return (true);
725	}
726
727	/*
728	 * Create enough scaffolding to allow recursive allocation in
729	 * malloc_ncpus().
730	 */
731	narenas_total = narenas_auto = 1;
732	arenas = init_arenas;
733	memset(arenas, 0, sizeof(arena_t *) * narenas_auto);
734
735	/*
736	 * Initialize one arena here.  The rest are lazily created in
737	 * choose_arena_hard().
738	 */
739	arenas_extend(0);
740	if (arenas[0] == NULL) {
741		malloc_mutex_unlock(&init_lock);
742		return (true);
743	}
744
745	/* Initialize allocation counters before any allocations can occur. */
746	if (config_stats && thread_allocated_tsd_boot()) {
747		malloc_mutex_unlock(&init_lock);
748		return (true);
749	}
750
751	if (arenas_tsd_boot()) {
752		malloc_mutex_unlock(&init_lock);
753		return (true);
754	}
755
756	if (config_tcache && tcache_boot1()) {
757		malloc_mutex_unlock(&init_lock);
758		return (true);
759	}
760
761	if (config_fill && quarantine_boot()) {
762		malloc_mutex_unlock(&init_lock);
763		return (true);
764	}
765
766	if (config_prof && prof_boot2()) {
767		malloc_mutex_unlock(&init_lock);
768		return (true);
769	}
770
771	malloc_mutex_unlock(&init_lock);
772	/**********************************************************************/
773	/* Recursive allocation may follow. */
774
775	ncpus = malloc_ncpus();
776
777#if (!defined(JEMALLOC_MUTEX_INIT_CB) && !defined(JEMALLOC_ZONE) \
778    && !defined(_WIN32))
779	/* LinuxThreads's pthread_atfork() allocates. */
780	if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent,
781	    jemalloc_postfork_child) != 0) {
782		malloc_write("<jemalloc>: Error in pthread_atfork()\n");
783		if (opt_abort)
784			abort();
785	}
786#endif
787
788	/* Done recursively allocating. */
789	/**********************************************************************/
790	malloc_mutex_lock(&init_lock);
791
792	if (mutex_boot()) {
793		malloc_mutex_unlock(&init_lock);
794		return (true);
795	}
796
797	if (opt_narenas == 0) {
798		/*
799		 * For SMP systems, create more than one arena per CPU by
800		 * default.
801		 */
802		if (ncpus > 1)
803			opt_narenas = ncpus << 2;
804		else
805			opt_narenas = 1;
806	}
807	narenas_auto = opt_narenas;
808	/*
809	 * Make sure that the arenas array can be allocated.  In practice, this
810	 * limit is enough to allow the allocator to function, but the ctl
811	 * machinery will fail to allocate memory at far lower limits.
812	 */
813	if (narenas_auto > chunksize / sizeof(arena_t *)) {
814		narenas_auto = chunksize / sizeof(arena_t *);
815		malloc_printf("<jemalloc>: Reducing narenas to limit (%d)\n",
816		    narenas_auto);
817	}
818	narenas_total = narenas_auto;
819
820	/* Allocate and initialize arenas. */
821	arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas_total);
822	if (arenas == NULL) {
823		malloc_mutex_unlock(&init_lock);
824		return (true);
825	}
826	/*
827	 * Zero the array.  In practice, this should always be pre-zeroed,
828	 * since it was just mmap()ed, but let's be sure.
829	 */
830	memset(arenas, 0, sizeof(arena_t *) * narenas_total);
831	/* Copy the pointer to the one arena that was already initialized. */
832	arenas[0] = init_arenas[0];
833
834	malloc_initialized = true;
835	malloc_mutex_unlock(&init_lock);
836
837	return (false);
838}
839
840/*
841 * End initialization functions.
842 */
843/******************************************************************************/
844/*
845 * Begin malloc(3)-compatible functions.
846 */
847
848static void *
849imalloc_prof_sample(size_t usize, prof_thr_cnt_t *cnt)
850{
851	void *p;
852
853	if (cnt == NULL)
854		return (NULL);
855	if (usize <= SMALL_MAXCLASS) {
856		p = imalloc(SMALL_MAXCLASS+1);
857		if (p == NULL)
858			return (NULL);
859		arena_prof_promoted(p, usize);
860	} else
861		p = imalloc(usize);
862
863	return (p);
864}
865
866JEMALLOC_ALWAYS_INLINE_C void *
867imalloc_prof(size_t usize, prof_thr_cnt_t *cnt)
868{
869	void *p;
870
871	if ((uintptr_t)cnt != (uintptr_t)1U)
872		p = imalloc_prof_sample(usize, cnt);
873	else
874		p = imalloc(usize);
875	if (p == NULL)
876		return (NULL);
877	prof_malloc(p, usize, cnt);
878
879	return (p);
880}
881
882/*
883 * MALLOC_BODY() is a macro rather than a function because its contents are in
884 * the fast path, but inlining would cause reliability issues when determining
885 * how many frames to discard from heap profiling backtraces.
886 */
887#define	MALLOC_BODY(ret, size, usize) do {				\
888	if (malloc_init())						\
889		ret = NULL;						\
890	else {								\
891		if (config_prof && opt_prof) {				\
892			prof_thr_cnt_t *cnt;				\
893									\
894			usize = s2u(size);				\
895			/*						\
896			 * Call PROF_ALLOC_PREP() here rather than in	\
897			 * imalloc_prof() so that imalloc_prof() can be	\
898			 * inlined without introducing uncertainty	\
899			 * about the number of backtrace frames to	\
900			 * ignore.  imalloc_prof() is in the fast path	\
901			 * when heap profiling is enabled, so inlining	\
902			 * is critical to performance.  (For		\
903			 * consistency all callers of PROF_ALLOC_PREP()	\
904			 * are structured similarly, even though e.g.	\
905			 * realloc() isn't called enough for inlining	\
906			 * to be critical.)				\
907			 */						\
908			PROF_ALLOC_PREP(1, usize, cnt);			\
909			ret = imalloc_prof(usize, cnt);			\
910		} else {						\
911			if (config_stats || (config_valgrind &&		\
912			    in_valgrind))				\
913				usize = s2u(size);			\
914			ret = imalloc(size);				\
915		}							\
916	}								\
917} while (0)
918
919void *
920je_malloc(size_t size)
921{
922	void *ret;
923	size_t usize JEMALLOC_CC_SILENCE_INIT(0);
924
925	if (size == 0)
926		size = 1;
927
928	MALLOC_BODY(ret, size, usize);
929
930	if (ret == NULL) {
931		if (config_xmalloc && opt_xmalloc) {
932			malloc_write("<jemalloc>: Error in malloc(): "
933			    "out of memory\n");
934			abort();
935		}
936		set_errno(ENOMEM);
937	}
938	if (config_stats && ret != NULL) {
939		assert(usize == isalloc(ret, config_prof));
940		thread_allocated_tsd_get()->allocated += usize;
941	}
942	UTRACE(0, size, ret);
943	JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, false);
944	return (ret);
945}
946
947static void *
948imemalign_prof_sample(size_t alignment, size_t usize, prof_thr_cnt_t *cnt)
949{
950	void *p;
951
952	if (cnt == NULL)
953		return (NULL);
954	if (usize <= SMALL_MAXCLASS) {
955		assert(sa2u(SMALL_MAXCLASS+1, alignment) != 0);
956		p = ipalloc(sa2u(SMALL_MAXCLASS+1, alignment), alignment,
957		    false);
958		if (p == NULL)
959			return (NULL);
960		arena_prof_promoted(p, usize);
961	} else
962		p = ipalloc(usize, alignment, false);
963
964	return (p);
965}
966
967JEMALLOC_ALWAYS_INLINE_C void *
968imemalign_prof(size_t alignment, size_t usize, prof_thr_cnt_t *cnt)
969{
970	void *p;
971
972	if ((uintptr_t)cnt != (uintptr_t)1U)
973		p = imemalign_prof_sample(alignment, usize, cnt);
974	else
975		p = ipalloc(usize, alignment, false);
976	if (p == NULL)
977		return (NULL);
978	prof_malloc(p, usize, cnt);
979
980	return (p);
981}
982
983JEMALLOC_ATTR(nonnull(1))
984#ifdef JEMALLOC_PROF
985/*
986 * Avoid any uncertainty as to how many backtrace frames to ignore in
987 * PROF_ALLOC_PREP().
988 */
989JEMALLOC_NOINLINE
990#endif
991static int
992imemalign(void **memptr, size_t alignment, size_t size, size_t min_alignment)
993{
994	int ret;
995	size_t usize;
996	void *result;
997
998	assert(min_alignment != 0);
999
1000	if (malloc_init()) {
1001		result = NULL;
1002		goto label_oom;
1003	} else {
1004		if (size == 0)
1005			size = 1;
1006
1007		/* Make sure that alignment is a large enough power of 2. */
1008		if (((alignment - 1) & alignment) != 0
1009		    || (alignment < min_alignment)) {
1010			if (config_xmalloc && opt_xmalloc) {
1011				malloc_write("<jemalloc>: Error allocating "
1012				    "aligned memory: invalid alignment\n");
1013				abort();
1014			}
1015			result = NULL;
1016			ret = EINVAL;
1017			goto label_return;
1018		}
1019
1020		usize = sa2u(size, alignment);
1021		if (usize == 0) {
1022			result = NULL;
1023			goto label_oom;
1024		}
1025
1026		if (config_prof && opt_prof) {
1027			prof_thr_cnt_t *cnt;
1028
1029			PROF_ALLOC_PREP(2, usize, cnt);
1030			result = imemalign_prof(alignment, usize, cnt);
1031		} else
1032			result = ipalloc(usize, alignment, false);
1033		if (result == NULL)
1034			goto label_oom;
1035	}
1036
1037	*memptr = result;
1038	ret = 0;
1039label_return:
1040	if (config_stats && result != NULL) {
1041		assert(usize == isalloc(result, config_prof));
1042		thread_allocated_tsd_get()->allocated += usize;
1043	}
1044	UTRACE(0, size, result);
1045	return (ret);
1046label_oom:
1047	assert(result == NULL);
1048	if (config_xmalloc && opt_xmalloc) {
1049		malloc_write("<jemalloc>: Error allocating aligned memory: "
1050		    "out of memory\n");
1051		abort();
1052	}
1053	ret = ENOMEM;
1054	goto label_return;
1055}
1056
1057int
1058je_posix_memalign(void **memptr, size_t alignment, size_t size)
1059{
1060	int ret = imemalign(memptr, alignment, size, sizeof(void *));
1061	JEMALLOC_VALGRIND_MALLOC(ret == 0, *memptr, isalloc(*memptr,
1062	    config_prof), false);
1063	return (ret);
1064}
1065
1066void *
1067je_aligned_alloc(size_t alignment, size_t size)
1068{
1069	void *ret;
1070	int err;
1071
1072	if ((err = imemalign(&ret, alignment, size, 1)) != 0) {
1073		ret = NULL;
1074		set_errno(err);
1075	}
1076	JEMALLOC_VALGRIND_MALLOC(err == 0, ret, isalloc(ret, config_prof),
1077	    false);
1078	return (ret);
1079}
1080
1081static void *
1082icalloc_prof_sample(size_t usize, prof_thr_cnt_t *cnt)
1083{
1084	void *p;
1085
1086	if (cnt == NULL)
1087		return (NULL);
1088	if (usize <= SMALL_MAXCLASS) {
1089		p = icalloc(SMALL_MAXCLASS+1);
1090		if (p == NULL)
1091			return (NULL);
1092		arena_prof_promoted(p, usize);
1093	} else
1094		p = icalloc(usize);
1095
1096	return (p);
1097}
1098
1099JEMALLOC_ALWAYS_INLINE_C void *
1100icalloc_prof(size_t usize, prof_thr_cnt_t *cnt)
1101{
1102	void *p;
1103
1104	if ((uintptr_t)cnt != (uintptr_t)1U)
1105		p = icalloc_prof_sample(usize, cnt);
1106	else
1107		p = icalloc(usize);
1108	if (p == NULL)
1109		return (NULL);
1110	prof_malloc(p, usize, cnt);
1111
1112	return (p);
1113}
1114
1115void *
1116je_calloc(size_t num, size_t size)
1117{
1118	void *ret;
1119	size_t num_size;
1120	size_t usize JEMALLOC_CC_SILENCE_INIT(0);
1121
1122	if (malloc_init()) {
1123		num_size = 0;
1124		ret = NULL;
1125		goto label_return;
1126	}
1127
1128	num_size = num * size;
1129	if (num_size == 0) {
1130		if (num == 0 || size == 0)
1131			num_size = 1;
1132		else {
1133			ret = NULL;
1134			goto label_return;
1135		}
1136	/*
1137	 * Try to avoid division here.  We know that it isn't possible to
1138	 * overflow during multiplication if neither operand uses any of the
1139	 * most significant half of the bits in a size_t.
1140	 */
1141	} else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2)))
1142	    && (num_size / size != num)) {
1143		/* size_t overflow. */
1144		ret = NULL;
1145		goto label_return;
1146	}
1147
1148	if (config_prof && opt_prof) {
1149		prof_thr_cnt_t *cnt;
1150
1151		usize = s2u(num_size);
1152		PROF_ALLOC_PREP(1, usize, cnt);
1153		ret = icalloc_prof(usize, cnt);
1154	} else {
1155		if (config_stats || (config_valgrind && in_valgrind))
1156			usize = s2u(num_size);
1157		ret = icalloc(num_size);
1158	}
1159
1160label_return:
1161	if (ret == NULL) {
1162		if (config_xmalloc && opt_xmalloc) {
1163			malloc_write("<jemalloc>: Error in calloc(): out of "
1164			    "memory\n");
1165			abort();
1166		}
1167		set_errno(ENOMEM);
1168	}
1169	if (config_stats && ret != NULL) {
1170		assert(usize == isalloc(ret, config_prof));
1171		thread_allocated_tsd_get()->allocated += usize;
1172	}
1173	UTRACE(0, num_size, ret);
1174	JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, true);
1175	return (ret);
1176}
1177
1178static void *
1179irealloc_prof_sample(void *oldptr, size_t usize, prof_thr_cnt_t *cnt)
1180{
1181	void *p;
1182
1183	if (cnt == NULL)
1184		return (NULL);
1185	if (usize <= SMALL_MAXCLASS) {
1186		p = iralloc(oldptr, SMALL_MAXCLASS+1, 0, 0, false);
1187		if (p == NULL)
1188			return (NULL);
1189		arena_prof_promoted(p, usize);
1190	} else
1191		p = iralloc(oldptr, usize, 0, 0, false);
1192
1193	return (p);
1194}
1195
1196JEMALLOC_ALWAYS_INLINE_C void *
1197irealloc_prof(void *oldptr, size_t old_usize, size_t usize, prof_thr_cnt_t *cnt)
1198{
1199	void *p;
1200	prof_ctx_t *old_ctx;
1201
1202	old_ctx = prof_ctx_get(oldptr);
1203	if ((uintptr_t)cnt != (uintptr_t)1U)
1204		p = irealloc_prof_sample(oldptr, usize, cnt);
1205	else
1206		p = iralloc(oldptr, usize, 0, 0, false);
1207	if (p == NULL)
1208		return (NULL);
1209	prof_realloc(p, usize, cnt, old_usize, old_ctx);
1210
1211	return (p);
1212}
1213
1214JEMALLOC_INLINE_C void
1215ifree(void *ptr)
1216{
1217	size_t usize;
1218	UNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);
1219
1220	assert(ptr != NULL);
1221	assert(malloc_initialized || IS_INITIALIZER);
1222
1223	if (config_prof && opt_prof) {
1224		usize = isalloc(ptr, config_prof);
1225		prof_free(ptr, usize);
1226	} else if (config_stats || config_valgrind)
1227		usize = isalloc(ptr, config_prof);
1228	if (config_stats)
1229		thread_allocated_tsd_get()->deallocated += usize;
1230	if (config_valgrind && in_valgrind)
1231		rzsize = p2rz(ptr);
1232	iqalloc(ptr);
1233	JEMALLOC_VALGRIND_FREE(ptr, rzsize);
1234}
1235
1236void *
1237je_realloc(void *ptr, size_t size)
1238{
1239	void *ret;
1240	size_t usize JEMALLOC_CC_SILENCE_INIT(0);
1241	size_t old_usize = 0;
1242	UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);
1243
1244	if (size == 0) {
1245		if (ptr != NULL) {
1246			/* realloc(ptr, 0) is equivalent to free(ptr). */
1247			UTRACE(ptr, 0, 0);
1248			ifree(ptr);
1249			return (NULL);
1250		}
1251		size = 1;
1252	}
1253
1254	if (ptr != NULL) {
1255		assert(malloc_initialized || IS_INITIALIZER);
1256		malloc_thread_init();
1257
1258		if ((config_prof && opt_prof) || config_stats ||
1259		    (config_valgrind && in_valgrind))
1260			old_usize = isalloc(ptr, config_prof);
1261		if (config_valgrind && in_valgrind)
1262			old_rzsize = config_prof ? p2rz(ptr) : u2rz(old_usize);
1263
1264		if (config_prof && opt_prof) {
1265			prof_thr_cnt_t *cnt;
1266
1267			usize = s2u(size);
1268			PROF_ALLOC_PREP(1, usize, cnt);
1269			ret = irealloc_prof(ptr, old_usize, usize, cnt);
1270		} else {
1271			if (config_stats || (config_valgrind && in_valgrind))
1272				usize = s2u(size);
1273			ret = iralloc(ptr, size, 0, 0, false);
1274		}
1275	} else {
1276		/* realloc(NULL, size) is equivalent to malloc(size). */
1277		MALLOC_BODY(ret, size, usize);
1278	}
1279
1280	if (ret == NULL) {
1281		if (config_xmalloc && opt_xmalloc) {
1282			malloc_write("<jemalloc>: Error in realloc(): "
1283			    "out of memory\n");
1284			abort();
1285		}
1286		set_errno(ENOMEM);
1287	}
1288	if (config_stats && ret != NULL) {
1289		thread_allocated_t *ta;
1290		assert(usize == isalloc(ret, config_prof));
1291		ta = thread_allocated_tsd_get();
1292		ta->allocated += usize;
1293		ta->deallocated += old_usize;
1294	}
1295	UTRACE(ptr, size, ret);
1296	JEMALLOC_VALGRIND_REALLOC(ret, usize, ptr, old_usize, old_rzsize,
1297	    false);
1298	return (ret);
1299}
1300
1301void
1302je_free(void *ptr)
1303{
1304
1305	UTRACE(ptr, 0, 0);
1306	if (ptr != NULL)
1307		ifree(ptr);
1308}
1309
1310/*
1311 * End malloc(3)-compatible functions.
1312 */
1313/******************************************************************************/
1314/*
1315 * Begin non-standard override functions.
1316 */
1317
1318#ifdef JEMALLOC_OVERRIDE_MEMALIGN
1319void *
1320je_memalign(size_t alignment, size_t size)
1321{
1322	void *ret JEMALLOC_CC_SILENCE_INIT(NULL);
1323	imemalign(&ret, alignment, size, 1);
1324	JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false);
1325	return (ret);
1326}
1327#endif
1328
1329#ifdef JEMALLOC_OVERRIDE_VALLOC
1330void *
1331je_valloc(size_t size)
1332{
1333	void *ret JEMALLOC_CC_SILENCE_INIT(NULL);
1334	imemalign(&ret, PAGE, size, 1);
1335	JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false);
1336	return (ret);
1337}
1338#endif
1339
1340/*
1341 * is_malloc(je_malloc) is some macro magic to detect if jemalloc_defs.h has
1342 * #define je_malloc malloc
1343 */
1344#define	malloc_is_malloc 1
1345#define	is_malloc_(a) malloc_is_ ## a
1346#define	is_malloc(a) is_malloc_(a)
1347
1348#if ((is_malloc(je_malloc) == 1) && defined(__GLIBC__) && !defined(__UCLIBC__))
1349/*
1350 * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible
1351 * to inconsistently reference libc's malloc(3)-compatible functions
1352 * (https://bugzilla.mozilla.org/show_bug.cgi?id=493541).
1353 *
1354 * These definitions interpose hooks in glibc.  The functions are actually
1355 * passed an extra argument for the caller return address, which will be
1356 * ignored.
1357 */
1358JEMALLOC_EXPORT void (* __free_hook)(void *ptr) = je_free;
1359JEMALLOC_EXPORT void *(* __malloc_hook)(size_t size) = je_malloc;
1360JEMALLOC_EXPORT void *(* __realloc_hook)(void *ptr, size_t size) = je_realloc;
1361JEMALLOC_EXPORT void *(* __memalign_hook)(size_t alignment, size_t size) =
1362    je_memalign;
1363#endif
1364
1365/*
1366 * End non-standard override functions.
1367 */
1368/******************************************************************************/
1369/*
1370 * Begin non-standard functions.
1371 */
1372
1373JEMALLOC_ALWAYS_INLINE_C void *
1374imallocx(size_t usize, size_t alignment, bool zero, bool try_tcache,
1375    arena_t *arena)
1376{
1377
1378	assert(usize == ((alignment == 0) ? s2u(usize) : sa2u(usize,
1379	    alignment)));
1380
1381	if (alignment != 0)
1382		return (ipalloct(usize, alignment, zero, try_tcache, arena));
1383	else if (zero)
1384		return (icalloct(usize, try_tcache, arena));
1385	else
1386		return (imalloct(usize, try_tcache, arena));
1387}
1388
1389static void *
1390imallocx_prof_sample(size_t usize, size_t alignment, bool zero, bool try_tcache,
1391    arena_t *arena, prof_thr_cnt_t *cnt)
1392{
1393	void *p;
1394
1395	if (cnt == NULL)
1396		return (NULL);
1397	if (usize <= SMALL_MAXCLASS) {
1398		size_t usize_promoted = (alignment == 0) ?
1399		    s2u(SMALL_MAXCLASS+1) : sa2u(SMALL_MAXCLASS+1, alignment);
1400		assert(usize_promoted != 0);
1401		p = imallocx(usize_promoted, alignment, zero, try_tcache,
1402		    arena);
1403		if (p == NULL)
1404			return (NULL);
1405		arena_prof_promoted(p, usize);
1406	} else
1407		p = imallocx(usize, alignment, zero, try_tcache, arena);
1408
1409	return (p);
1410}
1411
1412JEMALLOC_ALWAYS_INLINE_C void *
1413imallocx_prof(size_t usize, size_t alignment, bool zero, bool try_tcache,
1414    arena_t *arena, prof_thr_cnt_t *cnt)
1415{
1416	void *p;
1417
1418	if ((uintptr_t)cnt != (uintptr_t)1U) {
1419		p = imallocx_prof_sample(usize, alignment, zero, try_tcache,
1420		    arena, cnt);
1421	} else
1422		p = imallocx(usize, alignment, zero, try_tcache, arena);
1423	if (p == NULL)
1424		return (NULL);
1425	prof_malloc(p, usize, cnt);
1426
1427	return (p);
1428}
1429
1430void *
1431je_mallocx(size_t size, int flags)
1432{
1433	void *p;
1434	size_t usize;
1435	size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK)
1436	    & (SIZE_T_MAX-1));
1437	bool zero = flags & MALLOCX_ZERO;
1438	unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
1439	arena_t *arena;
1440	bool try_tcache;
1441
1442	assert(size != 0);
1443
1444	if (malloc_init())
1445		goto label_oom;
1446
1447	if (arena_ind != UINT_MAX) {
1448		arena = arenas[arena_ind];
1449		try_tcache = false;
1450	} else {
1451		arena = NULL;
1452		try_tcache = true;
1453	}
1454
1455	usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);
1456	assert(usize != 0);
1457
1458	if (config_prof && opt_prof) {
1459		prof_thr_cnt_t *cnt;
1460
1461		PROF_ALLOC_PREP(1, usize, cnt);
1462		p = imallocx_prof(usize, alignment, zero, try_tcache, arena,
1463		    cnt);
1464	} else
1465		p = imallocx(usize, alignment, zero, try_tcache, arena);
1466	if (p == NULL)
1467		goto label_oom;
1468
1469	if (config_stats) {
1470		assert(usize == isalloc(p, config_prof));
1471		thread_allocated_tsd_get()->allocated += usize;
1472	}
1473	UTRACE(0, size, p);
1474	JEMALLOC_VALGRIND_MALLOC(true, p, usize, zero);
1475	return (p);
1476label_oom:
1477	if (config_xmalloc && opt_xmalloc) {
1478		malloc_write("<jemalloc>: Error in mallocx(): out of memory\n");
1479		abort();
1480	}
1481	UTRACE(0, size, 0);
1482	return (NULL);
1483}
1484
1485static void *
1486irallocx_prof_sample(void *oldptr, size_t size, size_t alignment, size_t usize,
1487    bool zero, bool try_tcache_alloc, bool try_tcache_dalloc, arena_t *arena,
1488    prof_thr_cnt_t *cnt)
1489{
1490	void *p;
1491
1492	if (cnt == NULL)
1493		return (NULL);
1494	if (usize <= SMALL_MAXCLASS) {
1495		p = iralloct(oldptr, SMALL_MAXCLASS+1, (SMALL_MAXCLASS+1 >=
1496		    size) ? 0 : size - (SMALL_MAXCLASS+1), alignment, zero,
1497		    try_tcache_alloc, try_tcache_dalloc, arena);
1498		if (p == NULL)
1499			return (NULL);
1500		arena_prof_promoted(p, usize);
1501	} else {
1502		p = iralloct(oldptr, size, 0, alignment, zero,
1503		    try_tcache_alloc, try_tcache_dalloc, arena);
1504	}
1505
1506	return (p);
1507}
1508
1509JEMALLOC_ALWAYS_INLINE_C void *
1510irallocx_prof(void *oldptr, size_t old_usize, size_t size, size_t alignment,
1511    size_t *usize, bool zero, bool try_tcache_alloc, bool try_tcache_dalloc,
1512    arena_t *arena, prof_thr_cnt_t *cnt)
1513{
1514	void *p;
1515	prof_ctx_t *old_ctx;
1516
1517	old_ctx = prof_ctx_get(oldptr);
1518	if ((uintptr_t)cnt != (uintptr_t)1U)
1519		p = irallocx_prof_sample(oldptr, size, alignment, *usize, zero,
1520		    try_tcache_alloc, try_tcache_dalloc, arena, cnt);
1521	else {
1522		p = iralloct(oldptr, size, 0, alignment, zero,
1523		    try_tcache_alloc, try_tcache_dalloc, arena);
1524	}
1525	if (p == NULL)
1526		return (NULL);
1527
1528	if (p == oldptr && alignment != 0) {
1529		/*
1530		 * The allocation did not move, so it is possible that the size
1531		 * class is smaller than would guarantee the requested
1532		 * alignment, and that the alignment constraint was
1533		 * serendipitously satisfied.  Additionally, old_usize may not
1534		 * be the same as the current usize because of in-place large
1535		 * reallocation.  Therefore, query the actual value of usize.
1536		 */
1537		*usize = isalloc(p, config_prof);
1538	}
1539	prof_realloc(p, *usize, cnt, old_usize, old_ctx);
1540
1541	return (p);
1542}
1543
1544void *
1545je_rallocx(void *ptr, size_t size, int flags)
1546{
1547	void *p;
1548	size_t usize, old_usize;
1549	UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);
1550	size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK)
1551	    & (SIZE_T_MAX-1));
1552	bool zero = flags & MALLOCX_ZERO;
1553	unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
1554	bool try_tcache_alloc, try_tcache_dalloc;
1555	arena_t *arena;
1556
1557	assert(ptr != NULL);
1558	assert(size != 0);
1559	assert(malloc_initialized || IS_INITIALIZER);
1560	malloc_thread_init();
1561
1562	if (arena_ind != UINT_MAX) {
1563		arena_chunk_t *chunk;
1564		try_tcache_alloc = false;
1565		chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
1566		try_tcache_dalloc = (chunk == ptr || chunk->arena !=
1567		    arenas[arena_ind]);
1568		arena = arenas[arena_ind];
1569	} else {
1570		try_tcache_alloc = true;
1571		try_tcache_dalloc = true;
1572		arena = NULL;
1573	}
1574
1575	if ((config_prof && opt_prof) || config_stats ||
1576	    (config_valgrind && in_valgrind))
1577		old_usize = isalloc(ptr, config_prof);
1578	if (config_valgrind && in_valgrind)
1579		old_rzsize = u2rz(old_usize);
1580
1581	if (config_prof && opt_prof) {
1582		prof_thr_cnt_t *cnt;
1583
1584		usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);
1585		assert(usize != 0);
1586		PROF_ALLOC_PREP(1, usize, cnt);
1587		p = irallocx_prof(ptr, old_usize, size, alignment, &usize, zero,
1588		    try_tcache_alloc, try_tcache_dalloc, arena, cnt);
1589		if (p == NULL)
1590			goto label_oom;
1591	} else {
1592		p = iralloct(ptr, size, 0, alignment, zero, try_tcache_alloc,
1593		    try_tcache_dalloc, arena);
1594		if (p == NULL)
1595			goto label_oom;
1596		if (config_stats || (config_valgrind && in_valgrind))
1597			usize = isalloc(p, config_prof);
1598	}
1599
1600	if (config_stats) {
1601		thread_allocated_t *ta;
1602		ta = thread_allocated_tsd_get();
1603		ta->allocated += usize;
1604		ta->deallocated += old_usize;
1605	}
1606	UTRACE(ptr, size, p);
1607	JEMALLOC_VALGRIND_REALLOC(p, usize, ptr, old_usize, old_rzsize, zero);
1608	return (p);
1609label_oom:
1610	if (config_xmalloc && opt_xmalloc) {
1611		malloc_write("<jemalloc>: Error in rallocx(): out of memory\n");
1612		abort();
1613	}
1614	UTRACE(ptr, size, 0);
1615	return (NULL);
1616}
1617
1618JEMALLOC_ALWAYS_INLINE_C size_t
1619ixallocx_helper(void *ptr, size_t old_usize, size_t size, size_t extra,
1620    size_t alignment, bool zero, arena_t *arena)
1621{
1622	size_t usize;
1623
1624	if (ixalloc(ptr, size, extra, alignment, zero))
1625		return (old_usize);
1626	usize = isalloc(ptr, config_prof);
1627
1628	return (usize);
1629}
1630
1631static size_t
1632ixallocx_prof_sample(void *ptr, size_t old_usize, size_t size, size_t extra,
1633    size_t alignment, size_t max_usize, bool zero, arena_t *arena,
1634    prof_thr_cnt_t *cnt)
1635{
1636	size_t usize;
1637
1638	if (cnt == NULL)
1639		return (old_usize);
1640	/* Use minimum usize to determine whether promotion may happen. */
1641	if (((alignment == 0) ? s2u(size) : sa2u(size, alignment)) <=
1642	    SMALL_MAXCLASS) {
1643		if (ixalloc(ptr, SMALL_MAXCLASS+1, (SMALL_MAXCLASS+1 >=
1644		    size+extra) ? 0 : size+extra - (SMALL_MAXCLASS+1),
1645		    alignment, zero))
1646			return (old_usize);
1647		usize = isalloc(ptr, config_prof);
1648		if (max_usize < PAGE)
1649			arena_prof_promoted(ptr, usize);
1650	} else {
1651		usize = ixallocx_helper(ptr, old_usize, size, extra, alignment,
1652		    zero, arena);
1653	}
1654
1655	return (usize);
1656}
1657
1658JEMALLOC_ALWAYS_INLINE_C size_t
1659ixallocx_prof(void *ptr, size_t old_usize, size_t size, size_t extra,
1660    size_t alignment, size_t max_usize, bool zero, arena_t *arena,
1661    prof_thr_cnt_t *cnt)
1662{
1663	size_t usize;
1664	prof_ctx_t *old_ctx;
1665
1666	old_ctx = prof_ctx_get(ptr);
1667	if ((uintptr_t)cnt != (uintptr_t)1U) {
1668		usize = ixallocx_prof_sample(ptr, old_usize, size, extra,
1669		    alignment, zero, max_usize, arena, cnt);
1670	} else {
1671		usize = ixallocx_helper(ptr, old_usize, size, extra, alignment,
1672		    zero, arena);
1673	}
1674	if (usize == old_usize)
1675		return (usize);
1676	prof_realloc(ptr, usize, cnt, old_usize, old_ctx);
1677
1678	return (usize);
1679}
1680
1681size_t
1682je_xallocx(void *ptr, size_t size, size_t extra, int flags)
1683{
1684	size_t usize, old_usize;
1685	UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);
1686	size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK)
1687	    & (SIZE_T_MAX-1));
1688	bool zero = flags & MALLOCX_ZERO;
1689	unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
1690	arena_t *arena;
1691
1692	assert(ptr != NULL);
1693	assert(size != 0);
1694	assert(SIZE_T_MAX - size >= extra);
1695	assert(malloc_initialized || IS_INITIALIZER);
1696	malloc_thread_init();
1697
1698	if (arena_ind != UINT_MAX)
1699		arena = arenas[arena_ind];
1700	else
1701		arena = NULL;
1702
1703	old_usize = isalloc(ptr, config_prof);
1704	if (config_valgrind && in_valgrind)
1705		old_rzsize = u2rz(old_usize);
1706
1707	if (config_prof && opt_prof) {
1708		prof_thr_cnt_t *cnt;
1709		/*
1710		 * usize isn't knowable before ixalloc() returns when extra is
1711		 * non-zero.  Therefore, compute its maximum possible value and
1712		 * use that in PROF_ALLOC_PREP() to decide whether to capture a
1713		 * backtrace.  prof_realloc() will use the actual usize to
1714		 * decide whether to sample.
1715		 */
1716		size_t max_usize = (alignment == 0) ? s2u(size+extra) :
1717		    sa2u(size+extra, alignment);
1718		PROF_ALLOC_PREP(1, max_usize, cnt);
1719		usize = ixallocx_prof(ptr, old_usize, size, extra, alignment,
1720		    max_usize, zero, arena, cnt);
1721	} else {
1722		usize = ixallocx_helper(ptr, old_usize, size, extra, alignment,
1723		    zero, arena);
1724	}
1725	if (usize == old_usize)
1726		goto label_not_resized;
1727
1728	if (config_stats) {
1729		thread_allocated_t *ta;
1730		ta = thread_allocated_tsd_get();
1731		ta->allocated += usize;
1732		ta->deallocated += old_usize;
1733	}
1734	JEMALLOC_VALGRIND_REALLOC(ptr, usize, ptr, old_usize, old_rzsize, zero);
1735label_not_resized:
1736	UTRACE(ptr, size, ptr);
1737	return (usize);
1738}
1739
1740size_t
1741je_sallocx(const void *ptr, int flags)
1742{
1743	size_t usize;
1744
1745	assert(malloc_initialized || IS_INITIALIZER);
1746	malloc_thread_init();
1747
1748	if (config_ivsalloc)
1749		usize = ivsalloc(ptr, config_prof);
1750	else {
1751		assert(ptr != NULL);
1752		usize = isalloc(ptr, config_prof);
1753	}
1754
1755	return (usize);
1756}
1757
1758void
1759je_dallocx(void *ptr, int flags)
1760{
1761	size_t usize;
1762	UNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);
1763	unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
1764	bool try_tcache;
1765
1766	assert(ptr != NULL);
1767	assert(malloc_initialized || IS_INITIALIZER);
1768
1769	if (arena_ind != UINT_MAX) {
1770		arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
1771		try_tcache = (chunk == ptr || chunk->arena !=
1772		    arenas[arena_ind]);
1773	} else
1774		try_tcache = true;
1775
1776	UTRACE(ptr, 0, 0);
1777	if (config_stats || config_valgrind)
1778		usize = isalloc(ptr, config_prof);
1779	if (config_prof && opt_prof) {
1780		if (config_stats == false && config_valgrind == false)
1781			usize = isalloc(ptr, config_prof);
1782		prof_free(ptr, usize);
1783	}
1784	if (config_stats)
1785		thread_allocated_tsd_get()->deallocated += usize;
1786	if (config_valgrind && in_valgrind)
1787		rzsize = p2rz(ptr);
1788	iqalloct(ptr, try_tcache);
1789	JEMALLOC_VALGRIND_FREE(ptr, rzsize);
1790}
1791
1792size_t
1793je_nallocx(size_t size, int flags)
1794{
1795	size_t usize;
1796	size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK)
1797	    & (SIZE_T_MAX-1));
1798
1799	assert(size != 0);
1800
1801	if (malloc_init())
1802		return (0);
1803
1804	usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);
1805	assert(usize != 0);
1806	return (usize);
1807}
1808
1809int
1810je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp,
1811    size_t newlen)
1812{
1813
1814	if (malloc_init())
1815		return (EAGAIN);
1816
1817	return (ctl_byname(name, oldp, oldlenp, newp, newlen));
1818}
1819
1820int
1821je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp)
1822{
1823
1824	if (malloc_init())
1825		return (EAGAIN);
1826
1827	return (ctl_nametomib(name, mibp, miblenp));
1828}
1829
1830int
1831je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1832  void *newp, size_t newlen)
1833{
1834
1835	if (malloc_init())
1836		return (EAGAIN);
1837
1838	return (ctl_bymib(mib, miblen, oldp, oldlenp, newp, newlen));
1839}
1840
1841void
1842je_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
1843    const char *opts)
1844{
1845
1846	stats_print(write_cb, cbopaque, opts);
1847}
1848
1849size_t
1850je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)
1851{
1852	size_t ret;
1853
1854	assert(malloc_initialized || IS_INITIALIZER);
1855	malloc_thread_init();
1856
1857	if (config_ivsalloc)
1858		ret = ivsalloc(ptr, config_prof);
1859	else
1860		ret = (ptr != NULL) ? isalloc(ptr, config_prof) : 0;
1861
1862	return (ret);
1863}
1864
1865/*
1866 * End non-standard functions.
1867 */
1868/******************************************************************************/
1869/*
1870 * The following functions are used by threading libraries for protection of
1871 * malloc during fork().
1872 */
1873
1874/*
1875 * If an application creates a thread before doing any allocation in the main
1876 * thread, then calls fork(2) in the main thread followed by memory allocation
1877 * in the child process, a race can occur that results in deadlock within the
1878 * child: the main thread may have forked while the created thread had
1879 * partially initialized the allocator.  Ordinarily jemalloc prevents
1880 * fork/malloc races via the following functions it registers during
1881 * initialization using pthread_atfork(), but of course that does no good if
1882 * the allocator isn't fully initialized at fork time.  The following library
1883 * constructor is a partial solution to this problem.  It may still possible to
1884 * trigger the deadlock described above, but doing so would involve forking via
1885 * a library constructor that runs before jemalloc's runs.
1886 */
1887JEMALLOC_ATTR(constructor)
1888static void
1889jemalloc_constructor(void)
1890{
1891
1892	malloc_init();
1893}
1894
1895#ifndef JEMALLOC_MUTEX_INIT_CB
1896void
1897jemalloc_prefork(void)
1898#else
1899JEMALLOC_EXPORT void
1900_malloc_prefork(void)
1901#endif
1902{
1903	unsigned i;
1904
1905#ifdef JEMALLOC_MUTEX_INIT_CB
1906	if (malloc_initialized == false)
1907		return;
1908#endif
1909	assert(malloc_initialized);
1910
1911	/* Acquire all mutexes in a safe order. */
1912	ctl_prefork();
1913	prof_prefork();
1914	malloc_mutex_prefork(&arenas_lock);
1915	for (i = 0; i < narenas_total; i++) {
1916		if (arenas[i] != NULL)
1917			arena_prefork(arenas[i]);
1918	}
1919	chunk_prefork();
1920	base_prefork();
1921	huge_prefork();
1922}
1923
1924#ifndef JEMALLOC_MUTEX_INIT_CB
1925void
1926jemalloc_postfork_parent(void)
1927#else
1928JEMALLOC_EXPORT void
1929_malloc_postfork(void)
1930#endif
1931{
1932	unsigned i;
1933
1934#ifdef JEMALLOC_MUTEX_INIT_CB
1935	if (malloc_initialized == false)
1936		return;
1937#endif
1938	assert(malloc_initialized);
1939
1940	/* Release all mutexes, now that fork() has completed. */
1941	huge_postfork_parent();
1942	base_postfork_parent();
1943	chunk_postfork_parent();
1944	for (i = 0; i < narenas_total; i++) {
1945		if (arenas[i] != NULL)
1946			arena_postfork_parent(arenas[i]);
1947	}
1948	malloc_mutex_postfork_parent(&arenas_lock);
1949	prof_postfork_parent();
1950	ctl_postfork_parent();
1951}
1952
1953void
1954jemalloc_postfork_child(void)
1955{
1956	unsigned i;
1957
1958	assert(malloc_initialized);
1959
1960	/* Release all mutexes, now that fork() has completed. */
1961	huge_postfork_child();
1962	base_postfork_child();
1963	chunk_postfork_child();
1964	for (i = 0; i < narenas_total; i++) {
1965		if (arenas[i] != NULL)
1966			arena_postfork_child(arenas[i]);
1967	}
1968	malloc_mutex_postfork_child(&arenas_lock);
1969	prof_postfork_child();
1970	ctl_postfork_child();
1971}
1972
1973/******************************************************************************/
1974/*
1975 * The following functions are used for TLS allocation/deallocation in static
1976 * binaries on FreeBSD.  The primary difference between these and i[mcd]alloc()
1977 * is that these avoid accessing TLS variables.
1978 */
1979
1980static void *
1981a0alloc(size_t size, bool zero)
1982{
1983
1984	if (malloc_init())
1985		return (NULL);
1986
1987	if (size == 0)
1988		size = 1;
1989
1990	if (size <= arena_maxclass)
1991		return (arena_malloc(arenas[0], size, zero, false));
1992	else
1993		return (huge_malloc(size, zero, huge_dss_prec_get(arenas[0])));
1994}
1995
1996void *
1997a0malloc(size_t size)
1998{
1999
2000	return (a0alloc(size, false));
2001}
2002
2003void *
2004a0calloc(size_t num, size_t size)
2005{
2006
2007	return (a0alloc(num * size, true));
2008}
2009
2010void
2011a0free(void *ptr)
2012{
2013	arena_chunk_t *chunk;
2014
2015	if (ptr == NULL)
2016		return;
2017
2018	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
2019	if (chunk != ptr)
2020		arena_dalloc(chunk, ptr, false);
2021	else
2022		huge_dalloc(ptr, true);
2023}
2024
2025/******************************************************************************/
2026