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