jemalloc.c revision cec0d63d8bc46205d38456024176a0ece590253e
1#define JEMALLOC_C_ 2#include "jemalloc/internal/jemalloc_internal.h" 3 4/******************************************************************************/ 5/* Data. */ 6 7/* Runtime configuration options. */ 8const char *je_malloc_conf JEMALLOC_ATTR(weak); 9bool opt_abort = 10#ifdef JEMALLOC_DEBUG 11 true 12#else 13 false 14#endif 15 ; 16const char *opt_junk = 17#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL)) 18 "true" 19#else 20 "false" 21#endif 22 ; 23bool opt_junk_alloc = 24#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL)) 25 true 26#else 27 false 28#endif 29 ; 30bool opt_junk_free = 31#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL)) 32 true 33#else 34 false 35#endif 36 ; 37 38size_t opt_quarantine = ZU(0); 39bool opt_redzone = false; 40bool opt_utrace = false; 41bool opt_xmalloc = false; 42bool opt_zero = false; 43size_t opt_narenas = 0; 44 45/* Initialized to true if the process is running inside Valgrind. */ 46bool in_valgrind; 47 48unsigned ncpus; 49 50/* Protects arenas initialization (arenas, narenas_total). */ 51static malloc_mutex_t arenas_lock; 52/* 53 * Arenas that are used to service external requests. Not all elements of the 54 * arenas array are necessarily used; arenas are created lazily as needed. 55 * 56 * arenas[0..narenas_auto) are used for automatic multiplexing of threads and 57 * arenas. arenas[narenas_auto..narenas_total) are only used if the application 58 * takes some action to create them and allocate from them. 59 */ 60static arena_t **arenas; 61static unsigned narenas_total; 62static arena_t *a0; /* arenas[0]; read-only after initialization. */ 63static unsigned narenas_auto; /* Read-only after initialization. */ 64 65typedef enum { 66 malloc_init_uninitialized = 3, 67 malloc_init_a0_initialized = 2, 68 malloc_init_recursible = 1, 69 malloc_init_initialized = 0 /* Common case --> jnz. */ 70} malloc_init_t; 71static malloc_init_t malloc_init_state = malloc_init_uninitialized; 72 73JEMALLOC_ALIGNED(CACHELINE) 74const size_t index2size_tab[NSIZES] = { 75#define SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup) \ 76 ((ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta)), 77 SIZE_CLASSES 78#undef SC 79}; 80 81JEMALLOC_ALIGNED(CACHELINE) 82const uint8_t size2index_tab[] = { 83#if LG_TINY_MIN == 0 84#warning "Dangerous LG_TINY_MIN" 85#define S2B_0(i) i, 86#elif LG_TINY_MIN == 1 87#warning "Dangerous LG_TINY_MIN" 88#define S2B_1(i) i, 89#elif LG_TINY_MIN == 2 90#warning "Dangerous LG_TINY_MIN" 91#define S2B_2(i) i, 92#elif LG_TINY_MIN == 3 93#define S2B_3(i) i, 94#elif LG_TINY_MIN == 4 95#define S2B_4(i) i, 96#elif LG_TINY_MIN == 5 97#define S2B_5(i) i, 98#elif LG_TINY_MIN == 6 99#define S2B_6(i) i, 100#elif LG_TINY_MIN == 7 101#define S2B_7(i) i, 102#elif LG_TINY_MIN == 8 103#define S2B_8(i) i, 104#elif LG_TINY_MIN == 9 105#define S2B_9(i) i, 106#elif LG_TINY_MIN == 10 107#define S2B_10(i) i, 108#elif LG_TINY_MIN == 11 109#define S2B_11(i) i, 110#else 111#error "Unsupported LG_TINY_MIN" 112#endif 113#if LG_TINY_MIN < 1 114#define S2B_1(i) S2B_0(i) S2B_0(i) 115#endif 116#if LG_TINY_MIN < 2 117#define S2B_2(i) S2B_1(i) S2B_1(i) 118#endif 119#if LG_TINY_MIN < 3 120#define S2B_3(i) S2B_2(i) S2B_2(i) 121#endif 122#if LG_TINY_MIN < 4 123#define S2B_4(i) S2B_3(i) S2B_3(i) 124#endif 125#if LG_TINY_MIN < 5 126#define S2B_5(i) S2B_4(i) S2B_4(i) 127#endif 128#if LG_TINY_MIN < 6 129#define S2B_6(i) S2B_5(i) S2B_5(i) 130#endif 131#if LG_TINY_MIN < 7 132#define S2B_7(i) S2B_6(i) S2B_6(i) 133#endif 134#if LG_TINY_MIN < 8 135#define S2B_8(i) S2B_7(i) S2B_7(i) 136#endif 137#if LG_TINY_MIN < 9 138#define S2B_9(i) S2B_8(i) S2B_8(i) 139#endif 140#if LG_TINY_MIN < 10 141#define S2B_10(i) S2B_9(i) S2B_9(i) 142#endif 143#if LG_TINY_MIN < 11 144#define S2B_11(i) S2B_10(i) S2B_10(i) 145#endif 146#define S2B_no(i) 147#define SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup) \ 148 S2B_##lg_delta_lookup(index) 149 SIZE_CLASSES 150#undef S2B_3 151#undef S2B_4 152#undef S2B_5 153#undef S2B_6 154#undef S2B_7 155#undef S2B_8 156#undef S2B_9 157#undef S2B_10 158#undef S2B_11 159#undef S2B_no 160#undef SC 161}; 162 163#ifdef JEMALLOC_THREADED_INIT 164/* Used to let the initializing thread recursively allocate. */ 165# define NO_INITIALIZER ((unsigned long)0) 166# define INITIALIZER pthread_self() 167# define IS_INITIALIZER (malloc_initializer == pthread_self()) 168static pthread_t malloc_initializer = NO_INITIALIZER; 169#else 170# define NO_INITIALIZER false 171# define INITIALIZER true 172# define IS_INITIALIZER malloc_initializer 173static bool malloc_initializer = NO_INITIALIZER; 174#endif 175 176/* Used to avoid initialization races. */ 177#ifdef _WIN32 178#if _WIN32_WINNT >= 0x0600 179static malloc_mutex_t init_lock = SRWLOCK_INIT; 180#else 181static malloc_mutex_t init_lock; 182static bool init_lock_initialized = false; 183 184JEMALLOC_ATTR(constructor) 185static void WINAPI 186_init_init_lock(void) 187{ 188 189 /* If another constructor in the same binary is using mallctl to 190 * e.g. setup chunk hooks, it may end up running before this one, 191 * and malloc_init_hard will crash trying to lock the uninitialized 192 * lock. So we force an initialization of the lock in 193 * malloc_init_hard as well. We don't try to care about atomicity 194 * of the accessed to the init_lock_initialized boolean, since it 195 * really only matters early in the process creation, before any 196 * separate thread normally starts doing anything. */ 197 if (!init_lock_initialized) 198 malloc_mutex_init(&init_lock); 199 init_lock_initialized = true; 200} 201 202#ifdef _MSC_VER 203# pragma section(".CRT$XCU", read) 204JEMALLOC_SECTION(".CRT$XCU") JEMALLOC_ATTR(used) 205static const void (WINAPI *init_init_lock)(void) = _init_init_lock; 206#endif 207#endif 208#else 209static malloc_mutex_t init_lock = MALLOC_MUTEX_INITIALIZER; 210#endif 211 212typedef struct { 213 void *p; /* Input pointer (as in realloc(p, s)). */ 214 size_t s; /* Request size. */ 215 void *r; /* Result pointer. */ 216} malloc_utrace_t; 217 218#ifdef JEMALLOC_UTRACE 219# define UTRACE(a, b, c) do { \ 220 if (unlikely(opt_utrace)) { \ 221 int utrace_serrno = errno; \ 222 malloc_utrace_t ut; \ 223 ut.p = (a); \ 224 ut.s = (b); \ 225 ut.r = (c); \ 226 utrace(&ut, sizeof(ut)); \ 227 errno = utrace_serrno; \ 228 } \ 229} while (0) 230#else 231# define UTRACE(a, b, c) 232#endif 233 234/******************************************************************************/ 235/* 236 * Function prototypes for static functions that are referenced prior to 237 * definition. 238 */ 239 240static bool malloc_init_hard_a0(void); 241static bool malloc_init_hard(void); 242 243/******************************************************************************/ 244/* 245 * Begin miscellaneous support functions. 246 */ 247 248JEMALLOC_ALWAYS_INLINE_C bool 249malloc_initialized(void) 250{ 251 252 return (malloc_init_state == malloc_init_initialized); 253} 254 255JEMALLOC_ALWAYS_INLINE_C void 256malloc_thread_init(void) 257{ 258 259 /* 260 * TSD initialization can't be safely done as a side effect of 261 * deallocation, because it is possible for a thread to do nothing but 262 * deallocate its TLS data via free(), in which case writing to TLS 263 * would cause write-after-free memory corruption. The quarantine 264 * facility *only* gets used as a side effect of deallocation, so make 265 * a best effort attempt at initializing its TSD by hooking all 266 * allocation events. 267 */ 268 if (config_fill && unlikely(opt_quarantine)) 269 quarantine_alloc_hook(); 270} 271 272JEMALLOC_ALWAYS_INLINE_C bool 273malloc_init_a0(void) 274{ 275 276 if (unlikely(malloc_init_state == malloc_init_uninitialized)) 277 return (malloc_init_hard_a0()); 278 return (false); 279} 280 281JEMALLOC_ALWAYS_INLINE_C bool 282malloc_init(void) 283{ 284 285 if (unlikely(!malloc_initialized()) && malloc_init_hard()) 286 return (true); 287 malloc_thread_init(); 288 289 return (false); 290} 291 292/* 293 * The a0*() functions are used instead of i[mcd]alloc() in situations that 294 * cannot tolerate TLS variable access. 295 */ 296 297arena_t * 298a0get(void) 299{ 300 301 assert(a0 != NULL); 302 return (a0); 303} 304 305static void * 306a0ialloc(size_t size, bool zero, bool is_metadata) 307{ 308 309 if (unlikely(malloc_init_a0())) 310 return (NULL); 311 312 return (iallocztm(NULL, size, zero, false, is_metadata, a0get())); 313} 314 315static void 316a0idalloc(void *ptr, bool is_metadata) 317{ 318 319 idalloctm(NULL, ptr, false, is_metadata); 320} 321 322void * 323a0malloc(size_t size) 324{ 325 326 return (a0ialloc(size, false, true)); 327} 328 329void 330a0dalloc(void *ptr) 331{ 332 333 a0idalloc(ptr, true); 334} 335 336/* 337 * FreeBSD's libc uses the bootstrap_*() functions in bootstrap-senstive 338 * situations that cannot tolerate TLS variable access (TLS allocation and very 339 * early internal data structure initialization). 340 */ 341 342void * 343bootstrap_malloc(size_t size) 344{ 345 346 if (unlikely(size == 0)) 347 size = 1; 348 349 return (a0ialloc(size, false, false)); 350} 351 352void * 353bootstrap_calloc(size_t num, size_t size) 354{ 355 size_t num_size; 356 357 num_size = num * size; 358 if (unlikely(num_size == 0)) { 359 assert(num == 0 || size == 0); 360 num_size = 1; 361 } 362 363 return (a0ialloc(num_size, true, false)); 364} 365 366void 367bootstrap_free(void *ptr) 368{ 369 370 if (unlikely(ptr == NULL)) 371 return; 372 373 a0idalloc(ptr, false); 374} 375 376/* Create a new arena and insert it into the arenas array at index ind. */ 377static arena_t * 378arena_init_locked(unsigned ind) 379{ 380 arena_t *arena; 381 382 /* Expand arenas if necessary. */ 383 assert(ind <= narenas_total); 384 if (ind > MALLOCX_ARENA_MAX) 385 return (NULL); 386 if (ind == narenas_total) { 387 unsigned narenas_new = narenas_total + 1; 388 arena_t **arenas_new = 389 (arena_t **)a0malloc(CACHELINE_CEILING(narenas_new * 390 sizeof(arena_t *))); 391 if (arenas_new == NULL) 392 return (NULL); 393 memcpy(arenas_new, arenas, narenas_total * sizeof(arena_t *)); 394 arenas_new[ind] = NULL; 395 /* 396 * Deallocate only if arenas came from a0malloc() (not 397 * base_alloc()). 398 */ 399 if (narenas_total != narenas_auto) 400 a0dalloc(arenas); 401 arenas = arenas_new; 402 narenas_total = narenas_new; 403 } 404 405 /* 406 * Another thread may have already initialized arenas[ind] if it's an 407 * auto arena. 408 */ 409 arena = arenas[ind]; 410 if (arena != NULL) { 411 assert(ind < narenas_auto); 412 return (arena); 413 } 414 415 /* Actually initialize the arena. */ 416 arena = arenas[ind] = arena_new(ind); 417 return (arena); 418} 419 420arena_t * 421arena_init(unsigned ind) 422{ 423 arena_t *arena; 424 425 malloc_mutex_lock(&arenas_lock); 426 arena = arena_init_locked(ind); 427 malloc_mutex_unlock(&arenas_lock); 428 return (arena); 429} 430 431unsigned 432narenas_total_get(void) 433{ 434 unsigned narenas; 435 436 malloc_mutex_lock(&arenas_lock); 437 narenas = narenas_total; 438 malloc_mutex_unlock(&arenas_lock); 439 440 return (narenas); 441} 442 443static void 444arena_bind_locked(tsd_t *tsd, unsigned ind) 445{ 446 arena_t *arena; 447 448 arena = arenas[ind]; 449 arena->nthreads++; 450 451 if (tsd_nominal(tsd)) 452 tsd_arena_set(tsd, arena); 453} 454 455static void 456arena_bind(tsd_t *tsd, unsigned ind) 457{ 458 459 malloc_mutex_lock(&arenas_lock); 460 arena_bind_locked(tsd, ind); 461 malloc_mutex_unlock(&arenas_lock); 462} 463 464void 465arena_migrate(tsd_t *tsd, unsigned oldind, unsigned newind) 466{ 467 arena_t *oldarena, *newarena; 468 469 malloc_mutex_lock(&arenas_lock); 470 oldarena = arenas[oldind]; 471 newarena = arenas[newind]; 472 oldarena->nthreads--; 473 newarena->nthreads++; 474 malloc_mutex_unlock(&arenas_lock); 475 tsd_arena_set(tsd, newarena); 476} 477 478unsigned 479arena_nbound(unsigned ind) 480{ 481 unsigned nthreads; 482 483 malloc_mutex_lock(&arenas_lock); 484 nthreads = arenas[ind]->nthreads; 485 malloc_mutex_unlock(&arenas_lock); 486 return (nthreads); 487} 488 489static void 490arena_unbind(tsd_t *tsd, unsigned ind) 491{ 492 arena_t *arena; 493 494 malloc_mutex_lock(&arenas_lock); 495 arena = arenas[ind]; 496 arena->nthreads--; 497 malloc_mutex_unlock(&arenas_lock); 498 tsd_arena_set(tsd, NULL); 499} 500 501arena_t * 502arena_get_hard(tsd_t *tsd, unsigned ind, bool init_if_missing) 503{ 504 arena_t *arena; 505 arena_t **arenas_cache = tsd_arenas_cache_get(tsd); 506 unsigned narenas_cache = tsd_narenas_cache_get(tsd); 507 unsigned narenas_actual = narenas_total_get(); 508 509 /* Deallocate old cache if it's too small. */ 510 if (arenas_cache != NULL && narenas_cache < narenas_actual) { 511 a0dalloc(arenas_cache); 512 arenas_cache = NULL; 513 narenas_cache = 0; 514 tsd_arenas_cache_set(tsd, arenas_cache); 515 tsd_narenas_cache_set(tsd, narenas_cache); 516 } 517 518 /* Allocate cache if it's missing. */ 519 if (arenas_cache == NULL) { 520 bool *arenas_cache_bypassp = tsd_arenas_cache_bypassp_get(tsd); 521 assert(ind < narenas_actual || !init_if_missing); 522 narenas_cache = (ind < narenas_actual) ? narenas_actual : ind+1; 523 524 if (tsd_nominal(tsd) && !*arenas_cache_bypassp) { 525 *arenas_cache_bypassp = true; 526 arenas_cache = (arena_t **)a0malloc(sizeof(arena_t *) * 527 narenas_cache); 528 *arenas_cache_bypassp = false; 529 } 530 if (arenas_cache == NULL) { 531 /* 532 * This function must always tell the truth, even if 533 * it's slow, so don't let OOM, thread cleanup (note 534 * tsd_nominal check), nor recursive allocation 535 * avoidance (note arenas_cache_bypass check) get in the 536 * way. 537 */ 538 if (ind >= narenas_actual) 539 return (NULL); 540 malloc_mutex_lock(&arenas_lock); 541 arena = arenas[ind]; 542 malloc_mutex_unlock(&arenas_lock); 543 return (arena); 544 } 545 assert(tsd_nominal(tsd) && !*arenas_cache_bypassp); 546 tsd_arenas_cache_set(tsd, arenas_cache); 547 tsd_narenas_cache_set(tsd, narenas_cache); 548 } 549 550 /* 551 * Copy to cache. It's possible that the actual number of arenas has 552 * increased since narenas_total_get() was called above, but that causes 553 * no correctness issues unless two threads concurrently execute the 554 * arenas.extend mallctl, which we trust mallctl synchronization to 555 * prevent. 556 */ 557 malloc_mutex_lock(&arenas_lock); 558 memcpy(arenas_cache, arenas, sizeof(arena_t *) * narenas_actual); 559 malloc_mutex_unlock(&arenas_lock); 560 if (narenas_cache > narenas_actual) { 561 memset(&arenas_cache[narenas_actual], 0, sizeof(arena_t *) * 562 (narenas_cache - narenas_actual)); 563 } 564 565 /* Read the refreshed cache, and init the arena if necessary. */ 566 arena = arenas_cache[ind]; 567 if (init_if_missing && arena == NULL) 568 arena = arenas_cache[ind] = arena_init(ind); 569 return (arena); 570} 571 572/* Slow path, called only by arena_choose(). */ 573arena_t * 574arena_choose_hard(tsd_t *tsd) 575{ 576 arena_t *ret; 577 578 if (narenas_auto > 1) { 579 unsigned i, choose, first_null; 580 581 choose = 0; 582 first_null = narenas_auto; 583 malloc_mutex_lock(&arenas_lock); 584 assert(a0get() != NULL); 585 for (i = 1; i < narenas_auto; i++) { 586 if (arenas[i] != NULL) { 587 /* 588 * Choose the first arena that has the lowest 589 * number of threads assigned to it. 590 */ 591 if (arenas[i]->nthreads < 592 arenas[choose]->nthreads) 593 choose = i; 594 } else if (first_null == narenas_auto) { 595 /* 596 * Record the index of the first uninitialized 597 * arena, in case all extant arenas are in use. 598 * 599 * NB: It is possible for there to be 600 * discontinuities in terms of initialized 601 * versus uninitialized arenas, due to the 602 * "thread.arena" mallctl. 603 */ 604 first_null = i; 605 } 606 } 607 608 if (arenas[choose]->nthreads == 0 609 || first_null == narenas_auto) { 610 /* 611 * Use an unloaded arena, or the least loaded arena if 612 * all arenas are already initialized. 613 */ 614 ret = arenas[choose]; 615 } else { 616 /* Initialize a new arena. */ 617 choose = first_null; 618 ret = arena_init_locked(choose); 619 if (ret == NULL) { 620 malloc_mutex_unlock(&arenas_lock); 621 return (NULL); 622 } 623 } 624 arena_bind_locked(tsd, choose); 625 malloc_mutex_unlock(&arenas_lock); 626 } else { 627 ret = a0get(); 628 arena_bind(tsd, 0); 629 } 630 631 return (ret); 632} 633 634void 635thread_allocated_cleanup(tsd_t *tsd) 636{ 637 638 /* Do nothing. */ 639} 640 641void 642thread_deallocated_cleanup(tsd_t *tsd) 643{ 644 645 /* Do nothing. */ 646} 647 648void 649arena_cleanup(tsd_t *tsd) 650{ 651 arena_t *arena; 652 653 arena = tsd_arena_get(tsd); 654 if (arena != NULL) 655 arena_unbind(tsd, arena->ind); 656} 657 658void 659arenas_cache_cleanup(tsd_t *tsd) 660{ 661 arena_t **arenas_cache; 662 663 arenas_cache = tsd_arenas_cache_get(tsd); 664 if (arenas_cache != NULL) { 665 tsd_arenas_cache_set(tsd, NULL); 666 a0dalloc(arenas_cache); 667 } 668} 669 670void 671narenas_cache_cleanup(tsd_t *tsd) 672{ 673 674 /* Do nothing. */ 675} 676 677void 678arenas_cache_bypass_cleanup(tsd_t *tsd) 679{ 680 681 /* Do nothing. */ 682} 683 684static void 685stats_print_atexit(void) 686{ 687 688 if (config_tcache && config_stats) { 689 unsigned narenas, i; 690 691 /* 692 * Merge stats from extant threads. This is racy, since 693 * individual threads do not lock when recording tcache stats 694 * events. As a consequence, the final stats may be slightly 695 * out of date by the time they are reported, if other threads 696 * continue to allocate. 697 */ 698 for (i = 0, narenas = narenas_total_get(); i < narenas; i++) { 699 arena_t *arena = arenas[i]; 700 if (arena != NULL) { 701 tcache_t *tcache; 702 703 /* 704 * tcache_stats_merge() locks bins, so if any 705 * code is introduced that acquires both arena 706 * and bin locks in the opposite order, 707 * deadlocks may result. 708 */ 709 malloc_mutex_lock(&arena->lock); 710 ql_foreach(tcache, &arena->tcache_ql, link) { 711 tcache_stats_merge(tcache, arena); 712 } 713 malloc_mutex_unlock(&arena->lock); 714 } 715 } 716 } 717 je_malloc_stats_print(NULL, NULL, NULL); 718} 719 720/* 721 * End miscellaneous support functions. 722 */ 723/******************************************************************************/ 724/* 725 * Begin initialization functions. 726 */ 727 728#ifndef JEMALLOC_HAVE_SECURE_GETENV 729static char * 730secure_getenv(const char *name) 731{ 732 733# ifdef JEMALLOC_HAVE_ISSETUGID 734 if (issetugid() != 0) 735 return (NULL); 736# endif 737 return (getenv(name)); 738} 739#endif 740 741static unsigned 742malloc_ncpus(void) 743{ 744 long result; 745 746#ifdef _WIN32 747 SYSTEM_INFO si; 748 GetSystemInfo(&si); 749 result = si.dwNumberOfProcessors; 750#else 751 result = sysconf(_SC_NPROCESSORS_ONLN); 752#endif 753 return ((result == -1) ? 1 : (unsigned)result); 754} 755 756static bool 757malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p, 758 char const **v_p, size_t *vlen_p) 759{ 760 bool accept; 761 const char *opts = *opts_p; 762 763 *k_p = opts; 764 765 for (accept = false; !accept;) { 766 switch (*opts) { 767 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 768 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': 769 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': 770 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': 771 case 'Y': case 'Z': 772 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 773 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': 774 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': 775 case 's': case 't': case 'u': case 'v': case 'w': case 'x': 776 case 'y': case 'z': 777 case '0': case '1': case '2': case '3': case '4': case '5': 778 case '6': case '7': case '8': case '9': 779 case '_': 780 opts++; 781 break; 782 case ':': 783 opts++; 784 *klen_p = (uintptr_t)opts - 1 - (uintptr_t)*k_p; 785 *v_p = opts; 786 accept = true; 787 break; 788 case '\0': 789 if (opts != *opts_p) { 790 malloc_write("<jemalloc>: Conf string ends " 791 "with key\n"); 792 } 793 return (true); 794 default: 795 malloc_write("<jemalloc>: Malformed conf string\n"); 796 return (true); 797 } 798 } 799 800 for (accept = false; !accept;) { 801 switch (*opts) { 802 case ',': 803 opts++; 804 /* 805 * Look ahead one character here, because the next time 806 * this function is called, it will assume that end of 807 * input has been cleanly reached if no input remains, 808 * but we have optimistically already consumed the 809 * comma if one exists. 810 */ 811 if (*opts == '\0') { 812 malloc_write("<jemalloc>: Conf string ends " 813 "with comma\n"); 814 } 815 *vlen_p = (uintptr_t)opts - 1 - (uintptr_t)*v_p; 816 accept = true; 817 break; 818 case '\0': 819 *vlen_p = (uintptr_t)opts - (uintptr_t)*v_p; 820 accept = true; 821 break; 822 default: 823 opts++; 824 break; 825 } 826 } 827 828 *opts_p = opts; 829 return (false); 830} 831 832static void 833malloc_conf_error(const char *msg, const char *k, size_t klen, const char *v, 834 size_t vlen) 835{ 836 837 malloc_printf("<jemalloc>: %s: %.*s:%.*s\n", msg, (int)klen, k, 838 (int)vlen, v); 839} 840 841static void 842malloc_conf_init(void) 843{ 844 unsigned i; 845 char buf[PATH_MAX + 1]; 846 const char *opts, *k, *v; 847 size_t klen, vlen; 848 849 /* 850 * Automatically configure valgrind before processing options. The 851 * valgrind option remains in jemalloc 3.x for compatibility reasons. 852 */ 853 if (config_valgrind) { 854 in_valgrind = (RUNNING_ON_VALGRIND != 0) ? true : false; 855 if (config_fill && unlikely(in_valgrind)) { 856 opt_junk = "false"; 857 opt_junk_alloc = false; 858 opt_junk_free = false; 859 assert(!opt_zero); 860 opt_quarantine = JEMALLOC_VALGRIND_QUARANTINE_DEFAULT; 861 opt_redzone = true; 862 } 863 if (config_tcache && unlikely(in_valgrind)) 864 opt_tcache = false; 865 } 866 867 for (i = 0; i < 3; i++) { 868 /* Get runtime configuration. */ 869 switch (i) { 870 case 0: 871 if (je_malloc_conf != NULL) { 872 /* 873 * Use options that were compiled into the 874 * program. 875 */ 876 opts = je_malloc_conf; 877 } else { 878 /* No configuration specified. */ 879 buf[0] = '\0'; 880 opts = buf; 881 } 882 break; 883 case 1: { 884 int linklen = 0; 885#ifndef _WIN32 886 int saved_errno = errno; 887 const char *linkname = 888# ifdef JEMALLOC_PREFIX 889 "/etc/"JEMALLOC_PREFIX"malloc.conf" 890# else 891 "/etc/malloc.conf" 892# endif 893 ; 894 895 /* 896 * Try to use the contents of the "/etc/malloc.conf" 897 * symbolic link's name. 898 */ 899 linklen = readlink(linkname, buf, sizeof(buf) - 1); 900 if (linklen == -1) { 901 /* No configuration specified. */ 902 linklen = 0; 903 /* Restore errno. */ 904 set_errno(saved_errno); 905 } 906#endif 907 buf[linklen] = '\0'; 908 opts = buf; 909 break; 910 } case 2: { 911 const char *envname = 912#ifdef JEMALLOC_PREFIX 913 JEMALLOC_CPREFIX"MALLOC_CONF" 914#else 915 "MALLOC_CONF" 916#endif 917 ; 918 919 if ((opts = secure_getenv(envname)) != NULL) { 920 /* 921 * Do nothing; opts is already initialized to 922 * the value of the MALLOC_CONF environment 923 * variable. 924 */ 925 } else { 926 /* No configuration specified. */ 927 buf[0] = '\0'; 928 opts = buf; 929 } 930 break; 931 } default: 932 not_reached(); 933 buf[0] = '\0'; 934 opts = buf; 935 } 936 937 while (*opts != '\0' && !malloc_conf_next(&opts, &k, &klen, &v, 938 &vlen)) { 939#define CONF_MATCH(n) \ 940 (sizeof(n)-1 == klen && strncmp(n, k, klen) == 0) 941#define CONF_MATCH_VALUE(n) \ 942 (sizeof(n)-1 == vlen && strncmp(n, v, vlen) == 0) 943#define CONF_HANDLE_BOOL(o, n, cont) \ 944 if (CONF_MATCH(n)) { \ 945 if (CONF_MATCH_VALUE("true")) \ 946 o = true; \ 947 else if (CONF_MATCH_VALUE("false")) \ 948 o = false; \ 949 else { \ 950 malloc_conf_error( \ 951 "Invalid conf value", \ 952 k, klen, v, vlen); \ 953 } \ 954 if (cont) \ 955 continue; \ 956 } 957#define CONF_HANDLE_SIZE_T(o, n, min, max, clip) \ 958 if (CONF_MATCH(n)) { \ 959 uintmax_t um; \ 960 char *end; \ 961 \ 962 set_errno(0); \ 963 um = malloc_strtoumax(v, &end, 0); \ 964 if (get_errno() != 0 || (uintptr_t)end -\ 965 (uintptr_t)v != vlen) { \ 966 malloc_conf_error( \ 967 "Invalid conf value", \ 968 k, klen, v, vlen); \ 969 } else if (clip) { \ 970 if ((min) != 0 && um < (min)) \ 971 o = (min); \ 972 else if (um > (max)) \ 973 o = (max); \ 974 else \ 975 o = um; \ 976 } else { \ 977 if (((min) != 0 && um < (min)) \ 978 || um > (max)) { \ 979 malloc_conf_error( \ 980 "Out-of-range " \ 981 "conf value", \ 982 k, klen, v, vlen); \ 983 } else \ 984 o = um; \ 985 } \ 986 continue; \ 987 } 988#define CONF_HANDLE_SSIZE_T(o, n, min, max) \ 989 if (CONF_MATCH(n)) { \ 990 long l; \ 991 char *end; \ 992 \ 993 set_errno(0); \ 994 l = strtol(v, &end, 0); \ 995 if (get_errno() != 0 || (uintptr_t)end -\ 996 (uintptr_t)v != vlen) { \ 997 malloc_conf_error( \ 998 "Invalid conf value", \ 999 k, klen, v, vlen); \ 1000 } else if (l < (ssize_t)(min) || l > \ 1001 (ssize_t)(max)) { \ 1002 malloc_conf_error( \ 1003 "Out-of-range conf value", \ 1004 k, klen, v, vlen); \ 1005 } else \ 1006 o = l; \ 1007 continue; \ 1008 } 1009#define CONF_HANDLE_CHAR_P(o, n, d) \ 1010 if (CONF_MATCH(n)) { \ 1011 size_t cpylen = (vlen <= \ 1012 sizeof(o)-1) ? vlen : \ 1013 sizeof(o)-1; \ 1014 strncpy(o, v, cpylen); \ 1015 o[cpylen] = '\0'; \ 1016 continue; \ 1017 } 1018 1019 CONF_HANDLE_BOOL(opt_abort, "abort", true) 1020 /* 1021 * Chunks always require at least one header page, 1022 * as many as 2^(LG_SIZE_CLASS_GROUP+1) data pages, and 1023 * possibly an additional page in the presence of 1024 * redzones. In order to simplify options processing, 1025 * use a conservative bound that accommodates all these 1026 * constraints. 1027 */ 1028 CONF_HANDLE_SIZE_T(opt_lg_chunk, "lg_chunk", LG_PAGE + 1029 LG_SIZE_CLASS_GROUP + (config_fill ? 2 : 1), 1030 (sizeof(size_t) << 3) - 1, true) 1031 if (strncmp("dss", k, klen) == 0) { 1032 int i; 1033 bool match = false; 1034 for (i = 0; i < dss_prec_limit; i++) { 1035 if (strncmp(dss_prec_names[i], v, vlen) 1036 == 0) { 1037 if (chunk_dss_prec_set(i)) { 1038 malloc_conf_error( 1039 "Error setting dss", 1040 k, klen, v, vlen); 1041 } else { 1042 opt_dss = 1043 dss_prec_names[i]; 1044 match = true; 1045 break; 1046 } 1047 } 1048 } 1049 if (!match) { 1050 malloc_conf_error("Invalid conf value", 1051 k, klen, v, vlen); 1052 } 1053 continue; 1054 } 1055 CONF_HANDLE_SIZE_T(opt_narenas, "narenas", 1, 1056 SIZE_T_MAX, false) 1057 CONF_HANDLE_SSIZE_T(opt_lg_dirty_mult, "lg_dirty_mult", 1058 -1, (sizeof(size_t) << 3) - 1) 1059 CONF_HANDLE_BOOL(opt_stats_print, "stats_print", true) 1060 if (config_fill) { 1061 if (CONF_MATCH("junk")) { 1062 if (CONF_MATCH_VALUE("true")) { 1063 opt_junk = "true"; 1064 opt_junk_alloc = opt_junk_free = 1065 true; 1066 } else if (CONF_MATCH_VALUE("false")) { 1067 opt_junk = "false"; 1068 opt_junk_alloc = opt_junk_free = 1069 false; 1070 } else if (CONF_MATCH_VALUE("alloc")) { 1071 opt_junk = "alloc"; 1072 opt_junk_alloc = true; 1073 opt_junk_free = false; 1074 } else if (CONF_MATCH_VALUE("free")) { 1075 opt_junk = "free"; 1076 opt_junk_alloc = false; 1077 opt_junk_free = true; 1078 } else { 1079 malloc_conf_error( 1080 "Invalid conf value", k, 1081 klen, v, vlen); 1082 } 1083 continue; 1084 } 1085 CONF_HANDLE_SIZE_T(opt_quarantine, "quarantine", 1086 0, SIZE_T_MAX, false) 1087 CONF_HANDLE_BOOL(opt_redzone, "redzone", true) 1088 CONF_HANDLE_BOOL(opt_zero, "zero", true) 1089 } 1090 if (config_utrace) { 1091 CONF_HANDLE_BOOL(opt_utrace, "utrace", true) 1092 } 1093 if (config_xmalloc) { 1094 CONF_HANDLE_BOOL(opt_xmalloc, "xmalloc", true) 1095 } 1096 if (config_tcache) { 1097 CONF_HANDLE_BOOL(opt_tcache, "tcache", 1098 !config_valgrind || !in_valgrind) 1099 if (CONF_MATCH("tcache")) { 1100 assert(config_valgrind && in_valgrind); 1101 if (opt_tcache) { 1102 opt_tcache = false; 1103 malloc_conf_error( 1104 "tcache cannot be enabled " 1105 "while running inside Valgrind", 1106 k, klen, v, vlen); 1107 } 1108 continue; 1109 } 1110 CONF_HANDLE_SSIZE_T(opt_lg_tcache_max, 1111 "lg_tcache_max", -1, 1112 (sizeof(size_t) << 3) - 1) 1113 } 1114 if (config_prof) { 1115 CONF_HANDLE_BOOL(opt_prof, "prof", true) 1116 CONF_HANDLE_CHAR_P(opt_prof_prefix, 1117 "prof_prefix", "jeprof") 1118 CONF_HANDLE_BOOL(opt_prof_active, "prof_active", 1119 true) 1120 CONF_HANDLE_BOOL(opt_prof_thread_active_init, 1121 "prof_thread_active_init", true) 1122 CONF_HANDLE_SIZE_T(opt_lg_prof_sample, 1123 "lg_prof_sample", 0, 1124 (sizeof(uint64_t) << 3) - 1, true) 1125 CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum", 1126 true) 1127 CONF_HANDLE_SSIZE_T(opt_lg_prof_interval, 1128 "lg_prof_interval", -1, 1129 (sizeof(uint64_t) << 3) - 1) 1130 CONF_HANDLE_BOOL(opt_prof_gdump, "prof_gdump", 1131 true) 1132 CONF_HANDLE_BOOL(opt_prof_final, "prof_final", 1133 true) 1134 CONF_HANDLE_BOOL(opt_prof_leak, "prof_leak", 1135 true) 1136 } 1137 malloc_conf_error("Invalid conf pair", k, klen, v, 1138 vlen); 1139#undef CONF_MATCH 1140#undef CONF_HANDLE_BOOL 1141#undef CONF_HANDLE_SIZE_T 1142#undef CONF_HANDLE_SSIZE_T 1143#undef CONF_HANDLE_CHAR_P 1144 } 1145 } 1146} 1147 1148/* init_lock must be held. */ 1149static bool 1150malloc_init_hard_needed(void) 1151{ 1152 1153 if (malloc_initialized() || (IS_INITIALIZER && malloc_init_state == 1154 malloc_init_recursible)) { 1155 /* 1156 * Another thread initialized the allocator before this one 1157 * acquired init_lock, or this thread is the initializing 1158 * thread, and it is recursively allocating. 1159 */ 1160 return (false); 1161 } 1162#ifdef JEMALLOC_THREADED_INIT 1163 if (malloc_initializer != NO_INITIALIZER && !IS_INITIALIZER) { 1164 /* Busy-wait until the initializing thread completes. */ 1165 do { 1166 malloc_mutex_unlock(&init_lock); 1167 CPU_SPINWAIT; 1168 malloc_mutex_lock(&init_lock); 1169 } while (!malloc_initialized()); 1170 return (false); 1171 } 1172#endif 1173 return (true); 1174} 1175 1176/* init_lock must be held. */ 1177static bool 1178malloc_init_hard_a0_locked(void) 1179{ 1180 1181 malloc_initializer = INITIALIZER; 1182 1183 if (config_prof) 1184 prof_boot0(); 1185 malloc_conf_init(); 1186 if (opt_stats_print) { 1187 /* Print statistics at exit. */ 1188 if (atexit(stats_print_atexit) != 0) { 1189 malloc_write("<jemalloc>: Error in atexit()\n"); 1190 if (opt_abort) 1191 abort(); 1192 } 1193 } 1194 if (base_boot()) 1195 return (true); 1196 if (chunk_boot()) 1197 return (true); 1198 if (ctl_boot()) 1199 return (true); 1200 if (config_prof) 1201 prof_boot1(); 1202 if (arena_boot()) 1203 return (true); 1204 if (config_tcache && tcache_boot()) 1205 return (true); 1206 if (malloc_mutex_init(&arenas_lock)) 1207 return (true); 1208 /* 1209 * Create enough scaffolding to allow recursive allocation in 1210 * malloc_ncpus(). 1211 */ 1212 narenas_total = narenas_auto = 1; 1213 arenas = &a0; 1214 memset(arenas, 0, sizeof(arena_t *) * narenas_auto); 1215 /* 1216 * Initialize one arena here. The rest are lazily created in 1217 * arena_choose_hard(). 1218 */ 1219 if (arena_init(0) == NULL) 1220 return (true); 1221 malloc_init_state = malloc_init_a0_initialized; 1222 return (false); 1223} 1224 1225static bool 1226malloc_init_hard_a0(void) 1227{ 1228 bool ret; 1229 1230 malloc_mutex_lock(&init_lock); 1231 ret = malloc_init_hard_a0_locked(); 1232 malloc_mutex_unlock(&init_lock); 1233 return (ret); 1234} 1235 1236/* 1237 * Initialize data structures which may trigger recursive allocation. 1238 * 1239 * init_lock must be held. 1240 */ 1241static void 1242malloc_init_hard_recursible(void) 1243{ 1244 1245 malloc_init_state = malloc_init_recursible; 1246 malloc_mutex_unlock(&init_lock); 1247 1248 ncpus = malloc_ncpus(); 1249 1250#if (!defined(JEMALLOC_MUTEX_INIT_CB) && !defined(JEMALLOC_ZONE) \ 1251 && !defined(_WIN32) && !defined(__native_client__)) 1252 /* LinuxThreads's pthread_atfork() allocates. */ 1253 if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent, 1254 jemalloc_postfork_child) != 0) { 1255 malloc_write("<jemalloc>: Error in pthread_atfork()\n"); 1256 if (opt_abort) 1257 abort(); 1258 } 1259#endif 1260 malloc_mutex_lock(&init_lock); 1261} 1262 1263/* init_lock must be held. */ 1264static bool 1265malloc_init_hard_finish(void) 1266{ 1267 1268 if (mutex_boot()) 1269 return (true); 1270 1271 if (opt_narenas == 0) { 1272 /* 1273 * For SMP systems, create more than one arena per CPU by 1274 * default. 1275 */ 1276 if (ncpus > 1) 1277 opt_narenas = ncpus << 2; 1278 else 1279 opt_narenas = 1; 1280 } 1281 narenas_auto = opt_narenas; 1282 /* 1283 * Make sure that the arenas array can be allocated. In practice, this 1284 * limit is enough to allow the allocator to function, but the ctl 1285 * machinery will fail to allocate memory at far lower limits. 1286 */ 1287 if (narenas_auto > chunksize / sizeof(arena_t *)) { 1288 narenas_auto = chunksize / sizeof(arena_t *); 1289 malloc_printf("<jemalloc>: Reducing narenas to limit (%d)\n", 1290 narenas_auto); 1291 } 1292 narenas_total = narenas_auto; 1293 1294 /* Allocate and initialize arenas. */ 1295 arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas_total); 1296 if (arenas == NULL) 1297 return (true); 1298 /* 1299 * Zero the array. In practice, this should always be pre-zeroed, 1300 * since it was just mmap()ed, but let's be sure. 1301 */ 1302 memset(arenas, 0, sizeof(arena_t *) * narenas_total); 1303 /* Copy the pointer to the one arena that was already initialized. */ 1304 arenas[0] = a0; 1305 1306 malloc_init_state = malloc_init_initialized; 1307 return (false); 1308} 1309 1310static bool 1311malloc_init_hard(void) 1312{ 1313 1314#if defined(_WIN32) && _WIN32_WINNT < 0x0600 1315 _init_init_lock(); 1316#endif 1317 malloc_mutex_lock(&init_lock); 1318 if (!malloc_init_hard_needed()) { 1319 malloc_mutex_unlock(&init_lock); 1320 return (false); 1321 } 1322 1323 if (malloc_init_state != malloc_init_a0_initialized && 1324 malloc_init_hard_a0_locked()) { 1325 malloc_mutex_unlock(&init_lock); 1326 return (true); 1327 } 1328 if (malloc_tsd_boot0()) { 1329 malloc_mutex_unlock(&init_lock); 1330 return (true); 1331 } 1332 if (config_prof && prof_boot2()) { 1333 malloc_mutex_unlock(&init_lock); 1334 return (true); 1335 } 1336 1337 malloc_init_hard_recursible(); 1338 1339 if (malloc_init_hard_finish()) { 1340 malloc_mutex_unlock(&init_lock); 1341 return (true); 1342 } 1343 1344 malloc_mutex_unlock(&init_lock); 1345 malloc_tsd_boot1(); 1346 return (false); 1347} 1348 1349/* 1350 * End initialization functions. 1351 */ 1352/******************************************************************************/ 1353/* 1354 * Begin malloc(3)-compatible functions. 1355 */ 1356 1357static void * 1358imalloc_prof_sample(tsd_t *tsd, size_t usize, prof_tctx_t *tctx) 1359{ 1360 void *p; 1361 1362 if (tctx == NULL) 1363 return (NULL); 1364 if (usize <= SMALL_MAXCLASS) { 1365 p = imalloc(tsd, LARGE_MINCLASS); 1366 if (p == NULL) 1367 return (NULL); 1368 arena_prof_promoted(p, usize); 1369 } else 1370 p = imalloc(tsd, usize); 1371 1372 return (p); 1373} 1374 1375JEMALLOC_ALWAYS_INLINE_C void * 1376imalloc_prof(tsd_t *tsd, size_t usize) 1377{ 1378 void *p; 1379 prof_tctx_t *tctx; 1380 1381 tctx = prof_alloc_prep(tsd, usize, prof_active_get_unlocked(), true); 1382 if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) 1383 p = imalloc_prof_sample(tsd, usize, tctx); 1384 else 1385 p = imalloc(tsd, usize); 1386 if (unlikely(p == NULL)) { 1387 prof_alloc_rollback(tsd, tctx, true); 1388 return (NULL); 1389 } 1390 prof_malloc(p, usize, tctx); 1391 1392 return (p); 1393} 1394 1395JEMALLOC_ALWAYS_INLINE_C void * 1396imalloc_body(size_t size, tsd_t **tsd, size_t *usize) 1397{ 1398 1399 if (unlikely(malloc_init())) 1400 return (NULL); 1401 *tsd = tsd_fetch(); 1402 1403 if (config_prof && opt_prof) { 1404 *usize = s2u(size); 1405 if (unlikely(*usize == 0)) 1406 return (NULL); 1407 return (imalloc_prof(*tsd, *usize)); 1408 } 1409 1410 if (config_stats || (config_valgrind && unlikely(in_valgrind))) 1411 *usize = s2u(size); 1412 return (imalloc(*tsd, size)); 1413} 1414 1415JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 1416void JEMALLOC_NOTHROW * 1417JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1) 1418je_malloc(size_t size) 1419{ 1420 void *ret; 1421 tsd_t *tsd; 1422 size_t usize JEMALLOC_CC_SILENCE_INIT(0); 1423 1424 if (size == 0) 1425 size = 1; 1426 1427 ret = imalloc_body(size, &tsd, &usize); 1428 if (unlikely(ret == NULL)) { 1429 if (config_xmalloc && unlikely(opt_xmalloc)) { 1430 malloc_write("<jemalloc>: Error in malloc(): " 1431 "out of memory\n"); 1432 abort(); 1433 } 1434 set_errno(ENOMEM); 1435 } 1436 if (config_stats && likely(ret != NULL)) { 1437 assert(usize == isalloc(ret, config_prof)); 1438 *tsd_thread_allocatedp_get(tsd) += usize; 1439 } 1440 UTRACE(0, size, ret); 1441 JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, false); 1442 return (ret); 1443} 1444 1445static void * 1446imemalign_prof_sample(tsd_t *tsd, size_t alignment, size_t usize, 1447 prof_tctx_t *tctx) 1448{ 1449 void *p; 1450 1451 if (tctx == NULL) 1452 return (NULL); 1453 if (usize <= SMALL_MAXCLASS) { 1454 assert(sa2u(LARGE_MINCLASS, alignment) == LARGE_MINCLASS); 1455 p = ipalloc(tsd, LARGE_MINCLASS, alignment, false); 1456 if (p == NULL) 1457 return (NULL); 1458 arena_prof_promoted(p, usize); 1459 } else 1460 p = ipalloc(tsd, usize, alignment, false); 1461 1462 return (p); 1463} 1464 1465JEMALLOC_ALWAYS_INLINE_C void * 1466imemalign_prof(tsd_t *tsd, size_t alignment, size_t usize) 1467{ 1468 void *p; 1469 prof_tctx_t *tctx; 1470 1471 tctx = prof_alloc_prep(tsd, usize, prof_active_get_unlocked(), true); 1472 if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) 1473 p = imemalign_prof_sample(tsd, alignment, usize, tctx); 1474 else 1475 p = ipalloc(tsd, usize, alignment, false); 1476 if (unlikely(p == NULL)) { 1477 prof_alloc_rollback(tsd, tctx, true); 1478 return (NULL); 1479 } 1480 prof_malloc(p, usize, tctx); 1481 1482 return (p); 1483} 1484 1485JEMALLOC_ATTR(nonnull(1)) 1486static int 1487imemalign(void **memptr, size_t alignment, size_t size, size_t min_alignment) 1488{ 1489 int ret; 1490 tsd_t *tsd; 1491 size_t usize; 1492 void *result; 1493 1494 assert(min_alignment != 0); 1495 1496 if (unlikely(malloc_init())) { 1497 result = NULL; 1498 goto label_oom; 1499 } 1500 tsd = tsd_fetch(); 1501 if (size == 0) 1502 size = 1; 1503 1504 /* Make sure that alignment is a large enough power of 2. */ 1505 if (unlikely(((alignment - 1) & alignment) != 0 1506 || (alignment < min_alignment))) { 1507 if (config_xmalloc && unlikely(opt_xmalloc)) { 1508 malloc_write("<jemalloc>: Error allocating " 1509 "aligned memory: invalid alignment\n"); 1510 abort(); 1511 } 1512 result = NULL; 1513 ret = EINVAL; 1514 goto label_return; 1515 } 1516 1517 usize = sa2u(size, alignment); 1518 if (unlikely(usize == 0)) { 1519 result = NULL; 1520 goto label_oom; 1521 } 1522 1523 if (config_prof && opt_prof) 1524 result = imemalign_prof(tsd, alignment, usize); 1525 else 1526 result = ipalloc(tsd, usize, alignment, false); 1527 if (unlikely(result == NULL)) 1528 goto label_oom; 1529 assert(((uintptr_t)result & (alignment - 1)) == ZU(0)); 1530 1531 *memptr = result; 1532 ret = 0; 1533label_return: 1534 if (config_stats && likely(result != NULL)) { 1535 assert(usize == isalloc(result, config_prof)); 1536 *tsd_thread_allocatedp_get(tsd) += usize; 1537 } 1538 UTRACE(0, size, result); 1539 return (ret); 1540label_oom: 1541 assert(result == NULL); 1542 if (config_xmalloc && unlikely(opt_xmalloc)) { 1543 malloc_write("<jemalloc>: Error allocating aligned memory: " 1544 "out of memory\n"); 1545 abort(); 1546 } 1547 ret = ENOMEM; 1548 goto label_return; 1549} 1550 1551JEMALLOC_EXPORT int JEMALLOC_NOTHROW 1552JEMALLOC_ATTR(nonnull(1)) 1553je_posix_memalign(void **memptr, size_t alignment, size_t size) 1554{ 1555 int ret = imemalign(memptr, alignment, size, sizeof(void *)); 1556 JEMALLOC_VALGRIND_MALLOC(ret == 0, *memptr, isalloc(*memptr, 1557 config_prof), false); 1558 return (ret); 1559} 1560 1561JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 1562void JEMALLOC_NOTHROW * 1563JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(2) 1564je_aligned_alloc(size_t alignment, size_t size) 1565{ 1566 void *ret; 1567 int err; 1568 1569 if (unlikely((err = imemalign(&ret, alignment, size, 1)) != 0)) { 1570 ret = NULL; 1571 set_errno(err); 1572 } 1573 JEMALLOC_VALGRIND_MALLOC(err == 0, ret, isalloc(ret, config_prof), 1574 false); 1575 return (ret); 1576} 1577 1578static void * 1579icalloc_prof_sample(tsd_t *tsd, size_t usize, prof_tctx_t *tctx) 1580{ 1581 void *p; 1582 1583 if (tctx == NULL) 1584 return (NULL); 1585 if (usize <= SMALL_MAXCLASS) { 1586 p = icalloc(tsd, LARGE_MINCLASS); 1587 if (p == NULL) 1588 return (NULL); 1589 arena_prof_promoted(p, usize); 1590 } else 1591 p = icalloc(tsd, usize); 1592 1593 return (p); 1594} 1595 1596JEMALLOC_ALWAYS_INLINE_C void * 1597icalloc_prof(tsd_t *tsd, size_t usize) 1598{ 1599 void *p; 1600 prof_tctx_t *tctx; 1601 1602 tctx = prof_alloc_prep(tsd, usize, prof_active_get_unlocked(), true); 1603 if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) 1604 p = icalloc_prof_sample(tsd, usize, tctx); 1605 else 1606 p = icalloc(tsd, usize); 1607 if (unlikely(p == NULL)) { 1608 prof_alloc_rollback(tsd, tctx, true); 1609 return (NULL); 1610 } 1611 prof_malloc(p, usize, tctx); 1612 1613 return (p); 1614} 1615 1616JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 1617void JEMALLOC_NOTHROW * 1618JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2) 1619je_calloc(size_t num, size_t size) 1620{ 1621 void *ret; 1622 tsd_t *tsd; 1623 size_t num_size; 1624 size_t usize JEMALLOC_CC_SILENCE_INIT(0); 1625 1626 if (unlikely(malloc_init())) { 1627 num_size = 0; 1628 ret = NULL; 1629 goto label_return; 1630 } 1631 tsd = tsd_fetch(); 1632 1633 num_size = num * size; 1634 if (unlikely(num_size == 0)) { 1635 if (num == 0 || size == 0) 1636 num_size = 1; 1637 else { 1638 ret = NULL; 1639 goto label_return; 1640 } 1641 /* 1642 * Try to avoid division here. We know that it isn't possible to 1643 * overflow during multiplication if neither operand uses any of the 1644 * most significant half of the bits in a size_t. 1645 */ 1646 } else if (unlikely(((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 1647 2))) && (num_size / size != num))) { 1648 /* size_t overflow. */ 1649 ret = NULL; 1650 goto label_return; 1651 } 1652 1653 if (config_prof && opt_prof) { 1654 usize = s2u(num_size); 1655 if (unlikely(usize == 0)) { 1656 ret = NULL; 1657 goto label_return; 1658 } 1659 ret = icalloc_prof(tsd, usize); 1660 } else { 1661 if (config_stats || (config_valgrind && unlikely(in_valgrind))) 1662 usize = s2u(num_size); 1663 ret = icalloc(tsd, num_size); 1664 } 1665 1666label_return: 1667 if (unlikely(ret == NULL)) { 1668 if (config_xmalloc && unlikely(opt_xmalloc)) { 1669 malloc_write("<jemalloc>: Error in calloc(): out of " 1670 "memory\n"); 1671 abort(); 1672 } 1673 set_errno(ENOMEM); 1674 } 1675 if (config_stats && likely(ret != NULL)) { 1676 assert(usize == isalloc(ret, config_prof)); 1677 *tsd_thread_allocatedp_get(tsd) += usize; 1678 } 1679 UTRACE(0, num_size, ret); 1680 JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, true); 1681 return (ret); 1682} 1683 1684static void * 1685irealloc_prof_sample(tsd_t *tsd, void *oldptr, size_t old_usize, size_t usize, 1686 prof_tctx_t *tctx) 1687{ 1688 void *p; 1689 1690 if (tctx == NULL) 1691 return (NULL); 1692 if (usize <= SMALL_MAXCLASS) { 1693 p = iralloc(tsd, oldptr, old_usize, LARGE_MINCLASS, 0, false); 1694 if (p == NULL) 1695 return (NULL); 1696 arena_prof_promoted(p, usize); 1697 } else 1698 p = iralloc(tsd, oldptr, old_usize, usize, 0, false); 1699 1700 return (p); 1701} 1702 1703JEMALLOC_ALWAYS_INLINE_C void * 1704irealloc_prof(tsd_t *tsd, void *oldptr, size_t old_usize, size_t usize) 1705{ 1706 void *p; 1707 bool prof_active; 1708 prof_tctx_t *old_tctx, *tctx; 1709 1710 prof_active = prof_active_get_unlocked(); 1711 old_tctx = prof_tctx_get(oldptr); 1712 tctx = prof_alloc_prep(tsd, usize, prof_active, true); 1713 if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) 1714 p = irealloc_prof_sample(tsd, oldptr, old_usize, usize, tctx); 1715 else 1716 p = iralloc(tsd, oldptr, old_usize, usize, 0, false); 1717 if (unlikely(p == NULL)) { 1718 prof_alloc_rollback(tsd, tctx, true); 1719 return (NULL); 1720 } 1721 prof_realloc(tsd, p, usize, tctx, prof_active, true, old_usize, 1722 old_tctx); 1723 1724 return (p); 1725} 1726 1727JEMALLOC_INLINE_C void 1728ifree(tsd_t *tsd, void *ptr, tcache_t *tcache) 1729{ 1730 size_t usize; 1731 UNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0); 1732 1733 assert(ptr != NULL); 1734 assert(malloc_initialized() || IS_INITIALIZER); 1735 1736 if (config_prof && opt_prof) { 1737 usize = isalloc(ptr, config_prof); 1738 prof_free(tsd, ptr, usize); 1739 } else if (config_stats || config_valgrind) 1740 usize = isalloc(ptr, config_prof); 1741 if (config_stats) 1742 *tsd_thread_deallocatedp_get(tsd) += usize; 1743 if (config_valgrind && unlikely(in_valgrind)) 1744 rzsize = p2rz(ptr); 1745 iqalloc(tsd, ptr, tcache); 1746 JEMALLOC_VALGRIND_FREE(ptr, rzsize); 1747} 1748 1749JEMALLOC_INLINE_C void 1750isfree(tsd_t *tsd, void *ptr, size_t usize, tcache_t *tcache) 1751{ 1752 UNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0); 1753 1754 assert(ptr != NULL); 1755 assert(malloc_initialized() || IS_INITIALIZER); 1756 1757 if (config_prof && opt_prof) 1758 prof_free(tsd, ptr, usize); 1759 if (config_stats) 1760 *tsd_thread_deallocatedp_get(tsd) += usize; 1761 if (config_valgrind && unlikely(in_valgrind)) 1762 rzsize = p2rz(ptr); 1763 isqalloc(tsd, ptr, usize, tcache); 1764 JEMALLOC_VALGRIND_FREE(ptr, rzsize); 1765} 1766 1767JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 1768void JEMALLOC_NOTHROW * 1769JEMALLOC_ALLOC_SIZE(2) 1770je_realloc(void *ptr, size_t size) 1771{ 1772 void *ret; 1773 tsd_t *tsd JEMALLOC_CC_SILENCE_INIT(NULL); 1774 size_t usize JEMALLOC_CC_SILENCE_INIT(0); 1775 size_t old_usize = 0; 1776 UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0); 1777 1778 if (unlikely(size == 0)) { 1779 if (ptr != NULL) { 1780 /* realloc(ptr, 0) is equivalent to free(ptr). */ 1781 UTRACE(ptr, 0, 0); 1782 tsd = tsd_fetch(); 1783 ifree(tsd, ptr, tcache_get(tsd, false)); 1784 return (NULL); 1785 } 1786 size = 1; 1787 } 1788 1789 if (likely(ptr != NULL)) { 1790 assert(malloc_initialized() || IS_INITIALIZER); 1791 malloc_thread_init(); 1792 tsd = tsd_fetch(); 1793 1794 old_usize = isalloc(ptr, config_prof); 1795 if (config_valgrind && unlikely(in_valgrind)) 1796 old_rzsize = config_prof ? p2rz(ptr) : u2rz(old_usize); 1797 1798 if (config_prof && opt_prof) { 1799 usize = s2u(size); 1800 ret = unlikely(usize == 0) ? NULL : irealloc_prof(tsd, 1801 ptr, old_usize, usize); 1802 } else { 1803 if (config_stats || (config_valgrind && 1804 unlikely(in_valgrind))) 1805 usize = s2u(size); 1806 ret = iralloc(tsd, ptr, old_usize, size, 0, false); 1807 } 1808 } else { 1809 /* realloc(NULL, size) is equivalent to malloc(size). */ 1810 ret = imalloc_body(size, &tsd, &usize); 1811 } 1812 1813 if (unlikely(ret == NULL)) { 1814 if (config_xmalloc && unlikely(opt_xmalloc)) { 1815 malloc_write("<jemalloc>: Error in realloc(): " 1816 "out of memory\n"); 1817 abort(); 1818 } 1819 set_errno(ENOMEM); 1820 } 1821 if (config_stats && likely(ret != NULL)) { 1822 assert(usize == isalloc(ret, config_prof)); 1823 *tsd_thread_allocatedp_get(tsd) += usize; 1824 *tsd_thread_deallocatedp_get(tsd) += old_usize; 1825 } 1826 UTRACE(ptr, size, ret); 1827 JEMALLOC_VALGRIND_REALLOC(true, ret, usize, true, ptr, old_usize, 1828 old_rzsize, true, false); 1829 return (ret); 1830} 1831 1832JEMALLOC_EXPORT void JEMALLOC_NOTHROW 1833je_free(void *ptr) 1834{ 1835 1836 UTRACE(ptr, 0, 0); 1837 if (likely(ptr != NULL)) { 1838 tsd_t *tsd = tsd_fetch(); 1839 ifree(tsd, ptr, tcache_get(tsd, false)); 1840 } 1841} 1842 1843/* 1844 * End malloc(3)-compatible functions. 1845 */ 1846/******************************************************************************/ 1847/* 1848 * Begin non-standard override functions. 1849 */ 1850 1851#ifdef JEMALLOC_OVERRIDE_MEMALIGN 1852JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 1853void JEMALLOC_NOTHROW * 1854JEMALLOC_ATTR(malloc) 1855je_memalign(size_t alignment, size_t size) 1856{ 1857 void *ret JEMALLOC_CC_SILENCE_INIT(NULL); 1858 if (unlikely(imemalign(&ret, alignment, size, 1) != 0)) 1859 ret = NULL; 1860 JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false); 1861 return (ret); 1862} 1863#endif 1864 1865#ifdef JEMALLOC_OVERRIDE_VALLOC 1866JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 1867void JEMALLOC_NOTHROW * 1868JEMALLOC_ATTR(malloc) 1869je_valloc(size_t size) 1870{ 1871 void *ret JEMALLOC_CC_SILENCE_INIT(NULL); 1872 if (unlikely(imemalign(&ret, PAGE, size, 1) != 0)) 1873 ret = NULL; 1874 JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false); 1875 return (ret); 1876} 1877#endif 1878 1879/* 1880 * is_malloc(je_malloc) is some macro magic to detect if jemalloc_defs.h has 1881 * #define je_malloc malloc 1882 */ 1883#define malloc_is_malloc 1 1884#define is_malloc_(a) malloc_is_ ## a 1885#define is_malloc(a) is_malloc_(a) 1886 1887#if ((is_malloc(je_malloc) == 1) && defined(JEMALLOC_GLIBC_MALLOC_HOOK)) 1888/* 1889 * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible 1890 * to inconsistently reference libc's malloc(3)-compatible functions 1891 * (https://bugzilla.mozilla.org/show_bug.cgi?id=493541). 1892 * 1893 * These definitions interpose hooks in glibc. The functions are actually 1894 * passed an extra argument for the caller return address, which will be 1895 * ignored. 1896 */ 1897JEMALLOC_EXPORT void (*__free_hook)(void *ptr) = je_free; 1898JEMALLOC_EXPORT void *(*__malloc_hook)(size_t size) = je_malloc; 1899JEMALLOC_EXPORT void *(*__realloc_hook)(void *ptr, size_t size) = je_realloc; 1900# ifdef JEMALLOC_GLIBC_MEMALIGN_HOOK 1901JEMALLOC_EXPORT void *(*__memalign_hook)(size_t alignment, size_t size) = 1902 je_memalign; 1903# endif 1904#endif 1905 1906/* 1907 * End non-standard override functions. 1908 */ 1909/******************************************************************************/ 1910/* 1911 * Begin non-standard functions. 1912 */ 1913 1914JEMALLOC_ALWAYS_INLINE_C bool 1915imallocx_flags_decode_hard(tsd_t *tsd, size_t size, int flags, size_t *usize, 1916 size_t *alignment, bool *zero, tcache_t **tcache, arena_t **arena) 1917{ 1918 1919 if ((flags & MALLOCX_LG_ALIGN_MASK) == 0) { 1920 *alignment = 0; 1921 *usize = s2u(size); 1922 } else { 1923 *alignment = MALLOCX_ALIGN_GET_SPECIFIED(flags); 1924 *usize = sa2u(size, *alignment); 1925 } 1926 *zero = MALLOCX_ZERO_GET(flags); 1927 if ((flags & MALLOCX_TCACHE_MASK) != 0) { 1928 if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE) 1929 *tcache = NULL; 1930 else 1931 *tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags)); 1932 } else 1933 *tcache = tcache_get(tsd, true); 1934 if ((flags & MALLOCX_ARENA_MASK) != 0) { 1935 unsigned arena_ind = MALLOCX_ARENA_GET(flags); 1936 *arena = arena_get(tsd, arena_ind, true, true); 1937 if (unlikely(*arena == NULL)) 1938 return (true); 1939 } else 1940 *arena = NULL; 1941 return (false); 1942} 1943 1944JEMALLOC_ALWAYS_INLINE_C bool 1945imallocx_flags_decode(tsd_t *tsd, size_t size, int flags, size_t *usize, 1946 size_t *alignment, bool *zero, tcache_t **tcache, arena_t **arena) 1947{ 1948 1949 if (likely(flags == 0)) { 1950 *usize = s2u(size); 1951 assert(*usize != 0); 1952 *alignment = 0; 1953 *zero = false; 1954 *tcache = tcache_get(tsd, true); 1955 *arena = NULL; 1956 return (false); 1957 } else { 1958 return (imallocx_flags_decode_hard(tsd, size, flags, usize, 1959 alignment, zero, tcache, arena)); 1960 } 1961} 1962 1963JEMALLOC_ALWAYS_INLINE_C void * 1964imallocx_flags(tsd_t *tsd, size_t usize, size_t alignment, bool zero, 1965 tcache_t *tcache, arena_t *arena) 1966{ 1967 1968 if (alignment != 0) 1969 return (ipalloct(tsd, usize, alignment, zero, tcache, arena)); 1970 if (zero) 1971 return (icalloct(tsd, usize, tcache, arena)); 1972 return (imalloct(tsd, usize, tcache, arena)); 1973} 1974 1975JEMALLOC_ALWAYS_INLINE_C void * 1976imallocx_maybe_flags(tsd_t *tsd, size_t size, int flags, size_t usize, 1977 size_t alignment, bool zero, tcache_t *tcache, arena_t *arena) 1978{ 1979 1980 if (likely(flags == 0)) 1981 return (imalloc(tsd, size)); 1982 return (imallocx_flags(tsd, usize, alignment, zero, tcache, arena)); 1983} 1984 1985static void * 1986imallocx_prof_sample(tsd_t *tsd, size_t size, int flags, size_t usize, 1987 size_t alignment, bool zero, tcache_t *tcache, arena_t *arena) 1988{ 1989 void *p; 1990 1991 if (usize <= SMALL_MAXCLASS) { 1992 assert(((alignment == 0) ? s2u(LARGE_MINCLASS) : 1993 sa2u(LARGE_MINCLASS, alignment)) == LARGE_MINCLASS); 1994 p = imallocx_maybe_flags(tsd, LARGE_MINCLASS, flags, 1995 LARGE_MINCLASS, alignment, zero, tcache, arena); 1996 if (p == NULL) 1997 return (NULL); 1998 arena_prof_promoted(p, usize); 1999 } else { 2000 p = imallocx_maybe_flags(tsd, size, flags, usize, alignment, 2001 zero, tcache, arena); 2002 } 2003 2004 return (p); 2005} 2006 2007JEMALLOC_ALWAYS_INLINE_C void * 2008imallocx_prof(tsd_t *tsd, size_t size, int flags, size_t *usize) 2009{ 2010 void *p; 2011 size_t alignment; 2012 bool zero; 2013 tcache_t *tcache; 2014 arena_t *arena; 2015 prof_tctx_t *tctx; 2016 2017 if (unlikely(imallocx_flags_decode(tsd, size, flags, usize, &alignment, 2018 &zero, &tcache, &arena))) 2019 return (NULL); 2020 tctx = prof_alloc_prep(tsd, *usize, prof_active_get_unlocked(), true); 2021 if (likely((uintptr_t)tctx == (uintptr_t)1U)) { 2022 p = imallocx_maybe_flags(tsd, size, flags, *usize, alignment, 2023 zero, tcache, arena); 2024 } else if ((uintptr_t)tctx > (uintptr_t)1U) { 2025 p = imallocx_prof_sample(tsd, size, flags, *usize, alignment, 2026 zero, tcache, arena); 2027 } else 2028 p = NULL; 2029 if (unlikely(p == NULL)) { 2030 prof_alloc_rollback(tsd, tctx, true); 2031 return (NULL); 2032 } 2033 prof_malloc(p, *usize, tctx); 2034 2035 assert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0)); 2036 return (p); 2037} 2038 2039JEMALLOC_ALWAYS_INLINE_C void * 2040imallocx_no_prof(tsd_t *tsd, size_t size, int flags, size_t *usize) 2041{ 2042 void *p; 2043 size_t alignment; 2044 bool zero; 2045 tcache_t *tcache; 2046 arena_t *arena; 2047 2048 if (likely(flags == 0)) { 2049 if (config_stats || (config_valgrind && unlikely(in_valgrind))) 2050 *usize = s2u(size); 2051 return (imalloc(tsd, size)); 2052 } 2053 2054 if (unlikely(imallocx_flags_decode_hard(tsd, size, flags, usize, 2055 &alignment, &zero, &tcache, &arena))) 2056 return (NULL); 2057 p = imallocx_flags(tsd, *usize, alignment, zero, tcache, arena); 2058 assert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0)); 2059 return (p); 2060} 2061 2062JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 2063void JEMALLOC_NOTHROW * 2064JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1) 2065je_mallocx(size_t size, int flags) 2066{ 2067 tsd_t *tsd; 2068 void *p; 2069 size_t usize; 2070 2071 assert(size != 0); 2072 2073 if (unlikely(malloc_init())) 2074 goto label_oom; 2075 tsd = tsd_fetch(); 2076 2077 if (config_prof && opt_prof) 2078 p = imallocx_prof(tsd, size, flags, &usize); 2079 else 2080 p = imallocx_no_prof(tsd, size, flags, &usize); 2081 if (unlikely(p == NULL)) 2082 goto label_oom; 2083 2084 if (config_stats) { 2085 assert(usize == isalloc(p, config_prof)); 2086 *tsd_thread_allocatedp_get(tsd) += usize; 2087 } 2088 UTRACE(0, size, p); 2089 JEMALLOC_VALGRIND_MALLOC(true, p, usize, MALLOCX_ZERO_GET(flags)); 2090 return (p); 2091label_oom: 2092 if (config_xmalloc && unlikely(opt_xmalloc)) { 2093 malloc_write("<jemalloc>: Error in mallocx(): out of memory\n"); 2094 abort(); 2095 } 2096 UTRACE(0, size, 0); 2097 return (NULL); 2098} 2099 2100static void * 2101irallocx_prof_sample(tsd_t *tsd, void *oldptr, size_t old_usize, size_t size, 2102 size_t alignment, size_t usize, bool zero, tcache_t *tcache, arena_t *arena, 2103 prof_tctx_t *tctx) 2104{ 2105 void *p; 2106 2107 if (tctx == NULL) 2108 return (NULL); 2109 if (usize <= SMALL_MAXCLASS) { 2110 p = iralloct(tsd, oldptr, old_usize, LARGE_MINCLASS, alignment, 2111 zero, tcache, arena); 2112 if (p == NULL) 2113 return (NULL); 2114 arena_prof_promoted(p, usize); 2115 } else { 2116 p = iralloct(tsd, oldptr, old_usize, size, alignment, zero, 2117 tcache, arena); 2118 } 2119 2120 return (p); 2121} 2122 2123JEMALLOC_ALWAYS_INLINE_C void * 2124irallocx_prof(tsd_t *tsd, void *oldptr, size_t old_usize, size_t size, 2125 size_t alignment, size_t *usize, bool zero, tcache_t *tcache, 2126 arena_t *arena) 2127{ 2128 void *p; 2129 bool prof_active; 2130 prof_tctx_t *old_tctx, *tctx; 2131 2132 prof_active = prof_active_get_unlocked(); 2133 old_tctx = prof_tctx_get(oldptr); 2134 tctx = prof_alloc_prep(tsd, *usize, prof_active, true); 2135 if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) { 2136 p = irallocx_prof_sample(tsd, oldptr, old_usize, size, 2137 alignment, *usize, zero, tcache, arena, tctx); 2138 } else { 2139 p = iralloct(tsd, oldptr, old_usize, size, alignment, zero, 2140 tcache, arena); 2141 } 2142 if (unlikely(p == NULL)) { 2143 prof_alloc_rollback(tsd, tctx, true); 2144 return (NULL); 2145 } 2146 2147 if (p == oldptr && alignment != 0) { 2148 /* 2149 * The allocation did not move, so it is possible that the size 2150 * class is smaller than would guarantee the requested 2151 * alignment, and that the alignment constraint was 2152 * serendipitously satisfied. Additionally, old_usize may not 2153 * be the same as the current usize because of in-place large 2154 * reallocation. Therefore, query the actual value of usize. 2155 */ 2156 *usize = isalloc(p, config_prof); 2157 } 2158 prof_realloc(tsd, p, *usize, tctx, prof_active, true, 2159 old_usize, old_tctx); 2160 2161 return (p); 2162} 2163 2164JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN 2165void JEMALLOC_NOTHROW * 2166JEMALLOC_ALLOC_SIZE(2) 2167je_rallocx(void *ptr, size_t size, int flags) 2168{ 2169 void *p; 2170 tsd_t *tsd; 2171 size_t usize; 2172 size_t old_usize; 2173 UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0); 2174 size_t alignment = MALLOCX_ALIGN_GET(flags); 2175 bool zero = flags & MALLOCX_ZERO; 2176 arena_t *arena; 2177 tcache_t *tcache; 2178 2179 assert(ptr != NULL); 2180 assert(size != 0); 2181 assert(malloc_initialized() || IS_INITIALIZER); 2182 malloc_thread_init(); 2183 tsd = tsd_fetch(); 2184 2185 if (unlikely((flags & MALLOCX_ARENA_MASK) != 0)) { 2186 unsigned arena_ind = MALLOCX_ARENA_GET(flags); 2187 arena = arena_get(tsd, arena_ind, true, true); 2188 if (unlikely(arena == NULL)) 2189 goto label_oom; 2190 } else 2191 arena = NULL; 2192 2193 if (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) { 2194 if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE) 2195 tcache = NULL; 2196 else 2197 tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags)); 2198 } else 2199 tcache = tcache_get(tsd, true); 2200 2201 old_usize = isalloc(ptr, config_prof); 2202 if (config_valgrind && unlikely(in_valgrind)) 2203 old_rzsize = u2rz(old_usize); 2204 2205 if (config_prof && opt_prof) { 2206 usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment); 2207 assert(usize != 0); 2208 p = irallocx_prof(tsd, ptr, old_usize, size, alignment, &usize, 2209 zero, tcache, arena); 2210 if (unlikely(p == NULL)) 2211 goto label_oom; 2212 } else { 2213 p = iralloct(tsd, ptr, old_usize, size, alignment, zero, 2214 tcache, arena); 2215 if (unlikely(p == NULL)) 2216 goto label_oom; 2217 if (config_stats || (config_valgrind && unlikely(in_valgrind))) 2218 usize = isalloc(p, config_prof); 2219 } 2220 assert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0)); 2221 2222 if (config_stats) { 2223 *tsd_thread_allocatedp_get(tsd) += usize; 2224 *tsd_thread_deallocatedp_get(tsd) += old_usize; 2225 } 2226 UTRACE(ptr, size, p); 2227 JEMALLOC_VALGRIND_REALLOC(true, p, usize, false, ptr, old_usize, 2228 old_rzsize, false, zero); 2229 return (p); 2230label_oom: 2231 if (config_xmalloc && unlikely(opt_xmalloc)) { 2232 malloc_write("<jemalloc>: Error in rallocx(): out of memory\n"); 2233 abort(); 2234 } 2235 UTRACE(ptr, size, 0); 2236 return (NULL); 2237} 2238 2239JEMALLOC_ALWAYS_INLINE_C size_t 2240ixallocx_helper(void *ptr, size_t old_usize, size_t size, size_t extra, 2241 size_t alignment, bool zero) 2242{ 2243 size_t usize; 2244 2245 if (ixalloc(ptr, old_usize, size, extra, alignment, zero)) 2246 return (old_usize); 2247 usize = isalloc(ptr, config_prof); 2248 2249 return (usize); 2250} 2251 2252static size_t 2253ixallocx_prof_sample(void *ptr, size_t old_usize, size_t size, size_t extra, 2254 size_t alignment, size_t max_usize, bool zero, prof_tctx_t *tctx) 2255{ 2256 size_t usize; 2257 2258 if (tctx == NULL) 2259 return (old_usize); 2260 /* Use minimum usize to determine whether promotion may happen. */ 2261 if (((alignment == 0) ? s2u(size) : sa2u(size, alignment)) <= 2262 SMALL_MAXCLASS) { 2263 if (ixalloc(ptr, old_usize, SMALL_MAXCLASS+1, 2264 (SMALL_MAXCLASS+1 >= size+extra) ? 0 : size+extra - 2265 (SMALL_MAXCLASS+1), alignment, zero)) 2266 return (old_usize); 2267 usize = isalloc(ptr, config_prof); 2268 if (max_usize < LARGE_MINCLASS) 2269 arena_prof_promoted(ptr, usize); 2270 } else { 2271 usize = ixallocx_helper(ptr, old_usize, size, extra, alignment, 2272 zero); 2273 } 2274 2275 return (usize); 2276} 2277 2278JEMALLOC_ALWAYS_INLINE_C size_t 2279ixallocx_prof(tsd_t *tsd, void *ptr, size_t old_usize, size_t size, 2280 size_t extra, size_t alignment, bool zero) 2281{ 2282 size_t max_usize, usize; 2283 bool prof_active; 2284 prof_tctx_t *old_tctx, *tctx; 2285 2286 prof_active = prof_active_get_unlocked(); 2287 old_tctx = prof_tctx_get(ptr); 2288 /* Clamp extra if necessary to avoid (size + extra) overflow. */ 2289 if (unlikely(size + extra > HUGE_MAXCLASS)) 2290 extra = HUGE_MAXCLASS - size; 2291 /* 2292 * usize isn't knowable before ixalloc() returns when extra is non-zero. 2293 * Therefore, compute its maximum possible value and use that in 2294 * prof_alloc_prep() to decide whether to capture a backtrace. 2295 * prof_realloc() will use the actual usize to decide whether to sample. 2296 */ 2297 max_usize = (alignment == 0) ? s2u(size+extra) : sa2u(size+extra, 2298 alignment); 2299 tctx = prof_alloc_prep(tsd, max_usize, prof_active, false); 2300 if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) { 2301 usize = ixallocx_prof_sample(ptr, old_usize, size, extra, 2302 alignment, zero, max_usize, tctx); 2303 } else { 2304 usize = ixallocx_helper(ptr, old_usize, size, extra, alignment, 2305 zero); 2306 } 2307 if (unlikely(usize == old_usize)) { 2308 prof_alloc_rollback(tsd, tctx, false); 2309 return (usize); 2310 } 2311 prof_realloc(tsd, ptr, usize, tctx, prof_active, false, old_usize, 2312 old_tctx); 2313 2314 return (usize); 2315} 2316 2317JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW 2318je_xallocx(void *ptr, size_t size, size_t extra, int flags) 2319{ 2320 tsd_t *tsd; 2321 size_t usize, old_usize; 2322 UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0); 2323 size_t alignment = MALLOCX_ALIGN_GET(flags); 2324 bool zero = flags & MALLOCX_ZERO; 2325 2326 assert(ptr != NULL); 2327 assert(size != 0); 2328 assert(SIZE_T_MAX - size >= extra); 2329 assert(malloc_initialized() || IS_INITIALIZER); 2330 malloc_thread_init(); 2331 tsd = tsd_fetch(); 2332 2333 old_usize = isalloc(ptr, config_prof); 2334 if (config_valgrind && unlikely(in_valgrind)) 2335 old_rzsize = u2rz(old_usize); 2336 2337 if (config_prof && opt_prof) { 2338 usize = ixallocx_prof(tsd, ptr, old_usize, size, extra, 2339 alignment, zero); 2340 } else { 2341 usize = ixallocx_helper(ptr, old_usize, size, extra, alignment, 2342 zero); 2343 } 2344 if (unlikely(usize == old_usize)) 2345 goto label_not_resized; 2346 2347 if (config_stats) { 2348 *tsd_thread_allocatedp_get(tsd) += usize; 2349 *tsd_thread_deallocatedp_get(tsd) += old_usize; 2350 } 2351 JEMALLOC_VALGRIND_REALLOC(false, ptr, usize, false, ptr, old_usize, 2352 old_rzsize, false, zero); 2353label_not_resized: 2354 UTRACE(ptr, size, ptr); 2355 return (usize); 2356} 2357 2358JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW 2359JEMALLOC_ATTR(pure) 2360je_sallocx(const void *ptr, int flags) 2361{ 2362 size_t usize; 2363 2364 assert(malloc_initialized() || IS_INITIALIZER); 2365 malloc_thread_init(); 2366 2367 if (config_ivsalloc) 2368 usize = ivsalloc(ptr, config_prof); 2369 else 2370 usize = isalloc(ptr, config_prof); 2371 2372 return (usize); 2373} 2374 2375JEMALLOC_EXPORT void JEMALLOC_NOTHROW 2376je_dallocx(void *ptr, int flags) 2377{ 2378 tsd_t *tsd; 2379 tcache_t *tcache; 2380 2381 assert(ptr != NULL); 2382 assert(malloc_initialized() || IS_INITIALIZER); 2383 2384 tsd = tsd_fetch(); 2385 if (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) { 2386 if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE) 2387 tcache = NULL; 2388 else 2389 tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags)); 2390 } else 2391 tcache = tcache_get(tsd, false); 2392 2393 UTRACE(ptr, 0, 0); 2394 ifree(tsd_fetch(), ptr, tcache); 2395} 2396 2397JEMALLOC_ALWAYS_INLINE_C size_t 2398inallocx(size_t size, int flags) 2399{ 2400 size_t usize; 2401 2402 if (likely((flags & MALLOCX_LG_ALIGN_MASK) == 0)) 2403 usize = s2u(size); 2404 else 2405 usize = sa2u(size, MALLOCX_ALIGN_GET_SPECIFIED(flags)); 2406 assert(usize != 0); 2407 return (usize); 2408} 2409 2410JEMALLOC_EXPORT void JEMALLOC_NOTHROW 2411je_sdallocx(void *ptr, size_t size, int flags) 2412{ 2413 tsd_t *tsd; 2414 tcache_t *tcache; 2415 size_t usize; 2416 2417 assert(ptr != NULL); 2418 assert(malloc_initialized() || IS_INITIALIZER); 2419 usize = inallocx(size, flags); 2420 assert(usize == isalloc(ptr, config_prof)); 2421 2422 tsd = tsd_fetch(); 2423 if (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) { 2424 if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE) 2425 tcache = NULL; 2426 else 2427 tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags)); 2428 } else 2429 tcache = tcache_get(tsd, false); 2430 2431 UTRACE(ptr, 0, 0); 2432 isfree(tsd, ptr, usize, tcache); 2433} 2434 2435JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW 2436JEMALLOC_ATTR(pure) 2437je_nallocx(size_t size, int flags) 2438{ 2439 2440 assert(size != 0); 2441 2442 if (unlikely(malloc_init())) 2443 return (0); 2444 2445 return (inallocx(size, flags)); 2446} 2447 2448JEMALLOC_EXPORT int JEMALLOC_NOTHROW 2449je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, 2450 size_t newlen) 2451{ 2452 2453 if (unlikely(malloc_init())) 2454 return (EAGAIN); 2455 2456 return (ctl_byname(name, oldp, oldlenp, newp, newlen)); 2457} 2458 2459JEMALLOC_EXPORT int JEMALLOC_NOTHROW 2460je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp) 2461{ 2462 2463 if (unlikely(malloc_init())) 2464 return (EAGAIN); 2465 2466 return (ctl_nametomib(name, mibp, miblenp)); 2467} 2468 2469JEMALLOC_EXPORT int JEMALLOC_NOTHROW 2470je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, 2471 void *newp, size_t newlen) 2472{ 2473 2474 if (unlikely(malloc_init())) 2475 return (EAGAIN); 2476 2477 return (ctl_bymib(mib, miblen, oldp, oldlenp, newp, newlen)); 2478} 2479 2480JEMALLOC_EXPORT void JEMALLOC_NOTHROW 2481je_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque, 2482 const char *opts) 2483{ 2484 2485 stats_print(write_cb, cbopaque, opts); 2486} 2487 2488JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW 2489je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr) 2490{ 2491 size_t ret; 2492 2493 assert(malloc_initialized() || IS_INITIALIZER); 2494 malloc_thread_init(); 2495 2496 if (config_ivsalloc) 2497 ret = ivsalloc(ptr, config_prof); 2498 else 2499 ret = (ptr == NULL) ? 0 : isalloc(ptr, config_prof); 2500 2501 return (ret); 2502} 2503 2504/* 2505 * End non-standard functions. 2506 */ 2507/******************************************************************************/ 2508/* 2509 * The following functions are used by threading libraries for protection of 2510 * malloc during fork(). 2511 */ 2512 2513/* 2514 * If an application creates a thread before doing any allocation in the main 2515 * thread, then calls fork(2) in the main thread followed by memory allocation 2516 * in the child process, a race can occur that results in deadlock within the 2517 * child: the main thread may have forked while the created thread had 2518 * partially initialized the allocator. Ordinarily jemalloc prevents 2519 * fork/malloc races via the following functions it registers during 2520 * initialization using pthread_atfork(), but of course that does no good if 2521 * the allocator isn't fully initialized at fork time. The following library 2522 * constructor is a partial solution to this problem. It may still be possible 2523 * to trigger the deadlock described above, but doing so would involve forking 2524 * via a library constructor that runs before jemalloc's runs. 2525 */ 2526JEMALLOC_ATTR(constructor) 2527static void 2528jemalloc_constructor(void) 2529{ 2530 2531 malloc_init(); 2532} 2533 2534#ifndef JEMALLOC_MUTEX_INIT_CB 2535void 2536jemalloc_prefork(void) 2537#else 2538JEMALLOC_EXPORT void 2539_malloc_prefork(void) 2540#endif 2541{ 2542 unsigned i; 2543 2544#ifdef JEMALLOC_MUTEX_INIT_CB 2545 if (!malloc_initialized()) 2546 return; 2547#endif 2548 assert(malloc_initialized()); 2549 2550 /* Acquire all mutexes in a safe order. */ 2551 ctl_prefork(); 2552 prof_prefork(); 2553 malloc_mutex_prefork(&arenas_lock); 2554 for (i = 0; i < narenas_total; i++) { 2555 if (arenas[i] != NULL) 2556 arena_prefork(arenas[i]); 2557 } 2558 chunk_prefork(); 2559 base_prefork(); 2560} 2561 2562#ifndef JEMALLOC_MUTEX_INIT_CB 2563void 2564jemalloc_postfork_parent(void) 2565#else 2566JEMALLOC_EXPORT void 2567_malloc_postfork(void) 2568#endif 2569{ 2570 unsigned i; 2571 2572#ifdef JEMALLOC_MUTEX_INIT_CB 2573 if (!malloc_initialized()) 2574 return; 2575#endif 2576 assert(malloc_initialized()); 2577 2578 /* Release all mutexes, now that fork() has completed. */ 2579 base_postfork_parent(); 2580 chunk_postfork_parent(); 2581 for (i = 0; i < narenas_total; i++) { 2582 if (arenas[i] != NULL) 2583 arena_postfork_parent(arenas[i]); 2584 } 2585 malloc_mutex_postfork_parent(&arenas_lock); 2586 prof_postfork_parent(); 2587 ctl_postfork_parent(); 2588} 2589 2590void 2591jemalloc_postfork_child(void) 2592{ 2593 unsigned i; 2594 2595 assert(malloc_initialized()); 2596 2597 /* Release all mutexes, now that fork() has completed. */ 2598 base_postfork_child(); 2599 chunk_postfork_child(); 2600 for (i = 0; i < narenas_total; i++) { 2601 if (arenas[i] != NULL) 2602 arena_postfork_child(arenas[i]); 2603 } 2604 malloc_mutex_postfork_child(&arenas_lock); 2605 prof_postfork_child(); 2606 ctl_postfork_child(); 2607} 2608 2609/******************************************************************************/ 2610