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