2aebc51dd19d791f66e35053fa291d51fd9cd4e1
[jemalloc.git] / jemalloc / src / jemalloc.c
1 #define JEMALLOC_C_
2 #include "jemalloc/internal/jemalloc_internal.h"
3
4 /******************************************************************************/
5 /* Data. */
6
7 malloc_mutex_t          arenas_lock;
8 arena_t                 **arenas;
9 unsigned                narenas;
10 static unsigned         next_arena;
11
12 #ifndef NO_TLS
13 __thread arena_t        *arenas_tls JEMALLOC_ATTR(tls_model("initial-exec"));
14 #else
15 pthread_key_t           arenas_tsd;
16 #endif
17
18 #ifdef JEMALLOC_STATS
19 #  ifndef NO_TLS
20 __thread thread_allocated_t     thread_allocated_tls;
21 #  else
22 pthread_key_t           thread_allocated_tsd;
23 #  endif
24 #endif
25
26 /* Set to true once the allocator has been initialized. */
27 static bool             malloc_initialized = false;
28
29 /* Used to let the initializing thread recursively allocate. */
30 static pthread_t        malloc_initializer = (unsigned long)0;
31
32 /* Used to avoid initialization races. */
33 static malloc_mutex_t   init_lock = MALLOC_MUTEX_INITIALIZER;
34
35 #ifdef DYNAMIC_PAGE_SHIFT
36 size_t          pagesize;
37 size_t          pagesize_mask;
38 size_t          lg_pagesize;
39 #endif
40
41 unsigned        ncpus;
42
43 /* Runtime configuration options. */
44 const char      *JEMALLOC_P(malloc_conf) JEMALLOC_ATTR(visibility("default"));
45 #ifdef JEMALLOC_DEBUG
46 bool    opt_abort = true;
47 #  ifdef JEMALLOC_FILL
48 bool    opt_junk = true;
49 #  endif
50 #else
51 bool    opt_abort = false;
52 #  ifdef JEMALLOC_FILL
53 bool    opt_junk = false;
54 #  endif
55 #endif
56 #ifdef JEMALLOC_SYSV
57 bool    opt_sysv = false;
58 #endif
59 #ifdef JEMALLOC_XMALLOC
60 bool    opt_xmalloc = false;
61 #endif
62 #ifdef JEMALLOC_FILL
63 bool    opt_zero = false;
64 #endif
65 size_t  opt_narenas = 0;
66
67 /******************************************************************************/
68 /* Function prototypes for non-inline static functions. */
69
70 static void     wrtmessage(void *cbopaque, const char *s);
71 static void     stats_print_atexit(void);
72 static unsigned malloc_ncpus(void);
73 #if (defined(JEMALLOC_STATS) && defined(NO_TLS))
74 static void     thread_allocated_cleanup(void *arg);
75 #endif
76 static bool     malloc_conf_next(char const **opts_p, char const **k_p,
77     size_t *klen_p, char const **v_p, size_t *vlen_p);
78 static void     malloc_conf_error(const char *msg, const char *k, size_t klen,
79     const char *v, size_t vlen);
80 static void     malloc_conf_init(void);
81 static bool     malloc_init_hard(void);
82
83 /******************************************************************************/
84 /* malloc_message() setup. */
85
86 #ifdef JEMALLOC_HAVE_ATTR
87 JEMALLOC_ATTR(visibility("hidden"))
88 #else
89 static
90 #endif
91 void
92 wrtmessage(void *cbopaque, const char *s)
93 {
94 #ifdef JEMALLOC_CC_SILENCE
95         int result =
96 #endif
97             write(STDERR_FILENO, s, strlen(s));
98 #ifdef JEMALLOC_CC_SILENCE
99         if (result < 0)
100                 result = errno;
101 #endif
102 }
103
104 void    (*JEMALLOC_P(malloc_message))(void *, const char *s)
105     JEMALLOC_ATTR(visibility("default")) = wrtmessage;
106
107 /******************************************************************************/
108 /*
109  * Begin miscellaneous support functions.
110  */
111
112 /* Create a new arena and insert it into the arenas array at index ind. */
113 arena_t *
114 arenas_extend(unsigned ind)
115 {
116         arena_t *ret;
117
118         /* Allocate enough space for trailing bins. */
119         ret = (arena_t *)base_alloc(offsetof(arena_t, bins)
120             + (sizeof(arena_bin_t) * nbins));
121         if (ret != NULL && arena_new(ret, ind) == false) {
122                 arenas[ind] = ret;
123                 return (ret);
124         }
125         /* Only reached if there is an OOM error. */
126
127         /*
128          * OOM here is quite inconvenient to propagate, since dealing with it
129          * would require a check for failure in the fast path.  Instead, punt
130          * by using arenas[0].  In practice, this is an extremely unlikely
131          * failure.
132          */
133         malloc_write("<jemalloc>: Error initializing arena\n");
134         if (opt_abort)
135                 abort();
136
137         return (arenas[0]);
138 }
139
140 /*
141  * Choose an arena based on a per-thread value (slow-path code only, called
142  * only by choose_arena()).
143  */
144 arena_t *
145 choose_arena_hard(void)
146 {
147         arena_t *ret;
148
149         if (narenas > 1) {
150                 malloc_mutex_lock(&arenas_lock);
151                 if ((ret = arenas[next_arena]) == NULL)
152                         ret = arenas_extend(next_arena);
153                 next_arena = (next_arena + 1) % narenas;
154                 malloc_mutex_unlock(&arenas_lock);
155         } else
156                 ret = arenas[0];
157
158         ARENA_SET(ret);
159
160         return (ret);
161 }
162
163 /*
164  * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so
165  * provide a wrapper.
166  */
167 int
168 buferror(int errnum, char *buf, size_t buflen)
169 {
170 #ifdef _GNU_SOURCE
171         char *b = strerror_r(errno, buf, buflen);
172         if (b != buf) {
173                 strncpy(buf, b, buflen);
174                 buf[buflen-1] = '\0';
175         }
176         return (0);
177 #else
178         return (strerror_r(errno, buf, buflen));
179 #endif
180 }
181
182 static void
183 stats_print_atexit(void)
184 {
185
186 #if (defined(JEMALLOC_TCACHE) && defined(JEMALLOC_STATS))
187         unsigned i;
188
189         /*
190          * Merge stats from extant threads.  This is racy, since individual
191          * threads do not lock when recording tcache stats events.  As a
192          * consequence, the final stats may be slightly out of date by the time
193          * they are reported, if other threads continue to allocate.
194          */
195         for (i = 0; i < narenas; i++) {
196                 arena_t *arena = arenas[i];
197                 if (arena != NULL) {
198                         tcache_t *tcache;
199
200                         /*
201                          * tcache_stats_merge() locks bins, so if any code is
202                          * introduced that acquires both arena and bin locks in
203                          * the opposite order, deadlocks may result.
204                          */
205                         malloc_mutex_lock(&arena->lock);
206                         ql_foreach(tcache, &arena->tcache_ql, link) {
207                                 tcache_stats_merge(tcache, arena);
208                         }
209                         malloc_mutex_unlock(&arena->lock);
210                 }
211         }
212 #endif
213         JEMALLOC_P(malloc_stats_print)(NULL, NULL, NULL);
214 }
215
216 /*
217  * End miscellaneous support functions.
218  */
219 /******************************************************************************/
220 /*
221  * Begin initialization functions.
222  */
223
224 static unsigned
225 malloc_ncpus(void)
226 {
227         unsigned ret;
228         long result;
229
230         result = sysconf(_SC_NPROCESSORS_ONLN);
231         if (result == -1) {
232                 /* Error. */
233                 ret = 1;
234         }
235         ret = (unsigned)result;
236
237         return (ret);
238 }
239
240 #if (defined(JEMALLOC_STATS) && defined(NO_TLS))
241 static void
242 thread_allocated_cleanup(void *arg)
243 {
244         uint64_t *allocated = (uint64_t *)arg;
245
246         if (allocated != NULL)
247                 idalloc(allocated);
248 }
249 #endif
250
251 /*
252  * FreeBSD's pthreads implementation calls malloc(3), so the malloc
253  * implementation has to take pains to avoid infinite recursion during
254  * initialization.
255  */
256 static inline bool
257 malloc_init(void)
258 {
259
260         if (malloc_initialized == false)
261                 return (malloc_init_hard());
262
263         return (false);
264 }
265
266 static bool
267 malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p,
268     char const **v_p, size_t *vlen_p)
269 {
270         bool accept;
271         const char *opts = *opts_p;
272
273         *k_p = opts;
274
275         for (accept = false; accept == false;) {
276                 switch (*opts) {
277                         case 'A': case 'B': case 'C': case 'D': case 'E':
278                         case 'F': case 'G': case 'H': case 'I': case 'J':
279                         case 'K': case 'L': case 'M': case 'N': case 'O':
280                         case 'P': case 'Q': case 'R': case 'S': case 'T':
281                         case 'U': case 'V': case 'W': case 'X': case 'Y':
282                         case 'Z':
283                         case 'a': case 'b': case 'c': case 'd': case 'e':
284                         case 'f': case 'g': case 'h': case 'i': case 'j':
285                         case 'k': case 'l': case 'm': case 'n': case 'o':
286                         case 'p': case 'q': case 'r': case 's': case 't':
287                         case 'u': case 'v': case 'w': case 'x': case 'y':
288                         case 'z':
289                         case '0': case '1': case '2': case '3': case '4':
290                         case '5': case '6': case '7': case '8': case '9':
291                         case '_':
292                                 opts++;
293                                 break;
294                         case ':':
295                                 opts++;
296                                 *klen_p = (uintptr_t)opts - 1 - (uintptr_t)*k_p;
297                                 *v_p = opts;
298                                 accept = true;
299                                 break;
300                         case '\0':
301                                 if (opts != *opts_p) {
302                                         malloc_write("<jemalloc>: Conf string "
303                                             "ends with key\n");
304                                 }
305                                 return (true);
306                         default:
307                                 malloc_write("<jemalloc>: Malformed conf "
308                                     "string\n");
309                                 return (true);
310                 }
311         }
312
313         for (accept = false; accept == false;) {
314                 switch (*opts) {
315                         case ',':
316                                 opts++;
317                                 /*
318                                  * Look ahead one character here, because the
319                                  * next time this function is called, it will
320                                  * assume that end of input has been cleanly
321                                  * reached if no input remains, but we have
322                                  * optimistically already consumed the comma if
323                                  * one exists.
324                                  */
325                                 if (*opts == '\0') {
326                                         malloc_write("<jemalloc>: Conf string "
327                                             "ends with comma\n");
328                                 }
329                                 *vlen_p = (uintptr_t)opts - 1 - (uintptr_t)*v_p;
330                                 accept = true;
331                                 break;
332                         case '\0':
333                                 *vlen_p = (uintptr_t)opts - (uintptr_t)*v_p;
334                                 accept = true;
335                                 break;
336                         default:
337                                 opts++;
338                                 break;
339                 }
340         }
341
342         *opts_p = opts;
343         return (false);
344 }
345
346 static void
347 malloc_conf_error(const char *msg, const char *k, size_t klen, const char *v,
348     size_t vlen)
349 {
350         char buf[PATH_MAX + 1];
351
352         malloc_write("<jemalloc>: ");
353         malloc_write(msg);
354         malloc_write(": ");
355         memcpy(buf, k, klen);
356         memcpy(&buf[klen], ":", 1);
357         memcpy(&buf[klen+1], v, vlen);
358         buf[klen+1+vlen] = '\0';
359         malloc_write(buf);
360         malloc_write("\n");
361 }
362
363 static void
364 malloc_conf_init(void)
365 {
366         unsigned i;
367         char buf[PATH_MAX + 1];
368         const char *opts, *k, *v;
369         size_t klen, vlen;
370
371         for (i = 0; i < 3; i++) {
372                 /* Get runtime configuration. */
373                 switch (i) {
374                 case 0:
375                         if (JEMALLOC_P(malloc_conf) != NULL) {
376                                 /*
377                                  * Use options that were compiled into the
378                                  * program.
379                                  */
380                                 opts = JEMALLOC_P(malloc_conf);
381                         } else {
382                                 /* No configuration specified. */
383                                 buf[0] = '\0';
384                                 opts = buf;
385                         }
386                         break;
387                 case 1: {
388                         int linklen;
389                         const char *linkname =
390 #ifdef JEMALLOC_PREFIX
391                             "/etc/"JEMALLOC_PREFIX"malloc.conf"
392 #else
393                             "/etc/malloc.conf"
394 #endif
395                             ;
396
397                         if ((linklen = readlink(linkname, buf,
398                             sizeof(buf) - 1)) != -1) {
399                                 /*
400                                  * Use the contents of the "/etc/malloc.conf"
401                                  * symbolic link's name.
402                                  */
403                                 buf[linklen] = '\0';
404                                 opts = buf;
405                         } else {
406                                 /* No configuration specified. */
407                                 buf[0] = '\0';
408                                 opts = buf;
409                         }
410                         break;
411                 }
412                 case 2: {
413                         const char *envname =
414 #ifdef JEMALLOC_PREFIX
415                             JEMALLOC_CPREFIX"MALLOC_CONF"
416 #else
417                             "MALLOC_CONF"
418 #endif
419                             ;
420
421                         if ((opts = getenv(envname)) != NULL) {
422                                 /*
423                                  * Do nothing; opts is already initialized to
424                                  * the value of the JEMALLOC_OPTIONS
425                                  * environment variable.
426                                  */
427                         } else {
428                                 /* No configuration specified. */
429                                 buf[0] = '\0';
430                                 opts = buf;
431                         }
432                         break;
433                 }
434                 default:
435                         /* NOTREACHED */
436                         assert(false);
437                         buf[0] = '\0';
438                         opts = buf;
439                 }
440
441                 while (*opts != '\0' && malloc_conf_next(&opts, &k, &klen, &v,
442                     &vlen) == false) {
443 #define CONF_HANDLE_BOOL(n)                                             \
444                         if (sizeof(#n)-1 == klen && strncmp(#n, k,      \
445                             klen) == 0) {                               \
446                                 if (strncmp("true", v, vlen) == 0 &&    \
447                                     vlen == sizeof("true")-1)           \
448                                         opt_##n = true;                 \
449                                 else if (strncmp("false", v, vlen) ==   \
450                                     0 && vlen == sizeof("false")-1)     \
451                                         opt_##n = false;                \
452                                 else {                                  \
453                                         malloc_conf_error(              \
454                                             "Invalid conf value",       \
455                                             k, klen, v, vlen);          \
456                                 }                                       \
457                                 continue;                               \
458                         }
459 #define CONF_HANDLE_SIZE_T(n, min, max)                                 \
460                         if (sizeof(#n)-1 == klen && strncmp(#n, k,      \
461                             klen) == 0) {                               \
462                                 unsigned long ul;                       \
463                                 char *end;                              \
464                                                                         \
465                                 errno = 0;                              \
466                                 ul = strtoul(v, &end, 0);               \
467                                 if (errno != 0 || (uintptr_t)end -      \
468                                     (uintptr_t)v != vlen) {             \
469                                         malloc_conf_error(              \
470                                             "Invalid conf value",       \
471                                             k, klen, v, vlen);          \
472                                 } else if (ul < min || ul > max) {      \
473                                         malloc_conf_error(              \
474                                             "Out-of-range conf value",  \
475                                             k, klen, v, vlen);          \
476                                 } else                                  \
477                                         opt_##n = ul;                   \
478                                 continue;                               \
479                         }
480 #define CONF_HANDLE_SSIZE_T(n, min, max)                                \
481                         if (sizeof(#n)-1 == klen && strncmp(#n, k,      \
482                             klen) == 0) {                               \
483                                 long l;                                 \
484                                 char *end;                              \
485                                                                         \
486                                 errno = 0;                              \
487                                 l = strtol(v, &end, 0);                 \
488                                 if (errno != 0 || (uintptr_t)end -      \
489                                     (uintptr_t)v != vlen) {             \
490                                         malloc_conf_error(              \
491                                             "Invalid conf value",       \
492                                             k, klen, v, vlen);          \
493                                 } else if (l < (ssize_t)min || l >      \
494                                     (ssize_t)max) {                     \
495                                         malloc_conf_error(              \
496                                             "Out-of-range conf value",  \
497                                             k, klen, v, vlen);          \
498                                 } else                                  \
499                                         opt_##n = l;                    \
500                                 continue;                               \
501                         }
502 #define CONF_HANDLE_CHAR_P(n, d)                                        \
503                         if (sizeof(#n)-1 == klen && strncmp(#n, k,      \
504                             klen) == 0) {                               \
505                                 size_t cpylen = (vlen <=                \
506                                     sizeof(opt_##n)-1) ? vlen :         \
507                                     sizeof(opt_##n)-1;                  \
508                                 strncpy(opt_##n, v, cpylen);            \
509                                 opt_##n[cpylen] = '\0';                 \
510                                 continue;                               \
511                         }
512
513                         CONF_HANDLE_BOOL(abort)
514                         CONF_HANDLE_SIZE_T(lg_qspace_max, LG_QUANTUM,
515                             PAGE_SHIFT-1)
516                         CONF_HANDLE_SIZE_T(lg_cspace_max, LG_QUANTUM,
517                             PAGE_SHIFT-1)
518                         /*
519                          * Chunks always require at least one * header page,
520                          * plus one data page.
521                          */
522                         CONF_HANDLE_SIZE_T(lg_chunk, PAGE_SHIFT+1,
523                             (sizeof(size_t) << 3) - 1)
524                         CONF_HANDLE_SIZE_T(narenas, 1, SIZE_T_MAX)
525                         CONF_HANDLE_SSIZE_T(lg_dirty_mult, -1,
526                             (sizeof(size_t) << 3) - 1)
527                         CONF_HANDLE_BOOL(stats_print)
528 #ifdef JEMALLOC_FILL
529                         CONF_HANDLE_BOOL(junk)
530                         CONF_HANDLE_BOOL(zero)
531 #endif
532 #ifdef JEMALLOC_SYSV
533                         CONF_HANDLE_BOOL(sysv)
534 #endif
535 #ifdef JEMALLOC_XMALLOC
536                         CONF_HANDLE_BOOL(xmalloc)
537 #endif
538 #ifdef JEMALLOC_TCACHE
539                         CONF_HANDLE_BOOL(tcache)
540                         CONF_HANDLE_SSIZE_T(lg_tcache_gc_sweep, -1,
541                             (sizeof(size_t) << 3) - 1)
542                         CONF_HANDLE_SSIZE_T(lg_tcache_max, -1,
543                             (sizeof(size_t) << 3) - 1)
544 #endif
545 #ifdef JEMALLOC_PROF
546                         CONF_HANDLE_BOOL(prof)
547                         CONF_HANDLE_CHAR_P(prof_prefix, "jeprof")
548                         CONF_HANDLE_SIZE_T(lg_prof_bt_max, 0, LG_PROF_BT_MAX)
549                         CONF_HANDLE_BOOL(prof_active)
550                         CONF_HANDLE_SSIZE_T(lg_prof_sample, 0,
551                             (sizeof(uint64_t) << 3) - 1)
552                         CONF_HANDLE_BOOL(prof_accum)
553                         CONF_HANDLE_SSIZE_T(lg_prof_tcmax, -1,
554                             (sizeof(size_t) << 3) - 1)
555                         CONF_HANDLE_SSIZE_T(lg_prof_interval, -1,
556                             (sizeof(uint64_t) << 3) - 1)
557                         CONF_HANDLE_BOOL(prof_gdump)
558                         CONF_HANDLE_BOOL(prof_leak)
559 #endif
560 #ifdef JEMALLOC_SWAP
561                         CONF_HANDLE_BOOL(overcommit)
562 #endif
563                         malloc_conf_error("Invalid conf pair", k, klen, v,
564                             vlen);
565 #undef CONF_HANDLE_BOOL
566 #undef CONF_HANDLE_SIZE_T
567 #undef CONF_HANDLE_SSIZE_T
568 #undef CONF_HANDLE_CHAR_P
569                 }
570
571                 /* Validate configuration of options that are inter-related. */
572                 if (opt_lg_qspace_max+1 >= opt_lg_cspace_max) {
573                         malloc_write("<jemalloc>: Invalid lg_[qc]space_max "
574                             "relationship; restoring defaults\n");
575                         opt_lg_qspace_max = LG_QSPACE_MAX_DEFAULT;
576                         opt_lg_cspace_max = LG_CSPACE_MAX_DEFAULT;
577                 }
578         }
579 }
580
581 static bool
582 malloc_init_hard(void)
583 {
584         arena_t *init_arenas[1];
585
586         malloc_mutex_lock(&init_lock);
587         if (malloc_initialized || malloc_initializer == pthread_self()) {
588                 /*
589                  * Another thread initialized the allocator before this one
590                  * acquired init_lock, or this thread is the initializing
591                  * thread, and it is recursively allocating.
592                  */
593                 malloc_mutex_unlock(&init_lock);
594                 return (false);
595         }
596         if (malloc_initializer != (unsigned long)0) {
597                 /* Busy-wait until the initializing thread completes. */
598                 do {
599                         malloc_mutex_unlock(&init_lock);
600                         CPU_SPINWAIT;
601                         malloc_mutex_lock(&init_lock);
602                 } while (malloc_initialized == false);
603                 malloc_mutex_unlock(&init_lock);
604                 return (false);
605         }
606
607 #ifdef DYNAMIC_PAGE_SHIFT
608         /* Get page size. */
609         {
610                 long result;
611
612                 result = sysconf(_SC_PAGESIZE);
613                 assert(result != -1);
614                 pagesize = (unsigned)result;
615
616                 /*
617                  * We assume that pagesize is a power of 2 when calculating
618                  * pagesize_mask and lg_pagesize.
619                  */
620                 assert(((result - 1) & result) == 0);
621                 pagesize_mask = result - 1;
622                 lg_pagesize = ffs((int)result) - 1;
623         }
624 #endif
625
626 #ifdef JEMALLOC_PROF
627         prof_boot0();
628 #endif
629
630         malloc_conf_init();
631
632         /* Register fork handlers. */
633         if (pthread_atfork(jemalloc_prefork, jemalloc_postfork,
634             jemalloc_postfork) != 0) {
635                 malloc_write("<jemalloc>: Error in pthread_atfork()\n");
636                 if (opt_abort)
637                         abort();
638         }
639
640         if (ctl_boot()) {
641                 malloc_mutex_unlock(&init_lock);
642                 return (true);
643         }
644
645         if (opt_stats_print) {
646                 /* Print statistics at exit. */
647                 if (atexit(stats_print_atexit) != 0) {
648                         malloc_write("<jemalloc>: Error in atexit()\n");
649                         if (opt_abort)
650                                 abort();
651                 }
652         }
653
654         if (chunk_boot()) {
655                 malloc_mutex_unlock(&init_lock);
656                 return (true);
657         }
658
659         if (base_boot()) {
660                 malloc_mutex_unlock(&init_lock);
661                 return (true);
662         }
663
664 #ifdef JEMALLOC_PROF
665         prof_boot1();
666 #endif
667
668         if (arena_boot()) {
669                 malloc_mutex_unlock(&init_lock);
670                 return (true);
671         }
672
673 #ifdef JEMALLOC_TCACHE
674         tcache_boot();
675 #endif
676
677         if (huge_boot()) {
678                 malloc_mutex_unlock(&init_lock);
679                 return (true);
680         }
681
682 #if (defined(JEMALLOC_STATS) && defined(NO_TLS))
683         /* Initialize allocation counters before any allocations can occur. */
684         if (pthread_key_create(&thread_allocated_tsd, thread_allocated_cleanup)
685             != 0) {
686                 malloc_mutex_unlock(&init_lock);
687                 return (true);
688         }
689 #endif
690
691         /*
692          * Create enough scaffolding to allow recursive allocation in
693          * malloc_ncpus().
694          */
695         narenas = 1;
696         arenas = init_arenas;
697         memset(arenas, 0, sizeof(arena_t *) * narenas);
698
699         /*
700          * Initialize one arena here.  The rest are lazily created in
701          * choose_arena_hard().
702          */
703         arenas_extend(0);
704         if (arenas[0] == NULL) {
705                 malloc_mutex_unlock(&init_lock);
706                 return (true);
707         }
708
709         /*
710          * Assign the initial arena to the initial thread, in order to avoid
711          * spurious creation of an extra arena if the application switches to
712          * threaded mode.
713          */
714         ARENA_SET(arenas[0]);
715
716         malloc_mutex_init(&arenas_lock);
717
718 #ifdef JEMALLOC_PROF
719         if (prof_boot2()) {
720                 malloc_mutex_unlock(&init_lock);
721                 return (true);
722         }
723 #endif
724
725         /* Get number of CPUs. */
726         malloc_initializer = pthread_self();
727         malloc_mutex_unlock(&init_lock);
728         ncpus = malloc_ncpus();
729         malloc_mutex_lock(&init_lock);
730
731         if (opt_narenas == 0) {
732                 /*
733                  * For SMP systems, create more than one arena per CPU by
734                  * default.
735                  */
736                 if (ncpus > 1)
737                         opt_narenas = ncpus << 2;
738                 else
739                         opt_narenas = 1;
740         }
741         narenas = opt_narenas;
742         /*
743          * Make sure that the arenas array can be allocated.  In practice, this
744          * limit is enough to allow the allocator to function, but the ctl
745          * machinery will fail to allocate memory at far lower limits.
746          */
747         if (narenas > chunksize / sizeof(arena_t *)) {
748                 char buf[UMAX2S_BUFSIZE];
749
750                 narenas = chunksize / sizeof(arena_t *);
751                 malloc_write("<jemalloc>: Reducing narenas to limit (");
752                 malloc_write(u2s(narenas, 10, buf));
753                 malloc_write(")\n");
754         }
755
756         next_arena = (narenas > 0) ? 1 : 0;
757
758 #ifdef NO_TLS
759         if (pthread_key_create(&arenas_tsd, NULL) != 0) {
760                 malloc_mutex_unlock(&init_lock);
761                 return (true);
762         }
763 #endif
764
765         /* Allocate and initialize arenas. */
766         arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas);
767         if (arenas == NULL) {
768                 malloc_mutex_unlock(&init_lock);
769                 return (true);
770         }
771         /*
772          * Zero the array.  In practice, this should always be pre-zeroed,
773          * since it was just mmap()ed, but let's be sure.
774          */
775         memset(arenas, 0, sizeof(arena_t *) * narenas);
776         /* Copy the pointer to the one arena that was already initialized. */
777         arenas[0] = init_arenas[0];
778
779 #ifdef JEMALLOC_ZONE
780         /* Register the custom zone. */
781         malloc_zone_register(create_zone());
782
783         /*
784          * Convert the default szone to an "overlay zone" that is capable of
785          * deallocating szone-allocated objects, but allocating new objects
786          * from jemalloc.
787          */
788         szone2ozone(malloc_default_zone());
789 #endif
790
791         malloc_initialized = true;
792         malloc_mutex_unlock(&init_lock);
793         return (false);
794 }
795
796
797 #ifdef JEMALLOC_ZONE
798 JEMALLOC_ATTR(constructor)
799 void
800 jemalloc_darwin_init(void)
801 {
802
803         if (malloc_init_hard())
804                 abort();
805 }
806 #endif
807
808 /*
809  * End initialization functions.
810  */
811 /******************************************************************************/
812 /*
813  * Begin malloc(3)-compatible functions.
814  */
815
816 JEMALLOC_ATTR(malloc)
817 JEMALLOC_ATTR(visibility("default"))
818 void *
819 JEMALLOC_P(malloc)(size_t size)
820 {
821         void *ret;
822 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
823         size_t usize
824 #  ifdef JEMALLOC_CC_SILENCE
825             = 0
826 #  endif
827             ;
828 #endif
829 #ifdef JEMALLOC_PROF
830         prof_thr_cnt_t *cnt
831 #  ifdef JEMALLOC_CC_SILENCE
832             = NULL
833 #  endif
834             ;
835 #endif
836
837         if (malloc_init()) {
838                 ret = NULL;
839                 goto OOM;
840         }
841
842         if (size == 0) {
843 #ifdef JEMALLOC_SYSV
844                 if (opt_sysv == false)
845 #endif
846                         size = 1;
847 #ifdef JEMALLOC_SYSV
848                 else {
849 #  ifdef JEMALLOC_XMALLOC
850                         if (opt_xmalloc) {
851                                 malloc_write("<jemalloc>: Error in malloc(): "
852                                     "invalid size 0\n");
853                                 abort();
854                         }
855 #  endif
856                         ret = NULL;
857                         goto RETURN;
858                 }
859 #endif
860         }
861
862 #ifdef JEMALLOC_PROF
863         if (opt_prof) {
864                 usize = s2u(size);
865                 if ((cnt = prof_alloc_prep(usize)) == NULL) {
866                         ret = NULL;
867                         goto OOM;
868                 }
869                 if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <=
870                     small_maxclass) {
871                         ret = imalloc(small_maxclass+1);
872                         if (ret != NULL)
873                                 arena_prof_promoted(ret, usize);
874                 } else
875                         ret = imalloc(size);
876         } else
877 #endif
878         {
879 #ifdef JEMALLOC_STATS
880                 usize = s2u(size);
881 #endif
882                 ret = imalloc(size);
883         }
884
885 OOM:
886         if (ret == NULL) {
887 #ifdef JEMALLOC_XMALLOC
888                 if (opt_xmalloc) {
889                         malloc_write("<jemalloc>: Error in malloc(): "
890                             "out of memory\n");
891                         abort();
892                 }
893 #endif
894                 errno = ENOMEM;
895         }
896
897 #ifdef JEMALLOC_SYSV
898 RETURN:
899 #endif
900 #ifdef JEMALLOC_PROF
901         if (opt_prof && ret != NULL)
902                 prof_malloc(ret, usize, cnt);
903 #endif
904 #ifdef JEMALLOC_STATS
905         if (ret != NULL) {
906                 assert(usize == isalloc(ret));
907                 ALLOCATED_ADD(usize, 0);
908         }
909 #endif
910         return (ret);
911 }
912
913 JEMALLOC_ATTR(nonnull(1))
914 JEMALLOC_ATTR(visibility("default"))
915 int
916 JEMALLOC_P(posix_memalign)(void **memptr, size_t alignment, size_t size)
917 {
918         int ret;
919         void *result;
920 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
921         size_t usize
922 #  ifdef JEMALLOC_CC_SILENCE
923             = 0
924 #  endif
925             ;
926 #endif
927 #ifdef JEMALLOC_PROF
928         prof_thr_cnt_t *cnt
929 #  ifdef JEMALLOC_CC_SILENCE
930             = NULL
931 #  endif
932             ;
933 #endif
934
935         if (malloc_init())
936                 result = NULL;
937         else {
938                 if (size == 0) {
939 #ifdef JEMALLOC_SYSV
940                         if (opt_sysv == false)
941 #endif
942                                 size = 1;
943 #ifdef JEMALLOC_SYSV
944                         else {
945 #  ifdef JEMALLOC_XMALLOC
946                                 if (opt_xmalloc) {
947                                         malloc_write("<jemalloc>: Error in "
948                                             "posix_memalign(): invalid size "
949                                             "0\n");
950                                         abort();
951                                 }
952 #  endif
953                                 result = NULL;
954                                 *memptr = NULL;
955                                 ret = 0;
956                                 goto RETURN;
957                         }
958 #endif
959                 }
960
961                 /* Make sure that alignment is a large enough power of 2. */
962                 if (((alignment - 1) & alignment) != 0
963                     || alignment < sizeof(void *)) {
964 #ifdef JEMALLOC_XMALLOC
965                         if (opt_xmalloc) {
966                                 malloc_write("<jemalloc>: Error in "
967                                     "posix_memalign(): invalid alignment\n");
968                                 abort();
969                         }
970 #endif
971                         result = NULL;
972                         ret = EINVAL;
973                         goto RETURN;
974                 }
975
976 #ifdef JEMALLOC_PROF
977                 if (opt_prof) {
978                         usize = sa2u(size, alignment, NULL);
979                         if ((cnt = prof_alloc_prep(usize)) == NULL) {
980                                 result = NULL;
981                                 ret = EINVAL;
982                         } else {
983                                 if (prof_promote && (uintptr_t)cnt !=
984                                     (uintptr_t)1U && usize <= small_maxclass) {
985                                         result = ipalloc(small_maxclass+1,
986                                             alignment, false);
987                                         if (result != NULL) {
988                                                 arena_prof_promoted(result,
989                                                     usize);
990                                         }
991                                 } else {
992                                         result = ipalloc(size, alignment,
993                                             false);
994                                 }
995                         }
996                 } else
997 #endif
998                 {
999 #ifdef JEMALLOC_STATS
1000                         usize = sa2u(size, alignment, NULL);
1001 #endif
1002                         result = ipalloc(size, alignment, false);
1003                 }
1004         }
1005
1006         if (result == NULL) {
1007 #ifdef JEMALLOC_XMALLOC
1008                 if (opt_xmalloc) {
1009                         malloc_write("<jemalloc>: Error in posix_memalign(): "
1010                             "out of memory\n");
1011                         abort();
1012                 }
1013 #endif
1014                 ret = ENOMEM;
1015                 goto RETURN;
1016         }
1017
1018         *memptr = result;
1019         ret = 0;
1020
1021 RETURN:
1022 #ifdef JEMALLOC_STATS
1023         if (result != NULL) {
1024                 assert(usize == isalloc(result));
1025                 ALLOCATED_ADD(usize, 0);
1026         }
1027 #endif
1028 #ifdef JEMALLOC_PROF
1029         if (opt_prof && result != NULL)
1030                 prof_malloc(result, usize, cnt);
1031 #endif
1032         return (ret);
1033 }
1034
1035 JEMALLOC_ATTR(malloc)
1036 JEMALLOC_ATTR(visibility("default"))
1037 void *
1038 JEMALLOC_P(calloc)(size_t num, size_t size)
1039 {
1040         void *ret;
1041         size_t num_size;
1042 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1043         size_t usize
1044 #  ifdef JEMALLOC_CC_SILENCE
1045             = 0
1046 #  endif
1047             ;
1048 #endif
1049 #ifdef JEMALLOC_PROF
1050         prof_thr_cnt_t *cnt
1051 #  ifdef JEMALLOC_CC_SILENCE
1052             = NULL
1053 #  endif
1054             ;
1055 #endif
1056
1057         if (malloc_init()) {
1058                 num_size = 0;
1059                 ret = NULL;
1060                 goto RETURN;
1061         }
1062
1063         num_size = num * size;
1064         if (num_size == 0) {
1065 #ifdef JEMALLOC_SYSV
1066                 if ((opt_sysv == false) && ((num == 0) || (size == 0)))
1067 #endif
1068                         num_size = 1;
1069 #ifdef JEMALLOC_SYSV
1070                 else {
1071                         ret = NULL;
1072                         goto RETURN;
1073                 }
1074 #endif
1075         /*
1076          * Try to avoid division here.  We know that it isn't possible to
1077          * overflow during multiplication if neither operand uses any of the
1078          * most significant half of the bits in a size_t.
1079          */
1080         } else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2)))
1081             && (num_size / size != num)) {
1082                 /* size_t overflow. */
1083                 ret = NULL;
1084                 goto RETURN;
1085         }
1086
1087 #ifdef JEMALLOC_PROF
1088         if (opt_prof) {
1089                 usize = s2u(num_size);
1090                 if ((cnt = prof_alloc_prep(usize)) == NULL) {
1091                         ret = NULL;
1092                         goto RETURN;
1093                 }
1094                 if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize
1095                     <= small_maxclass) {
1096                         ret = icalloc(small_maxclass+1);
1097                         if (ret != NULL)
1098                                 arena_prof_promoted(ret, usize);
1099                 } else
1100                         ret = icalloc(num_size);
1101         } else
1102 #endif
1103         {
1104 #ifdef JEMALLOC_STATS
1105                 usize = s2u(num_size);
1106 #endif
1107                 ret = icalloc(num_size);
1108         }
1109
1110 RETURN:
1111         if (ret == NULL) {
1112 #ifdef JEMALLOC_XMALLOC
1113                 if (opt_xmalloc) {
1114                         malloc_write("<jemalloc>: Error in calloc(): out of "
1115                             "memory\n");
1116                         abort();
1117                 }
1118 #endif
1119                 errno = ENOMEM;
1120         }
1121
1122 #ifdef JEMALLOC_PROF
1123         if (opt_prof && ret != NULL)
1124                 prof_malloc(ret, usize, cnt);
1125 #endif
1126 #ifdef JEMALLOC_STATS
1127         if (ret != NULL) {
1128                 assert(usize == isalloc(ret));
1129                 ALLOCATED_ADD(usize, 0);
1130         }
1131 #endif
1132         return (ret);
1133 }
1134
1135 JEMALLOC_ATTR(visibility("default"))
1136 void *
1137 JEMALLOC_P(realloc)(void *ptr, size_t size)
1138 {
1139         void *ret;
1140 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1141         size_t usize
1142 #  ifdef JEMALLOC_CC_SILENCE
1143             = 0
1144 #  endif
1145             ;
1146         size_t old_size = 0;
1147 #endif
1148 #ifdef JEMALLOC_PROF
1149         prof_thr_cnt_t *cnt
1150 #  ifdef JEMALLOC_CC_SILENCE
1151             = NULL
1152 #  endif
1153             ;
1154         prof_ctx_t *old_ctx
1155 #  ifdef JEMALLOC_CC_SILENCE
1156             = NULL
1157 #  endif
1158             ;
1159 #endif
1160
1161         if (size == 0) {
1162 #ifdef JEMALLOC_SYSV
1163                 if (opt_sysv == false)
1164 #endif
1165                         size = 1;
1166 #ifdef JEMALLOC_SYSV
1167                 else {
1168                         if (ptr != NULL) {
1169 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1170                                 old_size = isalloc(ptr);
1171 #endif
1172 #ifdef JEMALLOC_PROF
1173                                 if (opt_prof) {
1174                                         old_ctx = prof_ctx_get(ptr);
1175                                         cnt = NULL;
1176                                 }
1177 #endif
1178                                 idalloc(ptr);
1179                         }
1180 #ifdef JEMALLOC_PROF
1181                         else if (opt_prof) {
1182                                 old_ctx = NULL;
1183                                 cnt = NULL;
1184                         }
1185 #endif
1186                         ret = NULL;
1187                         goto RETURN;
1188                 }
1189 #endif
1190         }
1191
1192         if (ptr != NULL) {
1193                 assert(malloc_initialized || malloc_initializer ==
1194                     pthread_self());
1195
1196 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1197                 old_size = isalloc(ptr);
1198 #endif
1199 #ifdef JEMALLOC_PROF
1200                 if (opt_prof) {
1201                         usize = s2u(size);
1202                         old_ctx = prof_ctx_get(ptr);
1203                         if ((cnt = prof_alloc_prep(usize)) == NULL) {
1204                                 ret = NULL;
1205                                 goto OOM;
1206                         }
1207                         if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U &&
1208                             usize <= small_maxclass) {
1209                                 ret = iralloc(ptr, small_maxclass+1, 0, 0,
1210                                     false, false);
1211                                 if (ret != NULL)
1212                                         arena_prof_promoted(ret, usize);
1213                         } else
1214                                 ret = iralloc(ptr, size, 0, 0, false, false);
1215                 } else
1216 #endif
1217                 {
1218 #ifdef JEMALLOC_STATS
1219                         usize = s2u(size);
1220 #endif
1221                         ret = iralloc(ptr, size, 0, 0, false, false);
1222                 }
1223
1224 #ifdef JEMALLOC_PROF
1225 OOM:
1226 #endif
1227                 if (ret == NULL) {
1228 #ifdef JEMALLOC_XMALLOC
1229                         if (opt_xmalloc) {
1230                                 malloc_write("<jemalloc>: Error in realloc(): "
1231                                     "out of memory\n");
1232                                 abort();
1233                         }
1234 #endif
1235                         errno = ENOMEM;
1236                 }
1237         } else {
1238 #ifdef JEMALLOC_PROF
1239                 if (opt_prof)
1240                         old_ctx = NULL;
1241 #endif
1242                 if (malloc_init()) {
1243 #ifdef JEMALLOC_PROF
1244                         if (opt_prof)
1245                                 cnt = NULL;
1246 #endif
1247                         ret = NULL;
1248                 } else {
1249 #ifdef JEMALLOC_PROF
1250                         if (opt_prof) {
1251                                 usize = s2u(size);
1252                                 if ((cnt = prof_alloc_prep(usize)) == NULL)
1253                                         ret = NULL;
1254                                 else {
1255                                         if (prof_promote && (uintptr_t)cnt !=
1256                                             (uintptr_t)1U && usize <=
1257                                             small_maxclass) {
1258                                                 ret = imalloc(small_maxclass+1);
1259                                                 if (ret != NULL) {
1260                                                         arena_prof_promoted(ret,
1261                                                             usize);
1262                                                 }
1263                                         } else
1264                                                 ret = imalloc(size);
1265                                 }
1266                         } else
1267 #endif
1268                         {
1269 #ifdef JEMALLOC_STATS
1270                                 usize = s2u(size);
1271 #endif
1272                                 ret = imalloc(size);
1273                         }
1274                 }
1275
1276                 if (ret == NULL) {
1277 #ifdef JEMALLOC_XMALLOC
1278                         if (opt_xmalloc) {
1279                                 malloc_write("<jemalloc>: Error in realloc(): "
1280                                     "out of memory\n");
1281                                 abort();
1282                         }
1283 #endif
1284                         errno = ENOMEM;
1285                 }
1286         }
1287
1288 #ifdef JEMALLOC_SYSV
1289 RETURN:
1290 #endif
1291 #ifdef JEMALLOC_PROF
1292         if (opt_prof)
1293                 prof_realloc(ret, usize, cnt, old_size, old_ctx);
1294 #endif
1295 #ifdef JEMALLOC_STATS
1296         if (ret != NULL) {
1297                 assert(usize == isalloc(ret));
1298                 ALLOCATED_ADD(usize, old_size);
1299         }
1300 #endif
1301         return (ret);
1302 }
1303
1304 JEMALLOC_ATTR(visibility("default"))
1305 void
1306 JEMALLOC_P(free)(void *ptr)
1307 {
1308
1309         if (ptr != NULL) {
1310 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1311                 size_t usize;
1312 #endif
1313
1314                 assert(malloc_initialized || malloc_initializer ==
1315                     pthread_self());
1316
1317 #ifdef JEMALLOC_STATS
1318                 usize = isalloc(ptr);
1319 #endif
1320 #ifdef JEMALLOC_PROF
1321                 if (opt_prof) {
1322 #  ifndef JEMALLOC_STATS
1323                         usize = isalloc(ptr);
1324 #  endif
1325                         prof_free(ptr, usize);
1326                 }
1327 #endif
1328 #ifdef JEMALLOC_STATS
1329                 ALLOCATED_ADD(0, usize);
1330 #endif
1331                 idalloc(ptr);
1332         }
1333 }
1334
1335 /*
1336  * End malloc(3)-compatible functions.
1337  */
1338 /******************************************************************************/
1339 /*
1340  * Begin non-standard override functions.
1341  *
1342  * These overrides are omitted if the JEMALLOC_PREFIX is defined, since the
1343  * entire point is to avoid accidental mixed allocator usage.
1344  */
1345 #ifndef JEMALLOC_PREFIX
1346
1347 #ifdef JEMALLOC_OVERRIDE_MEMALIGN
1348 JEMALLOC_ATTR(malloc)
1349 JEMALLOC_ATTR(visibility("default"))
1350 void *
1351 JEMALLOC_P(memalign)(size_t alignment, size_t size)
1352 {
1353         void *ret;
1354 #ifdef JEMALLOC_CC_SILENCE
1355         int result =
1356 #endif
1357             JEMALLOC_P(posix_memalign)(&ret, alignment, size);
1358 #ifdef JEMALLOC_CC_SILENCE
1359         if (result != 0)
1360                 return (NULL);
1361 #endif
1362         return (ret);
1363 }
1364 #endif
1365
1366 #ifdef JEMALLOC_OVERRIDE_VALLOC
1367 JEMALLOC_ATTR(malloc)
1368 JEMALLOC_ATTR(visibility("default"))
1369 void *
1370 JEMALLOC_P(valloc)(size_t size)
1371 {
1372         void *ret;
1373 #ifdef JEMALLOC_CC_SILENCE
1374         int result =
1375 #endif
1376             JEMALLOC_P(posix_memalign)(&ret, PAGE_SIZE, size);
1377 #ifdef JEMALLOC_CC_SILENCE
1378         if (result != 0)
1379                 return (NULL);
1380 #endif
1381         return (ret);
1382 }
1383 #endif
1384
1385 #endif /* JEMALLOC_PREFIX */
1386 /*
1387  * End non-standard override functions.
1388  */
1389 /******************************************************************************/
1390 /*
1391  * Begin non-standard functions.
1392  */
1393
1394 JEMALLOC_ATTR(visibility("default"))
1395 size_t
1396 JEMALLOC_P(malloc_usable_size)(const void *ptr)
1397 {
1398         size_t ret;
1399
1400         assert(malloc_initialized || malloc_initializer == pthread_self());
1401
1402 #ifdef JEMALLOC_IVSALLOC
1403         ret = ivsalloc(ptr);
1404 #else
1405         assert(ptr != NULL);
1406         ret = isalloc(ptr);
1407 #endif
1408
1409         return (ret);
1410 }
1411
1412 JEMALLOC_ATTR(visibility("default"))
1413 void
1414 JEMALLOC_P(malloc_stats_print)(void (*write_cb)(void *, const char *),
1415     void *cbopaque, const char *opts)
1416 {
1417
1418         stats_print(write_cb, cbopaque, opts);
1419 }
1420
1421 JEMALLOC_ATTR(visibility("default"))
1422 int
1423 JEMALLOC_P(mallctl)(const char *name, void *oldp, size_t *oldlenp, void *newp,
1424     size_t newlen)
1425 {
1426
1427         if (malloc_init())
1428                 return (EAGAIN);
1429
1430         return (ctl_byname(name, oldp, oldlenp, newp, newlen));
1431 }
1432
1433 JEMALLOC_ATTR(visibility("default"))
1434 int
1435 JEMALLOC_P(mallctlnametomib)(const char *name, size_t *mibp, size_t *miblenp)
1436 {
1437
1438         if (malloc_init())
1439                 return (EAGAIN);
1440
1441         return (ctl_nametomib(name, mibp, miblenp));
1442 }
1443
1444 JEMALLOC_ATTR(visibility("default"))
1445 int
1446 JEMALLOC_P(mallctlbymib)(const size_t *mib, size_t miblen, void *oldp,
1447     size_t *oldlenp, void *newp, size_t newlen)
1448 {
1449
1450         if (malloc_init())
1451                 return (EAGAIN);
1452
1453         return (ctl_bymib(mib, miblen, oldp, oldlenp, newp, newlen));
1454 }
1455
1456 JEMALLOC_INLINE void *
1457 iallocm(size_t size, size_t alignment, bool zero)
1458 {
1459
1460         if (alignment != 0)
1461                 return (ipalloc(size, alignment, zero));
1462         else if (zero)
1463                 return (icalloc(size));
1464         else
1465                 return (imalloc(size));
1466 }
1467
1468 JEMALLOC_ATTR(nonnull(1))
1469 JEMALLOC_ATTR(visibility("default"))
1470 int
1471 JEMALLOC_P(allocm)(void **ptr, size_t *rsize, size_t size, int flags)
1472 {
1473         void *p;
1474         size_t usize;
1475         size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK)
1476             & (SIZE_T_MAX-1));
1477         bool zero = flags & ALLOCM_ZERO;
1478 #ifdef JEMALLOC_PROF
1479         prof_thr_cnt_t *cnt;
1480 #endif
1481
1482         assert(ptr != NULL);
1483         assert(size != 0);
1484
1485         if (malloc_init())
1486                 goto OOM;
1487
1488 #ifdef JEMALLOC_PROF
1489         if (opt_prof) {
1490                 usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment,
1491                     NULL);
1492                 if ((cnt = prof_alloc_prep(usize)) == NULL)
1493                         goto OOM;
1494                 if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <=
1495                     small_maxclass) {
1496                         p = iallocm(small_maxclass+1, alignment, zero);
1497                         if (p == NULL)
1498                                 goto OOM;
1499                         arena_prof_promoted(p, usize);
1500                 } else {
1501                         p = iallocm(size, alignment, zero);
1502                         if (p == NULL)
1503                                 goto OOM;
1504                 }
1505
1506                 if (rsize != NULL)
1507                         *rsize = usize;
1508         } else
1509 #endif
1510         {
1511                 p = iallocm(size, alignment, zero);
1512                 if (p == NULL)
1513                         goto OOM;
1514 #ifndef JEMALLOC_STATS
1515                 if (rsize != NULL)
1516 #endif
1517                 {
1518                         usize = (alignment == 0) ? s2u(size) : sa2u(size,
1519                             alignment, NULL);
1520 #ifdef JEMALLOC_STATS
1521                         if (rsize != NULL)
1522 #endif
1523                                 *rsize = usize;
1524                 }
1525         }
1526
1527         *ptr = p;
1528 #ifdef JEMALLOC_STATS
1529         assert(usize == isalloc(p));
1530         ALLOCATED_ADD(usize, 0);
1531 #endif
1532         return (ALLOCM_SUCCESS);
1533 OOM:
1534 #ifdef JEMALLOC_XMALLOC
1535         if (opt_xmalloc) {
1536                 malloc_write("<jemalloc>: Error in allocm(): "
1537                     "out of memory\n");
1538                 abort();
1539         }
1540 #endif
1541         *ptr = NULL;
1542         return (ALLOCM_ERR_OOM);
1543 }
1544
1545 JEMALLOC_ATTR(nonnull(1))
1546 JEMALLOC_ATTR(visibility("default"))
1547 int
1548 JEMALLOC_P(rallocm)(void **ptr, size_t *rsize, size_t size, size_t extra,
1549     int flags)
1550 {
1551         void *p, *q;
1552         size_t usize;
1553 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1554         size_t old_size;
1555 #endif
1556         size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK)
1557             & (SIZE_T_MAX-1));
1558         bool zero = flags & ALLOCM_ZERO;
1559         bool no_move = flags & ALLOCM_NO_MOVE;
1560 #ifdef JEMALLOC_PROF
1561         prof_thr_cnt_t *cnt;
1562         prof_ctx_t *old_ctx;
1563 #endif
1564
1565         assert(ptr != NULL);
1566         assert(*ptr != NULL);
1567         assert(size != 0);
1568         assert(SIZE_T_MAX - size >= extra);
1569         assert(malloc_initialized || malloc_initializer == pthread_self());
1570
1571         p = *ptr;
1572 #ifdef JEMALLOC_PROF
1573         if (opt_prof) {
1574                 /*
1575                  * usize isn't knowable before iralloc() returns when extra is
1576                  * non-zero.  Therefore, compute its maximum possible value and
1577                  * use that in prof_alloc_prep() to decide whether to capture a
1578                  * backtrace.  prof_realloc() will use the actual usize to
1579                  * decide whether to sample.
1580                  */
1581                 size_t max_usize = (alignment == 0) ? s2u(size+extra) :
1582                     sa2u(size+extra, alignment, NULL);
1583                 old_size = isalloc(p);
1584                 old_ctx = prof_ctx_get(p);
1585                 if ((cnt = prof_alloc_prep(max_usize)) == NULL)
1586                         goto OOM;
1587                 if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && max_usize
1588                     <= small_maxclass) {
1589                         q = iralloc(p, small_maxclass+1, (small_maxclass+1 >=
1590                             size+extra) ? 0 : size+extra - (small_maxclass+1),
1591                             alignment, zero, no_move);
1592                         if (q == NULL)
1593                                 goto ERR;
1594                         usize = isalloc(q);
1595                         arena_prof_promoted(q, usize);
1596                 } else {
1597                         q = iralloc(p, size, extra, alignment, zero, no_move);
1598                         if (q == NULL)
1599                                 goto ERR;
1600                         usize = isalloc(q);
1601                 }
1602                 prof_realloc(q, usize, cnt, old_size, old_ctx);
1603         } else
1604 #endif
1605         {
1606 #ifdef JEMALLOC_STATS
1607                 old_size = isalloc(p);
1608 #endif
1609                 q = iralloc(p, size, extra, alignment, zero, no_move);
1610                 if (q == NULL)
1611                         goto ERR;
1612 #ifndef JEMALLOC_STATS
1613                 if (rsize != NULL)
1614 #endif
1615                 {
1616                         usize = isalloc(q);
1617 #ifdef JEMALLOC_STATS
1618                         if (rsize != NULL)
1619 #endif
1620                                 *rsize = usize;
1621                 }
1622         }
1623
1624         *ptr = q;
1625 #ifdef JEMALLOC_STATS
1626         ALLOCATED_ADD(usize, old_size);
1627 #endif
1628         return (ALLOCM_SUCCESS);
1629 ERR:
1630         if (no_move)
1631                 return (ALLOCM_ERR_NOT_MOVED);
1632 #ifdef JEMALLOC_PROF
1633 OOM:
1634 #endif
1635 #ifdef JEMALLOC_XMALLOC
1636         if (opt_xmalloc) {
1637                 malloc_write("<jemalloc>: Error in rallocm(): "
1638                     "out of memory\n");
1639                 abort();
1640         }
1641 #endif
1642         return (ALLOCM_ERR_OOM);
1643 }
1644
1645 JEMALLOC_ATTR(nonnull(1))
1646 JEMALLOC_ATTR(visibility("default"))
1647 int
1648 JEMALLOC_P(sallocm)(const void *ptr, size_t *rsize, int flags)
1649 {
1650         size_t sz;
1651
1652         assert(malloc_initialized || malloc_initializer == pthread_self());
1653
1654 #ifdef JEMALLOC_IVSALLOC
1655         sz = ivsalloc(ptr);
1656 #else
1657         assert(ptr != NULL);
1658         sz = isalloc(ptr);
1659 #endif
1660         assert(rsize != NULL);
1661         *rsize = sz;
1662
1663         return (ALLOCM_SUCCESS);
1664 }
1665
1666 JEMALLOC_ATTR(nonnull(1))
1667 JEMALLOC_ATTR(visibility("default"))
1668 int
1669 JEMALLOC_P(dallocm)(void *ptr, int flags)
1670 {
1671 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1672         size_t usize;
1673 #endif
1674
1675         assert(ptr != NULL);
1676         assert(malloc_initialized || malloc_initializer == pthread_self());
1677
1678 #ifdef JEMALLOC_STATS
1679         usize = isalloc(ptr);
1680 #endif
1681 #ifdef JEMALLOC_PROF
1682         if (opt_prof) {
1683 #  ifndef JEMALLOC_STATS
1684                 usize = isalloc(ptr);
1685 #  endif
1686                 prof_free(ptr, usize);
1687         }
1688 #endif
1689 #ifdef JEMALLOC_STATS
1690         ALLOCATED_ADD(0, usize);
1691 #endif
1692         idalloc(ptr);
1693
1694         return (ALLOCM_SUCCESS);
1695 }
1696
1697 /*
1698  * End non-standard functions.
1699  */
1700 /******************************************************************************/
1701
1702 /*
1703  * The following functions are used by threading libraries for protection of
1704  * malloc during fork().
1705  */
1706
1707 void
1708 jemalloc_prefork(void)
1709 {
1710         unsigned i;
1711
1712         /* Acquire all mutexes in a safe order. */
1713
1714         malloc_mutex_lock(&arenas_lock);
1715         for (i = 0; i < narenas; i++) {
1716                 if (arenas[i] != NULL)
1717                         malloc_mutex_lock(&arenas[i]->lock);
1718         }
1719
1720         malloc_mutex_lock(&base_mtx);
1721
1722         malloc_mutex_lock(&huge_mtx);
1723
1724 #ifdef JEMALLOC_DSS
1725         malloc_mutex_lock(&dss_mtx);
1726 #endif
1727
1728 #ifdef JEMALLOC_SWAP
1729         malloc_mutex_lock(&swap_mtx);
1730 #endif
1731 }
1732
1733 void
1734 jemalloc_postfork(void)
1735 {
1736         unsigned i;
1737
1738         /* Release all mutexes, now that fork() has completed. */
1739
1740 #ifdef JEMALLOC_SWAP
1741         malloc_mutex_unlock(&swap_mtx);
1742 #endif
1743
1744 #ifdef JEMALLOC_DSS
1745         malloc_mutex_unlock(&dss_mtx);
1746 #endif
1747
1748         malloc_mutex_unlock(&huge_mtx);
1749
1750         malloc_mutex_unlock(&base_mtx);
1751
1752         for (i = 0; i < narenas; i++) {
1753                 if (arenas[i] != NULL)
1754                         malloc_mutex_unlock(&arenas[i]->lock);
1755         }
1756         malloc_mutex_unlock(&arenas_lock);
1757 }
1758
1759 /******************************************************************************/