1 /* -*- Mode: C; tab-width: 8; c-basic-offset: 8 -*- */ 2 /* vim:set softtabstop=8 shiftwidth=8: */ 3 /*- 4 * Copyright (C) 2006-2008 Jason Evans <jasone (at) FreeBSD.org>. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice(s), this list of conditions and the following disclaimer as 12 * the first lines of this file unmodified other than the possible 13 * addition of one or more copyright notices. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice(s), this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 28 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 29 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 ******************************************************************************* 32 * 33 * This allocator implementation is designed to provide scalable performance 34 * for multi-threaded programs on multi-processor systems. The following 35 * features are included for this purpose: 36 * 37 * + Multiple arenas are used if there are multiple CPUs, which reduces lock 38 * contention and cache sloshing. 39 * 40 * + Cache line sharing between arenas is avoided for internal data 41 * structures. 42 * 43 * + Memory is managed in chunks and runs (chunks can be split into runs), 44 * rather than as individual pages. This provides a constant-time 45 * mechanism for associating allocations with particular arenas. 46 * 47 * Allocation requests are rounded up to the nearest size class, and no record 48 * of the original request size is maintained. Allocations are broken into 49 * categories according to size class. Assuming runtime defaults, 4 kB pages 50 * and a 16 byte quantum on a 32-bit system, the size classes in each category 51 * are as follows: 52 * 53 * |=====================================| 54 * | Category | Subcategory | Size | 55 * |=====================================| 56 * | Small | Tiny | 2 | 57 * | | | 4 | 58 * | | | 8 | 59 * | |----------------+---------| 60 * | | Quantum-spaced | 16 | 61 * | | | 32 | 62 * | | | 48 | 63 * | | | ... | 64 * | | | 480 | 65 * | | | 496 | 66 * | | | 512 | 67 * | |----------------+---------| 68 * | | Sub-page | 1 kB | 69 * | | | 2 kB | 70 * |=====================================| 71 * | Large | 4 kB | 72 * | | 8 kB | 73 * | | 12 kB | 74 * | | ... | 75 * | | 1012 kB | 76 * | | 1016 kB | 77 * | | 1020 kB | 78 * |=====================================| 79 * | Huge | 1 MB | 80 * | | 2 MB | 81 * | | 3 MB | 82 * | | ... | 83 * |=====================================| 84 * 85 * A different mechanism is used for each category: 86 * 87 * Small : Each size class is segregated into its own set of runs. Each run 88 * maintains a bitmap of which regions are free/allocated. 89 * 90 * Large : Each allocation is backed by a dedicated run. Metadata are stored 91 * in the associated arena chunk header maps. 92 * 93 * Huge : Each allocation is backed by a dedicated contiguous set of chunks. 94 * Metadata are stored in a separate red-black tree. 95 * 96 ******************************************************************************* 97 */ 98 99 /* 100 * NOTE(mbelshe): Added these defines to fit within chromium build system. 101 */ 102 #define MOZ_MEMORY_WINDOWS 103 #define MOZ_MEMORY 104 #define DONT_OVERRIDE_LIBC 105 106 /* 107 * MALLOC_PRODUCTION disables assertions and statistics gathering. It also 108 * defaults the A and J runtime options to off. These settings are appropriate 109 * for production systems. 110 */ 111 #ifndef MOZ_MEMORY_DEBUG 112 # define MALLOC_PRODUCTION 113 #endif 114 115 /* 116 * Use only one arena by default. Mozilla does not currently make extensive 117 * use of concurrent allocation, so the increased fragmentation associated with 118 * multiple arenas is not warranted. 119 */ 120 #define MOZ_MEMORY_NARENAS_DEFAULT_ONE 121 122 /* 123 * MALLOC_STATS enables statistics calculation, and is required for 124 * jemalloc_stats(). 125 */ 126 #define MALLOC_STATS 127 128 #ifndef MALLOC_PRODUCTION 129 /* 130 * MALLOC_DEBUG enables assertions and other sanity checks, and disables 131 * inline functions. 132 */ 133 # define MALLOC_DEBUG 134 135 /* Memory filling (junk/zero). */ 136 # define MALLOC_FILL 137 138 /* Allocation tracing. */ 139 # ifndef MOZ_MEMORY_WINDOWS 140 # define MALLOC_UTRACE 141 # endif 142 143 /* Support optional abort() on OOM. */ 144 # define MALLOC_XMALLOC 145 146 /* Support SYSV semantics. */ 147 # define MALLOC_SYSV 148 #endif 149 150 /* 151 * MALLOC_VALIDATE causes malloc_usable_size() to perform some pointer 152 * validation. There are many possible errors that validation does not even 153 * attempt to detect. 154 */ 155 #define MALLOC_VALIDATE 156 157 /* Embed no-op macros that support memory allocation tracking via valgrind. */ 158 #ifdef MOZ_VALGRIND 159 # define MALLOC_VALGRIND 160 #endif 161 #ifdef MALLOC_VALGRIND 162 # include <valgrind/valgrind.h> 163 #else 164 # define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) 165 # define VALGRIND_FREELIKE_BLOCK(addr, rzB) 166 #endif 167 168 /* 169 * MALLOC_BALANCE enables monitoring of arena lock contention and dynamically 170 * re-balances arena load if exponentially averaged contention exceeds a 171 * certain threshold. 172 */ 173 /* #define MALLOC_BALANCE */ 174 175 #if (!defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN)) 176 /* 177 * MALLOC_PAGEFILE causes all mmap()ed memory to be backed by temporary 178 * files, so that if a chunk is mapped, it is guaranteed to be swappable. 179 * This avoids asynchronous OOM failures that are due to VM over-commit. 180 * 181 * XXX OS X over-commits, so we should probably use mmap() instead of 182 * vm_allocate(), so that MALLOC_PAGEFILE works. 183 */ 184 #define MALLOC_PAGEFILE 185 #endif 186 187 #ifdef MALLOC_PAGEFILE 188 /* Write size when initializing a page file. */ 189 # define MALLOC_PAGEFILE_WRITE_SIZE 512 190 #endif 191 192 #ifdef MOZ_MEMORY_LINUX 193 #define _GNU_SOURCE /* For mremap(2). */ 194 #define issetugid() 0 195 #if 0 /* Enable in order to test decommit code on Linux. */ 196 # define MALLOC_DECOMMIT 197 #endif 198 #endif 199 200 #ifndef MOZ_MEMORY_WINCE 201 #include <sys/types.h> 202 203 #include <errno.h> 204 #include <stdlib.h> 205 #endif 206 #include <limits.h> 207 #include <stdarg.h> 208 #include <stdio.h> 209 #include <string.h> 210 211 #ifdef MOZ_MEMORY_WINDOWS 212 #ifndef MOZ_MEMORY_WINCE 213 //#include <cruntime.h> 214 //#include <internal.h> 215 #include <io.h> 216 #else 217 #include <cmnintrin.h> 218 #include <crtdefs.h> 219 #define SIZE_MAX UINT_MAX 220 #endif 221 #include <windows.h> 222 223 #pragma warning( disable: 4267 4996 4146 ) 224 225 #define false FALSE 226 #define true TRUE 227 #define inline __inline 228 #define SIZE_T_MAX SIZE_MAX 229 #define STDERR_FILENO 2 230 #define PATH_MAX MAX_PATH 231 #define vsnprintf _vsnprintf 232 233 #ifndef NO_TLS 234 static unsigned long tlsIndex = 0xffffffff; 235 #endif 236 237 #define __thread 238 #ifdef MOZ_MEMORY_WINCE 239 #define _pthread_self() GetCurrentThreadId() 240 #else 241 #define _pthread_self() __threadid() 242 #endif 243 #define issetugid() 0 244 245 #ifndef MOZ_MEMORY_WINCE 246 /* use MSVC intrinsics */ 247 #pragma intrinsic(_BitScanForward) 248 static __forceinline int 249 ffs(int x) 250 { 251 unsigned long i; 252 253 if (_BitScanForward(&i, x) != 0) 254 return (i + 1); 255 256 return (0); 257 } 258 259 /* Implement getenv without using malloc */ 260 static char mozillaMallocOptionsBuf[64]; 261 262 #define getenv xgetenv 263 static char * 264 getenv(const char *name) 265 { 266 267 if (GetEnvironmentVariableA(name, (LPSTR)&mozillaMallocOptionsBuf, 268 sizeof(mozillaMallocOptionsBuf)) > 0) 269 return (mozillaMallocOptionsBuf); 270 271 return (NULL); 272 } 273 274 #else /* WIN CE */ 275 276 #define ENOMEM 12 277 #define EINVAL 22 278 279 static __forceinline int 280 ffs(int x) 281 { 282 283 return 32 - _CountLeadingZeros((-x) & x); 284 } 285 #endif 286 287 typedef unsigned char uint8_t; 288 typedef unsigned uint32_t; 289 typedef unsigned long long uint64_t; 290 typedef unsigned long long uintmax_t; 291 typedef long ssize_t; 292 293 #define MALLOC_DECOMMIT 294 #endif 295 296 #ifndef MOZ_MEMORY_WINDOWS 297 #ifndef MOZ_MEMORY_SOLARIS 298 #include <sys/cdefs.h> 299 #endif 300 #ifndef __DECONST 301 # define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) 302 #endif 303 #ifndef MOZ_MEMORY 304 __FBSDID("$FreeBSD: head/lib/libc/stdlib/malloc.c 180599 2008-07-18 19:35:44Z jasone $"); 305 #include "libc_private.h" 306 #ifdef MALLOC_DEBUG 307 # define _LOCK_DEBUG 308 #endif 309 #include "spinlock.h" 310 #include "namespace.h" 311 #endif 312 #include <sys/mman.h> 313 #ifndef MADV_FREE 314 # define MADV_FREE MADV_DONTNEED 315 #endif 316 #ifndef MAP_NOSYNC 317 # define MAP_NOSYNC 0 318 #endif 319 #include <sys/param.h> 320 #ifndef MOZ_MEMORY 321 #include <sys/stddef.h> 322 #endif 323 #include <sys/time.h> 324 #include <sys/types.h> 325 #ifndef MOZ_MEMORY_SOLARIS 326 #include <sys/sysctl.h> 327 #endif 328 #include <sys/uio.h> 329 #ifndef MOZ_MEMORY 330 #include <sys/ktrace.h> /* Must come after several other sys/ includes. */ 331 332 #include <machine/atomic.h> 333 #include <machine/cpufunc.h> 334 #include <machine/vmparam.h> 335 #endif 336 337 #include <errno.h> 338 #include <limits.h> 339 #ifndef SIZE_T_MAX 340 # define SIZE_T_MAX SIZE_MAX 341 #endif 342 #include <pthread.h> 343 #ifdef MOZ_MEMORY_DARWIN 344 #define _pthread_self pthread_self 345 #define _pthread_mutex_init pthread_mutex_init 346 #define _pthread_mutex_trylock pthread_mutex_trylock 347 #define _pthread_mutex_lock pthread_mutex_lock 348 #define _pthread_mutex_unlock pthread_mutex_unlock 349 #endif 350 #include <sched.h> 351 #include <stdarg.h> 352 #include <stdbool.h> 353 #include <stdio.h> 354 #include <stdint.h> 355 #include <stdlib.h> 356 #include <string.h> 357 #ifndef MOZ_MEMORY_DARWIN 358 #include <strings.h> 359 #endif 360 #include <unistd.h> 361 362 #ifdef MOZ_MEMORY_DARWIN 363 #include <libkern/OSAtomic.h> 364 #include <mach/mach_error.h> 365 #include <mach/mach_init.h> 366 #include <mach/vm_map.h> 367 #include <malloc/malloc.h> 368 #endif 369 370 #ifndef MOZ_MEMORY 371 #include "un-namespace.h" 372 #endif 373 374 #endif 375 376 #include "jemalloc.h" 377 378 #undef bool 379 #define bool jemalloc_bool 380 381 #ifdef MOZ_MEMORY_DARWIN 382 static const bool __isthreaded = true; 383 #endif 384 385 #if defined(MOZ_MEMORY_SOLARIS) && defined(MAP_ALIGN) && !defined(JEMALLOC_NEVER_USES_MAP_ALIGN) 386 #define JEMALLOC_USES_MAP_ALIGN /* Required on Solaris 10. Might improve performance elsewhere. */ 387 #endif 388 389 #if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6) 390 #define JEMALLOC_USES_MAP_ALIGN /* Required for Windows CE < 6 */ 391 #endif 392 393 #define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) 394 395 #include "qr.h" 396 #include "ql.h" 397 #ifdef MOZ_MEMORY_WINDOWS 398 /* MSVC++ does not support C99 variable-length arrays. */ 399 # define RB_NO_C99_VARARRAYS 400 #endif 401 #include "rb.h" 402 403 #ifdef MALLOC_DEBUG 404 /* Disable inlining to make debugging easier. */ 405 #ifdef inline 406 #undef inline 407 #endif 408 409 # define inline 410 #endif 411 412 /* Size of stack-allocated buffer passed to strerror_r(). */ 413 #define STRERROR_BUF 64 414 415 /* Minimum alignment of allocations is 2^QUANTUM_2POW_MIN bytes. */ 416 # define QUANTUM_2POW_MIN 4 417 #ifdef MOZ_MEMORY_SIZEOF_PTR_2POW 418 # define SIZEOF_PTR_2POW MOZ_MEMORY_SIZEOF_PTR_2POW 419 #else 420 # define SIZEOF_PTR_2POW 2 421 #endif 422 #define PIC 423 #ifndef MOZ_MEMORY_DARWIN 424 static const bool __isthreaded = true; 425 #else 426 # define NO_TLS 427 #endif 428 #if 0 429 #ifdef __i386__ 430 # define QUANTUM_2POW_MIN 4 431 # define SIZEOF_PTR_2POW 2 432 # define CPU_SPINWAIT __asm__ volatile("pause") 433 #endif 434 #ifdef __ia64__ 435 # define QUANTUM_2POW_MIN 4 436 # define SIZEOF_PTR_2POW 3 437 #endif 438 #ifdef __alpha__ 439 # define QUANTUM_2POW_MIN 4 440 # define SIZEOF_PTR_2POW 3 441 # define NO_TLS 442 #endif 443 #ifdef __sparc64__ 444 # define QUANTUM_2POW_MIN 4 445 # define SIZEOF_PTR_2POW 3 446 # define NO_TLS 447 #endif 448 #ifdef __amd64__ 449 # define QUANTUM_2POW_MIN 4 450 # define SIZEOF_PTR_2POW 3 451 # define CPU_SPINWAIT __asm__ volatile("pause") 452 #endif 453 #ifdef __arm__ 454 # define QUANTUM_2POW_MIN 3 455 # define SIZEOF_PTR_2POW 2 456 # define NO_TLS 457 #endif 458 #ifdef __mips__ 459 # define QUANTUM_2POW_MIN 3 460 # define SIZEOF_PTR_2POW 2 461 # define NO_TLS 462 #endif 463 #ifdef __powerpc__ 464 # define QUANTUM_2POW_MIN 4 465 # define SIZEOF_PTR_2POW 2 466 #endif 467 #endif 468 469 #define SIZEOF_PTR (1U << SIZEOF_PTR_2POW) 470 471 /* sizeof(int) == (1U << SIZEOF_INT_2POW). */ 472 #ifndef SIZEOF_INT_2POW 473 # define SIZEOF_INT_2POW 2 474 #endif 475 476 /* We can't use TLS in non-PIC programs, since TLS relies on loader magic. */ 477 #if (!defined(PIC) && !defined(NO_TLS)) 478 # define NO_TLS 479 #endif 480 481 #ifdef NO_TLS 482 /* MALLOC_BALANCE requires TLS. */ 483 # ifdef MALLOC_BALANCE 484 # undef MALLOC_BALANCE 485 # endif 486 #endif 487 488 /* 489 * Size and alignment of memory chunks that are allocated by the OS's virtual 490 * memory system. 491 */ 492 #if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6) 493 #define CHUNK_2POW_DEFAULT 21 494 #else 495 #define CHUNK_2POW_DEFAULT 20 496 #endif 497 /* Maximum number of dirty pages per arena. */ 498 #define DIRTY_MAX_DEFAULT (1U << 10) 499 500 /* Default reserve chunks. */ 501 #define RESERVE_MIN_2POW_DEFAULT 1 502 /* 503 * Default range (in chunks) between reserve_min and reserve_max, in addition 504 * to the mandatory one chunk per arena. 505 */ 506 #ifdef MALLOC_PAGEFILE 507 # define RESERVE_RANGE_2POW_DEFAULT 5 508 #else 509 # define RESERVE_RANGE_2POW_DEFAULT 0 510 #endif 511 512 /* 513 * Maximum size of L1 cache line. This is used to avoid cache line aliasing, 514 * so over-estimates are okay (up to a point), but under-estimates will 515 * negatively affect performance. 516 */ 517 #define CACHELINE_2POW 6 518 #define CACHELINE ((size_t)(1U << CACHELINE_2POW)) 519 520 /* Smallest size class to support. */ 521 #define TINY_MIN_2POW 1 522 523 /* 524 * Maximum size class that is a multiple of the quantum, but not (necessarily) 525 * a power of 2. Above this size, allocations are rounded up to the nearest 526 * power of 2. 527 */ 528 #define SMALL_MAX_2POW_DEFAULT 9 529 #define SMALL_MAX_DEFAULT (1U << SMALL_MAX_2POW_DEFAULT) 530 531 /* 532 * RUN_MAX_OVRHD indicates maximum desired run header overhead. Runs are sized 533 * as small as possible such that this setting is still honored, without 534 * violating other constraints. The goal is to make runs as small as possible 535 * without exceeding a per run external fragmentation threshold. 536 * 537 * We use binary fixed point math for overhead computations, where the binary 538 * point is implicitly RUN_BFP bits to the left. 539 * 540 * Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be 541 * honored for some/all object sizes, since there is one bit of header overhead 542 * per object (plus a constant). This constraint is relaxed (ignored) for runs 543 * that are so small that the per-region overhead is greater than: 544 * 545 * (RUN_MAX_OVRHD / (reg_size << (3+RUN_BFP)) 546 */ 547 #define RUN_BFP 12 548 /* \/ Implicit binary fixed point. */ 549 #define RUN_MAX_OVRHD 0x0000003dU 550 #define RUN_MAX_OVRHD_RELAX 0x00001800U 551 552 /* Put a cap on small object run size. This overrides RUN_MAX_OVRHD. */ 553 #define RUN_MAX_SMALL_2POW 15 554 #define RUN_MAX_SMALL (1U << RUN_MAX_SMALL_2POW) 555 556 /* 557 * Hyper-threaded CPUs may need a special instruction inside spin loops in 558 * order to yield to another virtual CPU. If no such instruction is defined 559 * above, make CPU_SPINWAIT a no-op. 560 */ 561 #ifndef CPU_SPINWAIT 562 # define CPU_SPINWAIT 563 #endif 564 565 /* 566 * Adaptive spinning must eventually switch to blocking, in order to avoid the 567 * potential for priority inversion deadlock. Backing off past a certain point 568 * can actually waste time. 569 */ 570 #define SPIN_LIMIT_2POW 11 571 572 /* 573 * Conversion from spinning to blocking is expensive; we use (1U << 574 * BLOCK_COST_2POW) to estimate how many more times costly blocking is than 575 * worst-case spinning. 576 */ 577 #define BLOCK_COST_2POW 4 578 579 #ifdef MALLOC_BALANCE 580 /* 581 * We use an exponential moving average to track recent lock contention, 582 * where the size of the history window is N, and alpha=2/(N+1). 583 * 584 * Due to integer math rounding, very small values here can cause 585 * substantial degradation in accuracy, thus making the moving average decay 586 * faster than it would with precise calculation. 587 */ 588 # define BALANCE_ALPHA_INV_2POW 9 589 590 /* 591 * Threshold value for the exponential moving contention average at which to 592 * re-assign a thread. 593 */ 594 # define BALANCE_THRESHOLD_DEFAULT (1U << (SPIN_LIMIT_2POW-4)) 595 #endif 596 597 /******************************************************************************/ 598 599 /* 600 * Mutexes based on spinlocks. We can't use normal pthread spinlocks in all 601 * places, because they require malloc()ed memory, which causes bootstrapping 602 * issues in some cases. 603 */ 604 #if defined(MOZ_MEMORY_WINDOWS) 605 #define malloc_mutex_t CRITICAL_SECTION 606 #define malloc_spinlock_t CRITICAL_SECTION 607 #elif defined(MOZ_MEMORY_DARWIN) 608 typedef struct { 609 OSSpinLock lock; 610 } malloc_mutex_t; 611 typedef struct { 612 OSSpinLock lock; 613 } malloc_spinlock_t; 614 #elif defined(MOZ_MEMORY) 615 typedef pthread_mutex_t malloc_mutex_t; 616 typedef pthread_mutex_t malloc_spinlock_t; 617 #else 618 /* XXX these should #ifdef these for freebsd (and linux?) only */ 619 typedef struct { 620 spinlock_t lock; 621 } malloc_mutex_t; 622 typedef malloc_spinlock_t malloc_mutex_t; 623 #endif 624 625 /* Set to true once the allocator has been initialized. */ 626 static bool malloc_initialized = false; 627 628 #if defined(MOZ_MEMORY_WINDOWS) 629 /* No init lock for Windows. */ 630 #elif defined(MOZ_MEMORY_DARWIN) 631 static malloc_mutex_t init_lock = {OS_SPINLOCK_INIT}; 632 #elif defined(MOZ_MEMORY_LINUX) 633 static malloc_mutex_t init_lock = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP; 634 #elif defined(MOZ_MEMORY) 635 static malloc_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER; 636 #else 637 static malloc_mutex_t init_lock = {_SPINLOCK_INITIALIZER}; 638 #endif 639 640 /******************************************************************************/ 641 /* 642 * Statistics data structures. 643 */ 644 645 #ifdef MALLOC_STATS 646 647 typedef struct malloc_bin_stats_s malloc_bin_stats_t; 648 struct malloc_bin_stats_s { 649 /* 650 * Number of allocation requests that corresponded to the size of this 651 * bin. 652 */ 653 uint64_t nrequests; 654 655 /* Total number of runs created for this bin's size class. */ 656 uint64_t nruns; 657 658 /* 659 * Total number of runs reused by extracting them from the runs tree for 660 * this bin's size class. 661 */ 662 uint64_t reruns; 663 664 /* High-water mark for this bin. */ 665 unsigned long highruns; 666 667 /* Current number of runs in this bin. */ 668 unsigned long curruns; 669 }; 670 671 typedef struct arena_stats_s arena_stats_t; 672 struct arena_stats_s { 673 /* Number of bytes currently mapped. */ 674 size_t mapped; 675 676 /* 677 * Total number of purge sweeps, total number of madvise calls made, 678 * and total pages purged in order to keep dirty unused memory under 679 * control. 680 */ 681 uint64_t npurge; 682 uint64_t nmadvise; 683 uint64_t purged; 684 #ifdef MALLOC_DECOMMIT 685 /* 686 * Total number of decommit/commit operations, and total number of 687 * pages decommitted. 688 */ 689 uint64_t ndecommit; 690 uint64_t ncommit; 691 uint64_t decommitted; 692 #endif 693 694 /* Per-size-category statistics. */ 695 size_t allocated_small; 696 uint64_t nmalloc_small; 697 uint64_t ndalloc_small; 698 699 size_t allocated_large; 700 uint64_t nmalloc_large; 701 uint64_t ndalloc_large; 702 703 #ifdef MALLOC_BALANCE 704 /* Number of times this arena reassigned a thread due to contention. */ 705 uint64_t nbalance; 706 #endif 707 }; 708 709 typedef struct chunk_stats_s chunk_stats_t; 710 struct chunk_stats_s { 711 /* Number of chunks that were allocated. */ 712 uint64_t nchunks; 713 714 /* High-water mark for number of chunks allocated. */ 715 unsigned long highchunks; 716 717 /* 718 * Current number of chunks allocated. This value isn't maintained for 719 * any other purpose, so keep track of it in order to be able to set 720 * highchunks. 721 */ 722 unsigned long curchunks; 723 }; 724 725 #endif /* #ifdef MALLOC_STATS */ 726 727 /******************************************************************************/ 728 /* 729 * Extent data structures. 730 */ 731 732 /* Tree of extents. */ 733 typedef struct extent_node_s extent_node_t; 734 struct extent_node_s { 735 /* Linkage for the size/address-ordered tree. */ 736 rb_node(extent_node_t) link_szad; 737 738 /* Linkage for the address-ordered tree. */ 739 rb_node(extent_node_t) link_ad; 740 741 /* Pointer to the extent that this tree node is responsible for. */ 742 void *addr; 743 744 /* Total region size. */ 745 size_t size; 746 }; 747 typedef rb_tree(extent_node_t) extent_tree_t; 748 749 /******************************************************************************/ 750 /* 751 * Radix tree data structures. 752 */ 753 754 #ifdef MALLOC_VALIDATE 755 /* 756 * Size of each radix tree node (must be a power of 2). This impacts tree 757 * depth. 758 */ 759 # if (SIZEOF_PTR == 4) 760 # define MALLOC_RTREE_NODESIZE (1U << 14) 761 # else 762 # define MALLOC_RTREE_NODESIZE CACHELINE 763 # endif 764 765 typedef struct malloc_rtree_s malloc_rtree_t; 766 struct malloc_rtree_s { 767 malloc_spinlock_t lock; 768 void **root; 769 unsigned height; 770 unsigned level2bits[1]; /* Dynamically sized. */ 771 }; 772 #endif 773 774 /******************************************************************************/ 775 /* 776 * Reserve data structures. 777 */ 778 779 /* Callback registration. */ 780 typedef struct reserve_reg_s reserve_reg_t; 781 struct reserve_reg_s { 782 /* Linkage for list of all registered callbacks. */ 783 ql_elm(reserve_reg_t) link; 784 785 /* Callback function pointer. */ 786 reserve_cb_t *cb; 787 788 /* Opaque application data pointer. */ 789 void *ctx; 790 791 /* 792 * Sequence number of condition notification most recently sent to this 793 * callback. 794 */ 795 uint64_t seq; 796 }; 797 798 /******************************************************************************/ 799 /* 800 * Arena data structures. 801 */ 802 803 typedef struct arena_s arena_t; 804 typedef struct arena_bin_s arena_bin_t; 805 806 /* Each element of the chunk map corresponds to one page within the chunk. */ 807 typedef struct arena_chunk_map_s arena_chunk_map_t; 808 struct arena_chunk_map_s { 809 /* 810 * Linkage for run trees. There are two disjoint uses: 811 * 812 * 1) arena_t's runs_avail tree. 813 * 2) arena_run_t conceptually uses this linkage for in-use non-full 814 * runs, rather than directly embedding linkage. 815 */ 816 rb_node(arena_chunk_map_t) link; 817 818 /* 819 * Run address (or size) and various flags are stored together. The bit 820 * layout looks like (assuming 32-bit system): 821 * 822 * ???????? ???????? ????---- --ckdzla 823 * 824 * ? : Unallocated: Run address for first/last pages, unset for internal 825 * pages. 826 * Small: Run address. 827 * Large: Run size for first page, unset for trailing pages. 828 * - : Unused. 829 * c : decommitted? 830 * k : key? 831 * d : dirty? 832 * z : zeroed? 833 * l : large? 834 * a : allocated? 835 * 836 * Following are example bit patterns for the three types of runs. 837 * 838 * r : run address 839 * s : run size 840 * x : don't care 841 * - : 0 842 * [cdzla] : bit set 843 * 844 * Unallocated: 845 * ssssssss ssssssss ssss---- --c----- 846 * xxxxxxxx xxxxxxxx xxxx---- ----d--- 847 * ssssssss ssssssss ssss---- -----z-- 848 * 849 * Small: 850 * rrrrrrrr rrrrrrrr rrrr---- -------a 851 * rrrrrrrr rrrrrrrr rrrr---- -------a 852 * rrrrrrrr rrrrrrrr rrrr---- -------a 853 * 854 * Large: 855 * ssssssss ssssssss ssss---- ------la 856 * -------- -------- -------- ------la 857 * -------- -------- -------- ------la 858 */ 859 size_t bits; 860 #ifdef MALLOC_DECOMMIT 861 #define CHUNK_MAP_DECOMMITTED ((size_t)0x20U) 862 #endif 863 #define CHUNK_MAP_KEY ((size_t)0x10U) 864 #define CHUNK_MAP_DIRTY ((size_t)0x08U) 865 #define CHUNK_MAP_ZEROED ((size_t)0x04U) 866 #define CHUNK_MAP_LARGE ((size_t)0x02U) 867 #define CHUNK_MAP_ALLOCATED ((size_t)0x01U) 868 }; 869 typedef rb_tree(arena_chunk_map_t) arena_avail_tree_t; 870 typedef rb_tree(arena_chunk_map_t) arena_run_tree_t; 871 872 /* Arena chunk header. */ 873 typedef struct arena_chunk_s arena_chunk_t; 874 struct arena_chunk_s { 875 /* Arena that owns the chunk. */ 876 arena_t *arena; 877 878 /* Linkage for the arena's chunks_dirty tree. */ 879 rb_node(arena_chunk_t) link_dirty; 880 881 /* Number of dirty pages. */ 882 size_t ndirty; 883 884 /* Map of pages within chunk that keeps track of free/large/small. */ 885 arena_chunk_map_t map[1]; /* Dynamically sized. */ 886 }; 887 typedef rb_tree(arena_chunk_t) arena_chunk_tree_t; 888 889 typedef struct arena_run_s arena_run_t; 890 struct arena_run_s { 891 #ifdef MALLOC_DEBUG 892 uint32_t magic; 893 # define ARENA_RUN_MAGIC 0x384adf93 894 #endif 895 896 /* Bin this run is associated with. */ 897 arena_bin_t *bin; 898 899 /* Index of first element that might have a free region. */ 900 unsigned regs_minelm; 901 902 /* Number of free regions in run. */ 903 unsigned nfree; 904 905 /* Bitmask of in-use regions (0: in use, 1: free). */ 906 unsigned regs_mask[1]; /* Dynamically sized. */ 907 }; 908 909 struct arena_bin_s { 910 /* 911 * Current run being used to service allocations of this bin's size 912 * class. 913 */ 914 arena_run_t *runcur; 915 916 /* 917 * Tree of non-full runs. This tree is used when looking for an 918 * existing run when runcur is no longer usable. We choose the 919 * non-full run that is lowest in memory; this policy tends to keep 920 * objects packed well, and it can also help reduce the number of 921 * almost-empty chunks. 922 */ 923 arena_run_tree_t runs; 924 925 /* Size of regions in a run for this bin's size class. */ 926 size_t reg_size; 927 928 /* Total size of a run for this bin's size class. */ 929 size_t run_size; 930 931 /* Total number of regions in a run for this bin's size class. */ 932 uint32_t nregs; 933 934 /* Number of elements in a run's regs_mask for this bin's size class. */ 935 uint32_t regs_mask_nelms; 936 937 /* Offset of first region in a run for this bin's size class. */ 938 uint32_t reg0_offset; 939 940 #ifdef MALLOC_STATS 941 /* Bin statistics. */ 942 malloc_bin_stats_t stats; 943 #endif 944 }; 945 946 struct arena_s { 947 #ifdef MALLOC_DEBUG 948 uint32_t magic; 949 # define ARENA_MAGIC 0x947d3d24 950 #endif 951 952 /* All operations on this arena require that lock be locked. */ 953 #ifdef MOZ_MEMORY 954 malloc_spinlock_t lock; 955 #else 956 pthread_mutex_t lock; 957 #endif 958 959 #ifdef MALLOC_STATS 960 arena_stats_t stats; 961 #endif 962 963 /* 964 * Chunk allocation sequence number, used to detect races with other 965 * threads during chunk allocation, and then discard unnecessary chunks. 966 */ 967 uint64_t chunk_seq; 968 969 /* Tree of dirty-page-containing chunks this arena manages. */ 970 arena_chunk_tree_t chunks_dirty; 971 972 /* 973 * In order to avoid rapid chunk allocation/deallocation when an arena 974 * oscillates right on the cusp of needing a new chunk, cache the most 975 * recently freed chunk. The spare is left in the arena's chunk trees 976 * until it is deleted. 977 * 978 * There is one spare chunk per arena, rather than one spare total, in 979 * order to avoid interactions between multiple threads that could make 980 * a single spare inadequate. 981 */ 982 arena_chunk_t *spare; 983 984 /* 985 * Current count of pages within unused runs that are potentially 986 * dirty, and for which madvise(... MADV_FREE) has not been called. By 987 * tracking this, we can institute a limit on how much dirty unused 988 * memory is mapped for each arena. 989 */ 990 size_t ndirty; 991 992 /* 993 * Size/address-ordered tree of this arena's available runs. This tree 994 * is used for first-best-fit run allocation. 995 */ 996 arena_avail_tree_t runs_avail; 997 998 #ifdef MALLOC_BALANCE 999 /* 1000 * The arena load balancing machinery needs to keep track of how much 1001 * lock contention there is. This value is exponentially averaged. 1002 */ 1003 uint32_t contention; 1004 #endif 1005 1006 /* 1007 * bins is used to store rings of free regions of the following sizes, 1008 * assuming a 16-byte quantum, 4kB pagesize, and default MALLOC_OPTIONS. 1009 * 1010 * bins[i] | size | 1011 * --------+------+ 1012 * 0 | 2 | 1013 * 1 | 4 | 1014 * 2 | 8 | 1015 * --------+------+ 1016 * 3 | 16 | 1017 * 4 | 32 | 1018 * 5 | 48 | 1019 * 6 | 64 | 1020 * : : 1021 * : : 1022 * 33 | 496 | 1023 * 34 | 512 | 1024 * --------+------+ 1025 * 35 | 1024 | 1026 * 36 | 2048 | 1027 * --------+------+ 1028 */ 1029 arena_bin_t bins[1]; /* Dynamically sized. */ 1030 }; 1031 1032 /******************************************************************************/ 1033 /* 1034 * Data. 1035 */ 1036 1037 /* Number of CPUs. */ 1038 static unsigned ncpus; 1039 1040 /* VM page size. */ 1041 static size_t pagesize; 1042 static size_t pagesize_mask; 1043 static size_t pagesize_2pow; 1044 1045 /* Various bin-related settings. */ 1046 static size_t bin_maxclass; /* Max size class for bins. */ 1047 static unsigned ntbins; /* Number of (2^n)-spaced tiny bins. */ 1048 static unsigned nqbins; /* Number of quantum-spaced bins. */ 1049 static unsigned nsbins; /* Number of (2^n)-spaced sub-page bins. */ 1050 static size_t small_min; 1051 static size_t small_max; 1052 1053 /* Various quantum-related settings. */ 1054 static size_t quantum; 1055 static size_t quantum_mask; /* (quantum - 1). */ 1056 1057 /* Various chunk-related settings. */ 1058 static size_t chunksize; 1059 static size_t chunksize_mask; /* (chunksize - 1). */ 1060 static size_t chunk_npages; 1061 static size_t arena_chunk_header_npages; 1062 static size_t arena_maxclass; /* Max size class for arenas. */ 1063 1064 /********/ 1065 /* 1066 * Chunks. 1067 */ 1068 1069 #ifdef MALLOC_VALIDATE 1070 static malloc_rtree_t *chunk_rtree; 1071 #endif 1072 1073 /* Protects chunk-related data structures. */ 1074 static malloc_mutex_t huge_mtx; 1075 1076 /* Tree of chunks that are stand-alone huge allocations. */ 1077 static extent_tree_t huge; 1078 1079 #ifdef MALLOC_STATS 1080 /* Huge allocation statistics. */ 1081 static uint64_t huge_nmalloc; 1082 static uint64_t huge_ndalloc; 1083 static size_t huge_allocated; 1084 #endif 1085 1086 /****************/ 1087 /* 1088 * Memory reserve. 1089 */ 1090 1091 #ifdef MALLOC_PAGEFILE 1092 static char pagefile_templ[PATH_MAX]; 1093 #endif 1094 1095 /* Protects reserve-related data structures. */ 1096 static malloc_mutex_t reserve_mtx; 1097 1098 /* 1099 * Bounds on acceptable reserve size, and current reserve size. Reserve 1100 * depletion may cause (reserve_cur < reserve_min). 1101 */ 1102 static size_t reserve_min; 1103 static size_t reserve_cur; 1104 static size_t reserve_max; 1105 1106 /* List of registered callbacks. */ 1107 static ql_head(reserve_reg_t) reserve_regs; 1108 1109 /* 1110 * Condition notification sequence number, used to determine whether all 1111 * registered callbacks have been notified of the most current condition. 1112 */ 1113 static uint64_t reserve_seq; 1114 1115 /* 1116 * Trees of chunks currently in the memory reserve. Depending on function, 1117 * different tree orderings are needed, which is why there are two trees with 1118 * the same contents. 1119 */ 1120 static extent_tree_t reserve_chunks_szad; 1121 static extent_tree_t reserve_chunks_ad; 1122 1123 /****************************/ 1124 /* 1125 * base (internal allocation). 1126 */ 1127 1128 /* 1129 * Current pages that are being used for internal memory allocations. These 1130 * pages are carved up in cacheline-size quanta, so that there is no chance of 1131 * false cache line sharing. 1132 */ 1133 static void *base_pages; 1134 static void *base_next_addr; 1135 #ifdef MALLOC_DECOMMIT 1136 static void *base_next_decommitted; 1137 #endif 1138 static void *base_past_addr; /* Addr immediately past base_pages. */ 1139 static extent_node_t *base_nodes; 1140 static reserve_reg_t *base_reserve_regs; 1141 static malloc_mutex_t base_mtx; 1142 #ifdef MALLOC_STATS 1143 static size_t base_mapped; 1144 #endif 1145 1146 /********/ 1147 /* 1148 * Arenas. 1149 */ 1150 1151 /* 1152 * Arenas that are used to service external requests. Not all elements of the 1153 * arenas array are necessarily used; arenas are created lazily as needed. 1154 */ 1155 static arena_t **arenas; 1156 static unsigned narenas; 1157 static unsigned narenas_2pow; 1158 #ifndef NO_TLS 1159 # ifdef MALLOC_BALANCE 1160 static unsigned narenas_2pow; 1161 # else 1162 static unsigned next_arena; 1163 # endif 1164 #endif 1165 #ifdef MOZ_MEMORY 1166 static malloc_spinlock_t arenas_lock; /* Protects arenas initialization. */ 1167 #else 1168 static pthread_mutex_t arenas_lock; /* Protects arenas initialization. */ 1169 #endif 1170 1171 #ifndef NO_TLS 1172 /* 1173 * Map of pthread_self() --> arenas[???], used for selecting an arena to use 1174 * for allocations. 1175 */ 1176 #ifndef MOZ_MEMORY_WINDOWS 1177 static __thread arena_t *arenas_map; 1178 #endif 1179 #endif 1180 1181 #ifdef MALLOC_STATS 1182 /* Chunk statistics. */ 1183 static chunk_stats_t stats_chunks; 1184 #endif 1185 1186 /*******************************/ 1187 /* 1188 * Runtime configuration options. 1189 */ 1190 const char *_malloc_options; 1191 1192 #ifndef MALLOC_PRODUCTION 1193 static bool opt_abort = true; 1194 #ifdef MALLOC_FILL 1195 static bool opt_junk = true; 1196 #endif 1197 #else 1198 static bool opt_abort = false; 1199 #ifdef MALLOC_FILL 1200 static bool opt_junk = false; 1201 #endif 1202 #endif 1203 static size_t opt_dirty_max = DIRTY_MAX_DEFAULT; 1204 #ifdef MALLOC_BALANCE 1205 static uint64_t opt_balance_threshold = BALANCE_THRESHOLD_DEFAULT; 1206 #endif 1207 static bool opt_print_stats = false; 1208 static size_t opt_quantum_2pow = QUANTUM_2POW_MIN; 1209 static size_t opt_small_max_2pow = SMALL_MAX_2POW_DEFAULT; 1210 static size_t opt_chunk_2pow = CHUNK_2POW_DEFAULT; 1211 static int opt_reserve_min_lshift = 0; 1212 static int opt_reserve_range_lshift = 0; 1213 #ifdef MALLOC_PAGEFILE 1214 static bool opt_pagefile = false; 1215 #endif 1216 #ifdef MALLOC_UTRACE 1217 static bool opt_utrace = false; 1218 #endif 1219 #ifdef MALLOC_SYSV 1220 static bool opt_sysv = false; 1221 #endif 1222 #ifdef MALLOC_XMALLOC 1223 static bool opt_xmalloc = false; 1224 #endif 1225 #ifdef MALLOC_FILL 1226 static bool opt_zero = false; 1227 #endif 1228 static int opt_narenas_lshift = 0; 1229 1230 #ifdef MALLOC_UTRACE 1231 typedef struct { 1232 void *p; 1233 size_t s; 1234 void *r; 1235 } malloc_utrace_t; 1236 1237 #define UTRACE(a, b, c) \ 1238 if (opt_utrace) { \ 1239 malloc_utrace_t ut; \ 1240 ut.p = (a); \ 1241 ut.s = (b); \ 1242 ut.r = (c); \ 1243 utrace(&ut, sizeof(ut)); \ 1244 } 1245 #else 1246 #define UTRACE(a, b, c) 1247 #endif 1248 1249 /******************************************************************************/ 1250 /* 1251 * Begin function prototypes for non-inline static functions. 1252 */ 1253 1254 static char *umax2s(uintmax_t x, char *s); 1255 static bool malloc_mutex_init(malloc_mutex_t *mutex); 1256 static bool malloc_spin_init(malloc_spinlock_t *lock); 1257 static void wrtmessage(const char *p1, const char *p2, const char *p3, 1258 const char *p4); 1259 #ifdef MALLOC_STATS 1260 #ifdef MOZ_MEMORY_DARWIN 1261 /* Avoid namespace collision with OS X's malloc APIs. */ 1262 #define malloc_printf moz_malloc_printf 1263 #endif 1264 static void malloc_printf(const char *format, ...); 1265 #endif 1266 static bool base_pages_alloc_mmap(size_t minsize); 1267 static bool base_pages_alloc(size_t minsize); 1268 static void *base_alloc(size_t size); 1269 static void *base_calloc(size_t number, size_t size); 1270 static extent_node_t *base_node_alloc(void); 1271 static void base_node_dealloc(extent_node_t *node); 1272 static reserve_reg_t *base_reserve_reg_alloc(void); 1273 static void base_reserve_reg_dealloc(reserve_reg_t *reg); 1274 #ifdef MALLOC_STATS 1275 static void stats_print(arena_t *arena); 1276 #endif 1277 static void *pages_map(void *addr, size_t size, int pfd); 1278 static void pages_unmap(void *addr, size_t size); 1279 static void *chunk_alloc_mmap(size_t size, bool pagefile); 1280 #ifdef MALLOC_PAGEFILE 1281 static int pagefile_init(size_t size); 1282 static void pagefile_close(int pfd); 1283 #endif 1284 static void *chunk_recycle_reserve(size_t size, bool zero); 1285 static void *chunk_alloc(size_t size, bool zero, bool pagefile); 1286 static extent_node_t *chunk_dealloc_reserve(void *chunk, size_t size); 1287 static void chunk_dealloc_mmap(void *chunk, size_t size); 1288 static void chunk_dealloc(void *chunk, size_t size); 1289 #ifndef NO_TLS 1290 static arena_t *choose_arena_hard(void); 1291 #endif 1292 static void arena_run_split(arena_t *arena, arena_run_t *run, size_t size, 1293 bool large, bool zero); 1294 static void arena_chunk_init(arena_t *arena, arena_chunk_t *chunk); 1295 static void arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk); 1296 static arena_run_t *arena_run_alloc(arena_t *arena, arena_bin_t *bin, 1297 size_t size, bool large, bool zero); 1298 static void arena_purge(arena_t *arena); 1299 static void arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty); 1300 static void arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, 1301 arena_run_t *run, size_t oldsize, size_t newsize); 1302 static void arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, 1303 arena_run_t *run, size_t oldsize, size_t newsize, bool dirty); 1304 static arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin); 1305 static void *arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin); 1306 static size_t arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size); 1307 #ifdef MALLOC_BALANCE 1308 static void arena_lock_balance_hard(arena_t *arena); 1309 #endif 1310 static void *arena_malloc_large(arena_t *arena, size_t size, bool zero); 1311 static void *arena_palloc(arena_t *arena, size_t alignment, size_t size, 1312 size_t alloc_size); 1313 static size_t arena_salloc(const void *ptr); 1314 static void arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, 1315 void *ptr); 1316 static void arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, 1317 void *ptr, size_t size, size_t oldsize); 1318 static bool arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, 1319 void *ptr, size_t size, size_t oldsize); 1320 static bool arena_ralloc_large(void *ptr, size_t size, size_t oldsize); 1321 static void *arena_ralloc(void *ptr, size_t size, size_t oldsize); 1322 static bool arena_new(arena_t *arena); 1323 static arena_t *arenas_extend(unsigned ind); 1324 static void *huge_malloc(size_t size, bool zero); 1325 static void *huge_palloc(size_t alignment, size_t size); 1326 static void *huge_ralloc(void *ptr, size_t size, size_t oldsize); 1327 static void huge_dalloc(void *ptr); 1328 static void malloc_print_stats(void); 1329 #ifndef MOZ_MEMORY_WINDOWS 1330 static 1331 #endif 1332 bool malloc_init_hard(void); 1333 static void reserve_shrink(void); 1334 static uint64_t reserve_notify(reserve_cnd_t cnd, size_t size, uint64_t seq); 1335 static uint64_t reserve_crit(size_t size, const char *fname, uint64_t seq); 1336 static void reserve_fail(size_t size, const char *fname); 1337 1338 void _malloc_prefork(void); 1339 void _malloc_postfork(void); 1340 1341 /* 1342 * End function prototypes. 1343 */ 1344 /******************************************************************************/ 1345 1346 /* 1347 * umax2s() provides minimal integer printing functionality, which is 1348 * especially useful for situations where allocation in vsnprintf() calls would 1349 * potentially cause deadlock. 1350 */ 1351 #define UMAX2S_BUFSIZE 21 1352 static char * 1353 umax2s(uintmax_t x, char *s) 1354 { 1355 unsigned i; 1356 1357 i = UMAX2S_BUFSIZE - 1; 1358 s[i] = '\0'; 1359 do { 1360 i--; 1361 s[i] = "0123456789"[x % 10]; 1362 x /= 10; 1363 } while (x > 0); 1364 1365 return (&s[i]); 1366 } 1367 1368 static void 1369 wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4) 1370 { 1371 #ifdef MOZ_MEMORY_WINCE 1372 wchar_t buf[1024]; 1373 #define WRT_PRINT(s) \ 1374 MultiByteToWideChar(CP_ACP, 0, s, -1, buf, 1024); \ 1375 OutputDebugStringW(buf) 1376 1377 WRT_PRINT(p1); 1378 WRT_PRINT(p2); 1379 WRT_PRINT(p3); 1380 WRT_PRINT(p4); 1381 #else 1382 #if defined(MOZ_MEMORY) && !defined(MOZ_MEMORY_WINDOWS) 1383 #define _write write 1384 #endif 1385 _write(STDERR_FILENO, p1, (unsigned int) strlen(p1)); 1386 _write(STDERR_FILENO, p2, (unsigned int) strlen(p2)); 1387 _write(STDERR_FILENO, p3, (unsigned int) strlen(p3)); 1388 _write(STDERR_FILENO, p4, (unsigned int) strlen(p4)); 1389 #endif 1390 1391 } 1392 1393 #define _malloc_message malloc_message 1394 1395 void (*_malloc_message)(const char *p1, const char *p2, const char *p3, 1396 const char *p4) = wrtmessage; 1397 1398 #ifdef MALLOC_DEBUG 1399 # define assert(e) do { \ 1400 if (!(e)) { \ 1401 char line_buf[UMAX2S_BUFSIZE]; \ 1402 _malloc_message(__FILE__, ":", umax2s(__LINE__, \ 1403 line_buf), ": Failed assertion: "); \ 1404 _malloc_message("\"", #e, "\"\n", ""); \ 1405 abort(); \ 1406 } \ 1407 } while (0) 1408 #else 1409 #define assert(e) 1410 #endif 1411 1412 /******************************************************************************/ 1413 /* 1414 * Begin mutex. We can't use normal pthread mutexes in all places, because 1415 * they require malloc()ed memory, which causes bootstrapping issues in some 1416 * cases. 1417 */ 1418 1419 static bool 1420 malloc_mutex_init(malloc_mutex_t *mutex) 1421 { 1422 #if defined(MOZ_MEMORY_WINCE) 1423 InitializeCriticalSection(mutex); 1424 #elif defined(MOZ_MEMORY_WINDOWS) 1425 // XXXMB 1426 //if (__isthreaded) 1427 // if (! __crtInitCritSecAndSpinCount(mutex, _CRT_SPINCOUNT)) 1428 // return (true); 1429 if (!InitializeCriticalSectionAndSpinCount(mutex, 4000)) 1430 return true; 1431 #elif defined(MOZ_MEMORY_DARWIN) 1432 mutex->lock = OS_SPINLOCK_INIT; 1433 #elif defined(MOZ_MEMORY_LINUX) 1434 pthread_mutexattr_t attr; 1435 if (pthread_mutexattr_init(&attr) != 0) 1436 return (true); 1437 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP); 1438 if (pthread_mutex_init(mutex, &attr) != 0) { 1439 pthread_mutexattr_destroy(&attr); 1440 return (true); 1441 } 1442 pthread_mutexattr_destroy(&attr); 1443 #elif defined(MOZ_MEMORY) 1444 if (pthread_mutex_init(mutex, NULL) != 0) 1445 return (true); 1446 #else 1447 static const spinlock_t lock = _SPINLOCK_INITIALIZER; 1448 1449 mutex->lock = lock; 1450 #endif 1451 return (false); 1452 } 1453 1454 static inline void 1455 malloc_mutex_lock(malloc_mutex_t *mutex) 1456 { 1457 1458 #if defined(MOZ_MEMORY_WINDOWS) 1459 EnterCriticalSection(mutex); 1460 #elif defined(MOZ_MEMORY_DARWIN) 1461 OSSpinLockLock(&mutex->lock); 1462 #elif defined(MOZ_MEMORY) 1463 pthread_mutex_lock(mutex); 1464 #else 1465 if (__isthreaded) 1466 _SPINLOCK(&mutex->lock); 1467 #endif 1468 } 1469 1470 static inline void 1471 malloc_mutex_unlock(malloc_mutex_t *mutex) 1472 { 1473 1474 #if defined(MOZ_MEMORY_WINDOWS) 1475 LeaveCriticalSection(mutex); 1476 #elif defined(MOZ_MEMORY_DARWIN) 1477 OSSpinLockUnlock(&mutex->lock); 1478 #elif defined(MOZ_MEMORY) 1479 pthread_mutex_unlock(mutex); 1480 #else 1481 if (__isthreaded) 1482 _SPINUNLOCK(&mutex->lock); 1483 #endif 1484 } 1485 1486 static bool 1487 malloc_spin_init(malloc_spinlock_t *lock) 1488 { 1489 #if defined(MOZ_MEMORY_WINCE) 1490 InitializeCriticalSection(lock); 1491 #elif defined(MOZ_MEMORY_WINDOWS) 1492 // XXXMB 1493 //if (__isthreaded) 1494 // if (! __crtInitCritSecAndSpinCount(lock, _CRT_SPINCOUNT)) 1495 // return (true); 1496 #elif defined(MOZ_MEMORY_DARWIN) 1497 lock->lock = OS_SPINLOCK_INIT; 1498 #elif defined(MOZ_MEMORY_LINUX) 1499 pthread_mutexattr_t attr; 1500 if (pthread_mutexattr_init(&attr) != 0) 1501 return (true); 1502 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP); 1503 if (pthread_mutex_init(lock, &attr) != 0) { 1504 pthread_mutexattr_destroy(&attr); 1505 return (true); 1506 } 1507 pthread_mutexattr_destroy(&attr); 1508 #elif defined(MOZ_MEMORY) 1509 if (pthread_mutex_init(lock, NULL) != 0) 1510 return (true); 1511 #else 1512 lock->lock = _SPINLOCK_INITIALIZER; 1513 #endif 1514 return (false); 1515 } 1516 1517 static inline void 1518 malloc_spin_lock(malloc_spinlock_t *lock) 1519 { 1520 1521 #if defined(MOZ_MEMORY_WINDOWS) 1522 EnterCriticalSection(lock); 1523 #elif defined(MOZ_MEMORY_DARWIN) 1524 OSSpinLockLock(&lock->lock); 1525 #elif defined(MOZ_MEMORY) 1526 pthread_mutex_lock(lock); 1527 #else 1528 if (__isthreaded) 1529 _SPINLOCK(&lock->lock); 1530 #endif 1531 } 1532 1533 static inline void 1534 malloc_spin_unlock(malloc_spinlock_t *lock) 1535 { 1536 #if defined(MOZ_MEMORY_WINDOWS) 1537 LeaveCriticalSection(lock); 1538 #elif defined(MOZ_MEMORY_DARWIN) 1539 OSSpinLockUnlock(&lock->lock); 1540 #elif defined(MOZ_MEMORY) 1541 pthread_mutex_unlock(lock); 1542 #else 1543 if (__isthreaded) 1544 _SPINUNLOCK(&lock->lock); 1545 #endif 1546 } 1547 1548 /* 1549 * End mutex. 1550 */ 1551 /******************************************************************************/ 1552 /* 1553 * Begin spin lock. Spin locks here are actually adaptive mutexes that block 1554 * after a period of spinning, because unbounded spinning would allow for 1555 * priority inversion. 1556 */ 1557 1558 #if defined(MOZ_MEMORY) && !defined(MOZ_MEMORY_DARWIN) 1559 # define malloc_spin_init malloc_mutex_init 1560 # define malloc_spin_lock malloc_mutex_lock 1561 # define malloc_spin_unlock malloc_mutex_unlock 1562 #endif 1563 1564 #ifndef MOZ_MEMORY 1565 /* 1566 * We use an unpublished interface to initialize pthread mutexes with an 1567 * allocation callback, in order to avoid infinite recursion. 1568 */ 1569 int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, 1570 void *(calloc_cb)(size_t, size_t)); 1571 1572 __weak_reference(_pthread_mutex_init_calloc_cb_stub, 1573 _pthread_mutex_init_calloc_cb); 1574 1575 int 1576 _pthread_mutex_init_calloc_cb_stub(pthread_mutex_t *mutex, 1577 void *(calloc_cb)(size_t, size_t)) 1578 { 1579 1580 return (0); 1581 } 1582 1583 static bool 1584 malloc_spin_init(pthread_mutex_t *lock) 1585 { 1586 1587 if (_pthread_mutex_init_calloc_cb(lock, base_calloc) != 0) 1588 return (true); 1589 1590 return (false); 1591 } 1592 1593 static inline unsigned 1594 malloc_spin_lock(pthread_mutex_t *lock) 1595 { 1596 unsigned ret = 0; 1597 1598 if (__isthreaded) { 1599 if (_pthread_mutex_trylock(lock) != 0) { 1600 unsigned i; 1601 volatile unsigned j; 1602 1603 /* Exponentially back off. */ 1604 for (i = 1; i <= SPIN_LIMIT_2POW; i++) { 1605 for (j = 0; j < (1U << i); j++) 1606 ret++; 1607 1608 CPU_SPINWAIT; 1609 if (_pthread_mutex_trylock(lock) == 0) 1610 return (ret); 1611 } 1612 1613 /* 1614 * Spinning failed. Block until the lock becomes 1615 * available, in order to avoid indefinite priority 1616 * inversion. 1617 */ 1618 _pthread_mutex_lock(lock); 1619 assert((ret << BLOCK_COST_2POW) != 0); 1620 return (ret << BLOCK_COST_2POW); 1621 } 1622 } 1623 1624 return (ret); 1625 } 1626 1627 static inline void 1628 malloc_spin_unlock(pthread_mutex_t *lock) 1629 { 1630 1631 if (__isthreaded) 1632 _pthread_mutex_unlock(lock); 1633 } 1634 #endif 1635 1636 /* 1637 * End spin lock. 1638 */ 1639 /******************************************************************************/ 1640 /* 1641 * Begin Utility functions/macros. 1642 */ 1643 1644 /* Return the chunk address for allocation address a. */ 1645 #define CHUNK_ADDR2BASE(a) \ 1646 ((void *)((uintptr_t)(a) & ~chunksize_mask)) 1647 1648 /* Return the chunk offset of address a. */ 1649 #define CHUNK_ADDR2OFFSET(a) \ 1650 ((size_t)((uintptr_t)(a) & chunksize_mask)) 1651 1652 /* Return the smallest chunk multiple that is >= s. */ 1653 #define CHUNK_CEILING(s) \ 1654 (((s) + chunksize_mask) & ~chunksize_mask) 1655 1656 /* Return the smallest cacheline multiple that is >= s. */ 1657 #define CACHELINE_CEILING(s) \ 1658 (((s) + (CACHELINE - 1)) & ~(CACHELINE - 1)) 1659 1660 /* Return the smallest quantum multiple that is >= a. */ 1661 #define QUANTUM_CEILING(a) \ 1662 (((a) + quantum_mask) & ~quantum_mask) 1663 1664 /* Return the smallest pagesize multiple that is >= s. */ 1665 #define PAGE_CEILING(s) \ 1666 (((s) + pagesize_mask) & ~pagesize_mask) 1667 1668 /* Compute the smallest power of 2 that is >= x. */ 1669 static inline size_t 1670 pow2_ceil(size_t x) 1671 { 1672 1673 x--; 1674 x |= x >> 1; 1675 x |= x >> 2; 1676 x |= x >> 4; 1677 x |= x >> 8; 1678 x |= x >> 16; 1679 #if (SIZEOF_PTR == 8) 1680 x |= x >> 32; 1681 #endif 1682 x++; 1683 return (x); 1684 } 1685 1686 #ifdef MALLOC_BALANCE 1687 /* 1688 * Use a simple linear congruential pseudo-random number generator: 1689 * 1690 * prn(y) = (a*x + c) % m 1691 * 1692 * where the following constants ensure maximal period: 1693 * 1694 * a == Odd number (relatively prime to 2^n), and (a-1) is a multiple of 4. 1695 * c == Odd number (relatively prime to 2^n). 1696 * m == 2^32 1697 * 1698 * See Knuth's TAOCP 3rd Ed., Vol. 2, pg. 17 for details on these constraints. 1699 * 1700 * This choice of m has the disadvantage that the quality of the bits is 1701 * proportional to bit position. For example. the lowest bit has a cycle of 2, 1702 * the next has a cycle of 4, etc. For this reason, we prefer to use the upper 1703 * bits. 1704 */ 1705 # define PRN_DEFINE(suffix, var, a, c) \ 1706 static inline void \ 1707 sprn_##suffix(uint32_t seed) \ 1708 { \ 1709 var = seed; \ 1710 } \ 1711 \ 1712 static inline uint32_t \ 1713 prn_##suffix(uint32_t lg_range) \ 1714 { \ 1715 uint32_t ret, x; \ 1716 \ 1717 assert(lg_range > 0); \ 1718 assert(lg_range <= 32); \ 1719 \ 1720 x = (var * (a)) + (c); \ 1721 var = x; \ 1722 ret = x >> (32 - lg_range); \ 1723 \ 1724 return (ret); \ 1725 } 1726 # define SPRN(suffix, seed) sprn_##suffix(seed) 1727 # define PRN(suffix, lg_range) prn_##suffix(lg_range) 1728 #endif 1729 1730 #ifdef MALLOC_BALANCE 1731 /* Define the PRNG used for arena assignment. */ 1732 static __thread uint32_t balance_x; 1733 PRN_DEFINE(balance, balance_x, 1297, 1301) 1734 #endif 1735 1736 #ifdef MALLOC_UTRACE 1737 static int 1738 utrace(const void *addr, size_t len) 1739 { 1740 malloc_utrace_t *ut = (malloc_utrace_t *)addr; 1741 1742 assert(len == sizeof(malloc_utrace_t)); 1743 1744 if (ut->p == NULL && ut->s == 0 && ut->r == NULL) 1745 malloc_printf("%d x USER malloc_init()\n", getpid()); 1746 else if (ut->p == NULL && ut->r != NULL) { 1747 malloc_printf("%d x USER %p = malloc(%zu)\n", getpid(), ut->r, 1748 ut->s); 1749 } else if (ut->p != NULL && ut->r != NULL) { 1750 malloc_printf("%d x USER %p = realloc(%p, %zu)\n", getpid(), 1751 ut->r, ut->p, ut->s); 1752 } else 1753 malloc_printf("%d x USER free(%p)\n", getpid(), ut->p); 1754 1755 return (0); 1756 } 1757 #endif 1758 1759 static inline const char * 1760 _getprogname(void) 1761 { 1762 1763 return ("<jemalloc>"); 1764 } 1765 1766 #ifdef MALLOC_STATS 1767 /* 1768 * Print to stderr in such a way as to (hopefully) avoid memory allocation. 1769 */ 1770 static void 1771 malloc_printf(const char *format, ...) 1772 { 1773 #ifndef WINCE 1774 char buf[4096]; 1775 va_list ap; 1776 1777 va_start(ap, format); 1778 vsnprintf(buf, sizeof(buf), format, ap); 1779 va_end(ap); 1780 _malloc_message(buf, "", "", ""); 1781 #endif 1782 } 1783 #endif 1784 1785 /******************************************************************************/ 1786 1787 #ifdef MALLOC_DECOMMIT 1788 static inline void 1789 pages_decommit(void *addr, size_t size) 1790 { 1791 1792 #ifdef MOZ_MEMORY_WINDOWS 1793 VirtualFree(addr, size, MEM_DECOMMIT); 1794 #else 1795 if (mmap(addr, size, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 1796 0) == MAP_FAILED) 1797 abort(); 1798 #endif 1799 } 1800 1801 static inline void 1802 pages_commit(void *addr, size_t size) 1803 { 1804 1805 # ifdef MOZ_MEMORY_WINDOWS 1806 VirtualAlloc(addr, size, MEM_COMMIT, PAGE_READWRITE); 1807 # else 1808 if (mmap(addr, size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | 1809 MAP_ANON, -1, 0) == MAP_FAILED) 1810 abort(); 1811 # endif 1812 } 1813 #endif 1814 1815 static bool 1816 base_pages_alloc_mmap(size_t minsize) 1817 { 1818 bool ret; 1819 size_t csize; 1820 #ifdef MALLOC_DECOMMIT 1821 size_t pminsize; 1822 #endif 1823 int pfd; 1824 1825 assert(minsize != 0); 1826 csize = CHUNK_CEILING(minsize); 1827 #ifdef MALLOC_PAGEFILE 1828 if (opt_pagefile) { 1829 pfd = pagefile_init(csize); 1830 if (pfd == -1) 1831 return (true); 1832 } else 1833 #endif 1834 pfd = -1; 1835 base_pages = pages_map(NULL, csize, pfd); 1836 if (base_pages == NULL) { 1837 ret = true; 1838 goto RETURN; 1839 } 1840 base_next_addr = base_pages; 1841 base_past_addr = (void *)((uintptr_t)base_pages + csize); 1842 #ifdef MALLOC_DECOMMIT 1843 /* 1844 * Leave enough pages for minsize committed, since otherwise they would 1845 * have to be immediately recommitted. 1846 */ 1847 pminsize = PAGE_CEILING(minsize); 1848 base_next_decommitted = (void *)((uintptr_t)base_pages + pminsize); 1849 if (pminsize < csize) 1850 pages_decommit(base_next_decommitted, csize - pminsize); 1851 #endif 1852 #ifdef MALLOC_STATS 1853 base_mapped += csize; 1854 #endif 1855 1856 ret = false; 1857 RETURN: 1858 #ifdef MALLOC_PAGEFILE 1859 if (pfd != -1) 1860 pagefile_close(pfd); 1861 #endif 1862 return (false); 1863 } 1864 1865 static bool 1866 base_pages_alloc(size_t minsize) 1867 { 1868 1869 if (base_pages_alloc_mmap(minsize) == false) 1870 return (false); 1871 1872 return (true); 1873 } 1874 1875 static void * 1876 base_alloc(size_t size) 1877 { 1878 void *ret; 1879 size_t csize; 1880 1881 /* Round size up to nearest multiple of the cacheline size. */ 1882 csize = CACHELINE_CEILING(size); 1883 1884 malloc_mutex_lock(&base_mtx); 1885 /* Make sure there's enough space for the allocation. */ 1886 if ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) { 1887 if (base_pages_alloc(csize)) { 1888 malloc_mutex_unlock(&base_mtx); 1889 return (NULL); 1890 } 1891 } 1892 /* Allocate. */ 1893 ret = base_next_addr; 1894 base_next_addr = (void *)((uintptr_t)base_next_addr + csize); 1895 #ifdef MALLOC_DECOMMIT 1896 /* Make sure enough pages are committed for the new allocation. */ 1897 if ((uintptr_t)base_next_addr > (uintptr_t)base_next_decommitted) { 1898 void *pbase_next_addr = 1899 (void *)(PAGE_CEILING((uintptr_t)base_next_addr)); 1900 1901 pages_commit(base_next_decommitted, (uintptr_t)pbase_next_addr - 1902 (uintptr_t)base_next_decommitted); 1903 base_next_decommitted = pbase_next_addr; 1904 } 1905 #endif 1906 malloc_mutex_unlock(&base_mtx); 1907 VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, false); 1908 1909 return (ret); 1910 } 1911 1912 static void * 1913 base_calloc(size_t number, size_t size) 1914 { 1915 void *ret; 1916 1917 ret = base_alloc(number * size); 1918 #ifdef MALLOC_VALGRIND 1919 if (ret != NULL) { 1920 VALGRIND_FREELIKE_BLOCK(ret, 0); 1921 VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, true); 1922 } 1923 #endif 1924 memset(ret, 0, number * size); 1925 1926 return (ret); 1927 } 1928 1929 static extent_node_t * 1930 base_node_alloc(void) 1931 { 1932 extent_node_t *ret; 1933 1934 malloc_mutex_lock(&base_mtx); 1935 if (base_nodes != NULL) { 1936 ret = base_nodes; 1937 base_nodes = *(extent_node_t **)ret; 1938 VALGRIND_FREELIKE_BLOCK(ret, 0); 1939 VALGRIND_MALLOCLIKE_BLOCK(ret, sizeof(extent_node_t), 0, false); 1940 malloc_mutex_unlock(&base_mtx); 1941 } else { 1942 malloc_mutex_unlock(&base_mtx); 1943 ret = (extent_node_t *)base_alloc(sizeof(extent_node_t)); 1944 } 1945 1946 return (ret); 1947 } 1948 1949 static void 1950 base_node_dealloc(extent_node_t *node) 1951 { 1952 1953 malloc_mutex_lock(&base_mtx); 1954 VALGRIND_FREELIKE_BLOCK(node, 0); 1955 VALGRIND_MALLOCLIKE_BLOCK(node, sizeof(extent_node_t *), 0, false); 1956 *(extent_node_t **)node = base_nodes; 1957 base_nodes = node; 1958 malloc_mutex_unlock(&base_mtx); 1959 } 1960 1961 static reserve_reg_t * 1962 base_reserve_reg_alloc(void) 1963 { 1964 reserve_reg_t *ret; 1965 1966 malloc_mutex_lock(&base_mtx); 1967 if (base_reserve_regs != NULL) { 1968 ret = base_reserve_regs; 1969 base_reserve_regs = *(reserve_reg_t **)ret; 1970 VALGRIND_FREELIKE_BLOCK(ret, 0); 1971 VALGRIND_MALLOCLIKE_BLOCK(ret, sizeof(reserve_reg_t), 0, false); 1972 malloc_mutex_unlock(&base_mtx); 1973 } else { 1974 malloc_mutex_unlock(&base_mtx); 1975 ret = (reserve_reg_t *)base_alloc(sizeof(reserve_reg_t)); 1976 } 1977 1978 return (ret); 1979 } 1980 1981 static void 1982 base_reserve_reg_dealloc(reserve_reg_t *reg) 1983 { 1984 1985 malloc_mutex_lock(&base_mtx); 1986 VALGRIND_FREELIKE_BLOCK(reg, 0); 1987 VALGRIND_MALLOCLIKE_BLOCK(reg, sizeof(reserve_reg_t *), 0, false); 1988 *(reserve_reg_t **)reg = base_reserve_regs; 1989 base_reserve_regs = reg; 1990 malloc_mutex_unlock(&base_mtx); 1991 } 1992 1993 /******************************************************************************/ 1994 1995 #ifdef MALLOC_STATS 1996 static void 1997 stats_print(arena_t *arena) 1998 { 1999 unsigned i, gap_start; 2000 2001 #ifdef MOZ_MEMORY_WINDOWS 2002 malloc_printf("dirty: %Iu page%s dirty, %I64u sweep%s," 2003 " %I64u madvise%s, %I64u page%s purged\n", 2004 arena->ndirty, arena->ndirty == 1 ? "" : "s", 2005 arena->stats.npurge, arena->stats.npurge == 1 ? "" : "s", 2006 arena->stats.nmadvise, arena->stats.nmadvise == 1 ? "" : "s", 2007 arena->stats.purged, arena->stats.purged == 1 ? "" : "s"); 2008 # ifdef MALLOC_DECOMMIT 2009 malloc_printf("decommit: %I64u decommit%s, %I64u commit%s," 2010 " %I64u page%s decommitted\n", 2011 arena->stats.ndecommit, (arena->stats.ndecommit == 1) ? "" : "s", 2012 arena->stats.ncommit, (arena->stats.ncommit == 1) ? "" : "s", 2013 arena->stats.decommitted, 2014 (arena->stats.decommitted == 1) ? "" : "s"); 2015 # endif 2016 2017 malloc_printf(" allocated nmalloc ndalloc\n"); 2018 malloc_printf("small: %12Iu %12I64u %12I64u\n", 2019 arena->stats.allocated_small, arena->stats.nmalloc_small, 2020 arena->stats.ndalloc_small); 2021 malloc_printf("large: %12Iu %12I64u %12I64u\n", 2022 arena->stats.allocated_large, arena->stats.nmalloc_large, 2023 arena->stats.ndalloc_large); 2024 malloc_printf("total: %12Iu %12I64u %12I64u\n", 2025 arena->stats.allocated_small + arena->stats.allocated_large, 2026 arena->stats.nmalloc_small + arena->stats.nmalloc_large, 2027 arena->stats.ndalloc_small + arena->stats.ndalloc_large); 2028 malloc_printf("mapped: %12Iu\n", arena->stats.mapped); 2029 #else 2030 malloc_printf("dirty: %zu page%s dirty, %llu sweep%s," 2031 " %llu madvise%s, %llu page%s purged\n", 2032 arena->ndirty, arena->ndirty == 1 ? "" : "s", 2033 arena->stats.npurge, arena->stats.npurge == 1 ? "" : "s", 2034 arena->stats.nmadvise, arena->stats.nmadvise == 1 ? "" : "s", 2035 arena->stats.purged, arena->stats.purged == 1 ? "" : "s"); 2036 # ifdef MALLOC_DECOMMIT 2037 malloc_printf("decommit: %llu decommit%s, %llu commit%s," 2038 " %llu page%s decommitted\n", 2039 arena->stats.ndecommit, (arena->stats.ndecommit == 1) ? "" : "s", 2040 arena->stats.ncommit, (arena->stats.ncommit == 1) ? "" : "s", 2041 arena->stats.decommitted, 2042 (arena->stats.decommitted == 1) ? "" : "s"); 2043 # endif 2044 2045 malloc_printf(" allocated nmalloc ndalloc\n"); 2046 malloc_printf("small: %12zu %12llu %12llu\n", 2047 arena->stats.allocated_small, arena->stats.nmalloc_small, 2048 arena->stats.ndalloc_small); 2049 malloc_printf("large: %12zu %12llu %12llu\n", 2050 arena->stats.allocated_large, arena->stats.nmalloc_large, 2051 arena->stats.ndalloc_large); 2052 malloc_printf("total: %12zu %12llu %12llu\n", 2053 arena->stats.allocated_small + arena->stats.allocated_large, 2054 arena->stats.nmalloc_small + arena->stats.nmalloc_large, 2055 arena->stats.ndalloc_small + arena->stats.ndalloc_large); 2056 malloc_printf("mapped: %12zu\n", arena->stats.mapped); 2057 #endif 2058 malloc_printf("bins: bin size regs pgs requests newruns" 2059 " reruns maxruns curruns\n"); 2060 for (i = 0, gap_start = UINT_MAX; i < ntbins + nqbins + nsbins; i++) { 2061 if (arena->bins[i].stats.nrequests == 0) { 2062 if (gap_start == UINT_MAX) 2063 gap_start = i; 2064 } else { 2065 if (gap_start != UINT_MAX) { 2066 if (i > gap_start + 1) { 2067 /* Gap of more than one size class. */ 2068 malloc_printf("[%u..%u]\n", 2069 gap_start, i - 1); 2070 } else { 2071 /* Gap of one size class. */ 2072 malloc_printf("[%u]\n", gap_start); 2073 } 2074 gap_start = UINT_MAX; 2075 } 2076 malloc_printf( 2077 #if defined(MOZ_MEMORY_WINDOWS) 2078 "%13u %1s %4u %4u %3u %9I64u %9I64u" 2079 " %9I64u %7u %7u\n", 2080 #else 2081 "%13u %1s %4u %4u %3u %9llu %9llu" 2082 " %9llu %7lu %7lu\n", 2083 #endif 2084 i, 2085 i < ntbins ? "T" : i < ntbins + nqbins ? "Q" : "S", 2086 arena->bins[i].reg_size, 2087 arena->bins[i].nregs, 2088 arena->bins[i].run_size >> pagesize_2pow, 2089 arena->bins[i].stats.nrequests, 2090 arena->bins[i].stats.nruns, 2091 arena->bins[i].stats.reruns, 2092 arena->bins[i].stats.highruns, 2093 arena->bins[i].stats.curruns); 2094 } 2095 } 2096 if (gap_start != UINT_MAX) { 2097 if (i > gap_start + 1) { 2098 /* Gap of more than one size class. */ 2099 malloc_printf("[%u..%u]\n", gap_start, i - 1); 2100 } else { 2101 /* Gap of one size class. */ 2102 malloc_printf("[%u]\n", gap_start); 2103 } 2104 } 2105 } 2106 #endif 2107 2108 /* 2109 * End Utility functions/macros. 2110 */ 2111 /******************************************************************************/ 2112 /* 2113 * Begin extent tree code. 2114 */ 2115 2116 static inline int 2117 extent_szad_comp(extent_node_t *a, extent_node_t *b) 2118 { 2119 int ret; 2120 size_t a_size = a->size; 2121 size_t b_size = b->size; 2122 2123 ret = (a_size > b_size) - (a_size < b_size); 2124 if (ret == 0) { 2125 uintptr_t a_addr = (uintptr_t)a->addr; 2126 uintptr_t b_addr = (uintptr_t)b->addr; 2127 2128 ret = (a_addr > b_addr) - (a_addr < b_addr); 2129 } 2130 2131 return (ret); 2132 } 2133 2134 /* Wrap red-black tree macros in functions. */ 2135 rb_wrap(static, extent_tree_szad_, extent_tree_t, extent_node_t, 2136 link_szad, extent_szad_comp) 2137 2138 static inline int 2139 extent_ad_comp(extent_node_t *a, extent_node_t *b) 2140 { 2141 uintptr_t a_addr = (uintptr_t)a->addr; 2142 uintptr_t b_addr = (uintptr_t)b->addr; 2143 2144 return ((a_addr > b_addr) - (a_addr < b_addr)); 2145 } 2146 2147 /* Wrap red-black tree macros in functions. */ 2148 rb_wrap(static, extent_tree_ad_, extent_tree_t, extent_node_t, link_ad, 2149 extent_ad_comp) 2150 2151 /* 2152 * End extent tree code. 2153 */ 2154 /******************************************************************************/ 2155 /* 2156 * Begin chunk management functions. 2157 */ 2158 2159 #ifdef MOZ_MEMORY_WINDOWS 2160 #ifdef MOZ_MEMORY_WINCE 2161 #define ALIGN_ADDR2OFFSET(al, ad) \ 2162 ((uintptr_t)ad & (al - 1)) 2163 static void * 2164 pages_map_align(size_t size, int pfd, size_t alignment) 2165 { 2166 2167 void *ret; 2168 int offset; 2169 if (size % alignment) 2170 size += (alignment - (size % alignment)); 2171 assert(size >= alignment); 2172 ret = pages_map(NULL, size, pfd); 2173 offset = ALIGN_ADDR2OFFSET(alignment, ret); 2174 if (offset) { 2175 /* try to over allocate by the ammount we're offset */ 2176 void *tmp; 2177 pages_unmap(ret, size); 2178 tmp = VirtualAlloc(NULL, size + alignment - offset, 2179 MEM_RESERVE, PAGE_NOACCESS); 2180 if (offset == ALIGN_ADDR2OFFSET(alignment, tmp)) 2181 ret = VirtualAlloc((void*)((intptr_t)tmp + alignment 2182 - offset), size, MEM_COMMIT, 2183 PAGE_READWRITE); 2184 else 2185 VirtualFree(tmp, 0, MEM_RELEASE); 2186 offset = ALIGN_ADDR2OFFSET(alignment, ret); 2187 2188 2189 if (offset) { 2190 /* over allocate to ensure we have an aligned region */ 2191 ret = VirtualAlloc(NULL, size + alignment, MEM_RESERVE, 2192 PAGE_NOACCESS); 2193 offset = ALIGN_ADDR2OFFSET(alignment, ret); 2194 ret = VirtualAlloc((void*)((intptr_t)ret + 2195 alignment - offset), 2196 size, MEM_COMMIT, PAGE_READWRITE); 2197 } 2198 } 2199 return (ret); 2200 } 2201 #endif 2202 2203 static void * 2204 pages_map(void *addr, size_t size, int pfd) 2205 { 2206 void *ret = NULL; 2207 #if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6) 2208 void *va_ret; 2209 assert(addr == NULL); 2210 va_ret = VirtualAlloc(addr, size, MEM_RESERVE, PAGE_NOACCESS); 2211 if (va_ret) 2212 ret = VirtualAlloc(va_ret, size, MEM_COMMIT, PAGE_READWRITE); 2213 assert(va_ret == ret); 2214 #else 2215 ret = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE, 2216 PAGE_READWRITE); 2217 #endif 2218 return (ret); 2219 } 2220 2221 static void 2222 pages_unmap(void *addr, size_t size) 2223 { 2224 if (VirtualFree(addr, 0, MEM_RELEASE) == 0) { 2225 #if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6) 2226 if (GetLastError() == ERROR_INVALID_PARAMETER) { 2227 MEMORY_BASIC_INFORMATION info; 2228 VirtualQuery(addr, &info, sizeof(info)); 2229 if (VirtualFree(info.AllocationBase, 0, MEM_RELEASE)) 2230 return; 2231 } 2232 #endif 2233 _malloc_message(_getprogname(), 2234 ": (malloc) Error in VirtualFree()\n", "", ""); 2235 if (opt_abort) 2236 abort(); 2237 } 2238 } 2239 #elif (defined(MOZ_MEMORY_DARWIN)) 2240 static void * 2241 pages_map(void *addr, size_t size, int pfd) 2242 { 2243 void *ret; 2244 kern_return_t err; 2245 int flags; 2246 2247 if (addr != NULL) { 2248 ret = addr; 2249 flags = 0; 2250 } else 2251 flags = VM_FLAGS_ANYWHERE; 2252 2253 err = vm_allocate((vm_map_t)mach_task_self(), (vm_address_t *)&ret, 2254 (vm_size_t)size, flags); 2255 if (err != KERN_SUCCESS) 2256 ret = NULL; 2257 2258 assert(ret == NULL || (addr == NULL && ret != addr) 2259 || (addr != NULL && ret == addr)); 2260 return (ret); 2261 } 2262 2263 static void 2264 pages_unmap(void *addr, size_t size) 2265 { 2266 kern_return_t err; 2267 2268 err = vm_deallocate((vm_map_t)mach_task_self(), (vm_address_t)addr, 2269 (vm_size_t)size); 2270 if (err != KERN_SUCCESS) { 2271 malloc_message(_getprogname(), 2272 ": (malloc) Error in vm_deallocate(): ", 2273 mach_error_string(err), "\n"); 2274 if (opt_abort) 2275 abort(); 2276 } 2277 } 2278 2279 #define VM_COPY_MIN (pagesize << 5) 2280 static inline void 2281 pages_copy(void *dest, const void *src, size_t n) 2282 { 2283 2284 assert((void *)((uintptr_t)dest & ~pagesize_mask) == dest); 2285 assert(n >= VM_COPY_MIN); 2286 assert((void *)((uintptr_t)src & ~pagesize_mask) == src); 2287 2288 vm_copy(mach_task_self(), (vm_address_t)src, (vm_size_t)n, 2289 (vm_address_t)dest); 2290 } 2291 #else /* MOZ_MEMORY_DARWIN */ 2292 #ifdef JEMALLOC_USES_MAP_ALIGN 2293 static void * 2294 pages_map_align(size_t size, int pfd, size_t alignment) 2295 { 2296 void *ret; 2297 2298 /* 2299 * We don't use MAP_FIXED here, because it can cause the *replacement* 2300 * of existing mappings, and we only want to create new mappings. 2301 */ 2302 #ifdef MALLOC_PAGEFILE 2303 if (pfd != -1) { 2304 ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | 2305 MAP_NOSYNC | MAP_ALIGN, pfd, 0); 2306 } else 2307 #endif 2308 { 2309 ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | 2310 MAP_NOSYNC | MAP_ALIGN | MAP_ANON, -1, 0); 2311 } 2312 assert(ret != NULL); 2313 2314 if (ret == MAP_FAILED) 2315 ret = NULL; 2316 return (ret); 2317 } 2318 #endif 2319 2320 static void * 2321 pages_map(void *addr, size_t size, int pfd) 2322 { 2323 void *ret; 2324 2325 /* 2326 * We don't use MAP_FIXED here, because it can cause the *replacement* 2327 * of existing mappings, and we only want to create new mappings. 2328 */ 2329 #ifdef MALLOC_PAGEFILE 2330 if (pfd != -1) { 2331 ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | 2332 MAP_NOSYNC, pfd, 0); 2333 } else 2334 #endif 2335 { 2336 ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | 2337 MAP_ANON, -1, 0); 2338 } 2339 assert(ret != NULL); 2340 2341 if (ret == MAP_FAILED) 2342 ret = NULL; 2343 else if (addr != NULL && ret != addr) { 2344 /* 2345 * We succeeded in mapping memory, but not in the right place. 2346 */ 2347 if (munmap(ret, size) == -1) { 2348 char buf[STRERROR_BUF]; 2349 2350 strerror_r(errno, buf, sizeof(buf)); 2351 _malloc_message(_getprogname(), 2352 ": (malloc) Error in munmap(): ", buf, "\n"); 2353 if (opt_abort) 2354 abort(); 2355 } 2356 ret = NULL; 2357 } 2358 2359 assert(ret == NULL || (addr == NULL && ret != addr) 2360 || (addr != NULL && ret == addr)); 2361 return (ret); 2362 } 2363 2364 static void 2365 pages_unmap(void *addr, size_t size) 2366 { 2367 2368 if (munmap(addr, size) == -1) { 2369 char buf[STRERROR_BUF]; 2370 2371 strerror_r(errno, buf, sizeof(buf)); 2372 _malloc_message(_getprogname(), 2373 ": (malloc) Error in munmap(): ", buf, "\n"); 2374 if (opt_abort) 2375 abort(); 2376 } 2377 } 2378 #endif 2379 2380 #ifdef MALLOC_VALIDATE 2381 static inline malloc_rtree_t * 2382 malloc_rtree_new(unsigned bits) 2383 { 2384 malloc_rtree_t *ret; 2385 unsigned bits_per_level, height, i; 2386 2387 bits_per_level = ffs(pow2_ceil((MALLOC_RTREE_NODESIZE / 2388 sizeof(void *)))) - 1; 2389 height = bits / bits_per_level; 2390 if (height * bits_per_level != bits) 2391 height++; 2392 assert(height * bits_per_level >= bits); 2393 2394 ret = (malloc_rtree_t*)base_calloc(1, sizeof(malloc_rtree_t) + (sizeof(unsigned) * 2395 (height - 1))); 2396 if (ret == NULL) 2397 return (NULL); 2398 2399 malloc_spin_init(&ret->lock); 2400 ret->height = height; 2401 if (bits_per_level * height > bits) 2402 ret->level2bits[0] = bits % bits_per_level; 2403 else 2404 ret->level2bits[0] = bits_per_level; 2405 for (i = 1; i < height; i++) 2406 ret->level2bits[i] = bits_per_level; 2407 2408 ret->root = (void**)base_calloc(1, sizeof(void *) << ret->level2bits[0]); 2409 if (ret->root == NULL) { 2410 /* 2411 * We leak the rtree here, since there's no generic base 2412 * deallocation. 2413 */ 2414 return (NULL); 2415 } 2416 2417 return (ret); 2418 } 2419 2420 /* The least significant bits of the key are ignored. */ 2421 static inline void * 2422 malloc_rtree_get(malloc_rtree_t *rtree, uintptr_t key) 2423 { 2424 void *ret; 2425 uintptr_t subkey; 2426 unsigned i, lshift, height, bits; 2427 void **node, **child; 2428 2429 malloc_spin_lock(&rtree->lock); 2430 for (i = lshift = 0, height = rtree->height, node = rtree->root; 2431 i < height - 1; 2432 i++, lshift += bits, node = child) { 2433 bits = rtree->level2bits[i]; 2434 subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits); 2435 child = (void**)node[subkey]; 2436 if (child == NULL) { 2437 malloc_spin_unlock(&rtree->lock); 2438 return (NULL); 2439 } 2440 } 2441 2442 /* node is a leaf, so it contains values rather than node pointers. */ 2443 bits = rtree->level2bits[i]; 2444 subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits); 2445 ret = node[subkey]; 2446 malloc_spin_unlock(&rtree->lock); 2447 2448 return (ret); 2449 } 2450 2451 static inline bool 2452 malloc_rtree_set(malloc_rtree_t *rtree, uintptr_t key, void *val) 2453 { 2454 uintptr_t subkey; 2455 unsigned i, lshift, height, bits; 2456 void **node, **child; 2457 2458 malloc_spin_lock(&rtree->lock); 2459 for (i = lshift = 0, height = rtree->height, node = rtree->root; 2460 i < height - 1; 2461 i++, lshift += bits, node = child) { 2462 bits = rtree->level2bits[i]; 2463 subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits); 2464 child = (void**)node[subkey]; 2465 if (child == NULL) { 2466 child = (void**)base_calloc(1, sizeof(void *) << 2467 rtree->level2bits[i+1]); 2468 if (child == NULL) { 2469 malloc_spin_unlock(&rtree->lock); 2470 return (true); 2471 } 2472 node[subkey] = child; 2473 } 2474 } 2475 2476 /* node is a leaf, so it contains values rather than node pointers. */ 2477 bits = rtree->level2bits[i]; 2478 subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits); 2479 node[subkey] = val; 2480 malloc_spin_unlock(&rtree->lock); 2481 2482 return (false); 2483 } 2484 #endif 2485 2486 static void * 2487 chunk_alloc_mmap(size_t size, bool pagefile) 2488 { 2489 void *ret; 2490 #ifndef JEMALLOC_USES_MAP_ALIGN 2491 size_t offset; 2492 #endif 2493 int pfd; 2494 2495 #ifdef MALLOC_PAGEFILE 2496 if (opt_pagefile && pagefile) { 2497 pfd = pagefile_init(size); 2498 if (pfd == -1) 2499 return (NULL); 2500 } else 2501 #endif 2502 pfd = -1; 2503 2504 /* 2505 * Windows requires that there be a 1:1 mapping between VM 2506 * allocation/deallocation operations. Therefore, take care here to 2507 * acquire the final result via one mapping operation. This means 2508 * unmapping any preliminary result that is not correctly aligned. 2509 * 2510 * The MALLOC_PAGEFILE code also benefits from this mapping algorithm, 2511 * since it reduces the number of page files. 2512 */ 2513 2514 #ifdef JEMALLOC_USES_MAP_ALIGN 2515 ret = pages_map_align(size, pfd, chunksize); 2516 #else 2517 ret = pages_map(NULL, size, pfd); 2518 if (ret == NULL) 2519 goto RETURN; 2520 2521 offset = CHUNK_ADDR2OFFSET(ret); 2522 if (offset != 0) { 2523 /* Deallocate, then try to allocate at (ret + size - offset). */ 2524 pages_unmap(ret, size); 2525 ret = pages_map((void *)((uintptr_t)ret + size - offset), size, 2526 pfd); 2527 while (ret == NULL) { 2528 /* 2529 * Over-allocate in order to map a memory region that 2530 * is definitely large enough. 2531 */ 2532 ret = pages_map(NULL, size + chunksize, -1); 2533 if (ret == NULL) 2534 goto RETURN; 2535 /* 2536 * Deallocate, then allocate the correct size, within 2537 * the over-sized mapping. 2538 */ 2539 offset = CHUNK_ADDR2OFFSET(ret); 2540 pages_unmap(ret, size + chunksize); 2541 if (offset == 0) 2542 ret = pages_map(ret, size, pfd); 2543 else { 2544 ret = pages_map((void *)((uintptr_t)ret + 2545 chunksize - offset), size, pfd); 2546 } 2547 /* 2548 * Failure here indicates a race with another thread, so 2549 * try again. 2550 */ 2551 } 2552 } 2553 RETURN: 2554 #endif 2555 #ifdef MALLOC_PAGEFILE 2556 if (pfd != -1) 2557 pagefile_close(pfd); 2558 #endif 2559 #ifdef MALLOC_STATS 2560 if (ret != NULL) 2561 stats_chunks.nchunks += (size / chunksize); 2562 #endif 2563 return (ret); 2564 } 2565 2566 #ifdef MALLOC_PAGEFILE 2567 static int 2568 pagefile_init(size_t size) 2569 { 2570 int ret; 2571 size_t i; 2572 char pagefile_path[PATH_MAX]; 2573 char zbuf[MALLOC_PAGEFILE_WRITE_SIZE]; 2574 2575 /* 2576 * Create a temporary file, then immediately unlink it so that it will 2577 * not persist. 2578 */ 2579 strcpy(pagefile_path, pagefile_templ); 2580 ret = mkstemp(pagefile_path); 2581 if (ret == -1) 2582 return (ret); 2583 if (unlink(pagefile_path)) { 2584 char buf[STRERROR_BUF]; 2585 2586 strerror_r(errno, buf, sizeof(buf)); 2587 _malloc_message(_getprogname(), ": (malloc) Error in unlink(\"", 2588 pagefile_path, "\"):"); 2589 _malloc_message(buf, "\n", "", ""); 2590 if (opt_abort) 2591 abort(); 2592 } 2593 2594 /* 2595 * Write sequential zeroes to the file in order to assure that disk 2596 * space is committed, with minimal fragmentation. It would be 2597 * sufficient to write one zero per disk block, but that potentially 2598 * results in more system calls, for no real gain. 2599 */ 2600 memset(zbuf, 0, sizeof(zbuf)); 2601 for (i = 0; i < size; i += sizeof(zbuf)) { 2602 if (write(ret, zbuf, sizeof(zbuf)) != sizeof(zbuf)) { 2603 if (errno != ENOSPC) { 2604 char buf[STRERROR_BUF]; 2605 2606 strerror_r(errno, buf, sizeof(buf)); 2607 _malloc_message(_getprogname(), 2608 ": (malloc) Error in write(): ", buf, "\n"); 2609 if (opt_abort) 2610 abort(); 2611 } 2612 pagefile_close(ret); 2613 return (-1); 2614 } 2615 } 2616 2617 return (ret); 2618 } 2619 2620 static void 2621 pagefile_close(int pfd) 2622 { 2623 2624 if (close(pfd)) { 2625 char buf[STRERROR_BUF]; 2626 2627 strerror_r(errno, buf, sizeof(buf)); 2628 _malloc_message(_getprogname(), 2629 ": (malloc) Error in close(): ", buf, "\n"); 2630 if (opt_abort) 2631 abort(); 2632 } 2633 } 2634 #endif 2635 2636 static void * 2637 chunk_recycle_reserve(size_t size, bool zero) 2638 { 2639 extent_node_t *node, key; 2640 2641 #ifdef MALLOC_DECOMMIT 2642 if (size != chunksize) 2643 return (NULL); 2644 #endif 2645 2646 key.addr = NULL; 2647 key.size = size; 2648 malloc_mutex_lock(&reserve_mtx); 2649 node = extent_tree_szad_nsearch(&reserve_chunks_szad, &key); 2650 if (node != NULL) { 2651 void *ret = node->addr; 2652 2653 /* Remove node from the tree. */ 2654 extent_tree_szad_remove(&reserve_chunks_szad, node); 2655 #ifndef MALLOC_DECOMMIT 2656 if (node->size == size) { 2657 #else 2658 assert(node->size == size); 2659 #endif 2660 extent_tree_ad_remove(&reserve_chunks_ad, node); 2661 base_node_dealloc(node); 2662 #ifndef MALLOC_DECOMMIT 2663 } else { 2664 /* 2665 * Insert the remainder of node's address range as a 2666 * smaller chunk. Its position within reserve_chunks_ad 2667 * does not change. 2668 */ 2669 assert(node->size > size); 2670 node->addr = (void *)((uintptr_t)node->addr + size); 2671 node->size -= size; 2672 extent_tree_szad_insert(&reserve_chunks_szad, node); 2673 } 2674 #endif 2675 reserve_cur -= size; 2676 /* 2677 * Try to replenish the reserve if this allocation depleted it. 2678 */ 2679 #ifndef MALLOC_DECOMMIT 2680 if (reserve_cur < reserve_min) { 2681 size_t diff = reserve_min - reserve_cur; 2682 #else 2683 while (reserve_cur < reserve_min) { 2684 # define diff chunksize 2685 #endif 2686 void *chunk; 2687 2688 malloc_mutex_unlock(&reserve_mtx); 2689 chunk = chunk_alloc_mmap(diff, true); 2690 malloc_mutex_lock(&reserve_mtx); 2691 if (chunk == NULL) { 2692 uint64_t seq = 0; 2693 2694 do { 2695 seq = reserve_notify(RESERVE_CND_LOW, 2696 size, seq); 2697 if (seq == 0) 2698 goto MALLOC_OUT; 2699 } while (reserve_cur < reserve_min); 2700 } else { 2701 extent_node_t *node; 2702 2703 node = chunk_dealloc_reserve(chunk, diff); 2704 if (node == NULL) { 2705 uint64_t seq = 0; 2706 2707 pages_unmap(chunk, diff); 2708 do { 2709 seq = reserve_notify( 2710 RESERVE_CND_LOW, size, seq); 2711 if (seq == 0) 2712 goto MALLOC_OUT; 2713 } while (reserve_cur < reserve_min); 2714 } 2715 } 2716 } 2717 MALLOC_OUT: 2718 malloc_mutex_unlock(&reserve_mtx); 2719 2720 #ifdef MALLOC_DECOMMIT 2721 pages_commit(ret, size); 2722 # undef diff 2723 #else 2724 if (zero) 2725 memset(ret, 0, size); 2726 #endif 2727 return (ret); 2728 } 2729 malloc_mutex_unlock(&reserve_mtx); 2730 2731 return (NULL); 2732 } 2733 2734 static void * 2735 chunk_alloc(size_t size, bool zero, bool pagefile) 2736 { 2737 void *ret; 2738 2739 assert(size != 0); 2740 assert((size & chunksize_mask) == 0); 2741 2742 ret = chunk_recycle_reserve(size, zero); 2743 if (ret != NULL) 2744 goto RETURN; 2745 2746 ret = chunk_alloc_mmap(size, pagefile); 2747 if (ret != NULL) { 2748 goto RETURN; 2749 } 2750 2751 /* All strategies for allocation failed. */ 2752 ret = NULL; 2753 RETURN: 2754 #ifdef MALLOC_STATS 2755 if (ret != NULL) 2756 stats_chunks.curchunks += (size / chunksize); 2757 if (stats_chunks.curchunks > stats_chunks.highchunks) 2758 stats_chunks.highchunks = stats_chunks.curchunks; 2759 #endif 2760 2761 #ifdef MALLOC_VALIDATE 2762 if (ret != NULL) { 2763 if (malloc_rtree_set(chunk_rtree, (uintptr_t)ret, ret)) { 2764 chunk_dealloc(ret, size); 2765 return (NULL); 2766 } 2767 } 2768 #endif 2769 2770 assert(CHUNK_ADDR2BASE(ret) == ret); 2771 return (ret); 2772 } 2773 2774 static extent_node_t * 2775 chunk_dealloc_reserve(void *chunk, size_t size) 2776 { 2777 extent_node_t *node; 2778 2779 #ifdef MALLOC_DECOMMIT 2780 if (size != chunksize) 2781 return (NULL); 2782 #else 2783 extent_node_t *prev, key; 2784 2785 key.addr = (void *)((uintptr_t)chunk + size); 2786 node = extent_tree_ad_nsearch(&reserve_chunks_ad, &key); 2787 /* Try to coalesce forward. */ 2788 if (node != NULL && node->addr == key.addr) { 2789 /* 2790 * Coalesce chunk with the following address range. This does 2791 * not change the position within reserve_chunks_ad, so only 2792 * remove/insert from/into reserve_chunks_szad. 2793 */ 2794 extent_tree_szad_remove(&reserve_chunks_szad, node); 2795 node->addr = chunk; 2796 node->size += size; 2797 extent_tree_szad_insert(&reserve_chunks_szad, node); 2798 } else { 2799 #endif 2800 /* Coalescing forward failed, so insert a new node. */ 2801 node = base_node_alloc(); 2802 if (node == NULL) 2803 return (NULL); 2804 node->addr = chunk; 2805 node->size = size; 2806 extent_tree_ad_insert(&reserve_chunks_ad, node); 2807 extent_tree_szad_insert(&reserve_chunks_szad, node); 2808 #ifndef MALLOC_DECOMMIT 2809 } 2810 2811 /* Try to coalesce backward. */ 2812 prev = extent_tree_ad_prev(&reserve_chunks_ad, node); 2813 if (prev != NULL && (void *)((uintptr_t)prev->addr + prev->size) == 2814 chunk) { 2815 /* 2816 * Coalesce chunk with the previous address range. This does 2817 * not change the position within reserve_chunks_ad, so only 2818 * remove/insert node from/into reserve_chunks_szad. 2819 */ 2820 extent_tree_szad_remove(&reserve_chunks_szad, prev); 2821 extent_tree_ad_remove(&reserve_chunks_ad, prev); 2822 2823 extent_tree_szad_remove(&reserve_chunks_szad, node); 2824 node->addr = prev->addr; 2825 node->size += prev->size; 2826 extent_tree_szad_insert(&reserve_chunks_szad, node); 2827 2828 base_node_dealloc(prev); 2829 } 2830 #endif 2831 2832 #ifdef MALLOC_DECOMMIT 2833 pages_decommit(chunk, size); 2834 #else 2835 madvise(chunk, size, MADV_FREE); 2836 #endif 2837 2838 reserve_cur += size; 2839 if (reserve_cur > reserve_max) 2840 reserve_shrink(); 2841 2842 return (node); 2843 } 2844 2845 static void 2846 chunk_dealloc_mmap(void *chunk, size_t size) 2847 { 2848 2849 pages_unmap(chunk, size); 2850 } 2851 2852 static void 2853 chunk_dealloc(void *chunk, size_t size) 2854 { 2855 extent_node_t *node; 2856 2857 assert(chunk != NULL); 2858 assert(CHUNK_ADDR2BASE(chunk) == chunk); 2859 assert(size != 0); 2860 assert((size & chunksize_mask) == 0); 2861 2862 #ifdef MALLOC_STATS 2863 stats_chunks.curchunks -= (size / chunksize); 2864 #endif 2865 #ifdef MALLOC_VALIDATE 2866 malloc_rtree_set(chunk_rtree, (uintptr_t)chunk, NULL); 2867 #endif 2868 2869 /* Try to merge chunk into the reserve. */ 2870 malloc_mutex_lock(&reserve_mtx); 2871 node = chunk_dealloc_reserve(chunk, size); 2872 malloc_mutex_unlock(&reserve_mtx); 2873 if (node == NULL) 2874 chunk_dealloc_mmap(chunk, size); 2875 } 2876 2877 /* 2878 * End chunk management functions. 2879 */ 2880 /******************************************************************************/ 2881 /* 2882 * Begin arena. 2883 */ 2884 2885 /* 2886 * Choose an arena based on a per-thread value (fast-path code, calls slow-path 2887 * code if necessary). 2888 */ 2889 static inline arena_t * 2890 choose_arena(void) 2891 { 2892 arena_t *ret; 2893 2894 /* 2895 * We can only use TLS if this is a PIC library, since for the static 2896 * library version, libc's malloc is used by TLS allocation, which 2897 * introduces a bootstrapping issue. 2898 */ 2899 #ifndef NO_TLS 2900 if (__isthreaded == false) { 2901 /* Avoid the overhead of TLS for single-threaded operation. */ 2902 return (arenas[0]); 2903 } 2904 2905 # ifdef MOZ_MEMORY_WINDOWS 2906 ret = (arena_t*)TlsGetValue(tlsIndex); 2907 # else 2908 ret = arenas_map; 2909 # endif 2910 2911 if (ret == NULL) { 2912 ret = choose_arena_hard(); 2913 assert(ret != NULL); 2914 } 2915 #else 2916 if (__isthreaded && narenas > 1) { 2917 unsigned long ind; 2918 2919 /* 2920 * Hash _pthread_self() to one of the arenas. There is a prime 2921 * number of arenas, so this has a reasonable chance of 2922 * working. Even so, the hashing can be easily thwarted by 2923 * inconvenient _pthread_self() values. Without specific 2924 * knowledge of how _pthread_self() calculates values, we can't 2925 * easily do much better than this. 2926 */ 2927 ind = (unsigned long) _pthread_self() % narenas; 2928 2929 /* 2930 * Optimistially assume that arenas[ind] has been initialized. 2931 * At worst, we find out that some other thread has already 2932 * done so, after acquiring the lock in preparation. Note that 2933 * this lazy locking also has the effect of lazily forcing 2934 * cache coherency; without the lock acquisition, there's no 2935 * guarantee that modification of arenas[ind] by another thread 2936 * would be seen on this CPU for an arbitrary amount of time. 2937 * 2938 * In general, this approach to modifying a synchronized value 2939 * isn't a good idea, but in this case we only ever modify the 2940 * value once, so things work out well. 2941 */ 2942 ret = arenas[ind]; 2943 if (ret == NULL) { 2944 /* 2945 * Avoid races with another thread that may have already 2946 * initialized arenas[ind]. 2947 */ 2948 malloc_spin_lock(&arenas_lock); 2949 if (arenas[ind] == NULL) 2950 ret = arenas_extend((unsigned)ind); 2951 else 2952 ret = arenas[ind]; 2953 malloc_spin_unlock(&arenas_lock); 2954 } 2955 } else 2956 ret = arenas[0]; 2957 #endif 2958 2959 assert(ret != NULL); 2960 return (ret); 2961 } 2962 2963 #ifndef NO_TLS 2964 /* 2965 * Choose an arena based on a per-thread value (slow-path code only, called 2966 * only by choose_arena()). 2967 */ 2968 static arena_t * 2969 choose_arena_hard(void) 2970 { 2971 arena_t *ret; 2972 2973 assert(__isthreaded); 2974 2975 #ifdef MALLOC_BALANCE 2976 /* Seed the PRNG used for arena load balancing. */ 2977 SPRN(balance, (uint32_t)(uintptr_t)(_pthread_self())); 2978 #endif 2979 2980 if (narenas > 1) { 2981 #ifdef MALLOC_BALANCE 2982 unsigned ind; 2983 2984 ind = PRN(balance, narenas_2pow); 2985 if ((ret = arenas[ind]) == NULL) { 2986 malloc_spin_lock(&arenas_lock); 2987 if ((ret = arenas[ind]) == NULL) 2988 ret = arenas_extend(ind); 2989 malloc_spin_unlock(&arenas_lock); 2990 } 2991 #else 2992 malloc_spin_lock(&arenas_lock); 2993 if ((ret = arenas[next_arena]) == NULL) 2994 ret = arenas_extend(next_arena); 2995 next_arena = (next_arena + 1) % narenas; 2996 malloc_spin_unlock(&arenas_lock); 2997 #endif 2998 } else 2999 ret = arenas[0]; 3000 3001 #ifdef MOZ_MEMORY_WINDOWS 3002 TlsSetValue(tlsIndex, ret); 3003 #else 3004 arenas_map = ret; 3005 #endif 3006 3007 return (ret); 3008 } 3009 #endif 3010 3011 static inline int 3012 arena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b) 3013 { 3014 uintptr_t a_chunk = (uintptr_t)a; 3015 uintptr_t b_chunk = (uintptr_t)b; 3016 3017 assert(a != NULL); 3018 assert(b != NULL); 3019 3020 return ((a_chunk > b_chunk) - (a_chunk < b_chunk)); 3021 } 3022 3023 /* Wrap red-black tree macros in functions. */ 3024 rb_wrap(static, arena_chunk_tree_dirty_, arena_chunk_tree_t, 3025 arena_chunk_t, link_dirty, arena_chunk_comp) 3026 3027 static inline int 3028 arena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) 3029 { 3030 uintptr_t a_mapelm = (uintptr_t)a; 3031 uintptr_t b_mapelm = (uintptr_t)b; 3032 3033 assert(a != NULL); 3034 assert(b != NULL); 3035 3036 return ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm)); 3037 } 3038 3039 /* Wrap red-black tree macros in functions. */ 3040 rb_wrap(static, arena_run_tree_, arena_run_tree_t, arena_chunk_map_t, link, 3041 arena_run_comp) 3042 3043 static inline int 3044 arena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) 3045 { 3046 int ret; 3047 size_t a_size = a->bits & ~pagesize_mask; 3048 size_t b_size = b->bits & ~pagesize_mask; 3049 3050 ret = (a_size > b_size) - (a_size < b_size); 3051 if (ret == 0) { 3052 uintptr_t a_mapelm, b_mapelm; 3053 3054 if ((a->bits & CHUNK_MAP_KEY) == 0) 3055 a_mapelm = (uintptr_t)a; 3056 else { 3057 /* 3058 * Treat keys as though they are lower than anything 3059 * else. 3060 */ 3061 a_mapelm = 0; 3062 } 3063 b_mapelm = (uintptr_t)b; 3064 3065 ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm); 3066 } 3067 3068 return (ret); 3069 } 3070 3071 /* Wrap red-black tree macros in functions. */ 3072 rb_wrap(static, arena_avail_tree_, arena_avail_tree_t, arena_chunk_map_t, link, 3073 arena_avail_comp) 3074 3075 static inline void * 3076 arena_run_reg_alloc(arena_run_t *run, arena_bin_t *bin) 3077 { 3078 void *ret; 3079 unsigned i, mask, bit, regind; 3080 3081 assert(run->magic == ARENA_RUN_MAGIC); 3082 assert(run->regs_minelm < bin->regs_mask_nelms); 3083 3084 /* 3085 * Move the first check outside the loop, so that run->regs_minelm can 3086 * be updated unconditionally, without the possibility of updating it 3087 * multiple times. 3088 */ 3089 i = run->regs_minelm; 3090 mask = run->regs_mask[i]; 3091 if (mask != 0) { 3092 /* Usable allocation found. */ 3093 bit = ffs((int)mask) - 1; 3094 3095 regind = ((i << (SIZEOF_INT_2POW + 3)) + bit); 3096 assert(regind < bin->nregs); 3097 ret = (void *)(((uintptr_t)run) + bin->reg0_offset 3098 + (bin->reg_size * regind)); 3099 3100 /* Clear bit. */ 3101 mask ^= (1U << bit); 3102 run->regs_mask[i] = mask; 3103 3104 return (ret); 3105 } 3106 3107 for (i++; i < bin->regs_mask_nelms; i++) { 3108 mask = run->regs_mask[i]; 3109 if (mask != 0) { 3110 /* Usable allocation found. */ 3111 bit = ffs((int)mask) - 1; 3112 3113 regind = ((i << (SIZEOF_INT_2POW + 3)) + bit); 3114 assert(regind < bin->nregs); 3115 ret = (void *)(((uintptr_t)run) + bin->reg0_offset 3116 + (bin->reg_size * regind)); 3117 3118 /* Clear bit. */ 3119 mask ^= (1U << bit); 3120 run->regs_mask[i] = mask; 3121 3122 /* 3123 * Make a note that nothing before this element 3124 * contains a free region. 3125 */ 3126 run->regs_minelm = i; /* Low payoff: + (mask == 0); */ 3127 3128 return (ret); 3129 } 3130 } 3131 /* Not reached. */ 3132 assert(0); 3133 return (NULL); 3134 } 3135 3136 static inline void 3137 arena_run_reg_dalloc(arena_run_t *run, arena_bin_t *bin, void *ptr, size_t size) 3138 { 3139 /* 3140 * To divide by a number D that is not a power of two we multiply 3141 * by (2^21 / D) and then right shift by 21 positions. 3142 * 3143 * X / D 3144 * 3145 * becomes 3146 * 3147 * (X * size_invs[(D >> QUANTUM_2POW_MIN) - 3]) >> SIZE_INV_SHIFT 3148 */ 3149 #define SIZE_INV_SHIFT 21 3150 #define SIZE_INV(s) (((1U << SIZE_INV_SHIFT) / (s << QUANTUM_2POW_MIN)) + 1) 3151 static const unsigned size_invs[] = { 3152 SIZE_INV(3), 3153 SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7), 3154 SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11), 3155 SIZE_INV(12),SIZE_INV(13), SIZE_INV(14), SIZE_INV(15), 3156 SIZE_INV(16),SIZE_INV(17), SIZE_INV(18), SIZE_INV(19), 3157 SIZE_INV(20),SIZE_INV(21), SIZE_INV(22), SIZE_INV(23), 3158 SIZE_INV(24),SIZE_INV(25), SIZE_INV(26), SIZE_INV(27), 3159 SIZE_INV(28),SIZE_INV(29), SIZE_INV(30), SIZE_INV(31) 3160 #if (QUANTUM_2POW_MIN < 4) 3161 , 3162 SIZE_INV(32), SIZE_INV(33), SIZE_INV(34), SIZE_INV(35), 3163 SIZE_INV(36), SIZE_INV(37), SIZE_INV(38), SIZE_INV(39), 3164 SIZE_INV(40), SIZE_INV(41), SIZE_INV(42), SIZE_INV(43), 3165 SIZE_INV(44), SIZE_INV(45), SIZE_INV(46), SIZE_INV(47), 3166 SIZE_INV(48), SIZE_INV(49), SIZE_INV(50), SIZE_INV(51), 3167 SIZE_INV(52), SIZE_INV(53), SIZE_INV(54), SIZE_INV(55), 3168 SIZE_INV(56), SIZE_INV(57), SIZE_INV(58), SIZE_INV(59), 3169 SIZE_INV(60), SIZE_INV(61), SIZE_INV(62), SIZE_INV(63) 3170 #endif 3171 }; 3172 unsigned diff, regind, elm, bit; 3173 3174 assert(run->magic == ARENA_RUN_MAGIC); 3175 assert(((sizeof(size_invs)) / sizeof(unsigned)) + 3 3176 >= (SMALL_MAX_DEFAULT >> QUANTUM_2POW_MIN)); 3177 3178 /* 3179 * Avoid doing division with a variable divisor if possible. Using 3180 * actual division here can reduce allocator throughput by over 20%! 3181 */ 3182 diff = (unsigned)((uintptr_t)ptr - (uintptr_t)run - bin->reg0_offset); 3183 if ((size & (size - 1)) == 0) { 3184 /* 3185 * log2_table allows fast division of a power of two in the 3186 * [1..128] range. 3187 * 3188 * (x / divisor) becomes (x >> log2_table[divisor - 1]). 3189 */ 3190 static const unsigned char log2_table[] = { 3191 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 3192 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3193 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3194 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3195 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3196 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3197 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3198 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7 3199 }; 3200 3201 if (size <= 128) 3202 regind = (diff >> log2_table[size - 1]); 3203 else if (size <= 32768) 3204 regind = diff >> (8 + log2_table[(size >> 8) - 1]); 3205 else { 3206 /* 3207 * The run size is too large for us to use the lookup 3208 * table. Use real division. 3209 */ 3210 regind = diff / size; 3211 } 3212 } else if (size <= ((sizeof(size_invs) / sizeof(unsigned)) 3213 << QUANTUM_2POW_MIN) + 2) { 3214 regind = size_invs[(size >> QUANTUM_2POW_MIN) - 3] * diff; 3215 regind >>= SIZE_INV_SHIFT; 3216 } else { 3217 /* 3218 * size_invs isn't large enough to handle this size class, so 3219 * calculate regind using actual division. This only happens 3220 * if the user increases small_max via the 'S' runtime 3221 * configuration option. 3222 */ 3223 regind = diff / size; 3224 }; 3225 assert(diff == regind * size); 3226 assert(regind < bin->nregs); 3227 3228 elm = regind >> (SIZEOF_INT_2POW + 3); 3229 if (elm < run->regs_minelm) 3230 run->regs_minelm = elm; 3231 bit = regind - (elm << (SIZEOF_INT_2POW + 3)); 3232 assert((run->regs_mask[elm] & (1U << bit)) == 0); 3233 run->regs_mask[elm] |= (1U << bit); 3234 #undef SIZE_INV 3235 #undef SIZE_INV_SHIFT 3236 } 3237 3238 static void 3239 arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large, 3240 bool zero) 3241 { 3242 arena_chunk_t *chunk; 3243 size_t old_ndirty, run_ind, total_pages, need_pages, rem_pages, i; 3244 3245 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); 3246 old_ndirty = chunk->ndirty; 3247 run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk) 3248 >> pagesize_2pow); 3249 total_pages = (chunk->map[run_ind].bits & ~pagesize_mask) >> 3250 pagesize_2pow; 3251 need_pages = (size >> pagesize_2pow); 3252 assert(need_pages > 0); 3253 assert(need_pages <= total_pages); 3254 rem_pages = total_pages - need_pages; 3255 3256 arena_avail_tree_remove(&arena->runs_avail, &chunk->map[run_ind]); 3257 3258 /* Keep track of trailing unused pages for later use. */ 3259 if (rem_pages > 0) { 3260 chunk->map[run_ind+need_pages].bits = (rem_pages << 3261 pagesize_2pow) | (chunk->map[run_ind+need_pages].bits & 3262 pagesize_mask); 3263 chunk->map[run_ind+total_pages-1].bits = (rem_pages << 3264 pagesize_2pow) | (chunk->map[run_ind+total_pages-1].bits & 3265 pagesize_mask); 3266 arena_avail_tree_insert(&arena->runs_avail, 3267 &chunk->map[run_ind+need_pages]); 3268 } 3269 3270 for (i = 0; i < need_pages; i++) { 3271 #ifdef MALLOC_DECOMMIT 3272 /* 3273 * Commit decommitted pages if necessary. If a decommitted 3274 * page is encountered, commit all needed adjacent decommitted 3275 * pages in one operation, in order to reduce system call 3276 * overhead. 3277 */ 3278 if (chunk->map[run_ind + i].bits & CHUNK_MAP_DECOMMITTED) { 3279 size_t j; 3280 3281 /* 3282 * Advance i+j to just past the index of the last page 3283 * to commit. Clear CHUNK_MAP_DECOMMITTED along the 3284 * way. 3285 */ 3286 for (j = 0; i + j < need_pages && (chunk->map[run_ind + 3287 i + j].bits & CHUNK_MAP_DECOMMITTED); j++) { 3288 chunk->map[run_ind + i + j].bits ^= 3289 CHUNK_MAP_DECOMMITTED; 3290 } 3291 3292 pages_commit((void *)((uintptr_t)chunk + ((run_ind + i) 3293 << pagesize_2pow)), (j << pagesize_2pow)); 3294 # ifdef MALLOC_STATS 3295 arena->stats.ncommit++; 3296 # endif 3297 } else /* No need to zero since commit zeros. */ 3298 #endif 3299 3300 /* Zero if necessary. */ 3301 if (zero) { 3302 if ((chunk->map[run_ind + i].bits & CHUNK_MAP_ZEROED) 3303 == 0) { 3304 VALGRIND_MALLOCLIKE_BLOCK((void *)((uintptr_t) 3305 chunk + ((run_ind + i) << pagesize_2pow)), 3306 pagesize, 0, false); 3307 memset((void *)((uintptr_t)chunk + ((run_ind 3308 + i) << pagesize_2pow)), 0, pagesize); 3309 VALGRIND_FREELIKE_BLOCK((void *)((uintptr_t) 3310 chunk + ((run_ind + i) << pagesize_2pow)), 3311 0); 3312 /* CHUNK_MAP_ZEROED is cleared below. */ 3313 } 3314 } 3315 3316 /* Update dirty page accounting. */ 3317 if (chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY) { 3318 chunk->ndirty--; 3319 arena->ndirty--; 3320 /* CHUNK_MAP_DIRTY is cleared below. */ 3321 } 3322 3323 /* Initialize the chunk map. */ 3324 if (large) { 3325 chunk->map[run_ind + i].bits = CHUNK_MAP_LARGE 3326 | CHUNK_MAP_ALLOCATED; 3327 } else { 3328 chunk->map[run_ind + i].bits = (size_t)run 3329 | CHUNK_MAP_ALLOCATED; 3330 } 3331 } 3332 3333 /* 3334 * Set the run size only in the first element for large runs. This is 3335 * primarily a debugging aid, since the lack of size info for trailing 3336 * pages only matters if the application tries to operate on an 3337 * interior pointer. 3338 */ 3339 if (large) 3340 chunk->map[run_ind].bits |= size; 3341 3342 if (chunk->ndirty == 0 && old_ndirty > 0) 3343 arena_chunk_tree_dirty_remove(&arena->chunks_dirty, chunk); 3344 } 3345 3346 static void 3347 arena_chunk_init(arena_t *arena, arena_chunk_t *chunk) 3348 { 3349 arena_run_t *run; 3350 size_t i; 3351 3352 VALGRIND_MALLOCLIKE_BLOCK(chunk, (arena_chunk_header_npages << 3353 pagesize_2pow), 0, false); 3354 #ifdef MALLOC_STATS 3355 arena->stats.mapped += chunksize; 3356 #endif 3357 3358 chunk->arena = arena; 3359 3360 /* 3361 * Claim that no pages are in use, since the header is merely overhead. 3362 */ 3363 chunk->ndirty = 0; 3364 3365 /* Initialize the map to contain one maximal free untouched run. */ 3366 run = (arena_run_t *)((uintptr_t)chunk + (arena_chunk_header_npages << 3367 pagesize_2pow)); 3368 for (i = 0; i < arena_chunk_header_npages; i++) 3369 chunk->map[i].bits = 0; 3370 chunk->map[i].bits = arena_maxclass 3371 #ifdef MALLOC_DECOMMIT 3372 | CHUNK_MAP_DECOMMITTED 3373 #endif 3374 | CHUNK_MAP_ZEROED; 3375 for (i++; i < chunk_npages-1; i++) { 3376 chunk->map[i].bits = 3377 #ifdef MALLOC_DECOMMIT 3378 CHUNK_MAP_DECOMMITTED | 3379 #endif 3380 CHUNK_MAP_ZEROED; 3381 } 3382 chunk->map[chunk_npages-1].bits = arena_maxclass 3383 #ifdef MALLOC_DECOMMIT 3384 | CHUNK_MAP_DECOMMITTED 3385 #endif 3386 | CHUNK_MAP_ZEROED; 3387 3388 #ifdef MALLOC_DECOMMIT 3389 /* 3390 * Start out decommitted, in order to force a closer correspondence 3391 * between dirty pages and committed untouched pages. 3392 */ 3393 pages_decommit(run, arena_maxclass); 3394 # ifdef MALLOC_STATS 3395 arena->stats.ndecommit++; 3396 arena->stats.decommitted += (chunk_npages - arena_chunk_header_npages); 3397 # endif 3398 #endif 3399 3400 /* Insert the run into the runs_avail tree. */ 3401 arena_avail_tree_insert(&arena->runs_avail, 3402 &chunk->map[arena_chunk_header_npages]); 3403 } 3404 3405 static void 3406 arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) 3407 { 3408 3409 if (arena->spare != NULL) { 3410 if (arena->spare->ndirty > 0) { 3411 arena_chunk_tree_dirty_remove( 3412 &chunk->arena->chunks_dirty, arena->spare); 3413 arena->ndirty -= arena->spare->ndirty; 3414 } 3415 VALGRIND_FREELIKE_BLOCK(arena->spare, 0); 3416 chunk_dealloc((void *)arena->spare, chunksize); 3417 #ifdef MALLOC_STATS 3418 arena->stats.mapped -= chunksize; 3419 #endif 3420 } 3421 3422 /* 3423 * Remove run from runs_avail, regardless of whether this chunk 3424 * will be cached, so that the arena does not use it. Dirty page 3425 * flushing only uses the chunks_dirty tree, so leaving this chunk in 3426 * the chunks_* trees is sufficient for that purpose. 3427 */ 3428 arena_avail_tree_remove(&arena->runs_avail, 3429 &chunk->map[arena_chunk_header_npages]); 3430 3431 arena->spare = chunk; 3432 } 3433 3434 static arena_run_t * 3435 arena_run_alloc(arena_t *arena, arena_bin_t *bin, size_t size, bool large, 3436 bool zero) 3437 { 3438 arena_chunk_t *chunk; 3439 arena_run_t *run; 3440 arena_chunk_map_t *mapelm, key; 3441 3442 assert(size <= arena_maxclass); 3443 assert((size & pagesize_mask) == 0); 3444 3445 chunk = NULL; 3446 while (true) { 3447 /* Search the arena's chunks for the lowest best fit. */ 3448 key.bits = size | CHUNK_MAP_KEY; 3449 mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key); 3450 if (mapelm != NULL) { 3451 arena_chunk_t *run_chunk = (arena_chunk_t*)CHUNK_ADDR2BASE(mapelm); 3452 size_t pageind = ((uintptr_t)mapelm - 3453 (uintptr_t)run_chunk->map) / 3454 sizeof(arena_chunk_map_t); 3455 3456 if (chunk != NULL) 3457 chunk_dealloc(chunk, chunksize); 3458 run = (arena_run_t *)((uintptr_t)run_chunk + (pageind 3459 << pagesize_2pow)); 3460 arena_run_split(arena, run, size, large, zero); 3461 return (run); 3462 } 3463 3464 if (arena->spare != NULL) { 3465 /* Use the spare. */ 3466 chunk = arena->spare; 3467 arena->spare = NULL; 3468 run = (arena_run_t *)((uintptr_t)chunk + 3469 (arena_chunk_header_npages << pagesize_2pow)); 3470 /* Insert the run into the runs_avail tree. */ 3471 arena_avail_tree_insert(&arena->runs_avail, 3472 &chunk->map[arena_chunk_header_npages]); 3473 arena_run_split(arena, run, size, large, zero); 3474 return (run); 3475 } 3476 3477 /* 3478 * No usable runs. Create a new chunk from which to allocate 3479 * the run. 3480 */ 3481 if (chunk == NULL) { 3482 uint64_t chunk_seq; 3483 3484 /* 3485 * Record the chunk allocation sequence number in order 3486 * to detect races. 3487 */ 3488 arena->chunk_seq++; 3489 chunk_seq = arena->chunk_seq; 3490 3491 /* 3492 * Drop the arena lock while allocating a chunk, since 3493 * reserve notifications may cause recursive 3494 * allocation. Dropping the lock here opens an 3495 * allocataion race, but we recover. 3496 */ 3497 malloc_mutex_unlock(&arena->lock); 3498 chunk = (arena_chunk_t *)chunk_alloc(chunksize, true, 3499 true); 3500 malloc_mutex_lock(&arena->lock); 3501 3502 /* 3503 * Check whether a race allowed a usable run to appear. 3504 */ 3505 if (bin != NULL && (run = bin->runcur) != NULL && 3506 run->nfree > 0) { 3507 if (chunk != NULL) 3508 chunk_dealloc(chunk, chunksize); 3509 return (run); 3510 } 3511 3512 /* 3513 * If this thread raced with another such that multiple 3514 * chunks were allocated, make sure that there is still 3515 * inadequate space before using this chunk. 3516 */ 3517 if (chunk_seq != arena->chunk_seq) 3518 continue; 3519 3520 /* 3521 * Check for an error *after* checking for a race, 3522 * since a race could also cause a transient OOM 3523 * condition. 3524 */ 3525 if (chunk == NULL) 3526 return (NULL); 3527 } 3528 3529 arena_chunk_init(arena, chunk); 3530 run = (arena_run_t *)((uintptr_t)chunk + 3531 (arena_chunk_header_npages << pagesize_2pow)); 3532 /* Update page map. */ 3533 arena_run_split(arena, run, size, large, zero); 3534 return (run); 3535 } 3536 } 3537 3538 static void 3539 arena_purge(arena_t *arena) 3540 { 3541 arena_chunk_t *chunk; 3542 size_t i, npages; 3543 #ifdef MALLOC_DEBUG 3544 size_t ndirty = 0; 3545 rb_foreach_begin(arena_chunk_t, link_dirty, &arena->chunks_dirty, 3546 chunk) { 3547 ndirty += chunk->ndirty; 3548 } rb_foreach_end(arena_chunk_t, link_dirty, &arena->chunks_dirty, chunk) 3549 assert(ndirty == arena->ndirty); 3550 #endif 3551 assert(arena->ndirty > opt_dirty_max); 3552 3553 #ifdef MALLOC_STATS 3554 arena->stats.npurge++; 3555 #endif 3556 3557 /* 3558 * Iterate downward through chunks until enough dirty memory has been 3559 * purged. Terminate as soon as possible in order to minimize the 3560 * number of system calls, even if a chunk has only been partially 3561 * purged. 3562 */ 3563 while (arena->ndirty > (opt_dirty_max >> 1)) { 3564 chunk = arena_chunk_tree_dirty_last(&arena->chunks_dirty); 3565 assert(chunk != NULL); 3566 3567 for (i = chunk_npages - 1; chunk->ndirty > 0; i--) { 3568 assert(i >= arena_chunk_header_npages); 3569 3570 if (chunk->map[i].bits & CHUNK_MAP_DIRTY) { 3571 #ifdef MALLOC_DECOMMIT 3572 assert((chunk->map[i].bits & 3573 CHUNK_MAP_DECOMMITTED) == 0); 3574 #endif 3575 chunk->map[i].bits ^= 3576 #ifdef MALLOC_DECOMMIT 3577 CHUNK_MAP_DECOMMITTED | 3578 #endif 3579 CHUNK_MAP_DIRTY; 3580 /* Find adjacent dirty run(s). */ 3581 for (npages = 1; i > arena_chunk_header_npages 3582 && (chunk->map[i - 1].bits & 3583 CHUNK_MAP_DIRTY); npages++) { 3584 i--; 3585 #ifdef MALLOC_DECOMMIT 3586 assert((chunk->map[i].bits & 3587 CHUNK_MAP_DECOMMITTED) == 0); 3588 #endif 3589 chunk->map[i].bits ^= 3590 #ifdef MALLOC_DECOMMIT 3591 CHUNK_MAP_DECOMMITTED | 3592 #endif 3593 CHUNK_MAP_DIRTY; 3594 } 3595 chunk->ndirty -= npages; 3596 arena->ndirty -= npages; 3597 3598 #ifdef MALLOC_DECOMMIT 3599 pages_decommit((void *)((uintptr_t) 3600 chunk + (i << pagesize_2pow)), 3601 (npages << pagesize_2pow)); 3602 # ifdef MALLOC_STATS 3603 arena->stats.ndecommit++; 3604 arena->stats.decommitted += npages; 3605 # endif 3606 #else 3607 madvise((void *)((uintptr_t)chunk + (i << 3608 pagesize_2pow)), (npages << pagesize_2pow), 3609 MADV_FREE); 3610 #endif 3611 #ifdef MALLOC_STATS 3612 arena->stats.nmadvise++; 3613 arena->stats.purged += npages; 3614 #endif 3615 if (arena->ndirty <= (opt_dirty_max >> 1)) 3616 break; 3617 } 3618 } 3619 3620 if (chunk->ndirty == 0) { 3621 arena_chunk_tree_dirty_remove(&arena->chunks_dirty, 3622 chunk); 3623 } 3624 } 3625 } 3626 3627 static void 3628 arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty) 3629 { 3630 arena_chunk_t *chunk; 3631 size_t size, run_ind, run_pages; 3632 3633 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); 3634 run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) 3635 >> pagesize_2pow); 3636 assert(run_ind >= arena_chunk_header_npages); 3637 assert(run_ind < chunk_npages); 3638 if ((chunk->map[run_ind].bits & CHUNK_MAP_LARGE) != 0) 3639 size = chunk->map[run_ind].bits & ~pagesize_mask; 3640 else 3641 size = run->bin->run_size; 3642 run_pages = (size >> pagesize_2pow); 3643 3644 /* Mark pages as unallocated in the chunk map. */ 3645 if (dirty) { 3646 size_t i; 3647 3648 for (i = 0; i < run_pages; i++) { 3649 assert((chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY) 3650 == 0); 3651 chunk->map[run_ind + i].bits = CHUNK_MAP_DIRTY; 3652 } 3653 3654 if (chunk->ndirty == 0) { 3655 arena_chunk_tree_dirty_insert(&arena->chunks_dirty, 3656 chunk); 3657 } 3658 chunk->ndirty += run_pages; 3659 arena->ndirty += run_pages; 3660 } else { 3661 size_t i; 3662 3663 for (i = 0; i < run_pages; i++) { 3664 chunk->map[run_ind + i].bits &= ~(CHUNK_MAP_LARGE | 3665 CHUNK_MAP_ALLOCATED); 3666 } 3667 } 3668 chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits & 3669 pagesize_mask); 3670 chunk->map[run_ind+run_pages-1].bits = size | 3671 (chunk->map[run_ind+run_pages-1].bits & pagesize_mask); 3672 3673 /* Try to coalesce forward. */ 3674 if (run_ind + run_pages < chunk_npages && 3675 (chunk->map[run_ind+run_pages].bits & CHUNK_MAP_ALLOCATED) == 0) { 3676 size_t nrun_size = chunk->map[run_ind+run_pages].bits & 3677 ~pagesize_mask; 3678 3679 /* 3680 * Remove successor from runs_avail; the coalesced run is 3681 * inserted later. 3682 */ 3683 arena_avail_tree_remove(&arena->runs_avail, 3684 &chunk->map[run_ind+run_pages]); 3685 3686 size += nrun_size; 3687 run_pages = size >> pagesize_2pow; 3688 3689 assert((chunk->map[run_ind+run_pages-1].bits & ~pagesize_mask) 3690 == nrun_size); 3691 chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits & 3692 pagesize_mask); 3693 chunk->map[run_ind+run_pages-1].bits = size | 3694 (chunk->map[run_ind+run_pages-1].bits & pagesize_mask); 3695 } 3696 3697 /* Try to coalesce backward. */ 3698 if (run_ind > arena_chunk_header_npages && (chunk->map[run_ind-1].bits & 3699 CHUNK_MAP_ALLOCATED) == 0) { 3700 size_t prun_size = chunk->map[run_ind-1].bits & ~pagesize_mask; 3701 3702 run_ind -= prun_size >> pagesize_2pow; 3703 3704 /* 3705 * Remove predecessor from runs_avail; the coalesced run is 3706 * inserted later. 3707 */ 3708 arena_avail_tree_remove(&arena->runs_avail, 3709 &chunk->map[run_ind]); 3710 3711 size += prun_size; 3712 run_pages = size >> pagesize_2pow; 3713 3714 assert((chunk->map[run_ind].bits & ~pagesize_mask) == 3715 prun_size); 3716 chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits & 3717 pagesize_mask); 3718 chunk->map[run_ind+run_pages-1].bits = size | 3719 (chunk->map[run_ind+run_pages-1].bits & pagesize_mask); 3720 } 3721 3722 /* Insert into runs_avail, now that coalescing is complete. */ 3723 arena_avail_tree_insert(&arena->runs_avail, &chunk->map[run_ind]); 3724 3725 /* Deallocate chunk if it is now completely unused. */ 3726 if ((chunk->map[arena_chunk_header_npages].bits & (~pagesize_mask | 3727 CHUNK_MAP_ALLOCATED)) == arena_maxclass) 3728 arena_chunk_dealloc(arena, chunk); 3729 3730 /* Enforce opt_dirty_max. */ 3731 if (arena->ndirty > opt_dirty_max) 3732 arena_purge(arena); 3733 } 3734 3735 static void 3736 arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, 3737 size_t oldsize, size_t newsize) 3738 { 3739 size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> pagesize_2pow; 3740 size_t head_npages = (oldsize - newsize) >> pagesize_2pow; 3741 3742 assert(oldsize > newsize); 3743 3744 /* 3745 * Update the chunk map so that arena_run_dalloc() can treat the 3746 * leading run as separately allocated. 3747 */ 3748 chunk->map[pageind].bits = (oldsize - newsize) | CHUNK_MAP_LARGE | 3749 CHUNK_MAP_ALLOCATED; 3750 chunk->map[pageind+head_npages].bits = newsize | CHUNK_MAP_LARGE | 3751 CHUNK_MAP_ALLOCATED; 3752 3753 arena_run_dalloc(arena, run, false); 3754 } 3755 3756 static void 3757 arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, 3758 size_t oldsize, size_t newsize, bool dirty) 3759 { 3760 size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> pagesize_2pow; 3761 size_t npages = newsize >> pagesize_2pow; 3762 3763 assert(oldsize > newsize); 3764 3765 /* 3766 * Update the chunk map so that arena_run_dalloc() can treat the 3767 * trailing run as separately allocated. 3768 */ 3769 chunk->map[pageind].bits = newsize | CHUNK_MAP_LARGE | 3770 CHUNK_MAP_ALLOCATED; 3771 chunk->map[pageind+npages].bits = (oldsize - newsize) | CHUNK_MAP_LARGE 3772 | CHUNK_MAP_ALLOCATED; 3773 3774 arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize), 3775 dirty); 3776 } 3777 3778 static arena_run_t * 3779 arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin) 3780 { 3781 arena_chunk_map_t *mapelm; 3782 arena_run_t *run; 3783 unsigned i, remainder; 3784 3785 /* Look for a usable run. */ 3786 mapelm = arena_run_tree_first(&bin->runs); 3787 if (mapelm != NULL) { 3788 /* run is guaranteed to have available space. */ 3789 arena_run_tree_remove(&bin->runs, mapelm); 3790 run = (arena_run_t *)(mapelm->bits & ~pagesize_mask); 3791 #ifdef MALLOC_STATS 3792 bin->stats.reruns++; 3793 #endif 3794 return (run); 3795 } 3796 /* No existing runs have any space available. */ 3797 3798 /* Allocate a new run. */ 3799 run = arena_run_alloc(arena, bin, bin->run_size, false, false); 3800 if (run == NULL) 3801 return (NULL); 3802 /* 3803 * Don't initialize if a race in arena_run_alloc() allowed an existing 3804 * run to become usable. 3805 */ 3806 if (run == bin->runcur) 3807 return (run); 3808 3809 VALGRIND_MALLOCLIKE_BLOCK(run, sizeof(arena_run_t) + (sizeof(unsigned) * 3810 (bin->regs_mask_nelms - 1)), 0, false); 3811 3812 /* Initialize run internals. */ 3813 run->bin = bin; 3814 3815 for (i = 0; i < bin->regs_mask_nelms - 1; i++) 3816 run->regs_mask[i] = UINT_MAX; 3817 remainder = bin->nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1); 3818 if (remainder == 0) 3819 run->regs_mask[i] = UINT_MAX; 3820 else { 3821 /* The last element has spare bits that need to be unset. */ 3822 run->regs_mask[i] = (UINT_MAX >> ((1U << (SIZEOF_INT_2POW + 3)) 3823 - remainder)); 3824 } 3825 3826 run->regs_minelm = 0; 3827 3828 run->nfree = bin->nregs; 3829 #ifdef MALLOC_DEBUG 3830 run->magic = ARENA_RUN_MAGIC; 3831 #endif 3832 3833 #ifdef MALLOC_STATS 3834 bin->stats.nruns++; 3835 bin->stats.curruns++; 3836 if (bin->stats.curruns > bin->stats.highruns) 3837 bin->stats.highruns = bin->stats.curruns; 3838 #endif 3839 return (run); 3840 } 3841 3842 /* bin->runcur must have space available before this function is called. */ 3843 static inline void * 3844 arena_bin_malloc_easy(arena_t *arena, arena_bin_t *bin, arena_run_t *run) 3845 { 3846 void *ret; 3847 3848 assert(run->magic == ARENA_RUN_MAGIC); 3849 assert(run->nfree > 0); 3850 3851 ret = arena_run_reg_alloc(run, bin); 3852 assert(ret != NULL); 3853 run->nfree--; 3854 3855 return (ret); 3856 } 3857 3858 /* Re-fill bin->runcur, then call arena_bin_malloc_easy(). */ 3859 static void * 3860 arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin) 3861 { 3862 3863 bin->runcur = arena_bin_nonfull_run_get(arena, bin); 3864 if (bin->runcur == NULL) 3865 return (NULL); 3866 assert(bin->runcur->magic == ARENA_RUN_MAGIC); 3867 assert(bin->runcur->nfree > 0); 3868 3869 return (arena_bin_malloc_easy(arena, bin, bin->runcur)); 3870 } 3871 3872 /* 3873 * Calculate bin->run_size such that it meets the following constraints: 3874 * 3875 * *) bin->run_size >= min_run_size 3876 * *) bin->run_size <= arena_maxclass 3877 * *) bin->run_size <= RUN_MAX_SMALL 3878 * *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed). 3879 * 3880 * bin->nregs, bin->regs_mask_nelms, and bin->reg0_offset are 3881 * also calculated here, since these settings are all interdependent. 3882 */ 3883 static size_t 3884 arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size) 3885 { 3886 size_t try_run_size, good_run_size; 3887 unsigned good_nregs, good_mask_nelms, good_reg0_offset; 3888 unsigned try_nregs, try_mask_nelms, try_reg0_offset; 3889 3890 assert(min_run_size >= pagesize); 3891 assert(min_run_size <= arena_maxclass); 3892 assert(min_run_size <= RUN_MAX_SMALL); 3893 3894 /* 3895 * Calculate known-valid settings before entering the run_size 3896 * expansion loop, so that the first part of the loop always copies 3897 * valid settings. 3898 * 3899 * The do..while loop iteratively reduces the number of regions until 3900 * the run header and the regions no longer overlap. A closed formula 3901 * would be quite messy, since there is an interdependency between the 3902 * header's mask length and the number of regions. 3903 */ 3904 try_run_size = min_run_size; 3905 try_nregs = ((try_run_size - sizeof(arena_run_t)) / bin->reg_size) 3906 + 1; /* Counter-act try_nregs-- in loop. */ 3907 do { 3908 try_nregs--; 3909 try_mask_nelms = (try_nregs >> (SIZEOF_INT_2POW + 3)) + 3910 ((try_nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1)) ? 1 : 0); 3911 try_reg0_offset = try_run_size - (try_nregs * bin->reg_size); 3912 } while (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1)) 3913 > try_reg0_offset); 3914 3915 /* run_size expansion loop. */ 3916 do { 3917 /* 3918 * Copy valid settings before trying more aggressive settings. 3919 */ 3920 good_run_size = try_run_size; 3921 good_nregs = try_nregs; 3922 good_mask_nelms = try_mask_nelms; 3923 good_reg0_offset = try_reg0_offset; 3924 3925 /* Try more aggressive settings. */ 3926 try_run_size += pagesize; 3927 try_nregs = ((try_run_size - sizeof(arena_run_t)) / 3928 bin->reg_size) + 1; /* Counter-act try_nregs-- in loop. */ 3929 do { 3930 try_nregs--; 3931 try_mask_nelms = (try_nregs >> (SIZEOF_INT_2POW + 3)) + 3932 ((try_nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1)) ? 3933 1 : 0); 3934 try_reg0_offset = try_run_size - (try_nregs * 3935 bin->reg_size); 3936 } while (sizeof(arena_run_t) + (sizeof(unsigned) * 3937 (try_mask_nelms - 1)) > try_reg0_offset); 3938 } while (try_run_size <= arena_maxclass && try_run_size <= RUN_MAX_SMALL 3939 && RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX 3940 && (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size); 3941 3942 assert(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1)) 3943 <= good_reg0_offset); 3944 assert((good_mask_nelms << (SIZEOF_INT_2POW + 3)) >= good_nregs); 3945 3946 /* Copy final settings. */ 3947 bin->run_size = good_run_size; 3948 bin->nregs = good_nregs; 3949 bin->regs_mask_nelms = good_mask_nelms; 3950 bin->reg0_offset = good_reg0_offset; 3951 3952 return (good_run_size); 3953 } 3954 3955 #ifdef MALLOC_BALANCE 3956 static inline void 3957 arena_lock_balance(arena_t *arena) 3958 { 3959 unsigned contention; 3960 3961 contention = malloc_spin_lock(&arena->lock); 3962 if (narenas > 1) { 3963 /* 3964 * Calculate the exponentially averaged contention for this 3965 * arena. Due to integer math always rounding down, this value 3966 * decays somewhat faster then normal. 3967 */ 3968 arena->contention = (((uint64_t)arena->contention 3969 * (uint64_t)((1U << BALANCE_ALPHA_INV_2POW)-1)) 3970 + (uint64_t)contention) >> BALANCE_ALPHA_INV_2POW; 3971 if (arena->contention >= opt_balance_threshold) 3972 arena_lock_balance_hard(arena); 3973 } 3974 } 3975 3976 static void 3977 arena_lock_balance_hard(arena_t *arena) 3978 { 3979 uint32_t ind; 3980 3981 arena->contention = 0; 3982 #ifdef MALLOC_STATS 3983 arena->stats.nbalance++; 3984 #endif 3985 ind = PRN(balance, narenas_2pow); 3986 if (arenas[ind] != NULL) { 3987 #ifdef MOZ_MEMORY_WINDOWS 3988 TlsSetValue(tlsIndex, arenas[ind]); 3989 #else 3990 arenas_map = arenas[ind]; 3991 #endif 3992 } else { 3993 malloc_spin_lock(&arenas_lock); 3994 if (arenas[ind] != NULL) { 3995 #ifdef MOZ_MEMORY_WINDOWS 3996 TlsSetValue(tlsIndex, arenas[ind]); 3997 #else 3998 arenas_map = arenas[ind]; 3999 #endif 4000 } else { 4001 #ifdef MOZ_MEMORY_WINDOWS 4002 TlsSetValue(tlsIndex, arenas_extend(ind)); 4003 #else 4004 arenas_map = arenas_extend(ind); 4005 #endif 4006 } 4007 malloc_spin_unlock(&arenas_lock); 4008 } 4009 } 4010 #endif 4011 4012 static inline void * 4013 arena_malloc_small(arena_t *arena, size_t size, bool zero) 4014 { 4015 void *ret; 4016 arena_bin_t *bin; 4017 arena_run_t *run; 4018 4019 if (size < small_min) { 4020 /* Tiny. */ 4021 size = pow2_ceil(size); 4022 bin = &arena->bins[ffs((int)(size >> (TINY_MIN_2POW + 4023 1)))]; 4024 #if (!defined(NDEBUG) || defined(MALLOC_STATS)) 4025 /* 4026 * Bin calculation is always correct, but we may need 4027 * to fix size for the purposes of assertions and/or 4028 * stats accuracy. 4029 */ 4030 if (size < (1U << TINY_MIN_2POW)) 4031 size = (1U << TINY_MIN_2POW); 4032 #endif 4033 } else if (size <= small_max) { 4034 /* Quantum-spaced. */ 4035 size = QUANTUM_CEILING(size); 4036 bin = &arena->bins[ntbins + (size >> opt_quantum_2pow) 4037 - 1]; 4038 } else { 4039 /* Sub-page. */ 4040 size = pow2_ceil(size); 4041 bin = &arena->bins[ntbins + nqbins 4042 + (ffs((int)(size >> opt_small_max_2pow)) - 2)]; 4043 } 4044 assert(size == bin->reg_size); 4045 4046 #ifdef MALLOC_BALANCE 4047 arena_lock_balance(arena); 4048 #else 4049 malloc_spin_lock(&arena->lock); 4050 #endif 4051 if ((run = bin->runcur) != NULL && run->nfree > 0) 4052 ret = arena_bin_malloc_easy(arena, bin, run); 4053 else 4054 ret = arena_bin_malloc_hard(arena, bin); 4055 4056 if (ret == NULL) { 4057 malloc_spin_unlock(&arena->lock); 4058 return (NULL); 4059 } 4060 4061 #ifdef MALLOC_STATS 4062 bin->stats.nrequests++; 4063 arena->stats.nmalloc_small++; 4064 arena->stats.allocated_small += size; 4065 #endif 4066 malloc_spin_unlock(&arena->lock); 4067 4068 VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, zero); 4069 if (zero == false) { 4070 #ifdef MALLOC_FILL 4071 if (opt_junk) 4072 memset(ret, 0xa5, size); 4073 else if (opt_zero) 4074 memset(ret, 0, size); 4075 #endif 4076 } else 4077 memset(ret, 0, size); 4078 4079 return (ret); 4080 } 4081 4082 static void * 4083 arena_malloc_large(arena_t *arena, size_t size, bool zero) 4084 { 4085 void *ret; 4086 4087 /* Large allocation. */ 4088 size = PAGE_CEILING(size); 4089 #ifdef MALLOC_BALANCE 4090 arena_lock_balance(arena); 4091 #else 4092 malloc_spin_lock(&arena->lock); 4093 #endif 4094 ret = (void *)arena_run_alloc(arena, NULL, size, true, zero); 4095 if (ret == NULL) { 4096 malloc_spin_unlock(&arena->lock); 4097 return (NULL); 4098 } 4099 #ifdef MALLOC_STATS 4100 arena->stats.nmalloc_large++; 4101 arena->stats.allocated_large += size; 4102 #endif 4103 malloc_spin_unlock(&arena->lock); 4104 4105 VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, zero); 4106 if (zero == false) { 4107 #ifdef MALLOC_FILL 4108 if (opt_junk) 4109 memset(ret, 0xa5, size); 4110 else if (opt_zero) 4111 memset(ret, 0, size); 4112 #endif 4113 } 4114 4115 return (ret); 4116 } 4117 4118 static inline void * 4119 arena_malloc(arena_t *arena, size_t size, bool zero) 4120 { 4121 4122 assert(arena != NULL); 4123 assert(arena->magic == ARENA_MAGIC); 4124 assert(size != 0); 4125 assert(QUANTUM_CEILING(size) <= arena_maxclass); 4126 4127 if (size <= bin_maxclass) { 4128 return (arena_malloc_small(arena, size, zero)); 4129 } else 4130 return (arena_malloc_large(arena, size, zero)); 4131 } 4132 4133 static inline void * 4134 imalloc(size_t size) 4135 { 4136 4137 assert(size != 0); 4138 4139 if (size <= arena_maxclass) 4140 return (arena_malloc(choose_arena(), size, false)); 4141 else 4142 return (huge_malloc(size, false)); 4143 } 4144 4145 static inline void * 4146 icalloc(size_t size) 4147 { 4148 4149 if (size <= arena_maxclass) 4150 return (arena_malloc(choose_arena(), size, true)); 4151 else 4152 return (huge_malloc(size, true)); 4153 } 4154 4155 /* Only handles large allocations that require more than page alignment. */ 4156 static void * 4157 arena_palloc(arena_t *arena, size_t alignment, size_t size, size_t alloc_size) 4158 { 4159 void *ret; 4160 size_t offset; 4161 arena_chunk_t *chunk; 4162 4163 assert((size & pagesize_mask) == 0); 4164 assert((alignment & pagesize_mask) == 0); 4165 4166 #ifdef MALLOC_BALANCE 4167 arena_lock_balance(arena); 4168 #else 4169 malloc_spin_lock(&arena->lock); 4170 #endif 4171 ret = (void *)arena_run_alloc(arena, NULL, alloc_size, true, false); 4172 if (ret == NULL) { 4173 malloc_spin_unlock(&arena->lock); 4174 return (NULL); 4175 } 4176 4177 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ret); 4178 4179 offset = (uintptr_t)ret & (alignment - 1); 4180 assert((offset & pagesize_mask) == 0); 4181 assert(offset < alloc_size); 4182 if (offset == 0) 4183 arena_run_trim_tail(arena, chunk, (arena_run_t*)ret, alloc_size, size, false); 4184 else { 4185 size_t leadsize, trailsize; 4186 4187 leadsize = alignment - offset; 4188 if (leadsize > 0) { 4189 arena_run_trim_head(arena, chunk, (arena_run_t*)ret, alloc_size, 4190 alloc_size - leadsize); 4191 ret = (void *)((uintptr_t)ret + leadsize); 4192 } 4193 4194 trailsize = alloc_size - leadsize - size; 4195 if (trailsize != 0) { 4196 /* Trim trailing space. */ 4197 assert(trailsize < alloc_size); 4198 arena_run_trim_tail(arena, chunk, (arena_run_t*)ret, size + trailsize, 4199 size, false); 4200 } 4201 } 4202 4203 #ifdef MALLOC_STATS 4204 arena->stats.nmalloc_large++; 4205 arena->stats.allocated_large += size; 4206 #endif 4207 malloc_spin_unlock(&arena->lock); 4208 4209 VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, false); 4210 #ifdef MALLOC_FILL 4211 if (opt_junk) 4212 memset(ret, 0xa5, size); 4213 else if (opt_zero) 4214 memset(ret, 0, size); 4215 #endif 4216 return (ret); 4217 } 4218 4219 static inline void * 4220 ipalloc(size_t alignment, size_t size) 4221 { 4222 void *ret; 4223 size_t ceil_size; 4224 4225 /* 4226 * Round size up to the nearest multiple of alignment. 4227 * 4228 * This done, we can take advantage of the fact that for each small 4229 * size class, every object is aligned at the smallest power of two 4230 * that is non-zero in the base two representation of the size. For 4231 * example: 4232 * 4233 * Size | Base 2 | Minimum alignment 4234 * -----+----------+------------------ 4235 * 96 | 1100000 | 32 4236 * 144 | 10100000 | 32 4237 * 192 | 11000000 | 64 4238 * 4239 * Depending on runtime settings, it is possible that arena_malloc() 4240 * will further round up to a power of two, but that never causes 4241 * correctness issues. 4242 */ 4243 ceil_size = (size + (alignment - 1)) & (-alignment); 4244 /* 4245 * (ceil_size < size) protects against the combination of maximal 4246 * alignment and size greater than maximal alignment. 4247 */ 4248 if (ceil_size < size) { 4249 /* size_t overflow. */ 4250 return (NULL); 4251 } 4252 4253 if (ceil_size <= pagesize || (alignment <= pagesize 4254 && ceil_size <= arena_maxclass)) 4255 ret = arena_malloc(choose_arena(), ceil_size, false); 4256 else { 4257 size_t run_size; 4258 4259 /* 4260 * We can't achieve sub-page alignment, so round up alignment 4261 * permanently; it makes later calculations simpler. 4262 */ 4263 alignment = PAGE_CEILING(alignment); 4264 ceil_size = PAGE_CEILING(size); 4265 /* 4266 * (ceil_size < size) protects against very large sizes within 4267 * pagesize of SIZE_T_MAX. 4268 * 4269 * (ceil_size + alignment < ceil_size) protects against the 4270 * combination of maximal alignment and ceil_size large enough 4271 * to cause overflow. This is similar to the first overflow 4272 * check above, but it needs to be repeated due to the new 4273 * ceil_size value, which may now be *equal* to maximal 4274 * alignment, whereas before we only detected overflow if the 4275 * original size was *greater* than maximal alignment. 4276 */ 4277 if (ceil_size < size || ceil_size + alignment < ceil_size) { 4278 /* size_t overflow. */ 4279 return (NULL); 4280 } 4281 4282 /* 4283 * Calculate the size of the over-size run that arena_palloc() 4284 * would need to allocate in order to guarantee the alignment. 4285 */ 4286 if (ceil_size >= alignment) 4287 run_size = ceil_size + alignment - pagesize; 4288 else { 4289 /* 4290 * It is possible that (alignment << 1) will cause 4291 * overflow, but it doesn't matter because we also 4292 * subtract pagesize, which in the case of overflow 4293 * leaves us with a very large run_size. That causes 4294 * the first conditional below to fail, which means 4295 * that the bogus run_size value never gets used for 4296 * anything important. 4297 */ 4298 run_size = (alignment << 1) - pagesize; 4299 } 4300 4301 if (run_size <= arena_maxclass) { 4302 ret = arena_palloc(choose_arena(), alignment, ceil_size, 4303 run_size); 4304 } else if (alignment <= chunksize) 4305 ret = huge_malloc(ceil_size, false); 4306 else 4307 ret = huge_palloc(alignment, ceil_size); 4308 } 4309 4310 assert(((uintptr_t)ret & (alignment - 1)) == 0); 4311 return (ret); 4312 } 4313 4314 /* Return the size of the allocation pointed to by ptr. */ 4315 static size_t 4316 arena_salloc(const void *ptr) 4317 { 4318 size_t ret; 4319 arena_chunk_t *chunk; 4320 size_t pageind, mapbits; 4321 4322 assert(ptr != NULL); 4323 assert(CHUNK_ADDR2BASE(ptr) != ptr); 4324 4325 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 4326 pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> pagesize_2pow); 4327 mapbits = chunk->map[pageind].bits; 4328 assert((mapbits & CHUNK_MAP_ALLOCATED) != 0); 4329 if ((mapbits & CHUNK_MAP_LARGE) == 0) { 4330 arena_run_t *run = (arena_run_t *)(mapbits & ~pagesize_mask); 4331 assert(run->magic == ARENA_RUN_MAGIC); 4332 ret = run->bin->reg_size; 4333 } else { 4334 ret = mapbits & ~pagesize_mask; 4335 assert(ret != 0); 4336 } 4337 4338 return (ret); 4339 } 4340 4341 #if (defined(MALLOC_VALIDATE) || defined(MOZ_MEMORY_DARWIN)) 4342 /* 4343 * Validate ptr before assuming that it points to an allocation. Currently, 4344 * the following validation is performed: 4345 * 4346 * + Check that ptr is not NULL. 4347 * 4348 * + Check that ptr lies within a mapped chunk. 4349 */ 4350 static inline size_t 4351 isalloc_validate(const void *ptr) 4352 { 4353 arena_chunk_t *chunk; 4354 4355 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 4356 if (chunk == NULL) 4357 return (0); 4358 4359 if (malloc_rtree_get(chunk_rtree, (uintptr_t)chunk) == NULL) 4360 return (0); 4361 4362 if (chunk != ptr) { 4363 assert(chunk->arena->magic == ARENA_MAGIC); 4364 return (arena_salloc(ptr)); 4365 } else { 4366 size_t ret; 4367 extent_node_t *node; 4368 extent_node_t key; 4369 4370 /* Chunk. */ 4371 key.addr = (void *)chunk; 4372 malloc_mutex_lock(&huge_mtx); 4373 node = extent_tree_ad_search(&huge, &key); 4374 if (node != NULL) 4375 ret = node->size; 4376 else 4377 ret = 0; 4378 malloc_mutex_unlock(&huge_mtx); 4379 return (ret); 4380 } 4381 } 4382 #endif 4383 4384 static inline size_t 4385 isalloc(const void *ptr) 4386 { 4387 size_t ret; 4388 arena_chunk_t *chunk; 4389 4390 assert(ptr != NULL); 4391 4392 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 4393 if (chunk != ptr) { 4394 /* Region. */ 4395 assert(chunk->arena->magic == ARENA_MAGIC); 4396 4397 ret = arena_salloc(ptr); 4398 } else { 4399 extent_node_t *node, key; 4400 4401 /* Chunk (huge allocation). */ 4402 4403 malloc_mutex_lock(&huge_mtx); 4404 4405 /* Extract from tree of huge allocations. */ 4406 key.addr = __DECONST(void *, ptr); 4407 node = extent_tree_ad_search(&huge, &key); 4408 assert(node != NULL); 4409 4410 ret = node->size; 4411 4412 malloc_mutex_unlock(&huge_mtx); 4413 } 4414 4415 return (ret); 4416 } 4417 4418 static inline void 4419 arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr, 4420 arena_chunk_map_t *mapelm) 4421 { 4422 arena_run_t *run; 4423 arena_bin_t *bin; 4424 size_t size; 4425 4426 run = (arena_run_t *)(mapelm->bits & ~pagesize_mask); 4427 assert(run->magic == ARENA_RUN_MAGIC); 4428 bin = run->bin; 4429 size = bin->reg_size; 4430 4431 #ifdef MALLOC_FILL 4432 if (opt_junk) 4433 memset(ptr, 0x5a, size); 4434 #endif 4435 4436 arena_run_reg_dalloc(run, bin, ptr, size); 4437 run->nfree++; 4438 4439 if (run->nfree == bin->nregs) { 4440 /* Deallocate run. */ 4441 if (run == bin->runcur) 4442 bin->runcur = NULL; 4443 else if (bin->nregs != 1) { 4444 size_t run_pageind = (((uintptr_t)run - 4445 (uintptr_t)chunk)) >> pagesize_2pow; 4446 arena_chunk_map_t *run_mapelm = 4447 &chunk->map[run_pageind]; 4448 /* 4449 * This block's conditional is necessary because if the 4450 * run only contains one region, then it never gets 4451 * inserted into the non-full runs tree. 4452 */ 4453 assert(arena_run_tree_search(&bin->runs, run_mapelm) == 4454 run_mapelm); 4455 arena_run_tree_remove(&bin->runs, run_mapelm); 4456 } 4457 #ifdef MALLOC_DEBUG 4458 run->magic = 0; 4459 #endif 4460 VALGRIND_FREELIKE_BLOCK(run, 0); 4461 arena_run_dalloc(arena, run, true); 4462 #ifdef MALLOC_STATS 4463 bin->stats.curruns--; 4464 #endif 4465 } else if (run->nfree == 1 && run != bin->runcur) { 4466 /* 4467 * Make sure that bin->runcur always refers to the lowest 4468 * non-full run, if one exists. 4469 */ 4470 if (bin->runcur == NULL) 4471 bin->runcur = run; 4472 else if ((uintptr_t)run < (uintptr_t)bin->runcur) { 4473 /* Switch runcur. */ 4474 if (bin->runcur->nfree > 0) { 4475 arena_chunk_t *runcur_chunk = 4476 (arena_chunk_t*)CHUNK_ADDR2BASE(bin->runcur); 4477 size_t runcur_pageind = 4478 (((uintptr_t)bin->runcur - 4479 (uintptr_t)runcur_chunk)) >> pagesize_2pow; 4480 arena_chunk_map_t *runcur_mapelm = 4481 &runcur_chunk->map[runcur_pageind]; 4482 4483 /* Insert runcur. */ 4484 assert(arena_run_tree_search(&bin->runs, 4485 runcur_mapelm) == NULL); 4486 arena_run_tree_insert(&bin->runs, 4487 runcur_mapelm); 4488 } 4489 bin->runcur = run; 4490 } else { 4491 size_t run_pageind = (((uintptr_t)run - 4492 (uintptr_t)chunk)) >> pagesize_2pow; 4493 arena_chunk_map_t *run_mapelm = 4494 &chunk->map[run_pageind]; 4495 4496 assert(arena_run_tree_search(&bin->runs, run_mapelm) == 4497 NULL); 4498 arena_run_tree_insert(&bin->runs, run_mapelm); 4499 } 4500 } 4501 #ifdef MALLOC_STATS 4502 arena->stats.allocated_small -= size; 4503 arena->stats.ndalloc_small++; 4504 #endif 4505 } 4506 4507 static void 4508 arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr) 4509 { 4510 /* Large allocation. */ 4511 malloc_spin_lock(&arena->lock); 4512 4513 #ifdef MALLOC_FILL 4514 #ifndef MALLOC_STATS 4515 if (opt_junk) 4516 #endif 4517 #endif 4518 { 4519 size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> 4520 pagesize_2pow; 4521 size_t size = chunk->map[pageind].bits & ~pagesize_mask; 4522 4523 #ifdef MALLOC_FILL 4524 #ifdef MALLOC_STATS 4525 if (opt_junk) 4526 #endif 4527 memset(ptr, 0x5a, size); 4528 #endif 4529 #ifdef MALLOC_STATS 4530 arena->stats.allocated_large -= size; 4531 #endif 4532 } 4533 #ifdef MALLOC_STATS 4534 arena->stats.ndalloc_large++; 4535 #endif 4536 4537 arena_run_dalloc(arena, (arena_run_t *)ptr, true); 4538 malloc_spin_unlock(&arena->lock); 4539 } 4540 4541 static inline void 4542 arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr) 4543 { 4544 size_t pageind; 4545 arena_chunk_map_t *mapelm; 4546 4547 assert(arena != NULL); 4548 assert(arena->magic == ARENA_MAGIC); 4549 assert(chunk->arena == arena); 4550 assert(ptr != NULL); 4551 assert(CHUNK_ADDR2BASE(ptr) != ptr); 4552 4553 pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> pagesize_2pow); 4554 mapelm = &chunk->map[pageind]; 4555 assert((mapelm->bits & CHUNK_MAP_ALLOCATED) != 0); 4556 if ((mapelm->bits & CHUNK_MAP_LARGE) == 0) { 4557 /* Small allocation. */ 4558 malloc_spin_lock(&arena->lock); 4559 arena_dalloc_small(arena, chunk, ptr, mapelm); 4560 malloc_spin_unlock(&arena->lock); 4561 } else 4562 arena_dalloc_large(arena, chunk, ptr); 4563 VALGRIND_FREELIKE_BLOCK(ptr, 0); 4564 } 4565 4566 static inline void 4567 idalloc(void *ptr) 4568 { 4569 arena_chunk_t *chunk; 4570 4571 assert(ptr != NULL); 4572 4573 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 4574 if (chunk != ptr) 4575 arena_dalloc(chunk->arena, chunk, ptr); 4576 else 4577 huge_dalloc(ptr); 4578 } 4579 4580 static void 4581 arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr, 4582 size_t size, size_t oldsize) 4583 { 4584 4585 assert(size < oldsize); 4586 4587 /* 4588 * Shrink the run, and make trailing pages available for other 4589 * allocations. 4590 */ 4591 #ifdef MALLOC_BALANCE 4592 arena_lock_balance(arena); 4593 #else 4594 malloc_spin_lock(&arena->lock); 4595 #endif 4596 arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size, 4597 true); 4598 #ifdef MALLOC_STATS 4599 arena->stats.allocated_large -= oldsize - size; 4600 #endif 4601 malloc_spin_unlock(&arena->lock); 4602 } 4603 4604 static bool 4605 arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, 4606 size_t size, size_t oldsize) 4607 { 4608 size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> pagesize_2pow; 4609 size_t npages = oldsize >> pagesize_2pow; 4610 4611 assert(oldsize == (chunk->map[pageind].bits & ~pagesize_mask)); 4612 4613 /* Try to extend the run. */ 4614 assert(size > oldsize); 4615 #ifdef MALLOC_BALANCE 4616 arena_lock_balance(arena); 4617 #else 4618 malloc_spin_lock(&arena->lock); 4619 #endif 4620 if (pageind + npages < chunk_npages && (chunk->map[pageind+npages].bits 4621 & CHUNK_MAP_ALLOCATED) == 0 && (chunk->map[pageind+npages].bits & 4622 ~pagesize_mask) >= size - oldsize) { 4623 /* 4624 * The next run is available and sufficiently large. Split the 4625 * following run, then merge the first part with the existing 4626 * allocation. 4627 */ 4628 arena_run_split(arena, (arena_run_t *)((uintptr_t)chunk + 4629 ((pageind+npages) << pagesize_2pow)), size - oldsize, true, 4630 false); 4631 4632 chunk->map[pageind].bits = size | CHUNK_MAP_LARGE | 4633 CHUNK_MAP_ALLOCATED; 4634 chunk->map[pageind+npages].bits = CHUNK_MAP_LARGE | 4635 CHUNK_MAP_ALLOCATED; 4636 4637 #ifdef MALLOC_STATS 4638 arena->stats.allocated_large += size - oldsize; 4639 #endif 4640 malloc_spin_unlock(&arena->lock); 4641 return (false); 4642 } 4643 malloc_spin_unlock(&arena->lock); 4644 4645 return (true); 4646 } 4647 4648 /* 4649 * Try to resize a large allocation, in order to avoid copying. This will 4650 * always fail if growing an object, and the following run is already in use. 4651 */ 4652 static bool 4653 arena_ralloc_large(void *ptr, size_t size, size_t oldsize) 4654 { 4655 size_t psize; 4656 4657 psize = PAGE_CEILING(size); 4658 if (psize == oldsize) { 4659 /* Same size class. */ 4660 #ifdef MALLOC_FILL 4661 if (opt_junk && size < oldsize) { 4662 memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - 4663 size); 4664 } 4665 #endif 4666 return (false); 4667 } else { 4668 arena_chunk_t *chunk; 4669 arena_t *arena; 4670 4671 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 4672 arena = chunk->arena; 4673 assert(arena->magic == ARENA_MAGIC); 4674 4675 if (psize < oldsize) { 4676 #ifdef MALLOC_FILL 4677 /* Fill before shrinking in order avoid a race. */ 4678 if (opt_junk) { 4679 memset((void *)((uintptr_t)ptr + size), 0x5a, 4680 oldsize - size); 4681 } 4682 #endif 4683 arena_ralloc_large_shrink(arena, chunk, ptr, psize, 4684 oldsize); 4685 return (false); 4686 } else { 4687 bool ret = arena_ralloc_large_grow(arena, chunk, ptr, 4688 psize, oldsize); 4689 #ifdef MALLOC_FILL 4690 if (ret == false && opt_zero) { 4691 memset((void *)((uintptr_t)ptr + oldsize), 0, 4692 size - oldsize); 4693 } 4694 #endif 4695 return (ret); 4696 } 4697 } 4698 } 4699 4700 static void * 4701 arena_ralloc(void *ptr, size_t size, size_t oldsize) 4702 { 4703 void *ret; 4704 size_t copysize; 4705 4706 /* Try to avoid moving the allocation. */ 4707 if (size < small_min) { 4708 if (oldsize < small_min && 4709 ffs((int)(pow2_ceil(size) >> (TINY_MIN_2POW + 1))) 4710 == ffs((int)(pow2_ceil(oldsize) >> (TINY_MIN_2POW + 1)))) 4711 goto IN_PLACE; /* Same size class. */ 4712 } else if (size <= small_max) { 4713 if (oldsize >= small_min && oldsize <= small_max && 4714 (QUANTUM_CEILING(size) >> opt_quantum_2pow) 4715 == (QUANTUM_CEILING(oldsize) >> opt_quantum_2pow)) 4716 goto IN_PLACE; /* Same size class. */ 4717 } else if (size <= bin_maxclass) { 4718 if (oldsize > small_max && oldsize <= bin_maxclass && 4719 pow2_ceil(size) == pow2_ceil(oldsize)) 4720 goto IN_PLACE; /* Same size class. */ 4721 } else if (oldsize > bin_maxclass && oldsize <= arena_maxclass) { 4722 assert(size > bin_maxclass); 4723 if (arena_ralloc_large(ptr, size, oldsize) == false) 4724 return (ptr); 4725 } 4726 4727 /* 4728 * If we get here, then size and oldsize are different enough that we 4729 * need to move the object. In that case, fall back to allocating new 4730 * space and copying. 4731 */ 4732 ret = arena_malloc(choose_arena(), size, false); 4733 if (ret == NULL) 4734 return (NULL); 4735 4736 /* Junk/zero-filling were already done by arena_malloc(). */ 4737 copysize = (size < oldsize) ? size : oldsize; 4738 #ifdef VM_COPY_MIN 4739 if (copysize >= VM_COPY_MIN) 4740 pages_copy(ret, ptr, copysize); 4741 else 4742 #endif 4743 memcpy(ret, ptr, copysize); 4744 idalloc(ptr); 4745 return (ret); 4746 IN_PLACE: 4747 #ifdef MALLOC_FILL 4748 if (opt_junk && size < oldsize) 4749 memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size); 4750 else if (opt_zero && size > oldsize) 4751 memset((void *)((uintptr_t)ptr + oldsize), 0, size - oldsize); 4752 #endif 4753 return (ptr); 4754 } 4755 4756 static inline void * 4757 iralloc(void *ptr, size_t size) 4758 { 4759 size_t oldsize; 4760 4761 assert(ptr != NULL); 4762 assert(size != 0); 4763 4764 oldsize = isalloc(ptr); 4765 4766 #ifndef MALLOC_VALGRIND 4767 if (size <= arena_maxclass) 4768 return (arena_ralloc(ptr, size, oldsize)); 4769 else 4770 return (huge_ralloc(ptr, size, oldsize)); 4771 #else 4772 /* 4773 * Valgrind does not provide a public interface for modifying an 4774 * existing allocation, so use malloc/memcpy/free instead. 4775 */ 4776 { 4777 void *ret = imalloc(size); 4778 if (ret != NULL) { 4779 if (oldsize < size) 4780 memcpy(ret, ptr, oldsize); 4781 else 4782 memcpy(ret, ptr, size); 4783 idalloc(ptr); 4784 } 4785 return (ret); 4786 } 4787 #endif 4788 } 4789 4790 static bool 4791 arena_new(arena_t *arena) 4792 { 4793 unsigned i; 4794 arena_bin_t *bin; 4795 size_t pow2_size, prev_run_size; 4796 4797 if (malloc_spin_init(&arena->lock)) 4798 return (true); 4799 4800 #ifdef MALLOC_STATS 4801 memset(&arena->stats, 0, sizeof(arena_stats_t)); 4802 #endif 4803 4804 arena->chunk_seq = 0; 4805 4806 /* Initialize chunks. */ 4807 arena_chunk_tree_dirty_new(&arena->chunks_dirty); 4808 arena->spare = NULL; 4809 4810 arena->ndirty = 0; 4811 4812 arena_avail_tree_new(&arena->runs_avail); 4813 4814 #ifdef MALLOC_BALANCE 4815 arena->contention = 0; 4816 #endif 4817 4818 /* Initialize bins. */ 4819 prev_run_size = pagesize; 4820 4821 /* (2^n)-spaced tiny bins. */ 4822 for (i = 0; i < ntbins; i++) { 4823 bin = &arena->bins[i]; 4824 bin->runcur = NULL; 4825 arena_run_tree_new(&bin->runs); 4826 4827 bin->reg_size = ((size_t)1 << (TINY_MIN_2POW + i)); 4828 4829 prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); 4830 4831 #ifdef MALLOC_STATS 4832 memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); 4833 #endif 4834 } 4835 4836 /* Quantum-spaced bins. */ 4837 for (; i < ntbins + nqbins; i++) { 4838 bin = &arena->bins[i]; 4839 bin->runcur = NULL; 4840 arena_run_tree_new(&bin->runs); 4841 4842 bin->reg_size = quantum * (i - ntbins + 1); 4843 4844 pow2_size = pow2_ceil(quantum * (i - ntbins + 1)); 4845 prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); 4846 4847 #ifdef MALLOC_STATS 4848 memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); 4849 #endif 4850 } 4851 4852 /* (2^n)-spaced sub-page bins. */ 4853 for (; i < ntbins + nqbins + nsbins; i++) { 4854 bin = &arena->bins[i]; 4855 bin->runcur = NULL; 4856 arena_run_tree_new(&bin->runs); 4857 4858 bin->reg_size = (small_max << (i - (ntbins + nqbins) + 1)); 4859 4860 prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); 4861 4862 #ifdef MALLOC_STATS 4863 memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); 4864 #endif 4865 } 4866 4867 #ifdef MALLOC_DEBUG 4868 arena->magic = ARENA_MAGIC; 4869 #endif 4870 4871 return (false); 4872 } 4873 4874 /* Create a new arena and insert it into the arenas array at index ind. */ 4875 static arena_t * 4876 arenas_extend(unsigned ind) 4877 { 4878 arena_t *ret; 4879 4880 /* Allocate enough space for trailing bins. */ 4881 ret = (arena_t *)base_alloc(sizeof(arena_t) 4882 + (sizeof(arena_bin_t) * (ntbins + nqbins + nsbins - 1))); 4883 if (ret != NULL && arena_new(ret) == false) { 4884 arenas[ind] = ret; 4885 return (ret); 4886 } 4887 /* Only reached if there is an OOM error. */ 4888 4889 /* 4890 * OOM here is quite inconvenient to propagate, since dealing with it 4891 * would require a check for failure in the fast path. Instead, punt 4892 * by using arenas[0]. In practice, this is an extremely unlikely 4893 * failure. 4894 */ 4895 _malloc_message(_getprogname(), 4896 ": (malloc) Error initializing arena\n", "", ""); 4897 if (opt_abort) 4898 abort(); 4899 4900 return (arenas[0]); 4901 } 4902 4903 /* 4904 * End arena. 4905 */ 4906 /******************************************************************************/ 4907 /* 4908 * Begin general internal functions. 4909 */ 4910 4911 static void * 4912 huge_malloc(size_t size, bool zero) 4913 { 4914 void *ret; 4915 size_t csize; 4916 #ifdef MALLOC_DECOMMIT 4917 size_t psize; 4918 #endif 4919 extent_node_t *node; 4920 4921 /* Allocate one or more contiguous chunks for this request. */ 4922 4923 csize = CHUNK_CEILING(size); 4924 if (csize == 0) { 4925 /* size is large enough to cause size_t wrap-around. */ 4926 return (NULL); 4927 } 4928 4929 /* Allocate an extent node with which to track the chunk. */ 4930 node = base_node_alloc(); 4931 if (node == NULL) 4932 return (NULL); 4933 4934 ret = chunk_alloc(csize, zero, true); 4935 if (ret == NULL) { 4936 base_node_dealloc(node); 4937 return (NULL); 4938 } 4939 4940 /* Insert node into huge. */ 4941 node->addr = ret; 4942 #ifdef MALLOC_DECOMMIT 4943 psize = PAGE_CEILING(size); 4944 node->size = psize; 4945 #else 4946 node->size = csize; 4947 #endif 4948 4949 malloc_mutex_lock(&huge_mtx); 4950 extent_tree_ad_insert(&huge, node); 4951 #ifdef MALLOC_STATS 4952 huge_nmalloc++; 4953 # ifdef MALLOC_DECOMMIT 4954 huge_allocated += psize; 4955 # else 4956 huge_allocated += csize; 4957 # endif 4958 #endif 4959 malloc_mutex_unlock(&huge_mtx); 4960 4961 #ifdef MALLOC_DECOMMIT 4962 if (csize - psize > 0) 4963 pages_decommit((void *)((uintptr_t)ret + psize), csize - psize); 4964 #endif 4965 4966 #ifdef MALLOC_DECOMMIT 4967 VALGRIND_MALLOCLIKE_BLOCK(ret, psize, 0, zero); 4968 #else 4969 VALGRIND_MALLOCLIKE_BLOCK(ret, csize, 0, zero); 4970 #endif 4971 4972 #ifdef MALLOC_FILL 4973 if (zero == false) { 4974 if (opt_junk) 4975 # ifdef MALLOC_DECOMMIT 4976 memset(ret, 0xa5, psize); 4977 # else 4978 memset(ret, 0xa5, csize); 4979 # endif 4980 else if (opt_zero) 4981 # ifdef MALLOC_DECOMMIT 4982 memset(ret, 0, psize); 4983 # else 4984 memset(ret, 0, csize); 4985 # endif 4986 } 4987 #endif 4988 4989 return (ret); 4990 } 4991 4992 /* Only handles large allocations that require more than chunk alignment. */ 4993 static void * 4994 huge_palloc(size_t alignment, size_t size) 4995 { 4996 void *ret; 4997 size_t alloc_size, chunk_size, offset; 4998 #ifdef MALLOC_DECOMMIT 4999 size_t psize; 5000 #endif 5001 extent_node_t *node; 5002 int pfd; 5003 5004 /* 5005 * This allocation requires alignment that is even larger than chunk 5006 * alignment. This means that huge_malloc() isn't good enough. 5007 * 5008 * Allocate almost twice as many chunks as are demanded by the size or 5009 * alignment, in order to assure the alignment can be achieved, then 5010 * unmap leading and trailing chunks. 5011 */ 5012 assert(alignment >= chunksize); 5013 5014 chunk_size = CHUNK_CEILING(size); 5015 5016 if (size >= alignment) 5017 alloc_size = chunk_size + alignment - chunksize; 5018 else 5019 alloc_size = (alignment << 1) - chunksize; 5020 5021 /* Allocate an extent node with which to track the chunk. */ 5022 node = base_node_alloc(); 5023 if (node == NULL) 5024 return (NULL); 5025 5026 /* 5027 * Windows requires that there be a 1:1 mapping between VM 5028 * allocation/deallocation operations. Therefore, take care here to 5029 * acquire the final result via one mapping operation. 5030 * 5031 * The MALLOC_PAGEFILE code also benefits from this mapping algorithm, 5032 * since it reduces the number of page files. 5033 */ 5034 #ifdef MALLOC_PAGEFILE 5035 if (opt_pagefile) { 5036 pfd = pagefile_init(size); 5037 if (pfd == -1) 5038 return (NULL); 5039 } else 5040 #endif 5041 pfd = -1; 5042 #ifdef JEMALLOC_USES_MAP_ALIGN 5043 ret = pages_map_align(chunk_size, pfd, alignment); 5044 #else 5045 do { 5046 void *over; 5047 5048 over = chunk_alloc(alloc_size, false, false); 5049 if (over == NULL) { 5050 base_node_dealloc(node); 5051 ret = NULL; 5052 goto RETURN; 5053 } 5054 5055 offset = (uintptr_t)over & (alignment - 1); 5056 assert((offset & chunksize_mask) == 0); 5057 assert(offset < alloc_size); 5058 ret = (void *)((uintptr_t)over + offset); 5059 chunk_dealloc(over, alloc_size); 5060 ret = pages_map(ret, chunk_size, pfd); 5061 /* 5062 * Failure here indicates a race with another thread, so try 5063 * again. 5064 */ 5065 } while (ret == NULL); 5066 #endif 5067 /* Insert node into huge. */ 5068 node->addr = ret; 5069 #ifdef MALLOC_DECOMMIT 5070 psize = PAGE_CEILING(size); 5071 node->size = psize; 5072 #else 5073 node->size = chunk_size; 5074 #endif 5075 5076 malloc_mutex_lock(&huge_mtx); 5077 extent_tree_ad_insert(&huge, node); 5078 #ifdef MALLOC_STATS 5079 huge_nmalloc++; 5080 # ifdef MALLOC_DECOMMIT 5081 huge_allocated += psize; 5082 # else 5083 huge_allocated += chunk_size; 5084 # endif 5085 #endif 5086 malloc_mutex_unlock(&huge_mtx); 5087 5088 #ifdef MALLOC_DECOMMIT 5089 if (chunk_size - psize > 0) { 5090 pages_decommit((void *)((uintptr_t)ret + psize), 5091 chunk_size - psize); 5092 } 5093 #endif 5094 5095 #ifdef MALLOC_DECOMMIT 5096 VALGRIND_MALLOCLIKE_BLOCK(ret, psize, 0, false); 5097 #else 5098 VALGRIND_MALLOCLIKE_BLOCK(ret, chunk_size, 0, false); 5099 #endif 5100 5101 #ifdef MALLOC_FILL 5102 if (opt_junk) 5103 # ifdef MALLOC_DECOMMIT 5104 memset(ret, 0xa5, psize); 5105 # else 5106 memset(ret, 0xa5, chunk_size); 5107 # endif 5108 else if (opt_zero) 5109 # ifdef MALLOC_DECOMMIT 5110 memset(ret, 0, psize); 5111 # else 5112 memset(ret, 0, chunk_size); 5113 # endif 5114 #endif 5115 5116 RETURN: 5117 #ifdef MALLOC_PAGEFILE 5118 if (pfd != -1) 5119 pagefile_close(pfd); 5120 #endif 5121 return (ret); 5122 } 5123 5124 static void * 5125 huge_ralloc(void *ptr, size_t size, size_t oldsize) 5126 { 5127 void *ret; 5128 size_t copysize; 5129 5130 /* Avoid moving the allocation if the size class would not change. */ 5131 5132 if (oldsize > arena_maxclass && 5133 CHUNK_CEILING(size) == CHUNK_CEILING(oldsize)) { 5134 #ifdef MALLOC_DECOMMIT 5135 size_t psize = PAGE_CEILING(size); 5136 #endif 5137 #ifdef MALLOC_FILL 5138 if (opt_junk && size < oldsize) { 5139 memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize 5140 - size); 5141 } 5142 #endif 5143 #ifdef MALLOC_DECOMMIT 5144 if (psize < oldsize) { 5145 extent_node_t *node, key; 5146 5147 pages_decommit((void *)((uintptr_t)ptr + psize), 5148 oldsize - psize); 5149 5150 /* Update recorded size. */ 5151 malloc_mutex_lock(&huge_mtx); 5152 key.addr = __DECONST(void *, ptr); 5153 node = extent_tree_ad_search(&huge, &key); 5154 assert(node != NULL); 5155 assert(node->size == oldsize); 5156 # ifdef MALLOC_STATS 5157 huge_allocated -= oldsize - psize; 5158 # endif 5159 node->size = psize; 5160 malloc_mutex_unlock(&huge_mtx); 5161 } else if (psize > oldsize) { 5162 extent_node_t *node, key; 5163 5164 pages_commit((void *)((uintptr_t)ptr + oldsize), 5165 psize - oldsize); 5166 5167 /* Update recorded size. */ 5168 malloc_mutex_lock(&huge_mtx); 5169 key.addr = __DECONST(void *, ptr); 5170 node = extent_tree_ad_search(&huge, &key); 5171 assert(node != NULL); 5172 assert(node->size == oldsize); 5173 # ifdef MALLOC_STATS 5174 huge_allocated += psize - oldsize; 5175 # endif 5176 node->size = psize; 5177 malloc_mutex_unlock(&huge_mtx); 5178 } 5179 #endif 5180 #ifdef MALLOC_FILL 5181 if (opt_zero && size > oldsize) { 5182 memset((void *)((uintptr_t)ptr + oldsize), 0, size 5183 - oldsize); 5184 } 5185 #endif 5186 return (ptr); 5187 } 5188 5189 /* 5190 * If we get here, then size and oldsize are different enough that we 5191 * need to use a different size class. In that case, fall back to 5192 * allocating new space and copying. 5193 */ 5194 ret = huge_malloc(size, false); 5195 if (ret == NULL) 5196 return (NULL); 5197 5198 copysize = (size < oldsize) ? size : oldsize; 5199 #ifdef VM_COPY_MIN 5200 if (copysize >= VM_COPY_MIN) 5201 pages_copy(ret, ptr, copysize); 5202 else 5203 #endif 5204 memcpy(ret, ptr, copysize); 5205 idalloc(ptr); 5206 return (ret); 5207 } 5208 5209 static void 5210 huge_dalloc(void *ptr) 5211 { 5212 extent_node_t *node, key; 5213 5214 malloc_mutex_lock(&huge_mtx); 5215 5216 /* Extract from tree of huge allocations. */ 5217 key.addr = ptr; 5218 node = extent_tree_ad_search(&huge, &key); 5219 assert(node != NULL); 5220 assert(node->addr == ptr); 5221 extent_tree_ad_remove(&huge, node); 5222 5223 #ifdef MALLOC_STATS 5224 huge_ndalloc++; 5225 huge_allocated -= node->size; 5226 #endif 5227 5228 malloc_mutex_unlock(&huge_mtx); 5229 5230 /* Unmap chunk. */ 5231 #ifdef MALLOC_FILL 5232 if (opt_junk) 5233 memset(node->addr, 0x5a, node->size); 5234 #endif 5235 #ifdef MALLOC_DECOMMIT 5236 chunk_dealloc(node->addr, CHUNK_CEILING(node->size)); 5237 #else 5238 chunk_dealloc(node->addr, node->size); 5239 #endif 5240 VALGRIND_FREELIKE_BLOCK(node->addr, 0); 5241 5242 base_node_dealloc(node); 5243 } 5244 5245 #ifdef MOZ_MEMORY_BSD 5246 static inline unsigned 5247 malloc_ncpus(void) 5248 { 5249 unsigned ret; 5250 int mib[2]; 5251 size_t len; 5252 5253 mib[0] = CTL_HW; 5254 mib[1] = HW_NCPU; 5255 len = sizeof(ret); 5256 if (sysctl(mib, 2, &ret, &len, (void *) 0, 0) == -1) { 5257 /* Error. */ 5258 return (1); 5259 } 5260 5261 return (ret); 5262 } 5263 #elif (defined(MOZ_MEMORY_LINUX)) 5264 #include <fcntl.h> 5265 5266 static inline unsigned 5267 malloc_ncpus(void) 5268 { 5269 unsigned ret; 5270 int fd, nread, column; 5271 char buf[1024]; 5272 static const char matchstr[] = "processor\t:"; 5273 int i; 5274 5275 /* 5276 * sysconf(3) would be the preferred method for determining the number 5277 * of CPUs, but it uses malloc internally, which causes untennable 5278 * recursion during malloc initialization. 5279 */ 5280 fd = open("/proc/cpuinfo", O_RDONLY); 5281 if (fd == -1) 5282 return (1); /* Error. */ 5283 /* 5284 * Count the number of occurrences of matchstr at the beginnings of 5285 * lines. This treats hyperthreaded CPUs as multiple processors. 5286 */ 5287 column = 0; 5288 ret = 0; 5289 while (true) { 5290 nread = read(fd, &buf, sizeof(buf)); 5291 if (nread <= 0) 5292 break; /* EOF or error. */ 5293 for (i = 0;i < nread;i++) { 5294 char c = buf[i]; 5295 if (c == '\n') 5296 column = 0; 5297 else if (column != -1) { 5298 if (c == matchstr[column]) { 5299 column++; 5300 if (column == sizeof(matchstr) - 1) { 5301 column = -1; 5302 ret++; 5303 } 5304 } else 5305 column = -1; 5306 } 5307 } 5308 } 5309 5310 if (ret == 0) 5311 ret = 1; /* Something went wrong in the parser. */ 5312 close(fd); 5313 5314 return (ret); 5315 } 5316 #elif (defined(MOZ_MEMORY_DARWIN)) 5317 #include <mach/mach_init.h> 5318 #include <mach/mach_host.h> 5319 5320 static inline unsigned 5321 malloc_ncpus(void) 5322 { 5323 kern_return_t error; 5324 natural_t n; 5325 processor_info_array_t pinfo; 5326 mach_msg_type_number_t pinfocnt; 5327 5328 error = host_processor_info(mach_host_self(), PROCESSOR_BASIC_INFO, 5329 &n, &pinfo, &pinfocnt); 5330 if (error != KERN_SUCCESS) 5331 return (1); /* Error. */ 5332 else 5333 return (n); 5334 } 5335 #elif (defined(MOZ_MEMORY_SOLARIS)) 5336 5337 static inline unsigned 5338 malloc_ncpus(void) 5339 { 5340 return sysconf(_SC_NPROCESSORS_ONLN); 5341 } 5342 #else 5343 static inline unsigned 5344 malloc_ncpus(void) 5345 { 5346 5347 /* 5348 * We lack a way to determine the number of CPUs on this platform, so 5349 * assume 1 CPU. 5350 */ 5351 return (1); 5352 } 5353 #endif 5354 5355 static void 5356 malloc_print_stats(void) 5357 { 5358 5359 if (opt_print_stats) { 5360 char s[UMAX2S_BUFSIZE]; 5361 _malloc_message("___ Begin malloc statistics ___\n", "", "", 5362 ""); 5363 _malloc_message("Assertions ", 5364 #ifdef NDEBUG 5365 "disabled", 5366 #else 5367 "enabled", 5368 #endif 5369 "\n", ""); 5370 _malloc_message("Boolean MALLOC_OPTIONS: ", 5371 opt_abort ? "A" : "a", "", ""); 5372 #ifdef MALLOC_FILL 5373 _malloc_message(opt_junk ? "J" : "j", "", "", ""); 5374 #endif 5375 #ifdef MALLOC_PAGEFILE 5376 _malloc_message(opt_pagefile ? "o" : "O", "", "", ""); 5377 #endif 5378 _malloc_message("P", "", "", ""); 5379 #ifdef MALLOC_UTRACE 5380 _malloc_message(opt_utrace ? "U" : "u", "", "", ""); 5381 #endif 5382 #ifdef MALLOC_SYSV 5383 _malloc_message(opt_sysv ? "V" : "v", "", "", ""); 5384 #endif 5385 #ifdef MALLOC_XMALLOC 5386 _malloc_message(opt_xmalloc ? "X" : "x", "", "", ""); 5387 #endif 5388 #ifdef MALLOC_FILL 5389 _malloc_message(opt_zero ? "Z" : "z", "", "", ""); 5390 #endif 5391 _malloc_message("\n", "", "", ""); 5392 5393 _malloc_message("CPUs: ", umax2s(ncpus, s), "\n", ""); 5394 _malloc_message("Max arenas: ", umax2s(narenas, s), "\n", ""); 5395 #ifdef MALLOC_BALANCE 5396 _malloc_message("Arena balance threshold: ", 5397 umax2s(opt_balance_threshold, s), "\n", ""); 5398 #endif 5399 _malloc_message("Pointer size: ", umax2s(sizeof(void *), s), 5400 "\n", ""); 5401 _malloc_message("Quantum size: ", umax2s(quantum, s), "\n", ""); 5402 _malloc_message("Max small size: ", umax2s(small_max, s), "\n", 5403 ""); 5404 _malloc_message("Max dirty pages per arena: ", 5405 umax2s(opt_dirty_max, s), "\n", ""); 5406 5407 _malloc_message("Chunk size: ", umax2s(chunksize, s), "", ""); 5408 _malloc_message(" (2^", umax2s(opt_chunk_2pow, s), ")\n", ""); 5409 5410 #ifdef MALLOC_STATS 5411 { 5412 size_t allocated, mapped; 5413 #ifdef MALLOC_BALANCE 5414 uint64_t nbalance = 0; 5415 #endif 5416 unsigned i; 5417 arena_t *arena; 5418 5419 /* Calculate and print allocated/mapped stats. */ 5420 5421 /* arenas. */ 5422 for (i = 0, allocated = 0; i < narenas; i++) { 5423 if (arenas[i] != NULL) { 5424 malloc_spin_lock(&arenas[i]->lock); 5425 allocated += 5426 arenas[i]->stats.allocated_small; 5427 allocated += 5428 arenas[i]->stats.allocated_large; 5429 #ifdef MALLOC_BALANCE 5430 nbalance += arenas[i]->stats.nbalance; 5431 #endif 5432 malloc_spin_unlock(&arenas[i]->lock); 5433 } 5434 } 5435 5436 /* huge/base. */ 5437 malloc_mutex_lock(&huge_mtx); 5438 allocated += huge_allocated; 5439 mapped = stats_chunks.curchunks * chunksize; 5440 malloc_mutex_unlock(&huge_mtx); 5441 5442 malloc_mutex_lock(&base_mtx); 5443 mapped += base_mapped; 5444 malloc_mutex_unlock(&base_mtx); 5445 5446 #ifdef MOZ_MEMORY_WINDOWS 5447 malloc_printf("Allocated: %lu, mapped: %lu\n", 5448 allocated, mapped); 5449 #else 5450 malloc_printf("Allocated: %zu, mapped: %zu\n", 5451 allocated, mapped); 5452 #endif 5453 5454 malloc_mutex_lock(&reserve_mtx); 5455 malloc_printf("Reserve: min " 5456 "cur max\n"); 5457 #ifdef MOZ_MEMORY_WINDOWS 5458 malloc_printf(" %12lu %12lu %12lu\n", 5459 CHUNK_CEILING(reserve_min) >> opt_chunk_2pow, 5460 reserve_cur >> opt_chunk_2pow, 5461 reserve_max >> opt_chunk_2pow); 5462 #else 5463 malloc_printf(" %12zu %12zu %12zu\n", 5464 CHUNK_CEILING(reserve_min) >> opt_chunk_2pow, 5465 reserve_cur >> opt_chunk_2pow, 5466 reserve_max >> opt_chunk_2pow); 5467 #endif 5468 malloc_mutex_unlock(&reserve_mtx); 5469 5470 #ifdef MALLOC_BALANCE 5471 malloc_printf("Arena balance reassignments: %llu\n", 5472 nbalance); 5473 #endif 5474 5475 /* Print chunk stats. */ 5476 { 5477 chunk_stats_t chunks_stats; 5478 5479 malloc_mutex_lock(&huge_mtx); 5480 chunks_stats = stats_chunks; 5481 malloc_mutex_unlock(&huge_mtx); 5482 5483 malloc_printf("chunks: nchunks " 5484 "highchunks curchunks\n"); 5485 malloc_printf(" %13llu%13lu%13lu\n", 5486 chunks_stats.nchunks, 5487 chunks_stats.highchunks, 5488 chunks_stats.curchunks); 5489 } 5490 5491 /* Print chunk stats. */ 5492 malloc_printf( 5493 "huge: nmalloc ndalloc allocated\n"); 5494 #ifdef MOZ_MEMORY_WINDOWS 5495 malloc_printf(" %12llu %12llu %12lu\n", 5496 huge_nmalloc, huge_ndalloc, huge_allocated); 5497 #else 5498 malloc_printf(" %12llu %12llu %12zu\n", 5499 huge_nmalloc, huge_ndalloc, huge_allocated); 5500 #endif 5501 /* Print stats for each arena. */ 5502 for (i = 0; i < narenas; i++) { 5503 arena = arenas[i]; 5504 if (arena != NULL) { 5505 malloc_printf( 5506 "\narenas[%u]:\n", i); 5507 malloc_spin_lock(&arena->lock); 5508 stats_print(arena); 5509 malloc_spin_unlock(&arena->lock); 5510 } 5511 } 5512 } 5513 #endif /* #ifdef MALLOC_STATS */ 5514 _malloc_message("--- End malloc statistics ---\n", "", "", ""); 5515 } 5516 } 5517 5518 /* 5519 * FreeBSD's pthreads implementation calls malloc(3), so the malloc 5520 * implementation has to take pains to avoid infinite recursion during 5521 * initialization. 5522 */ 5523 #if (defined(MOZ_MEMORY_WINDOWS) || defined(MOZ_MEMORY_DARWIN)) && !defined(MOZ_MEMORY_WINCE) 5524 #define malloc_init() false 5525 #else 5526 static inline bool 5527 malloc_init(void) 5528 { 5529 5530 if (malloc_initialized == false) 5531 return (malloc_init_hard()); 5532 5533 return (false); 5534 } 5535 #endif 5536 5537 #if !defined(MOZ_MEMORY_WINDOWS) || defined(MOZ_MEMORY_WINCE) 5538 static 5539 #endif 5540 bool 5541 je_malloc_init_hard(void) 5542 { 5543 unsigned i; 5544 char buf[PATH_MAX + 1]; 5545 const char *opts; 5546 long result; 5547 #ifndef MOZ_MEMORY_WINDOWS 5548 int linklen; 5549 #endif 5550 5551 #ifndef MOZ_MEMORY_WINDOWS 5552 malloc_mutex_lock(&init_lock); 5553 #endif 5554 5555 if (malloc_initialized) { 5556 /* 5557 * Another thread initialized the allocator before this one 5558 * acquired init_lock. 5559 */ 5560 #ifndef MOZ_MEMORY_WINDOWS 5561 malloc_mutex_unlock(&init_lock); 5562 #endif 5563 return (false); 5564 } 5565 5566 #ifdef MOZ_MEMORY_WINDOWS 5567 /* get a thread local storage index */ 5568 tlsIndex = TlsAlloc(); 5569 #endif 5570 5571 /* Get page size and number of CPUs */ 5572 #ifdef MOZ_MEMORY_WINDOWS 5573 { 5574 SYSTEM_INFO info; 5575 5576 GetSystemInfo(&info); 5577 result = info.dwPageSize; 5578 5579 pagesize = (unsigned) result; 5580 5581 ncpus = info.dwNumberOfProcessors; 5582 } 5583 #else 5584 ncpus = malloc_ncpus(); 5585 5586 result = sysconf(_SC_PAGESIZE); 5587 assert(result != -1); 5588 5589 pagesize = (unsigned) result; 5590 #endif 5591 5592 /* 5593 * We assume that pagesize is a power of 2 when calculating 5594 * pagesize_mask and pagesize_2pow. 5595 */ 5596 assert(((result - 1) & result) == 0); 5597 pagesize_mask = result - 1; 5598 pagesize_2pow = ffs((int)result) - 1; 5599 5600 #ifdef MALLOC_PAGEFILE 5601 /* 5602 * Determine where to create page files. It is insufficient to 5603 * unconditionally use P_tmpdir (typically "/tmp"), since for some 5604 * operating systems /tmp is a separate filesystem that is rather small. 5605 * Therefore prefer, in order, the following locations: 5606 * 5607 * 1) MALLOC_TMPDIR 5608 * 2) TMPDIR 5609 * 3) P_tmpdir 5610 */ 5611 { 5612 char *s; 5613 size_t slen; 5614 static const char suffix[] = "/jemalloc.XXXXXX"; 5615 5616 if ((s = getenv("MALLOC_TMPDIR")) == NULL && (s = 5617 getenv("TMPDIR")) == NULL) 5618 s = P_tmpdir; 5619 slen = strlen(s); 5620 if (slen + sizeof(suffix) > sizeof(pagefile_templ)) { 5621 _malloc_message(_getprogname(), 5622 ": (malloc) Page file path too long\n", 5623 "", ""); 5624 abort(); 5625 } 5626 memcpy(pagefile_templ, s, slen); 5627 memcpy(&pagefile_templ[slen], suffix, sizeof(suffix)); 5628 } 5629 #endif 5630 5631 for (i = 0; i < 3; i++) { 5632 unsigned j; 5633 5634 /* Get runtime configuration. */ 5635 switch (i) { 5636 case 0: 5637 #ifndef MOZ_MEMORY_WINDOWS 5638 if ((linklen = readlink("/etc/malloc.conf", buf, 5639 sizeof(buf) - 1)) != -1) { 5640 /* 5641 * Use the contents of the "/etc/malloc.conf" 5642 * symbolic link's name. 5643 */ 5644 buf[linklen] = '\0'; 5645 opts = buf; 5646 } else 5647 #endif 5648 { 5649 /* No configuration specified. */ 5650 buf[0] = '\0'; 5651 opts = buf; 5652 } 5653 break; 5654 case 1: 5655 if (issetugid() == 0 && (opts = 5656 getenv("MALLOC_OPTIONS")) != NULL) { 5657 /* 5658 * Do nothing; opts is already initialized to 5659 * the value of the MALLOC_OPTIONS environment 5660 * variable. 5661 */ 5662 } else { 5663 /* No configuration specified. */ 5664 buf[0] = '\0'; 5665 opts = buf; 5666 } 5667 break; 5668 case 2: 5669 if (_malloc_options != NULL) { 5670 /* 5671 * Use options that were compiled into the 5672 * program. 5673 */ 5674 opts = _malloc_options; 5675 } else { 5676 /* No configuration specified. */ 5677 buf[0] = '\0'; 5678 opts = buf; 5679 } 5680 break; 5681 default: 5682 /* NOTREACHED */ 5683 buf[0] = '\0'; 5684 opts = buf; 5685 assert(false); 5686 } 5687 5688 for (j = 0; opts[j] != '\0'; j++) { 5689 unsigned k, nreps; 5690 bool nseen; 5691 5692 /* Parse repetition count, if any. */ 5693 for (nreps = 0, nseen = false;; j++, nseen = true) { 5694 switch (opts[j]) { 5695 case '0': case '1': case '2': case '3': 5696 case '4': case '5': case '6': case '7': 5697 case '8': case '9': 5698 nreps *= 10; 5699 nreps += opts[j] - '0'; 5700 break; 5701 default: 5702 goto MALLOC_OUT; 5703 } 5704 } 5705 MALLOC_OUT: 5706 if (nseen == false) 5707 nreps = 1; 5708 5709 for (k = 0; k < nreps; k++) { 5710 switch (opts[j]) { 5711 case 'a': 5712 opt_abort = false; 5713 break; 5714 case 'A': 5715 opt_abort = true; 5716 break; 5717 case 'b': 5718 #ifdef MALLOC_BALANCE 5719 opt_balance_threshold >>= 1; 5720 #endif 5721 break; 5722 case 'B': 5723 #ifdef MALLOC_BALANCE 5724 if (opt_balance_threshold == 0) 5725 opt_balance_threshold = 1; 5726 else if ((opt_balance_threshold << 1) 5727 > opt_balance_threshold) 5728 opt_balance_threshold <<= 1; 5729 #endif 5730 break; 5731 case 'f': 5732 opt_dirty_max >>= 1; 5733 break; 5734 case 'F': 5735 if (opt_dirty_max == 0) 5736 opt_dirty_max = 1; 5737 else if ((opt_dirty_max << 1) != 0) 5738 opt_dirty_max <<= 1; 5739 break; 5740 case 'g': 5741 opt_reserve_range_lshift--; 5742 break; 5743 case 'G': 5744 opt_reserve_range_lshift++; 5745 break; 5746 #ifdef MALLOC_FILL 5747 case 'j': 5748 opt_junk = false; 5749 break; 5750 case 'J': 5751 opt_junk = true; 5752 break; 5753 #endif 5754 case 'k': 5755 /* 5756 * Chunks always require at least one 5757 * header page, so chunks can never be 5758 * smaller than two pages. 5759 */ 5760 if (opt_chunk_2pow > pagesize_2pow + 1) 5761 opt_chunk_2pow--; 5762 break; 5763 case 'K': 5764 if (opt_chunk_2pow + 1 < 5765 (sizeof(size_t) << 3)) 5766 opt_chunk_2pow++; 5767 break; 5768 case 'n': 5769 opt_narenas_lshift--; 5770 break; 5771 case 'N': 5772 opt_narenas_lshift++; 5773 break; 5774 #ifdef MALLOC_PAGEFILE 5775 case 'o': 5776 /* Do not over-commit. */ 5777 opt_pagefile = true; 5778 break; 5779 case 'O': 5780 /* Allow over-commit. */ 5781 opt_pagefile = false; 5782 break; 5783 #endif 5784 case 'p': 5785 opt_print_stats = false; 5786 break; 5787 case 'P': 5788 opt_print_stats = true; 5789 break; 5790 case 'q': 5791 if (opt_quantum_2pow > QUANTUM_2POW_MIN) 5792 opt_quantum_2pow--; 5793 break; 5794 case 'Q': 5795 if (opt_quantum_2pow < pagesize_2pow - 5796 1) 5797 opt_quantum_2pow++; 5798 break; 5799 case 'r': 5800 opt_reserve_min_lshift--; 5801 break; 5802 case 'R': 5803 opt_reserve_min_lshift++; 5804 break; 5805 case 's': 5806 if (opt_small_max_2pow > 5807 QUANTUM_2POW_MIN) 5808 opt_small_max_2pow--; 5809 break; 5810 case 'S': 5811 if (opt_small_max_2pow < pagesize_2pow 5812 - 1) 5813 opt_small_max_2pow++; 5814 break; 5815 #ifdef MALLOC_UTRACE 5816 case 'u': 5817 opt_utrace = false; 5818 break; 5819 case 'U': 5820 opt_utrace = true; 5821 break; 5822 #endif 5823 #ifdef MALLOC_SYSV 5824 case 'v': 5825 opt_sysv = false; 5826 break; 5827 case 'V': 5828 opt_sysv = true; 5829 break; 5830 #endif 5831 #ifdef MALLOC_XMALLOC 5832 case 'x': 5833 opt_xmalloc = false; 5834 break; 5835 case 'X': 5836 opt_xmalloc = true; 5837 break; 5838 #endif 5839 #ifdef MALLOC_FILL 5840 case 'z': 5841 opt_zero = false; 5842 break; 5843 case 'Z': 5844 opt_zero = true; 5845 break; 5846 #endif 5847 default: { 5848 char cbuf[2]; 5849 5850 cbuf[0] = opts[j]; 5851 cbuf[1] = '\0'; 5852 _malloc_message(_getprogname(), 5853 ": (malloc) Unsupported character " 5854 "in malloc options: '", cbuf, 5855 "'\n"); 5856 } 5857 } 5858 } 5859 } 5860 } 5861 5862 /* Take care to call atexit() only once. */ 5863 if (opt_print_stats) { 5864 #ifndef MOZ_MEMORY_WINDOWS 5865 /* Print statistics at exit. */ 5866 atexit(malloc_print_stats); 5867 #endif 5868 } 5869 5870 #if (!defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN)) 5871 /* Prevent potential deadlock on malloc locks after fork. */ 5872 pthread_atfork(_malloc_prefork, _malloc_postfork, _malloc_postfork); 5873 #endif 5874 5875 /* Set variables according to the value of opt_small_max_2pow. */ 5876 if (opt_small_max_2pow < opt_quantum_2pow) 5877 opt_small_max_2pow = opt_quantum_2pow; 5878 small_max = ((size_t)1 << opt_small_max_2pow); 5879 5880 /* Set bin-related variables. */ 5881 bin_maxclass = (pagesize >> 1); 5882 assert(opt_quantum_2pow >= TINY_MIN_2POW); 5883 ntbins = opt_quantum_2pow - TINY_MIN_2POW; 5884 assert(ntbins <= opt_quantum_2pow); 5885 nqbins = (small_max >> opt_quantum_2pow); 5886 nsbins = pagesize_2pow - opt_small_max_2pow - 1; 5887 5888 /* Set variables according to the value of opt_quantum_2pow. */ 5889 quantum = ((size_t)1 << opt_quantum_2pow); 5890 quantum_mask = quantum - 1; 5891 if (ntbins > 0) 5892 small_min = (quantum >> 1) + 1; 5893 else 5894 small_min = 1; 5895 assert(small_min <= quantum); 5896 5897 /* Set variables according to the value of opt_chunk_2pow. */ 5898 chunksize = ((size_t)1 << opt_chunk_2pow); 5899 chunksize_mask = chunksize - 1; 5900 chunk_npages = (chunksize >> pagesize_2pow); 5901 { 5902 size_t header_size; 5903 5904 /* 5905 * Compute the header size such that it is large 5906 * enough to contain the page map and enough nodes for the 5907 * worst case: one node per non-header page plus one extra for 5908 * situations where we briefly have one more node allocated 5909 * than we will need. 5910 */ 5911 header_size = sizeof(arena_chunk_t) + 5912 (sizeof(arena_chunk_map_t) * (chunk_npages - 1)); 5913 arena_chunk_header_npages = (header_size >> pagesize_2pow) + 5914 ((header_size & pagesize_mask) != 0); 5915 } 5916 arena_maxclass = chunksize - (arena_chunk_header_npages << 5917 pagesize_2pow); 5918 5919 #ifdef JEMALLOC_USES_MAP_ALIGN 5920 /* 5921 * When using MAP_ALIGN, the alignment parameter must be a power of two 5922 * multiple of the system pagesize, or mmap will fail. 5923 */ 5924 assert((chunksize % pagesize) == 0); 5925 assert((1 << (ffs(chunksize / pagesize) - 1)) == (chunksize/pagesize)); 5926 #endif 5927 5928 UTRACE(0, 0, 0); 5929 5930 #ifdef MALLOC_STATS 5931 memset(&stats_chunks, 0, sizeof(chunk_stats_t)); 5932 #endif 5933 5934 /* Various sanity checks that regard configuration. */ 5935 assert(quantum >= sizeof(void *)); 5936 assert(quantum <= pagesize); 5937 assert(chunksize >= pagesize); 5938 assert(quantum * 4 <= chunksize); 5939 5940 /* Initialize chunks data. */ 5941 malloc_mutex_init(&huge_mtx); 5942 extent_tree_ad_new(&huge); 5943 #ifdef MALLOC_STATS 5944 huge_nmalloc = 0; 5945 huge_ndalloc = 0; 5946 huge_allocated = 0; 5947 #endif 5948 5949 /* Initialize base allocation data structures. */ 5950 #ifdef MALLOC_STATS 5951 base_mapped = 0; 5952 #endif 5953 base_nodes = NULL; 5954 base_reserve_regs = NULL; 5955 malloc_mutex_init(&base_mtx); 5956 5957 #ifdef MOZ_MEMORY_NARENAS_DEFAULT_ONE 5958 narenas = 1; 5959 #else 5960 if (ncpus > 1) { 5961 /* 5962 * For SMP systems, create four times as many arenas as there 5963 * are CPUs by default. 5964 */ 5965 opt_narenas_lshift += 2; 5966 } 5967 5968 /* Determine how many arenas to use. */ 5969 narenas = ncpus; 5970 #endif 5971 if (opt_narenas_lshift > 0) { 5972 if ((narenas << opt_narenas_lshift) > narenas) 5973 narenas <<= opt_narenas_lshift; 5974 /* 5975 * Make sure not to exceed the limits of what base_alloc() can 5976 * handle. 5977 */ 5978 if (narenas * sizeof(arena_t *) > chunksize) 5979 narenas = chunksize / sizeof(arena_t *); 5980 } else if (opt_narenas_lshift < 0) { 5981 if ((narenas >> -opt_narenas_lshift) < narenas) 5982 narenas >>= -opt_narenas_lshift; 5983 /* Make sure there is at least one arena. */ 5984 if (narenas == 0) 5985 narenas = 1; 5986 } 5987 #ifdef MALLOC_BALANCE 5988 assert(narenas != 0); 5989 for (narenas_2pow = 0; 5990 (narenas >> (narenas_2pow + 1)) != 0; 5991 narenas_2pow++); 5992 #endif 5993 5994 #ifdef NO_TLS 5995 if (narenas > 1) { 5996 static const unsigned primes[] = {1, 3, 5, 7, 11, 13, 17, 19, 5997 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 5998 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 5999 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 6000 223, 227, 229, 233, 239, 241, 251, 257, 263}; 6001 unsigned nprimes, parenas; 6002 6003 /* 6004 * Pick a prime number of hash arenas that is more than narenas 6005 * so that direct hashing of pthread_self() pointers tends to 6006 * spread allocations evenly among the arenas. 6007 */ 6008 assert((narenas & 1) == 0); /* narenas must be even. */ 6009 nprimes = (sizeof(primes) >> SIZEOF_INT_2POW); 6010 parenas = primes[nprimes - 1]; /* In case not enough primes. */ 6011 for (i = 1; i < nprimes; i++) { 6012 if (primes[i] > narenas) { 6013 parenas = primes[i]; 6014 break; 6015 } 6016 } 6017 narenas = parenas; 6018 } 6019 #endif 6020 6021 #ifndef NO_TLS 6022 # ifndef MALLOC_BALANCE 6023 next_arena = 0; 6024 # endif 6025 #endif 6026 6027 /* Allocate and initialize arenas. */ 6028 arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas); 6029 if (arenas == NULL) { 6030 #ifndef MOZ_MEMORY_WINDOWS 6031 malloc_mutex_unlock(&init_lock); 6032 #endif 6033 return (true); 6034 } 6035 /* 6036 * Zero the array. In practice, this should always be pre-zeroed, 6037 * since it was just mmap()ed, but let's be sure. 6038 */ 6039 memset(arenas, 0, sizeof(arena_t *) * narenas); 6040 6041 /* 6042 * Initialize one arena here. The rest are lazily created in 6043 * choose_arena_hard(). 6044 */ 6045 arenas_extend(0); 6046 if (arenas[0] == NULL) { 6047 #ifndef MOZ_MEMORY_WINDOWS 6048 malloc_mutex_unlock(&init_lock); 6049 #endif 6050 return (true); 6051 } 6052 #ifndef NO_TLS 6053 /* 6054 * Assign the initial arena to the initial thread, in order to avoid 6055 * spurious creation of an extra arena if the application switches to 6056 * threaded mode. 6057 */ 6058 #ifdef MOZ_MEMORY_WINDOWS 6059 TlsSetValue(tlsIndex, arenas[0]); 6060 #else 6061 arenas_map = arenas[0]; 6062 #endif 6063 #endif 6064 6065 /* 6066 * Seed here for the initial thread, since choose_arena_hard() is only 6067 * called for other threads. The seed value doesn't really matter. 6068 */ 6069 #ifdef MALLOC_BALANCE 6070 SPRN(balance, 42); 6071 #endif 6072 6073 malloc_spin_init(&arenas_lock); 6074 6075 #ifdef MALLOC_VALIDATE 6076 chunk_rtree = malloc_rtree_new((SIZEOF_PTR << 3) - opt_chunk_2pow); 6077 if (chunk_rtree == NULL) 6078 return (true); 6079 #endif 6080 6081 /* 6082 * Configure and initialize the memory reserve. This needs to happen 6083 * late during initialization, since chunks are allocated. 6084 */ 6085 malloc_mutex_init(&reserve_mtx); 6086 reserve_min = 0; 6087 reserve_cur = 0; 6088 reserve_max = 0; 6089 if (RESERVE_RANGE_2POW_DEFAULT + opt_reserve_range_lshift >= 0) { 6090 reserve_max += chunksize << (RESERVE_RANGE_2POW_DEFAULT + 6091 opt_reserve_range_lshift); 6092 } 6093 ql_new(&reserve_regs); 6094 reserve_seq = 0; 6095 extent_tree_szad_new(&reserve_chunks_szad); 6096 extent_tree_ad_new(&reserve_chunks_ad); 6097 if (RESERVE_MIN_2POW_DEFAULT + opt_reserve_min_lshift >= 0) { 6098 reserve_min_set(chunksize << (RESERVE_MIN_2POW_DEFAULT + 6099 opt_reserve_min_lshift)); 6100 } 6101 6102 malloc_initialized = true; 6103 #ifndef MOZ_MEMORY_WINDOWS 6104 malloc_mutex_unlock(&init_lock); 6105 #endif 6106 return (false); 6107 } 6108 6109 /* XXX Why not just expose malloc_print_stats()? */ 6110 #ifdef MOZ_MEMORY_WINDOWS 6111 void 6112 malloc_shutdown() 6113 { 6114 6115 malloc_print_stats(); 6116 } 6117 #endif 6118 6119 /* 6120 * End general internal functions. 6121 */ 6122 /******************************************************************************/ 6123 /* 6124 * Begin malloc(3)-compatible functions. 6125 */ 6126 6127 /* 6128 * Inline the standard malloc functions if they are being subsumed by Darwin's 6129 * zone infrastructure. 6130 */ 6131 #ifdef MOZ_MEMORY_DARWIN 6132 # define ZONE_INLINE inline 6133 #else 6134 # define ZONE_INLINE 6135 #endif 6136 6137 /* Mangle standard interfaces on Darwin and Windows CE, 6138 in order to avoid linking problems. */ 6139 #ifdef MOZ_MEMORY_DARWIN 6140 #define DONT_OVERRIDE_LIBC 6141 #endif 6142 6143 #if defined(DONT_OVERRIDE_LIBC) 6144 #define malloc(a) je_malloc(a) 6145 #define valloc(a) je_valloc(a) 6146 #define calloc(a, b) je_calloc(a, b) 6147 #define realloc(a, b) je_realloc(a, b) 6148 #define free(a) je_free(a) 6149 #define _msize(p) je_msize(p) 6150 #define _recalloc(p, n, s) je_recalloc(p, n, s) 6151 #define memalign(a, s) je_memalign(a, s) 6152 #endif 6153 6154 ZONE_INLINE 6155 void * 6156 malloc(size_t size) 6157 { 6158 void *ret; 6159 6160 if (malloc_init()) { 6161 ret = NULL; 6162 goto RETURN; 6163 } 6164 6165 if (size == 0) { 6166 #ifdef MALLOC_SYSV 6167 if (opt_sysv == false) 6168 #endif 6169 size = 1; 6170 #ifdef MALLOC_SYSV 6171 else { 6172 ret = NULL; 6173 goto RETURN; 6174 } 6175 #endif 6176 } 6177 6178 ret = imalloc(size); 6179 6180 RETURN: 6181 if (ret == NULL) { 6182 #ifdef MALLOC_XMALLOC 6183 if (opt_xmalloc) { 6184 _malloc_message(_getprogname(), 6185 ": (malloc) Error in malloc(): out of memory\n", "", 6186 ""); 6187 abort(); 6188 } 6189 #endif 6190 errno = ENOMEM; 6191 } 6192 6193 UTRACE(0, size, ret); 6194 return (ret); 6195 } 6196 6197 #ifdef MOZ_MEMORY_SOLARIS 6198 # ifdef __SUNPRO_C 6199 void * 6200 memalign(size_t alignment, size_t size); 6201 #pragma no_inline(memalign) 6202 # elif (defined(__GNU_C__)) 6203 __attribute__((noinline)) 6204 # endif 6205 #else 6206 inline 6207 #endif 6208 void * 6209 memalign(size_t alignment, size_t size) 6210 { 6211 void *ret; 6212 6213 assert(((alignment - 1) & alignment) == 0 && alignment >= 6214 sizeof(void *)); 6215 6216 if (malloc_init()) { 6217 ret = NULL; 6218 goto RETURN; 6219 } 6220 6221 ret = ipalloc(alignment, size); 6222 6223 RETURN: 6224 #ifdef MALLOC_XMALLOC 6225 if (opt_xmalloc && ret == NULL) { 6226 _malloc_message(_getprogname(), 6227 ": (malloc) Error in memalign(): out of memory\n", "", ""); 6228 abort(); 6229 } 6230 #endif 6231 UTRACE(0, size, ret); 6232 return (ret); 6233 } 6234 6235 ZONE_INLINE 6236 int 6237 posix_memalign(void **memptr, size_t alignment, size_t size) 6238 { 6239 void *result; 6240 6241 /* Make sure that alignment is a large enough power of 2. */ 6242 if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void *)) { 6243 #ifdef MALLOC_XMALLOC 6244 if (opt_xmalloc) { 6245 _malloc_message(_getprogname(), 6246 ": (malloc) Error in posix_memalign(): " 6247 "invalid alignment\n", "", ""); 6248 abort(); 6249 } 6250 #endif 6251 return (EINVAL); 6252 } 6253 6254 #ifdef MOZ_MEMORY_DARWIN 6255 result = moz_memalign(alignment, size); 6256 #else 6257 result = memalign(alignment, size); 6258 #endif 6259 if (result == NULL) 6260 return (ENOMEM); 6261 6262 *memptr = result; 6263 return (0); 6264 } 6265 6266 ZONE_INLINE 6267 void * 6268 valloc(size_t size) 6269 { 6270 #ifdef MOZ_MEMORY_DARWIN 6271 return (moz_memalign(pagesize, size)); 6272 #else 6273 return (memalign(pagesize, size)); 6274 #endif 6275 } 6276 6277 ZONE_INLINE 6278 void * 6279 calloc(size_t num, size_t size) 6280 { 6281 void *ret; 6282 size_t num_size; 6283 6284 if (malloc_init()) { 6285 num_size = 0; 6286 ret = NULL; 6287 goto RETURN; 6288 } 6289 6290 num_size = num * size; 6291 if (num_size == 0) { 6292 #ifdef MALLOC_SYSV 6293 if ((opt_sysv == false) && ((num == 0) || (size == 0))) 6294 #endif 6295 num_size = 1; 6296 #ifdef MALLOC_SYSV 6297 else { 6298 ret = NULL; 6299 goto RETURN; 6300 } 6301 #endif 6302 /* 6303 * Try to avoid division here. We know that it isn't possible to 6304 * overflow during multiplication if neither operand uses any of the 6305 * most significant half of the bits in a size_t. 6306 */ 6307 } else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2))) 6308 && (num_size / size != num)) { 6309 /* size_t overflow. */ 6310 ret = NULL; 6311 goto RETURN; 6312 } 6313 6314 ret = icalloc(num_size); 6315 6316 RETURN: 6317 if (ret == NULL) { 6318 #ifdef MALLOC_XMALLOC 6319 if (opt_xmalloc) { 6320 _malloc_message(_getprogname(), 6321 ": (malloc) Error in calloc(): out of memory\n", "", 6322 ""); 6323 abort(); 6324 } 6325 #endif 6326 errno = ENOMEM; 6327 } 6328 6329 UTRACE(0, num_size, ret); 6330 return (ret); 6331 } 6332 6333 ZONE_INLINE 6334 void * 6335 realloc(void *ptr, size_t size) 6336 { 6337 void *ret; 6338 6339 if (size == 0) { 6340 #ifdef MALLOC_SYSV 6341 if (opt_sysv == false) 6342 #endif 6343 size = 1; 6344 #ifdef MALLOC_SYSV 6345 else { 6346 if (ptr != NULL) 6347 idalloc(ptr); 6348 ret = NULL; 6349 goto RETURN; 6350 } 6351 #endif 6352 } 6353 6354 if (ptr != NULL) { 6355 assert(malloc_initialized); 6356 6357 ret = iralloc(ptr, size); 6358 6359 if (ret == NULL) { 6360 #ifdef MALLOC_XMALLOC 6361 if (opt_xmalloc) { 6362 _malloc_message(_getprogname(), 6363 ": (malloc) Error in realloc(): out of " 6364 "memory\n", "", ""); 6365 abort(); 6366 } 6367 #endif 6368 errno = ENOMEM; 6369 } 6370 } else { 6371 if (malloc_init()) 6372 ret = NULL; 6373 else 6374 ret = imalloc(size); 6375 6376 if (ret == NULL) { 6377 #ifdef MALLOC_XMALLOC 6378 if (opt_xmalloc) { 6379 _malloc_message(_getprogname(), 6380 ": (malloc) Error in realloc(): out of " 6381 "memory\n", "", ""); 6382 abort(); 6383 } 6384 #endif 6385 errno = ENOMEM; 6386 } 6387 } 6388 6389 #ifdef MALLOC_SYSV 6390 RETURN: 6391 #endif 6392 UTRACE(ptr, size, ret); 6393 return (ret); 6394 } 6395 6396 ZONE_INLINE 6397 void 6398 free(void *ptr) 6399 { 6400 6401 UTRACE(ptr, 0, 0); 6402 if (ptr != NULL) { 6403 assert(malloc_initialized); 6404 6405 idalloc(ptr); 6406 } 6407 } 6408 6409 /* 6410 * End malloc(3)-compatible functions. 6411 */ 6412 /******************************************************************************/ 6413 /* 6414 * Begin non-standard functions. 6415 */ 6416 6417 size_t 6418 malloc_usable_size(const void *ptr) 6419 { 6420 6421 #ifdef MALLOC_VALIDATE 6422 return (isalloc_validate(ptr)); 6423 #else 6424 assert(ptr != NULL); 6425 6426 return (isalloc(ptr)); 6427 #endif 6428 } 6429 6430 void 6431 jemalloc_stats(jemalloc_stats_t *stats) 6432 { 6433 size_t i; 6434 6435 assert(stats != NULL); 6436 6437 /* 6438 * Gather runtime settings. 6439 */ 6440 stats->opt_abort = opt_abort; 6441 stats->opt_junk = 6442 #ifdef MALLOC_FILL 6443 opt_junk ? true : 6444 #endif 6445 false; 6446 stats->opt_utrace = 6447 #ifdef MALLOC_UTRACE 6448 opt_utrace ? true : 6449 #endif 6450 false; 6451 stats->opt_sysv = 6452 #ifdef MALLOC_SYSV 6453 opt_sysv ? true : 6454 #endif 6455 false; 6456 stats->opt_xmalloc = 6457 #ifdef MALLOC_XMALLOC 6458 opt_xmalloc ? true : 6459 #endif 6460 false; 6461 stats->opt_zero = 6462 #ifdef MALLOC_FILL 6463 opt_zero ? true : 6464 #endif 6465 false; 6466 stats->narenas = narenas; 6467 stats->balance_threshold = 6468 #ifdef MALLOC_BALANCE 6469 opt_balance_threshold 6470 #else 6471 SIZE_T_MAX 6472 #endif 6473 ; 6474 stats->quantum = quantum; 6475 stats->small_max = small_max; 6476 stats->large_max = arena_maxclass; 6477 stats->chunksize = chunksize; 6478 stats->dirty_max = opt_dirty_max; 6479 6480 malloc_mutex_lock(&reserve_mtx); 6481 stats->reserve_min = reserve_min; 6482 stats->reserve_max = reserve_max; 6483 stats->reserve_cur = reserve_cur; 6484 malloc_mutex_unlock(&reserve_mtx); 6485 6486 /* 6487 * Gather current memory usage statistics. 6488 */ 6489 stats->mapped = 0; 6490 stats->committed = 0; 6491 stats->allocated = 0; 6492 stats->dirty = 0; 6493 6494 /* Get huge mapped/allocated. */ 6495 malloc_mutex_lock(&huge_mtx); 6496 stats->mapped += stats_chunks.curchunks * chunksize; 6497 #ifdef MALLOC_DECOMMIT 6498 stats->committed += huge_allocated; 6499 #endif 6500 stats->allocated += huge_allocated; 6501 malloc_mutex_unlock(&huge_mtx); 6502 6503 /* Get base mapped. */ 6504 malloc_mutex_lock(&base_mtx); 6505 stats->mapped += base_mapped; 6506 #ifdef MALLOC_DECOMMIT 6507 stats->committed += base_mapped; 6508 #endif 6509 malloc_mutex_unlock(&base_mtx); 6510 6511 /* Iterate over arenas and their chunks. */ 6512 for (i = 0; i < narenas; i++) { 6513 arena_t *arena = arenas[i]; 6514 if (arena != NULL) { 6515 arena_chunk_t *chunk; 6516 6517 malloc_spin_lock(&arena->lock); 6518 stats->allocated += arena->stats.allocated_small; 6519 stats->allocated += arena->stats.allocated_large; 6520 #ifdef MALLOC_DECOMMIT 6521 rb_foreach_begin(arena_chunk_t, link_dirty, 6522 &arena->chunks_dirty, chunk) { 6523 size_t j; 6524 6525 for (j = 0; j < chunk_npages; j++) { 6526 if ((chunk->map[j].bits & 6527 CHUNK_MAP_DECOMMITTED) == 0) 6528 stats->committed += pagesize; 6529 } 6530 } rb_foreach_end(arena_chunk_t, link_dirty, 6531 &arena->chunks_dirty, chunk) 6532 #endif 6533 stats->dirty += (arena->ndirty << pagesize_2pow); 6534 malloc_spin_unlock(&arena->lock); 6535 } 6536 } 6537 6538 #ifndef MALLOC_DECOMMIT 6539 stats->committed = stats->mapped; 6540 #endif 6541 } 6542 6543 void * 6544 xmalloc(size_t size) 6545 { 6546 void *ret; 6547 6548 if (malloc_init()) 6549 reserve_fail(size, "xmalloc"); 6550 6551 if (size == 0) { 6552 #ifdef MALLOC_SYSV 6553 if (opt_sysv == false) 6554 #endif 6555 size = 1; 6556 #ifdef MALLOC_SYSV 6557 else { 6558 _malloc_message(_getprogname(), 6559 ": (malloc) Error in xmalloc(): ", 6560 "invalid size 0", "\n"); 6561 abort(); 6562 } 6563 #endif 6564 } 6565 6566 ret = imalloc(size); 6567 if (ret == NULL) { 6568 uint64_t seq = 0; 6569 6570 do { 6571 seq = reserve_crit(size, "xmalloc", seq); 6572 ret = imalloc(size); 6573 } while (ret == NULL); 6574 } 6575 6576 UTRACE(0, size, ret); 6577 return (ret); 6578 } 6579 6580 void * 6581 xcalloc(size_t num, size_t size) 6582 { 6583 void *ret; 6584 size_t num_size; 6585 6586 num_size = num * size; 6587 if (malloc_init()) 6588 reserve_fail(num_size, "xcalloc"); 6589 6590 if (num_size == 0) { 6591 #ifdef MALLOC_SYSV 6592 if ((opt_sysv == false) && ((num == 0) || (size == 0))) 6593 #endif 6594 num_size = 1; 6595 #ifdef MALLOC_SYSV 6596 else { 6597 _malloc_message(_getprogname(), 6598 ": (malloc) Error in xcalloc(): ", 6599 "invalid size 0", "\n"); 6600 abort(); 6601 } 6602 #endif 6603 /* 6604 * Try to avoid division here. We know that it isn't possible to 6605 * overflow during multiplication if neither operand uses any of the 6606 * most significant half of the bits in a size_t. 6607 */ 6608 } else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2))) 6609 && (num_size / size != num)) { 6610 /* size_t overflow. */ 6611 _malloc_message(_getprogname(), 6612 ": (malloc) Error in xcalloc(): ", 6613 "size overflow", "\n"); 6614 abort(); 6615 } 6616 6617 ret = icalloc(num_size); 6618 if (ret == NULL) { 6619 uint64_t seq = 0; 6620 6621 do { 6622 seq = reserve_crit(num_size, "xcalloc", seq); 6623 ret = icalloc(num_size); 6624 } while (ret == NULL); 6625 } 6626 6627 UTRACE(0, num_size, ret); 6628 return (ret); 6629 } 6630 6631 void * 6632 xrealloc(void *ptr, size_t size) 6633 { 6634 void *ret; 6635 6636 if (size == 0) { 6637 #ifdef MALLOC_SYSV 6638 if (opt_sysv == false) 6639 #endif 6640 size = 1; 6641 #ifdef MALLOC_SYSV 6642 else { 6643 if (ptr != NULL) 6644 idalloc(ptr); 6645 _malloc_message(_getprogname(), 6646 ": (malloc) Error in xrealloc(): ", 6647 "invalid size 0", "\n"); 6648 abort(); 6649 } 6650 #endif 6651 } 6652 6653 if (ptr != NULL) { 6654 assert(malloc_initialized); 6655 6656 ret = iralloc(ptr, size); 6657 if (ret == NULL) { 6658 uint64_t seq = 0; 6659 6660 do { 6661 seq = reserve_crit(size, "xrealloc", seq); 6662 ret = iralloc(ptr, size); 6663 } while (ret == NULL); 6664 } 6665 } else { 6666 if (malloc_init()) 6667 reserve_fail(size, "xrealloc"); 6668 6669 ret = imalloc(size); 6670 if (ret == NULL) { 6671 uint64_t seq = 0; 6672 6673 do { 6674 seq = reserve_crit(size, "xrealloc", seq); 6675 ret = imalloc(size); 6676 } while (ret == NULL); 6677 } 6678 } 6679 6680 UTRACE(ptr, size, ret); 6681 return (ret); 6682 } 6683 6684 void * 6685 xmemalign(size_t alignment, size_t size) 6686 { 6687 void *ret; 6688 6689 assert(((alignment - 1) & alignment) == 0 && alignment >= 6690 sizeof(void *)); 6691 6692 if (malloc_init()) 6693 reserve_fail(size, "xmemalign"); 6694 6695 ret = ipalloc(alignment, size); 6696 if (ret == NULL) { 6697 uint64_t seq = 0; 6698 6699 do { 6700 seq = reserve_crit(size, "xmemalign", seq); 6701 ret = ipalloc(alignment, size); 6702 } while (ret == NULL); 6703 } 6704 6705 UTRACE(0, size, ret); 6706 return (ret); 6707 } 6708 6709 static void 6710 reserve_shrink(void) 6711 { 6712 extent_node_t *node; 6713 6714 assert(reserve_cur > reserve_max); 6715 #ifdef MALLOC_DEBUG 6716 { 6717 extent_node_t *node; 6718 size_t reserve_size; 6719 6720 reserve_size = 0; 6721 rb_foreach_begin(extent_node_t, link_szad, &reserve_chunks_szad, 6722 node) { 6723 reserve_size += node->size; 6724 } rb_foreach_end(extent_node_t, link_szad, &reserve_chunks_szad, 6725 node) 6726 assert(reserve_size == reserve_cur); 6727 6728 reserve_size = 0; 6729 rb_foreach_begin(extent_node_t, link_ad, &reserve_chunks_ad, 6730 node) { 6731 reserve_size += node->size; 6732 } rb_foreach_end(extent_node_t, link_ad, &reserve_chunks_ad, 6733 node) 6734 assert(reserve_size == reserve_cur); 6735 } 6736 #endif 6737 6738 /* Discard chunks until the the reserve is below the size limit. */ 6739 rb_foreach_reverse_begin(extent_node_t, link_ad, &reserve_chunks_ad, 6740 node) { 6741 #ifndef MALLOC_DECOMMIT 6742 if (node->size <= reserve_cur - reserve_max) { 6743 #endif 6744 extent_node_t *tnode = extent_tree_ad_prev( 6745 &reserve_chunks_ad, node); 6746 6747 #ifdef MALLOC_DECOMMIT 6748 assert(node->size <= reserve_cur - reserve_max); 6749 #endif 6750 6751 /* Discard the entire [multi-]chunk. */ 6752 extent_tree_szad_remove(&reserve_chunks_szad, node); 6753 extent_tree_ad_remove(&reserve_chunks_ad, node); 6754 reserve_cur -= node->size; 6755 pages_unmap(node->addr, node->size); 6756 #ifdef MALLOC_STATS 6757 stats_chunks.curchunks -= (node->size / chunksize); 6758 #endif 6759 base_node_dealloc(node); 6760 if (reserve_cur == reserve_max) 6761 break; 6762 6763 rb_foreach_reverse_prev(extent_node_t, link_ad, 6764 extent_ad_comp, &reserve_chunks_ad, tnode); 6765 #ifndef MALLOC_DECOMMIT 6766 } else { 6767 /* Discard the end of the multi-chunk. */ 6768 extent_tree_szad_remove(&reserve_chunks_szad, node); 6769 node->size -= reserve_cur - reserve_max; 6770 extent_tree_szad_insert(&reserve_chunks_szad, node); 6771 pages_unmap((void *)((uintptr_t)node->addr + 6772 node->size), reserve_cur - reserve_max); 6773 #ifdef MALLOC_STATS 6774 stats_chunks.curchunks -= ((reserve_cur - reserve_max) / 6775 chunksize); 6776 #endif 6777 reserve_cur = reserve_max; 6778 break; 6779 } 6780 #endif 6781 assert(reserve_cur > reserve_max); 6782 } rb_foreach_reverse_end(extent_node_t, link_ad, &reserve_chunks_ad, 6783 node) 6784 } 6785 6786 /* Send a condition notification. */ 6787 static uint64_t 6788 reserve_notify(reserve_cnd_t cnd, size_t size, uint64_t seq) 6789 { 6790 reserve_reg_t *reg; 6791 6792 /* seq is used to keep track of distinct condition-causing events. */ 6793 if (seq == 0) { 6794 /* Allocate new sequence number. */ 6795 reserve_seq++; 6796 seq = reserve_seq; 6797 } 6798 6799 /* 6800 * Advance to the next callback registration and send a notification, 6801 * unless one has already been sent for this condition-causing event. 6802 */ 6803 reg = ql_first(&reserve_regs); 6804 if (reg == NULL) 6805 return (0); 6806 ql_first(&reserve_regs) = ql_next(&reserve_regs, reg, link); 6807 if (reg->seq == seq) 6808 return (0); 6809 reg->seq = seq; 6810 malloc_mutex_unlock(&reserve_mtx); 6811 reg->cb(reg->ctx, cnd, size); 6812 malloc_mutex_lock(&reserve_mtx); 6813 6814 return (seq); 6815 } 6816 6817 /* Allocation failure due to OOM. Try to free some memory via callbacks. */ 6818 static uint64_t 6819 reserve_crit(size_t size, const char *fname, uint64_t seq) 6820 { 6821 6822 /* 6823 * Send one condition notification. Iteration is handled by the 6824 * caller of this function. 6825 */ 6826 malloc_mutex_lock(&reserve_mtx); 6827 seq = reserve_notify(RESERVE_CND_CRIT, size, seq); 6828 malloc_mutex_unlock(&reserve_mtx); 6829 6830 /* If no notification could be sent, then no further recourse exists. */ 6831 if (seq == 0) 6832 reserve_fail(size, fname); 6833 6834 return (seq); 6835 } 6836 6837 /* Permanent allocation failure due to OOM. */ 6838 static void 6839 reserve_fail(size_t size, const char *fname) 6840 { 6841 uint64_t seq = 0; 6842 6843 /* Send fail notifications. */ 6844 malloc_mutex_lock(&reserve_mtx); 6845 do { 6846 seq = reserve_notify(RESERVE_CND_FAIL, size, seq); 6847 } while (seq != 0); 6848 malloc_mutex_unlock(&reserve_mtx); 6849 6850 /* Terminate the application. */ 6851 _malloc_message(_getprogname(), 6852 ": (malloc) Error in ", fname, "(): out of memory\n"); 6853 abort(); 6854 } 6855 6856 bool 6857 reserve_cb_register(reserve_cb_t *cb, void *ctx) 6858 { 6859 reserve_reg_t *reg = base_reserve_reg_alloc(); 6860 if (reg == NULL) 6861 return (true); 6862 6863 ql_elm_new(reg, link); 6864 reg->cb = cb; 6865 reg->ctx = ctx; 6866 reg->seq = 0; 6867 6868 malloc_mutex_lock(&reserve_mtx); 6869 ql_head_insert(&reserve_regs, reg, link); 6870 malloc_mutex_unlock(&reserve_mtx); 6871 6872 return (false); 6873 } 6874 6875 bool 6876 reserve_cb_unregister(reserve_cb_t *cb, void *ctx) 6877 { 6878 reserve_reg_t *reg = NULL; 6879 6880 malloc_mutex_lock(&reserve_mtx); 6881 ql_foreach(reg, &reserve_regs, link) { 6882 if (reg->cb == cb && reg->ctx == ctx) { 6883 ql_remove(&reserve_regs, reg, link); 6884 break; 6885 } 6886 } 6887 malloc_mutex_unlock(&reserve_mtx); 6888 6889 if (reg != NULL) 6890 base_reserve_reg_dealloc(reg); 6891 return (false); 6892 return (true); 6893 } 6894 6895 size_t 6896 reserve_cur_get(void) 6897 { 6898 size_t ret; 6899 6900 malloc_mutex_lock(&reserve_mtx); 6901 ret = reserve_cur; 6902 malloc_mutex_unlock(&reserve_mtx); 6903 6904 return (ret); 6905 } 6906 6907 size_t 6908 reserve_min_get(void) 6909 { 6910 size_t ret; 6911 6912 malloc_mutex_lock(&reserve_mtx); 6913 ret = reserve_min; 6914 malloc_mutex_unlock(&reserve_mtx); 6915 6916 return (ret); 6917 } 6918 6919 bool 6920 reserve_min_set(size_t min) 6921 { 6922 6923 min = CHUNK_CEILING(min); 6924 6925 malloc_mutex_lock(&reserve_mtx); 6926 /* Keep |reserve_max - reserve_min| the same. */ 6927 if (min < reserve_min) { 6928 reserve_max -= reserve_min - min; 6929 reserve_min = min; 6930 } else { 6931 /* Protect against wrap-around. */ 6932 if (reserve_max + min - reserve_min < reserve_max) { 6933 reserve_min = SIZE_T_MAX - (reserve_max - reserve_min) 6934 - chunksize + 1; 6935 reserve_max = SIZE_T_MAX - chunksize + 1; 6936 } else { 6937 reserve_max += min - reserve_min; 6938 reserve_min = min; 6939 } 6940 } 6941 6942 /* Resize the reserve if necessary. */ 6943 if (reserve_cur < reserve_min) { 6944 size_t size = reserve_min - reserve_cur; 6945 6946 /* Force the reserve to grow by allocating/deallocating. */ 6947 malloc_mutex_unlock(&reserve_mtx); 6948 #ifdef MALLOC_DECOMMIT 6949 { 6950 void **chunks; 6951 size_t i, n; 6952 6953 n = size >> opt_chunk_2pow; 6954 chunks = (void**)imalloc(n * sizeof(void *)); 6955 if (chunks == NULL) 6956 return (true); 6957 for (i = 0; i < n; i++) { 6958 chunks[i] = huge_malloc(chunksize, false); 6959 if (chunks[i] == NULL) { 6960 size_t j; 6961 6962 for (j = 0; j < i; j++) { 6963 huge_dalloc(chunks[j]); 6964 } 6965 idalloc(chunks); 6966 return (true); 6967 } 6968 } 6969 for (i = 0; i < n; i++) 6970 huge_dalloc(chunks[i]); 6971 idalloc(chunks); 6972 } 6973 #else 6974 { 6975 void *x = huge_malloc(size, false); 6976 if (x == NULL) { 6977 return (true); 6978 } 6979 huge_dalloc(x); 6980 } 6981 #endif 6982 } else if (reserve_cur > reserve_max) { 6983 reserve_shrink(); 6984 malloc_mutex_unlock(&reserve_mtx); 6985 } else 6986 malloc_mutex_unlock(&reserve_mtx); 6987 6988 return (false); 6989 } 6990 6991 #ifdef MOZ_MEMORY_WINDOWS 6992 void* 6993 _recalloc(void *ptr, size_t count, size_t size) 6994 { 6995 size_t oldsize = (ptr != NULL) ? isalloc(ptr) : 0; 6996 size_t newsize = count * size; 6997 6998 /* 6999 * In order for all trailing bytes to be zeroed, the caller needs to 7000 * use calloc(), followed by recalloc(). However, the current calloc() 7001 * implementation only zeros the bytes requested, so if recalloc() is 7002 * to work 100% correctly, calloc() will need to change to zero 7003 * trailing bytes. 7004 */ 7005 7006 ptr = realloc(ptr, newsize); 7007 if (ptr != NULL && oldsize < newsize) { 7008 memset((void *)((uintptr_t)ptr + oldsize), 0, newsize - 7009 oldsize); 7010 } 7011 7012 return ptr; 7013 } 7014 7015 /* 7016 * This impl of _expand doesn't ever actually expand or shrink blocks: it 7017 * simply replies that you may continue using a shrunk block. 7018 */ 7019 void* 7020 _expand(void *ptr, size_t newsize) 7021 { 7022 if (isalloc(ptr) >= newsize) 7023 return ptr; 7024 7025 return NULL; 7026 } 7027 7028 size_t 7029 _msize(const void *ptr) 7030 { 7031 return malloc_usable_size(ptr); 7032 } 7033 #endif 7034 7035 /* 7036 * End non-standard functions. 7037 */ 7038 /******************************************************************************/ 7039 /* 7040 * Begin library-private functions, used by threading libraries for protection 7041 * of malloc during fork(). These functions are only called if the program is 7042 * running in threaded mode, so there is no need to check whether the program 7043 * is threaded here. 7044 */ 7045 7046 void 7047 _malloc_prefork(void) 7048 { 7049 unsigned i; 7050 7051 /* Acquire all mutexes in a safe order. */ 7052 7053 malloc_spin_lock(&arenas_lock); 7054 for (i = 0; i < narenas; i++) { 7055 if (arenas[i] != NULL) 7056 malloc_spin_lock(&arenas[i]->lock); 7057 } 7058 malloc_spin_unlock(&arenas_lock); 7059 7060 malloc_mutex_lock(&base_mtx); 7061 7062 malloc_mutex_lock(&huge_mtx); 7063 } 7064 7065 void 7066 _malloc_postfork(void) 7067 { 7068 unsigned i; 7069 7070 /* Release all mutexes, now that fork() has completed. */ 7071 7072 malloc_mutex_unlock(&huge_mtx); 7073 7074 malloc_mutex_unlock(&base_mtx); 7075 7076 malloc_spin_lock(&arenas_lock); 7077 for (i = 0; i < narenas; i++) { 7078 if (arenas[i] != NULL) 7079 malloc_spin_unlock(&arenas[i]->lock); 7080 } 7081 malloc_spin_unlock(&arenas_lock); 7082 } 7083 7084 /* 7085 * End library-private functions. 7086 */ 7087 /******************************************************************************/ 7088 7089 #ifdef HAVE_LIBDL 7090 # include <dlfcn.h> 7091 #endif 7092 7093 #ifdef MOZ_MEMORY_DARWIN 7094 static malloc_zone_t zone; 7095 static struct malloc_introspection_t zone_introspect; 7096 7097 static size_t 7098 zone_size(malloc_zone_t *zone, void *ptr) 7099 { 7100 7101 /* 7102 * There appear to be places within Darwin (such as setenv(3)) that 7103 * cause calls to this function with pointers that *no* zone owns. If 7104 * we knew that all pointers were owned by *some* zone, we could split 7105 * our zone into two parts, and use one as the default allocator and 7106 * the other as the default deallocator/reallocator. Since that will 7107 * not work in practice, we must check all pointers to assure that they 7108 * reside within a mapped chunk before determining size. 7109 */ 7110 return (isalloc_validate(ptr)); 7111 } 7112 7113 static void * 7114 zone_malloc(malloc_zone_t *zone, size_t size) 7115 { 7116 7117 return (malloc(size)); 7118 } 7119 7120 static void * 7121 zone_calloc(malloc_zone_t *zone, size_t num, size_t size) 7122 { 7123 7124 return (calloc(num, size)); 7125 } 7126 7127 static void * 7128 zone_valloc(malloc_zone_t *zone, size_t size) 7129 { 7130 void *ret = NULL; /* Assignment avoids useless compiler warning. */ 7131 7132 posix_memalign(&ret, pagesize, size); 7133 7134 return (ret); 7135 } 7136 7137 static void 7138 zone_free(malloc_zone_t *zone, void *ptr) 7139 { 7140 7141 free(ptr); 7142 } 7143 7144 static void * 7145 zone_realloc(malloc_zone_t *zone, void *ptr, size_t size) 7146 { 7147 7148 return (realloc(ptr, size)); 7149 } 7150 7151 static void * 7152 zone_destroy(malloc_zone_t *zone) 7153 { 7154 7155 /* This function should never be called. */ 7156 assert(false); 7157 return (NULL); 7158 } 7159 7160 static size_t 7161 zone_good_size(malloc_zone_t *zone, size_t size) 7162 { 7163 size_t ret; 7164 void *p; 7165 7166 /* 7167 * Actually create an object of the appropriate size, then find out 7168 * how large it could have been without moving up to the next size 7169 * class. 7170 */ 7171 p = malloc(size); 7172 if (p != NULL) { 7173 ret = isalloc(p); 7174 free(p); 7175 } else 7176 ret = size; 7177 7178 return (ret); 7179 } 7180 7181 static void 7182 zone_force_lock(malloc_zone_t *zone) 7183 { 7184 7185 _malloc_prefork(); 7186 } 7187 7188 static void 7189 zone_force_unlock(malloc_zone_t *zone) 7190 { 7191 7192 _malloc_postfork(); 7193 } 7194 7195 static malloc_zone_t * 7196 create_zone(void) 7197 { 7198 7199 assert(malloc_initialized); 7200 7201 zone.size = (void *)zone_size; 7202 zone.malloc = (void *)zone_malloc; 7203 zone.calloc = (void *)zone_calloc; 7204 zone.valloc = (void *)zone_valloc; 7205 zone.free = (void *)zone_free; 7206 zone.realloc = (void *)zone_realloc; 7207 zone.destroy = (void *)zone_destroy; 7208 zone.zone_name = "jemalloc_zone"; 7209 zone.batch_malloc = NULL; 7210 zone.batch_free = NULL; 7211 zone.introspect = &zone_introspect; 7212 7213 zone_introspect.enumerator = NULL; 7214 zone_introspect.good_size = (void *)zone_good_size; 7215 zone_introspect.check = NULL; 7216 zone_introspect.print = NULL; 7217 zone_introspect.log = NULL; 7218 zone_introspect.force_lock = (void *)zone_force_lock; 7219 zone_introspect.force_unlock = (void *)zone_force_unlock; 7220 zone_introspect.statistics = NULL; 7221 7222 return (&zone); 7223 } 7224 7225 __attribute__((constructor)) 7226 void 7227 jemalloc_darwin_init(void) 7228 { 7229 extern unsigned malloc_num_zones; 7230 extern malloc_zone_t **malloc_zones; 7231 7232 if (malloc_init_hard()) 7233 abort(); 7234 7235 /* 7236 * The following code is *not* thread-safe, so it's critical that 7237 * initialization be manually triggered. 7238 */ 7239 7240 /* Register the custom zones. */ 7241 malloc_zone_register(create_zone()); 7242 assert(malloc_zones[malloc_num_zones - 1] == &zone); 7243 7244 /* 7245 * Shift malloc_zones around so that zone is first, which makes it the 7246 * default zone. 7247 */ 7248 assert(malloc_num_zones > 1); 7249 memmove(&malloc_zones[1], &malloc_zones[0], 7250 sizeof(malloc_zone_t *) * (malloc_num_zones - 1)); 7251 malloc_zones[0] = &zone; 7252 } 7253 7254 #elif defined(__GLIBC__) && !defined(__UCLIBC__) 7255 /* 7256 * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible 7257 * to inconsistently reference libc's malloc(3)-compatible functions 7258 * (bug 493541). 7259 * 7260 * These definitions interpose hooks in glibc. The functions are actually 7261 * passed an extra argument for the caller return address, which will be 7262 * ignored. 7263 */ 7264 void (*__free_hook)(void *ptr) = free; 7265 void *(*__malloc_hook)(size_t size) = malloc; 7266 void *(*__realloc_hook)(void *ptr, size_t size) = realloc; 7267 void *(*__memalign_hook)(size_t alignment, size_t size) = memalign; 7268 7269 #elif defined(RTLD_DEEPBIND) 7270 /* 7271 * XXX On systems that support RTLD_GROUP or DF_1_GROUP, do their 7272 * implementations permit similar inconsistencies? Should STV_SINGLETON 7273 * visibility be used for interposition where available? 7274 */ 7275 # error "Interposing malloc is unsafe on this system without libc malloc hooks." 7276 #endif 7277 7278