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