2 #include "jemalloc/internal/jemalloc_internal.h"
4 /******************************************************************************/
7 malloc_mutex_t arenas_lock;
10 static unsigned next_arena;
13 __thread arena_t *arenas_tls JEMALLOC_ATTR(tls_model("initial-exec"));
15 pthread_key_t arenas_tsd;
20 __thread thread_allocated_t thread_allocated_tls;
22 pthread_key_t thread_allocated_tsd;
26 /* Set to true once the allocator has been initialized. */
27 static bool malloc_initialized = false;
29 /* Used to let the initializing thread recursively allocate. */
30 static pthread_t malloc_initializer = (unsigned long)0;
32 /* Used to avoid initialization races. */
33 static malloc_mutex_t init_lock = MALLOC_MUTEX_INITIALIZER;
35 #ifdef DYNAMIC_PAGE_SHIFT
43 /* Runtime configuration options. */
44 const char *JEMALLOC_P(malloc_conf) JEMALLOC_ATTR(visibility("default"));
46 bool opt_abort = true;
51 bool opt_abort = false;
53 bool opt_junk = false;
57 bool opt_sysv = false;
59 #ifdef JEMALLOC_XMALLOC
60 bool opt_xmalloc = false;
63 bool opt_zero = false;
65 size_t opt_narenas = 0;
67 /******************************************************************************/
68 /* Function prototypes for non-inline static functions. */
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);
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);
83 /******************************************************************************/
84 /* malloc_message() setup. */
86 #ifdef JEMALLOC_HAVE_ATTR
87 JEMALLOC_ATTR(visibility("hidden"))
92 wrtmessage(void *cbopaque, const char *s)
94 #ifdef JEMALLOC_CC_SILENCE
97 write(STDERR_FILENO, s, strlen(s));
98 #ifdef JEMALLOC_CC_SILENCE
104 void (*JEMALLOC_P(malloc_message))(void *, const char *s)
105 JEMALLOC_ATTR(visibility("default")) = wrtmessage;
107 /******************************************************************************/
109 * Begin miscellaneous support functions.
112 /* Create a new arena and insert it into the arenas array at index ind. */
114 arenas_extend(unsigned ind)
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) {
125 /* Only reached if there is an OOM error. */
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
133 malloc_write("<jemalloc>: Error initializing arena\n");
141 * Choose an arena based on a per-thread value (slow-path code only, called
142 * only by choose_arena()).
145 choose_arena_hard(void)
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);
164 * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so
168 buferror(int errnum, char *buf, size_t buflen)
171 char *b = strerror_r(errno, buf, buflen);
173 strncpy(buf, b, buflen);
174 buf[buflen-1] = '\0';
178 return (strerror_r(errno, buf, buflen));
183 stats_print_atexit(void)
186 #if (defined(JEMALLOC_TCACHE) && defined(JEMALLOC_STATS))
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.
195 for (i = 0; i < narenas; i++) {
196 arena_t *arena = arenas[i];
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.
205 malloc_mutex_lock(&arena->lock);
206 ql_foreach(tcache, &arena->tcache_ql, link) {
207 tcache_stats_merge(tcache, arena);
209 malloc_mutex_unlock(&arena->lock);
213 JEMALLOC_P(malloc_stats_print)(NULL, NULL, NULL);
217 * End miscellaneous support functions.
219 /******************************************************************************/
221 * Begin initialization functions.
230 result = sysconf(_SC_NPROCESSORS_ONLN);
235 ret = (unsigned)result;
240 #if (defined(JEMALLOC_STATS) && defined(NO_TLS))
242 thread_allocated_cleanup(void *arg)
244 uint64_t *allocated = (uint64_t *)arg;
246 if (allocated != NULL)
252 * FreeBSD's pthreads implementation calls malloc(3), so the malloc
253 * implementation has to take pains to avoid infinite recursion during
260 if (malloc_initialized == false)
261 return (malloc_init_hard());
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)
271 const char *opts = *opts_p;
275 for (accept = false; accept == false;) {
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':
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':
289 case '0': case '1': case '2': case '3': case '4':
290 case '5': case '6': case '7': case '8': case '9':
296 *klen_p = (uintptr_t)opts - 1 - (uintptr_t)*k_p;
301 if (opts != *opts_p) {
302 malloc_write("<jemalloc>: Conf string "
307 malloc_write("<jemalloc>: Malformed conf "
313 for (accept = false; accept == false;) {
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
326 malloc_write("<jemalloc>: Conf string "
327 "ends with comma\n");
329 *vlen_p = (uintptr_t)opts - 1 - (uintptr_t)*v_p;
333 *vlen_p = (uintptr_t)opts - (uintptr_t)*v_p;
347 malloc_conf_error(const char *msg, const char *k, size_t klen, const char *v,
350 char buf[PATH_MAX + 1];
352 malloc_write("<jemalloc>: ");
355 memcpy(buf, k, klen);
356 memcpy(&buf[klen], ":", 1);
357 memcpy(&buf[klen+1], v, vlen);
358 buf[klen+1+vlen] = '\0';
364 malloc_conf_init(void)
367 char buf[PATH_MAX + 1];
368 const char *opts, *k, *v;
371 for (i = 0; i < 3; i++) {
372 /* Get runtime configuration. */
375 if (JEMALLOC_P(malloc_conf) != NULL) {
377 * Use options that were compiled into the
380 opts = JEMALLOC_P(malloc_conf);
382 /* No configuration specified. */
389 const char *linkname =
390 #ifdef JEMALLOC_PREFIX
391 "/etc/"JEMALLOC_PREFIX"malloc.conf"
397 if ((linklen = readlink(linkname, buf,
398 sizeof(buf) - 1)) != -1) {
400 * Use the contents of the "/etc/malloc.conf"
401 * symbolic link's name.
406 /* No configuration specified. */
413 const char *envname =
414 #ifdef JEMALLOC_PREFIX
415 JEMALLOC_CPREFIX"MALLOC_CONF"
421 if ((opts = getenv(envname)) != NULL) {
423 * Do nothing; opts is already initialized to
424 * the value of the JEMALLOC_OPTIONS
425 * environment variable.
428 /* No configuration specified. */
441 while (*opts != '\0' && malloc_conf_next(&opts, &k, &klen, &v,
443 #define CONF_HANDLE_BOOL(n) \
444 if (sizeof(#n)-1 == klen && strncmp(#n, k, \
446 if (strncmp("true", v, vlen) == 0 && \
447 vlen == sizeof("true")-1) \
449 else if (strncmp("false", v, vlen) == \
450 0 && vlen == sizeof("false")-1) \
454 "Invalid conf value", \
459 #define CONF_HANDLE_SIZE_T(n, min, max) \
460 if (sizeof(#n)-1 == klen && strncmp(#n, k, \
466 ul = strtoul(v, &end, 0); \
467 if (errno != 0 || (uintptr_t)end - \
468 (uintptr_t)v != vlen) { \
470 "Invalid conf value", \
472 } else if (ul < min || ul > max) { \
474 "Out-of-range conf value", \
480 #define CONF_HANDLE_SSIZE_T(n, min, max) \
481 if (sizeof(#n)-1 == klen && strncmp(#n, k, \
487 l = strtol(v, &end, 0); \
488 if (errno != 0 || (uintptr_t)end - \
489 (uintptr_t)v != vlen) { \
491 "Invalid conf value", \
493 } else if (l < (ssize_t)min || l > \
496 "Out-of-range conf value", \
502 #define CONF_HANDLE_CHAR_P(n, d) \
503 if (sizeof(#n)-1 == klen && strncmp(#n, k, \
505 size_t cpylen = (vlen <= \
506 sizeof(opt_##n)-1) ? vlen : \
508 strncpy(opt_##n, v, cpylen); \
509 opt_##n[cpylen] = '\0'; \
513 CONF_HANDLE_BOOL(abort)
514 CONF_HANDLE_SIZE_T(lg_qspace_max, LG_QUANTUM,
516 CONF_HANDLE_SIZE_T(lg_cspace_max, LG_QUANTUM,
519 * Chunks always require at least one * header page,
520 * plus one data page.
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)
529 CONF_HANDLE_BOOL(junk)
530 CONF_HANDLE_BOOL(zero)
533 CONF_HANDLE_BOOL(sysv)
535 #ifdef JEMALLOC_XMALLOC
536 CONF_HANDLE_BOOL(xmalloc)
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)
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)
561 CONF_HANDLE_BOOL(overcommit)
563 malloc_conf_error("Invalid conf pair", k, klen, v,
565 #undef CONF_HANDLE_BOOL
566 #undef CONF_HANDLE_SIZE_T
567 #undef CONF_HANDLE_SSIZE_T
568 #undef CONF_HANDLE_CHAR_P
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;
582 malloc_init_hard(void)
584 arena_t *init_arenas[1];
586 malloc_mutex_lock(&init_lock);
587 if (malloc_initialized || malloc_initializer == pthread_self()) {
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.
593 malloc_mutex_unlock(&init_lock);
596 if (malloc_initializer != (unsigned long)0) {
597 /* Busy-wait until the initializing thread completes. */
599 malloc_mutex_unlock(&init_lock);
601 malloc_mutex_lock(&init_lock);
602 } while (malloc_initialized == false);
603 malloc_mutex_unlock(&init_lock);
607 #ifdef DYNAMIC_PAGE_SHIFT
612 result = sysconf(_SC_PAGESIZE);
613 assert(result != -1);
614 pagesize = (unsigned)result;
617 * We assume that pagesize is a power of 2 when calculating
618 * pagesize_mask and lg_pagesize.
620 assert(((result - 1) & result) == 0);
621 pagesize_mask = result - 1;
622 lg_pagesize = ffs((int)result) - 1;
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");
641 malloc_mutex_unlock(&init_lock);
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");
655 malloc_mutex_unlock(&init_lock);
660 malloc_mutex_unlock(&init_lock);
669 malloc_mutex_unlock(&init_lock);
673 #ifdef JEMALLOC_TCACHE
678 malloc_mutex_unlock(&init_lock);
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)
686 malloc_mutex_unlock(&init_lock);
692 * Create enough scaffolding to allow recursive allocation in
696 arenas = init_arenas;
697 memset(arenas, 0, sizeof(arena_t *) * narenas);
700 * Initialize one arena here. The rest are lazily created in
701 * choose_arena_hard().
704 if (arenas[0] == NULL) {
705 malloc_mutex_unlock(&init_lock);
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
714 ARENA_SET(arenas[0]);
716 malloc_mutex_init(&arenas_lock);
720 malloc_mutex_unlock(&init_lock);
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);
731 if (opt_narenas == 0) {
733 * For SMP systems, create more than one arena per CPU by
737 opt_narenas = ncpus << 2;
741 narenas = opt_narenas;
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.
747 if (narenas > chunksize / sizeof(arena_t *)) {
748 char buf[UMAX2S_BUFSIZE];
750 narenas = chunksize / sizeof(arena_t *);
751 malloc_write("<jemalloc>: Reducing narenas to limit (");
752 malloc_write(u2s(narenas, 10, buf));
756 next_arena = (narenas > 0) ? 1 : 0;
759 if (pthread_key_create(&arenas_tsd, NULL) != 0) {
760 malloc_mutex_unlock(&init_lock);
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);
772 * Zero the array. In practice, this should always be pre-zeroed,
773 * since it was just mmap()ed, but let's be sure.
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];
780 /* Register the custom zone. */
781 malloc_zone_register(create_zone());
784 * Convert the default szone to an "overlay zone" that is capable of
785 * deallocating szone-allocated objects, but allocating new objects
788 szone2ozone(malloc_default_zone());
791 malloc_initialized = true;
792 malloc_mutex_unlock(&init_lock);
798 JEMALLOC_ATTR(constructor)
800 jemalloc_darwin_init(void)
803 if (malloc_init_hard())
809 * End initialization functions.
811 /******************************************************************************/
813 * Begin malloc(3)-compatible functions.
816 JEMALLOC_ATTR(malloc)
817 JEMALLOC_ATTR(visibility("default"))
819 JEMALLOC_P(malloc)(size_t size)
822 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
824 # ifdef JEMALLOC_CC_SILENCE
831 # ifdef JEMALLOC_CC_SILENCE
844 if (opt_sysv == false)
849 # ifdef JEMALLOC_XMALLOC
851 malloc_write("<jemalloc>: Error in malloc(): "
865 if ((cnt = prof_alloc_prep(usize)) == NULL) {
869 if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <=
871 ret = imalloc(small_maxclass+1);
873 arena_prof_promoted(ret, usize);
879 #ifdef JEMALLOC_STATS
887 #ifdef JEMALLOC_XMALLOC
889 malloc_write("<jemalloc>: Error in malloc(): "
901 if (opt_prof && ret != NULL)
902 prof_malloc(ret, usize, cnt);
904 #ifdef JEMALLOC_STATS
906 assert(usize == isalloc(ret));
907 ALLOCATED_ADD(usize, 0);
913 JEMALLOC_ATTR(nonnull(1))
914 JEMALLOC_ATTR(visibility("default"))
916 JEMALLOC_P(posix_memalign)(void **memptr, size_t alignment, size_t size)
920 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
922 # ifdef JEMALLOC_CC_SILENCE
929 # ifdef JEMALLOC_CC_SILENCE
940 if (opt_sysv == false)
945 # ifdef JEMALLOC_XMALLOC
947 malloc_write("<jemalloc>: Error in "
948 "posix_memalign(): invalid size "
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
966 malloc_write("<jemalloc>: Error in "
967 "posix_memalign(): invalid alignment\n");
978 usize = sa2u(size, alignment, NULL);
979 if ((cnt = prof_alloc_prep(usize)) == NULL) {
983 if (prof_promote && (uintptr_t)cnt !=
984 (uintptr_t)1U && usize <= small_maxclass) {
985 result = ipalloc(small_maxclass+1,
987 if (result != NULL) {
988 arena_prof_promoted(result,
992 result = ipalloc(size, alignment,
999 #ifdef JEMALLOC_STATS
1000 usize = sa2u(size, alignment, NULL);
1002 result = ipalloc(size, alignment, false);
1006 if (result == NULL) {
1007 #ifdef JEMALLOC_XMALLOC
1009 malloc_write("<jemalloc>: Error in posix_memalign(): "
1022 #ifdef JEMALLOC_STATS
1023 if (result != NULL) {
1024 assert(usize == isalloc(result));
1025 ALLOCATED_ADD(usize, 0);
1028 #ifdef JEMALLOC_PROF
1029 if (opt_prof && result != NULL)
1030 prof_malloc(result, usize, cnt);
1035 JEMALLOC_ATTR(malloc)
1036 JEMALLOC_ATTR(visibility("default"))
1038 JEMALLOC_P(calloc)(size_t num, size_t size)
1042 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1044 # ifdef JEMALLOC_CC_SILENCE
1049 #ifdef JEMALLOC_PROF
1051 # ifdef JEMALLOC_CC_SILENCE
1057 if (malloc_init()) {
1063 num_size = num * size;
1064 if (num_size == 0) {
1065 #ifdef JEMALLOC_SYSV
1066 if ((opt_sysv == false) && ((num == 0) || (size == 0)))
1069 #ifdef JEMALLOC_SYSV
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.
1080 } else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2)))
1081 && (num_size / size != num)) {
1082 /* size_t overflow. */
1087 #ifdef JEMALLOC_PROF
1089 usize = s2u(num_size);
1090 if ((cnt = prof_alloc_prep(usize)) == NULL) {
1094 if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize
1095 <= small_maxclass) {
1096 ret = icalloc(small_maxclass+1);
1098 arena_prof_promoted(ret, usize);
1100 ret = icalloc(num_size);
1104 #ifdef JEMALLOC_STATS
1105 usize = s2u(num_size);
1107 ret = icalloc(num_size);
1112 #ifdef JEMALLOC_XMALLOC
1114 malloc_write("<jemalloc>: Error in calloc(): out of "
1122 #ifdef JEMALLOC_PROF
1123 if (opt_prof && ret != NULL)
1124 prof_malloc(ret, usize, cnt);
1126 #ifdef JEMALLOC_STATS
1128 assert(usize == isalloc(ret));
1129 ALLOCATED_ADD(usize, 0);
1135 JEMALLOC_ATTR(visibility("default"))
1137 JEMALLOC_P(realloc)(void *ptr, size_t size)
1140 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1142 # ifdef JEMALLOC_CC_SILENCE
1146 size_t old_size = 0;
1148 #ifdef JEMALLOC_PROF
1150 # ifdef JEMALLOC_CC_SILENCE
1155 # ifdef JEMALLOC_CC_SILENCE
1162 #ifdef JEMALLOC_SYSV
1163 if (opt_sysv == false)
1166 #ifdef JEMALLOC_SYSV
1169 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1170 old_size = isalloc(ptr);
1172 #ifdef JEMALLOC_PROF
1174 old_ctx = prof_ctx_get(ptr);
1180 #ifdef JEMALLOC_PROF
1181 else if (opt_prof) {
1193 assert(malloc_initialized || malloc_initializer ==
1196 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1197 old_size = isalloc(ptr);
1199 #ifdef JEMALLOC_PROF
1202 old_ctx = prof_ctx_get(ptr);
1203 if ((cnt = prof_alloc_prep(usize)) == NULL) {
1207 if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U &&
1208 usize <= small_maxclass) {
1209 ret = iralloc(ptr, small_maxclass+1, 0, 0,
1212 arena_prof_promoted(ret, usize);
1214 ret = iralloc(ptr, size, 0, 0, false, false);
1218 #ifdef JEMALLOC_STATS
1221 ret = iralloc(ptr, size, 0, 0, false, false);
1224 #ifdef JEMALLOC_PROF
1228 #ifdef JEMALLOC_XMALLOC
1230 malloc_write("<jemalloc>: Error in realloc(): "
1238 #ifdef JEMALLOC_PROF
1242 if (malloc_init()) {
1243 #ifdef JEMALLOC_PROF
1249 #ifdef JEMALLOC_PROF
1252 if ((cnt = prof_alloc_prep(usize)) == NULL)
1255 if (prof_promote && (uintptr_t)cnt !=
1256 (uintptr_t)1U && usize <=
1258 ret = imalloc(small_maxclass+1);
1260 arena_prof_promoted(ret,
1264 ret = imalloc(size);
1269 #ifdef JEMALLOC_STATS
1272 ret = imalloc(size);
1277 #ifdef JEMALLOC_XMALLOC
1279 malloc_write("<jemalloc>: Error in realloc(): "
1288 #ifdef JEMALLOC_SYSV
1291 #ifdef JEMALLOC_PROF
1293 prof_realloc(ret, usize, cnt, old_size, old_ctx);
1295 #ifdef JEMALLOC_STATS
1297 assert(usize == isalloc(ret));
1298 ALLOCATED_ADD(usize, old_size);
1304 JEMALLOC_ATTR(visibility("default"))
1306 JEMALLOC_P(free)(void *ptr)
1310 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1314 assert(malloc_initialized || malloc_initializer ==
1317 #ifdef JEMALLOC_STATS
1318 usize = isalloc(ptr);
1320 #ifdef JEMALLOC_PROF
1322 # ifndef JEMALLOC_STATS
1323 usize = isalloc(ptr);
1325 prof_free(ptr, usize);
1328 #ifdef JEMALLOC_STATS
1329 ALLOCATED_ADD(0, usize);
1336 * End malloc(3)-compatible functions.
1338 /******************************************************************************/
1340 * Begin non-standard override functions.
1342 * These overrides are omitted if the JEMALLOC_PREFIX is defined, since the
1343 * entire point is to avoid accidental mixed allocator usage.
1345 #ifndef JEMALLOC_PREFIX
1347 #ifdef JEMALLOC_OVERRIDE_MEMALIGN
1348 JEMALLOC_ATTR(malloc)
1349 JEMALLOC_ATTR(visibility("default"))
1351 JEMALLOC_P(memalign)(size_t alignment, size_t size)
1354 #ifdef JEMALLOC_CC_SILENCE
1357 JEMALLOC_P(posix_memalign)(&ret, alignment, size);
1358 #ifdef JEMALLOC_CC_SILENCE
1366 #ifdef JEMALLOC_OVERRIDE_VALLOC
1367 JEMALLOC_ATTR(malloc)
1368 JEMALLOC_ATTR(visibility("default"))
1370 JEMALLOC_P(valloc)(size_t size)
1373 #ifdef JEMALLOC_CC_SILENCE
1376 JEMALLOC_P(posix_memalign)(&ret, PAGE_SIZE, size);
1377 #ifdef JEMALLOC_CC_SILENCE
1385 #endif /* JEMALLOC_PREFIX */
1387 * End non-standard override functions.
1389 /******************************************************************************/
1391 * Begin non-standard functions.
1394 JEMALLOC_ATTR(visibility("default"))
1396 JEMALLOC_P(malloc_usable_size)(const void *ptr)
1400 assert(malloc_initialized || malloc_initializer == pthread_self());
1402 #ifdef JEMALLOC_IVSALLOC
1403 ret = ivsalloc(ptr);
1405 assert(ptr != NULL);
1412 JEMALLOC_ATTR(visibility("default"))
1414 JEMALLOC_P(malloc_stats_print)(void (*write_cb)(void *, const char *),
1415 void *cbopaque, const char *opts)
1418 stats_print(write_cb, cbopaque, opts);
1421 JEMALLOC_ATTR(visibility("default"))
1423 JEMALLOC_P(mallctl)(const char *name, void *oldp, size_t *oldlenp, void *newp,
1430 return (ctl_byname(name, oldp, oldlenp, newp, newlen));
1433 JEMALLOC_ATTR(visibility("default"))
1435 JEMALLOC_P(mallctlnametomib)(const char *name, size_t *mibp, size_t *miblenp)
1441 return (ctl_nametomib(name, mibp, miblenp));
1444 JEMALLOC_ATTR(visibility("default"))
1446 JEMALLOC_P(mallctlbymib)(const size_t *mib, size_t miblen, void *oldp,
1447 size_t *oldlenp, void *newp, size_t newlen)
1453 return (ctl_bymib(mib, miblen, oldp, oldlenp, newp, newlen));
1456 JEMALLOC_INLINE void *
1457 iallocm(size_t size, size_t alignment, bool zero)
1461 return (ipalloc(size, alignment, zero));
1463 return (icalloc(size));
1465 return (imalloc(size));
1468 JEMALLOC_ATTR(nonnull(1))
1469 JEMALLOC_ATTR(visibility("default"))
1471 JEMALLOC_P(allocm)(void **ptr, size_t *rsize, size_t size, int flags)
1475 size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK)
1477 bool zero = flags & ALLOCM_ZERO;
1478 #ifdef JEMALLOC_PROF
1479 prof_thr_cnt_t *cnt;
1482 assert(ptr != NULL);
1488 #ifdef JEMALLOC_PROF
1490 usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment,
1492 if ((cnt = prof_alloc_prep(usize)) == NULL)
1494 if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <=
1496 p = iallocm(small_maxclass+1, alignment, zero);
1499 arena_prof_promoted(p, usize);
1501 p = iallocm(size, alignment, zero);
1511 p = iallocm(size, alignment, zero);
1514 #ifndef JEMALLOC_STATS
1518 usize = (alignment == 0) ? s2u(size) : sa2u(size,
1520 #ifdef JEMALLOC_STATS
1528 #ifdef JEMALLOC_STATS
1529 assert(usize == isalloc(p));
1530 ALLOCATED_ADD(usize, 0);
1532 return (ALLOCM_SUCCESS);
1534 #ifdef JEMALLOC_XMALLOC
1536 malloc_write("<jemalloc>: Error in allocm(): "
1542 return (ALLOCM_ERR_OOM);
1545 JEMALLOC_ATTR(nonnull(1))
1546 JEMALLOC_ATTR(visibility("default"))
1548 JEMALLOC_P(rallocm)(void **ptr, size_t *rsize, size_t size, size_t extra,
1553 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1556 size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK)
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;
1565 assert(ptr != NULL);
1566 assert(*ptr != NULL);
1568 assert(SIZE_T_MAX - size >= extra);
1569 assert(malloc_initialized || malloc_initializer == pthread_self());
1572 #ifdef JEMALLOC_PROF
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.
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)
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);
1595 arena_prof_promoted(q, usize);
1597 q = iralloc(p, size, extra, alignment, zero, no_move);
1602 prof_realloc(q, usize, cnt, old_size, old_ctx);
1606 #ifdef JEMALLOC_STATS
1607 old_size = isalloc(p);
1609 q = iralloc(p, size, extra, alignment, zero, no_move);
1612 #ifndef JEMALLOC_STATS
1617 #ifdef JEMALLOC_STATS
1625 #ifdef JEMALLOC_STATS
1626 ALLOCATED_ADD(usize, old_size);
1628 return (ALLOCM_SUCCESS);
1631 return (ALLOCM_ERR_NOT_MOVED);
1632 #ifdef JEMALLOC_PROF
1635 #ifdef JEMALLOC_XMALLOC
1637 malloc_write("<jemalloc>: Error in rallocm(): "
1642 return (ALLOCM_ERR_OOM);
1645 JEMALLOC_ATTR(nonnull(1))
1646 JEMALLOC_ATTR(visibility("default"))
1648 JEMALLOC_P(sallocm)(const void *ptr, size_t *rsize, int flags)
1652 assert(malloc_initialized || malloc_initializer == pthread_self());
1654 #ifdef JEMALLOC_IVSALLOC
1657 assert(ptr != NULL);
1660 assert(rsize != NULL);
1663 return (ALLOCM_SUCCESS);
1666 JEMALLOC_ATTR(nonnull(1))
1667 JEMALLOC_ATTR(visibility("default"))
1669 JEMALLOC_P(dallocm)(void *ptr, int flags)
1671 #if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS))
1675 assert(ptr != NULL);
1676 assert(malloc_initialized || malloc_initializer == pthread_self());
1678 #ifdef JEMALLOC_STATS
1679 usize = isalloc(ptr);
1681 #ifdef JEMALLOC_PROF
1683 # ifndef JEMALLOC_STATS
1684 usize = isalloc(ptr);
1686 prof_free(ptr, usize);
1689 #ifdef JEMALLOC_STATS
1690 ALLOCATED_ADD(0, usize);
1694 return (ALLOCM_SUCCESS);
1698 * End non-standard functions.
1700 /******************************************************************************/
1703 * The following functions are used by threading libraries for protection of
1704 * malloc during fork().
1708 jemalloc_prefork(void)
1712 /* Acquire all mutexes in a safe order. */
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);
1720 malloc_mutex_lock(&base_mtx);
1722 malloc_mutex_lock(&huge_mtx);
1725 malloc_mutex_lock(&dss_mtx);
1728 #ifdef JEMALLOC_SWAP
1729 malloc_mutex_lock(&swap_mtx);
1734 jemalloc_postfork(void)
1738 /* Release all mutexes, now that fork() has completed. */
1740 #ifdef JEMALLOC_SWAP
1741 malloc_mutex_unlock(&swap_mtx);
1745 malloc_mutex_unlock(&dss_mtx);
1748 malloc_mutex_unlock(&huge_mtx);
1750 malloc_mutex_unlock(&base_mtx);
1752 for (i = 0; i < narenas; i++) {
1753 if (arenas[i] != NULL)
1754 malloc_mutex_unlock(&arenas[i]->lock);
1756 malloc_mutex_unlock(&arenas_lock);
1759 /******************************************************************************/