1 /* -*- Mode: C; tab-width: 8; c-basic-offset: 8 -*- */
2 /* vim:set softtabstop=8 shiftwidth=8: */
4 * Copyright (C) 2006-2008 Jason Evans <jasone@FreeBSD.org>.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
31 *******************************************************************************
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:
37 * + Multiple arenas are used if there are multiple CPUs, which reduces lock
38 * contention and cache sloshing.
40 * + Cache line sharing between arenas is avoided for internal data
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.
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
53 * |=====================================|
54 * | Category | Subcategory | Size |
55 * |=====================================|
56 * | Small | Tiny | 2 |
59 * | |----------------+---------|
60 * | | Quantum-spaced | 16 |
67 * | |----------------+---------|
68 * | | Sub-page | 1 kB |
70 * |=====================================|
78 * |=====================================|
83 * |=====================================|
85 * A different mechanism is used for each category:
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.
90 * Large : Each allocation is backed by a dedicated run. Metadata are stored
91 * in the associated arena chunk header maps.
93 * Huge : Each allocation is backed by a dedicated contiguous set of chunks.
94 * Metadata are stored in a separate red-black tree.
96 *******************************************************************************
100 * NOTE(mbelshe): Added these defines to fit within chromium build system.
102 #define MOZ_MEMORY_WINDOWS
104 #define DONT_OVERRIDE_LIBC
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.
111 #ifndef MOZ_MEMORY_DEBUG
112 # define MALLOC_PRODUCTION
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.
120 #define MOZ_MEMORY_NARENAS_DEFAULT_ONE
123 * MALLOC_STATS enables statistics calculation, and is required for
128 #ifndef MALLOC_PRODUCTION
130 * MALLOC_DEBUG enables assertions and other sanity checks, and disables
133 # define MALLOC_DEBUG
135 /* Memory filling (junk/zero). */
138 /* Allocation tracing. */
139 # ifndef MOZ_MEMORY_WINDOWS
140 # define MALLOC_UTRACE
143 /* Support optional abort() on OOM. */
144 # define MALLOC_XMALLOC
146 /* Support SYSV semantics. */
151 * MALLOC_VALIDATE causes malloc_usable_size() to perform some pointer
152 * validation. There are many possible errors that validation does not even
155 #define MALLOC_VALIDATE
157 /* Embed no-op macros that support memory allocation tracking via valgrind. */
159 # define MALLOC_VALGRIND
161 #ifdef MALLOC_VALGRIND
162 # include <valgrind/valgrind.h>
164 # define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)
165 # define VALGRIND_FREELIKE_BLOCK(addr, rzB)
169 * MALLOC_BALANCE enables monitoring of arena lock contention and dynamically
170 * re-balances arena load if exponentially averaged contention exceeds a
173 /* #define MALLOC_BALANCE */
175 #if (!defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN))
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.
181 * XXX OS X over-commits, so we should probably use mmap() instead of
182 * vm_allocate(), so that MALLOC_PAGEFILE works.
184 #define MALLOC_PAGEFILE
187 #ifdef MALLOC_PAGEFILE
188 /* Write size when initializing a page file. */
189 # define MALLOC_PAGEFILE_WRITE_SIZE 512
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
200 #ifndef MOZ_MEMORY_WINCE
201 #include <sys/types.h>
211 #ifdef MOZ_MEMORY_WINDOWS
212 #ifndef MOZ_MEMORY_WINCE
213 //#include <cruntime.h>
214 //#include <internal.h>
217 #include <cmnintrin.h>
219 #define SIZE_MAX UINT_MAX
223 #pragma warning( disable: 4267 4996 4146 )
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
234 static unsigned long tlsIndex = 0xffffffff;
238 #ifdef MOZ_MEMORY_WINCE
239 #define _pthread_self() GetCurrentThreadId()
241 #define _pthread_self() __threadid()
243 #define issetugid() 0
245 #ifndef MOZ_MEMORY_WINCE
246 /* use MSVC intrinsics */
247 #pragma intrinsic(_BitScanForward)
248 static __forceinline int
253 if (_BitScanForward(&i, x) != 0)
259 /* Implement getenv without using malloc */
260 static char mozillaMallocOptionsBuf[64];
262 #define getenv xgetenv
264 getenv(const char *name)
267 if (GetEnvironmentVariableA(name, (LPSTR)&mozillaMallocOptionsBuf,
268 sizeof(mozillaMallocOptionsBuf)) > 0)
269 return (mozillaMallocOptionsBuf);
279 static __forceinline int
283 return 32 - _CountLeadingZeros((-x) & x);
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;
293 #define MALLOC_DECOMMIT
296 #ifndef MOZ_MEMORY_WINDOWS
297 #ifndef MOZ_MEMORY_SOLARIS
298 #include <sys/cdefs.h>
301 # define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
304 __FBSDID("$FreeBSD: head/lib/libc/stdlib/malloc.c 180599 2008-07-18 19:35:44Z jasone $");
305 #include "libc_private.h"
309 #include "spinlock.h"
310 #include "namespace.h"
312 #include <sys/mman.h>
314 # define MADV_FREE MADV_DONTNEED
317 # define MAP_NOSYNC 0
319 #include <sys/param.h>
321 #include <sys/stddef.h>
323 #include <sys/time.h>
324 #include <sys/types.h>
325 #ifndef MOZ_MEMORY_SOLARIS
326 #include <sys/sysctl.h>
330 #include <sys/ktrace.h> /* Must come after several other sys/ includes. */
332 #include <machine/atomic.h>
333 #include <machine/cpufunc.h>
334 #include <machine/vmparam.h>
340 # define SIZE_T_MAX SIZE_MAX
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
357 #ifndef MOZ_MEMORY_DARWIN
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>
371 #include "un-namespace.h"
376 #include "jemalloc.h"
379 #define bool jemalloc_bool
381 #ifdef MOZ_MEMORY_DARWIN
382 static const bool __isthreaded = true;
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. */
389 #if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6)
390 #define JEMALLOC_USES_MAP_ALIGN /* Required for Windows CE < 6 */
393 #define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
397 #ifdef MOZ_MEMORY_WINDOWS
398 /* MSVC++ does not support C99 variable-length arrays. */
399 # define RB_NO_C99_VARARRAYS
404 /* Disable inlining to make debugging easier. */
412 /* Size of stack-allocated buffer passed to strerror_r(). */
413 #define STRERROR_BUF 64
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
420 # define SIZEOF_PTR_2POW 2
423 #ifndef MOZ_MEMORY_DARWIN
424 static const bool __isthreaded = true;
430 # define QUANTUM_2POW_MIN 4
431 # define SIZEOF_PTR_2POW 2
432 # define CPU_SPINWAIT __asm__ volatile("pause")
435 # define QUANTUM_2POW_MIN 4
436 # define SIZEOF_PTR_2POW 3
439 # define QUANTUM_2POW_MIN 4
440 # define SIZEOF_PTR_2POW 3
444 # define QUANTUM_2POW_MIN 4
445 # define SIZEOF_PTR_2POW 3
449 # define QUANTUM_2POW_MIN 4
450 # define SIZEOF_PTR_2POW 3
451 # define CPU_SPINWAIT __asm__ volatile("pause")
454 # define QUANTUM_2POW_MIN 3
455 # define SIZEOF_PTR_2POW 2
459 # define QUANTUM_2POW_MIN 3
460 # define SIZEOF_PTR_2POW 2
464 # define QUANTUM_2POW_MIN 4
465 # define SIZEOF_PTR_2POW 2
469 #define SIZEOF_PTR (1U << SIZEOF_PTR_2POW)
471 /* sizeof(int) == (1U << SIZEOF_INT_2POW). */
472 #ifndef SIZEOF_INT_2POW
473 # define SIZEOF_INT_2POW 2
476 /* We can't use TLS in non-PIC programs, since TLS relies on loader magic. */
477 #if (!defined(PIC) && !defined(NO_TLS))
482 /* MALLOC_BALANCE requires TLS. */
483 # ifdef MALLOC_BALANCE
484 # undef MALLOC_BALANCE
489 * Size and alignment of memory chunks that are allocated by the OS's virtual
492 #if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6)
493 #define CHUNK_2POW_DEFAULT 21
495 #define CHUNK_2POW_DEFAULT 20
497 /* Maximum number of dirty pages per arena. */
498 #define DIRTY_MAX_DEFAULT (1U << 10)
500 /* Default reserve chunks. */
501 #define RESERVE_MIN_2POW_DEFAULT 1
503 * Default range (in chunks) between reserve_min and reserve_max, in addition
504 * to the mandatory one chunk per arena.
506 #ifdef MALLOC_PAGEFILE
507 # define RESERVE_RANGE_2POW_DEFAULT 5
509 # define RESERVE_RANGE_2POW_DEFAULT 0
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.
517 #define CACHELINE_2POW 6
518 #define CACHELINE ((size_t)(1U << CACHELINE_2POW))
520 /* Smallest size class to support. */
521 #define TINY_MIN_2POW 1
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
528 #define SMALL_MAX_2POW_DEFAULT 9
529 #define SMALL_MAX_DEFAULT (1U << SMALL_MAX_2POW_DEFAULT)
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.
537 * We use binary fixed point math for overhead computations, where the binary
538 * point is implicitly RUN_BFP bits to the left.
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:
545 * (RUN_MAX_OVRHD / (reg_size << (3+RUN_BFP))
548 /* \/ Implicit binary fixed point. */
549 #define RUN_MAX_OVRHD 0x0000003dU
550 #define RUN_MAX_OVRHD_RELAX 0x00001800U
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)
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.
562 # define CPU_SPINWAIT
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.
570 #define SPIN_LIMIT_2POW 11
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.
577 #define BLOCK_COST_2POW 4
579 #ifdef MALLOC_BALANCE
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).
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.
588 # define BALANCE_ALPHA_INV_2POW 9
591 * Threshold value for the exponential moving contention average at which to
592 * re-assign a thread.
594 # define BALANCE_THRESHOLD_DEFAULT (1U << (SPIN_LIMIT_2POW-4))
597 /******************************************************************************/
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.
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)
614 #elif defined(MOZ_MEMORY)
615 typedef pthread_mutex_t malloc_mutex_t;
616 typedef pthread_mutex_t malloc_spinlock_t;
618 /* XXX these should #ifdef these for freebsd (and linux?) only */
622 typedef malloc_spinlock_t malloc_mutex_t;
625 /* Set to true once the allocator has been initialized. */
626 static bool malloc_initialized = false;
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;
637 static malloc_mutex_t init_lock = {_SPINLOCK_INITIALIZER};
640 /******************************************************************************/
642 * Statistics data structures.
647 typedef struct malloc_bin_stats_s malloc_bin_stats_t;
648 struct malloc_bin_stats_s {
650 * Number of allocation requests that corresponded to the size of this
655 /* Total number of runs created for this bin's size class. */
659 * Total number of runs reused by extracting them from the runs tree for
660 * this bin's size class.
664 /* High-water mark for this bin. */
665 unsigned long highruns;
667 /* Current number of runs in this bin. */
668 unsigned long curruns;
671 typedef struct arena_stats_s arena_stats_t;
672 struct arena_stats_s {
673 /* Number of bytes currently mapped. */
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
684 #ifdef MALLOC_DECOMMIT
686 * Total number of decommit/commit operations, and total number of
691 uint64_t decommitted;
694 /* Per-size-category statistics. */
695 size_t allocated_small;
696 uint64_t nmalloc_small;
697 uint64_t ndalloc_small;
699 size_t allocated_large;
700 uint64_t nmalloc_large;
701 uint64_t ndalloc_large;
703 #ifdef MALLOC_BALANCE
704 /* Number of times this arena reassigned a thread due to contention. */
709 typedef struct chunk_stats_s chunk_stats_t;
710 struct chunk_stats_s {
711 /* Number of chunks that were allocated. */
714 /* High-water mark for number of chunks allocated. */
715 unsigned long highchunks;
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
722 unsigned long curchunks;
725 #endif /* #ifdef MALLOC_STATS */
727 /******************************************************************************/
729 * Extent data structures.
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;
738 /* Linkage for the address-ordered tree. */
739 rb_node(extent_node_t) link_ad;
741 /* Pointer to the extent that this tree node is responsible for. */
744 /* Total region size. */
747 typedef rb_tree(extent_node_t) extent_tree_t;
749 /******************************************************************************/
751 * Radix tree data structures.
754 #ifdef MALLOC_VALIDATE
756 * Size of each radix tree node (must be a power of 2). This impacts tree
759 # if (SIZEOF_PTR == 4)
760 # define MALLOC_RTREE_NODESIZE (1U << 14)
762 # define MALLOC_RTREE_NODESIZE CACHELINE
765 typedef struct malloc_rtree_s malloc_rtree_t;
766 struct malloc_rtree_s {
767 malloc_spinlock_t lock;
770 unsigned level2bits[1]; /* Dynamically sized. */
774 /******************************************************************************/
776 * Reserve data structures.
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;
785 /* Callback function pointer. */
788 /* Opaque application data pointer. */
792 * Sequence number of condition notification most recently sent to this
798 /******************************************************************************/
800 * Arena data structures.
803 typedef struct arena_s arena_t;
804 typedef struct arena_bin_s arena_bin_t;
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 {
810 * Linkage for run trees. There are two disjoint uses:
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.
816 rb_node(arena_chunk_map_t) link;
819 * Run address (or size) and various flags are stored together. The bit
820 * layout looks like (assuming 32-bit system):
822 * ???????? ???????? ????---- --ckdzla
824 * ? : Unallocated: Run address for first/last pages, unset for internal
826 * Small: Run address.
827 * Large: Run size for first page, unset for trailing pages.
836 * Following are example bit patterns for the three types of runs.
845 * ssssssss ssssssss ssss---- --c-----
846 * xxxxxxxx xxxxxxxx xxxx---- ----d---
847 * ssssssss ssssssss ssss---- -----z--
850 * rrrrrrrr rrrrrrrr rrrr---- -------a
851 * rrrrrrrr rrrrrrrr rrrr---- -------a
852 * rrrrrrrr rrrrrrrr rrrr---- -------a
855 * ssssssss ssssssss ssss---- ------la
856 * -------- -------- -------- ------la
857 * -------- -------- -------- ------la
860 #ifdef MALLOC_DECOMMIT
861 #define CHUNK_MAP_DECOMMITTED ((size_t)0x20U)
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)
869 typedef rb_tree(arena_chunk_map_t) arena_avail_tree_t;
870 typedef rb_tree(arena_chunk_map_t) arena_run_tree_t;
872 /* Arena chunk header. */
873 typedef struct arena_chunk_s arena_chunk_t;
874 struct arena_chunk_s {
875 /* Arena that owns the chunk. */
878 /* Linkage for the arena's chunks_dirty tree. */
879 rb_node(arena_chunk_t) link_dirty;
881 /* Number of dirty pages. */
884 /* Map of pages within chunk that keeps track of free/large/small. */
885 arena_chunk_map_t map[1]; /* Dynamically sized. */
887 typedef rb_tree(arena_chunk_t) arena_chunk_tree_t;
889 typedef struct arena_run_s arena_run_t;
893 # define ARENA_RUN_MAGIC 0x384adf93
896 /* Bin this run is associated with. */
899 /* Index of first element that might have a free region. */
900 unsigned regs_minelm;
902 /* Number of free regions in run. */
905 /* Bitmask of in-use regions (0: in use, 1: free). */
906 unsigned regs_mask[1]; /* Dynamically sized. */
911 * Current run being used to service allocations of this bin's size
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.
923 arena_run_tree_t runs;
925 /* Size of regions in a run for this bin's size class. */
928 /* Total size of a run for this bin's size class. */
931 /* Total number of regions in a run for this bin's size class. */
934 /* Number of elements in a run's regs_mask for this bin's size class. */
935 uint32_t regs_mask_nelms;
937 /* Offset of first region in a run for this bin's size class. */
938 uint32_t reg0_offset;
941 /* Bin statistics. */
942 malloc_bin_stats_t stats;
949 # define ARENA_MAGIC 0x947d3d24
952 /* All operations on this arena require that lock be locked. */
954 malloc_spinlock_t lock;
956 pthread_mutex_t lock;
964 * Chunk allocation sequence number, used to detect races with other
965 * threads during chunk allocation, and then discard unnecessary chunks.
969 /* Tree of dirty-page-containing chunks this arena manages. */
970 arena_chunk_tree_t chunks_dirty;
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.
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.
982 arena_chunk_t *spare;
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.
993 * Size/address-ordered tree of this arena's available runs. This tree
994 * is used for first-best-fit run allocation.
996 arena_avail_tree_t runs_avail;
998 #ifdef MALLOC_BALANCE
1000 * The arena load balancing machinery needs to keep track of how much
1001 * lock contention there is. This value is exponentially averaged.
1003 uint32_t contention;
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.
1029 arena_bin_t bins[1]; /* Dynamically sized. */
1032 /******************************************************************************/
1037 /* Number of CPUs. */
1038 static unsigned ncpus;
1041 static size_t pagesize;
1042 static size_t pagesize_mask;
1043 static size_t pagesize_2pow;
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;
1053 /* Various quantum-related settings. */
1054 static size_t quantum;
1055 static size_t quantum_mask; /* (quantum - 1). */
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. */
1069 #ifdef MALLOC_VALIDATE
1070 static malloc_rtree_t *chunk_rtree;
1073 /* Protects chunk-related data structures. */
1074 static malloc_mutex_t huge_mtx;
1076 /* Tree of chunks that are stand-alone huge allocations. */
1077 static extent_tree_t huge;
1080 /* Huge allocation statistics. */
1081 static uint64_t huge_nmalloc;
1082 static uint64_t huge_ndalloc;
1083 static size_t huge_allocated;
1091 #ifdef MALLOC_PAGEFILE
1092 static char pagefile_templ[PATH_MAX];
1095 /* Protects reserve-related data structures. */
1096 static malloc_mutex_t reserve_mtx;
1099 * Bounds on acceptable reserve size, and current reserve size. Reserve
1100 * depletion may cause (reserve_cur < reserve_min).
1102 static size_t reserve_min;
1103 static size_t reserve_cur;
1104 static size_t reserve_max;
1106 /* List of registered callbacks. */
1107 static ql_head(reserve_reg_t) reserve_regs;
1110 * Condition notification sequence number, used to determine whether all
1111 * registered callbacks have been notified of the most current condition.
1113 static uint64_t reserve_seq;
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.
1120 static extent_tree_t reserve_chunks_szad;
1121 static extent_tree_t reserve_chunks_ad;
1123 /****************************/
1125 * base (internal allocation).
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.
1133 static void *base_pages;
1134 static void *base_next_addr;
1135 #ifdef MALLOC_DECOMMIT
1136 static void *base_next_decommitted;
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;
1143 static size_t base_mapped;
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.
1155 static arena_t **arenas;
1156 static unsigned narenas;
1157 static unsigned narenas_2pow;
1159 # ifdef MALLOC_BALANCE
1160 static unsigned narenas_2pow;
1162 static unsigned next_arena;
1166 static malloc_spinlock_t arenas_lock; /* Protects arenas initialization. */
1168 static pthread_mutex_t arenas_lock; /* Protects arenas initialization. */
1173 * Map of pthread_self() --> arenas[???], used for selecting an arena to use
1176 #ifndef MOZ_MEMORY_WINDOWS
1177 static __thread arena_t *arenas_map;
1182 /* Chunk statistics. */
1183 static chunk_stats_t stats_chunks;
1186 /*******************************/
1188 * Runtime configuration options.
1190 const char *_malloc_options;
1192 #ifndef MALLOC_PRODUCTION
1193 static bool opt_abort = true;
1195 static bool opt_junk = true;
1198 static bool opt_abort = false;
1200 static bool opt_junk = false;
1203 static size_t opt_dirty_max = DIRTY_MAX_DEFAULT;
1204 #ifdef MALLOC_BALANCE
1205 static uint64_t opt_balance_threshold = BALANCE_THRESHOLD_DEFAULT;
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;
1216 #ifdef MALLOC_UTRACE
1217 static bool opt_utrace = false;
1220 static bool opt_sysv = false;
1222 #ifdef MALLOC_XMALLOC
1223 static bool opt_xmalloc = false;
1226 static bool opt_zero = false;
1228 static int opt_narenas_lshift = 0;
1230 #ifdef MALLOC_UTRACE
1237 #define UTRACE(a, b, c) \
1239 malloc_utrace_t ut; \
1243 utrace(&ut, sizeof(ut)); \
1246 #define UTRACE(a, b, c)
1249 /******************************************************************************/
1251 * Begin function prototypes for non-inline static functions.
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,
1260 #ifdef MOZ_MEMORY_DARWIN
1261 /* Avoid namespace collision with OS X's malloc APIs. */
1262 #define malloc_printf moz_malloc_printf
1264 static void malloc_printf(const char *format, ...);
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);
1275 static void stats_print(arena_t *arena);
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);
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);
1290 static arena_t *choose_arena_hard(void);
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);
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,
1313 static size_t arena_salloc(const void *ptr);
1314 static void arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk,
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
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);
1338 void _malloc_prefork(void);
1339 void _malloc_postfork(void);
1342 * End function prototypes.
1344 /******************************************************************************/
1347 * umax2s() provides minimal integer printing functionality, which is
1348 * especially useful for situations where allocation in vsnprintf() calls would
1349 * potentially cause deadlock.
1351 #define UMAX2S_BUFSIZE 21
1353 umax2s(uintmax_t x, char *s)
1357 i = UMAX2S_BUFSIZE - 1;
1361 s[i] = "0123456789"[x % 10];
1369 wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4)
1371 #ifdef MOZ_MEMORY_WINCE
1373 #define WRT_PRINT(s) \
1374 MultiByteToWideChar(CP_ACP, 0, s, -1, buf, 1024); \
1375 OutputDebugStringW(buf)
1382 #if defined(MOZ_MEMORY) && !defined(MOZ_MEMORY_WINDOWS)
1383 #define _write write
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));
1393 #define _malloc_message malloc_message
1395 void (*_malloc_message)(const char *p1, const char *p2, const char *p3,
1396 const char *p4) = wrtmessage;
1399 # define assert(e) do { \
1401 char line_buf[UMAX2S_BUFSIZE]; \
1402 _malloc_message(__FILE__, ":", umax2s(__LINE__, \
1403 line_buf), ": Failed assertion: "); \
1404 _malloc_message("\"", #e, "\"\n", ""); \
1412 /******************************************************************************/
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
1420 malloc_mutex_init(malloc_mutex_t *mutex)
1422 #if defined(MOZ_MEMORY_WINCE)
1423 InitializeCriticalSection(mutex);
1424 #elif defined(MOZ_MEMORY_WINDOWS)
1427 // if (! __crtInitCritSecAndSpinCount(mutex, _CRT_SPINCOUNT))
1429 if (!InitializeCriticalSectionAndSpinCount(mutex, 4000))
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)
1437 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
1438 if (pthread_mutex_init(mutex, &attr) != 0) {
1439 pthread_mutexattr_destroy(&attr);
1442 pthread_mutexattr_destroy(&attr);
1443 #elif defined(MOZ_MEMORY)
1444 if (pthread_mutex_init(mutex, NULL) != 0)
1447 static const spinlock_t lock = _SPINLOCK_INITIALIZER;
1455 malloc_mutex_lock(malloc_mutex_t *mutex)
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);
1466 _SPINLOCK(&mutex->lock);
1471 malloc_mutex_unlock(malloc_mutex_t *mutex)
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);
1482 _SPINUNLOCK(&mutex->lock);
1487 malloc_spin_init(malloc_spinlock_t *lock)
1489 #if defined(MOZ_MEMORY_WINCE)
1490 InitializeCriticalSection(lock);
1491 #elif defined(MOZ_MEMORY_WINDOWS)
1494 // if (! __crtInitCritSecAndSpinCount(lock, _CRT_SPINCOUNT))
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)
1502 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
1503 if (pthread_mutex_init(lock, &attr) != 0) {
1504 pthread_mutexattr_destroy(&attr);
1507 pthread_mutexattr_destroy(&attr);
1508 #elif defined(MOZ_MEMORY)
1509 if (pthread_mutex_init(lock, NULL) != 0)
1512 lock->lock = _SPINLOCK_INITIALIZER;
1518 malloc_spin_lock(malloc_spinlock_t *lock)
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);
1529 _SPINLOCK(&lock->lock);
1534 malloc_spin_unlock(malloc_spinlock_t *lock)
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);
1544 _SPINUNLOCK(&lock->lock);
1551 /******************************************************************************/
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.
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
1566 * We use an unpublished interface to initialize pthread mutexes with an
1567 * allocation callback, in order to avoid infinite recursion.
1569 int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex,
1570 void *(calloc_cb)(size_t, size_t));
1572 __weak_reference(_pthread_mutex_init_calloc_cb_stub,
1573 _pthread_mutex_init_calloc_cb);
1576 _pthread_mutex_init_calloc_cb_stub(pthread_mutex_t *mutex,
1577 void *(calloc_cb)(size_t, size_t))
1584 malloc_spin_init(pthread_mutex_t *lock)
1587 if (_pthread_mutex_init_calloc_cb(lock, base_calloc) != 0)
1593 static inline unsigned
1594 malloc_spin_lock(pthread_mutex_t *lock)
1599 if (_pthread_mutex_trylock(lock) != 0) {
1601 volatile unsigned j;
1603 /* Exponentially back off. */
1604 for (i = 1; i <= SPIN_LIMIT_2POW; i++) {
1605 for (j = 0; j < (1U << i); j++)
1609 if (_pthread_mutex_trylock(lock) == 0)
1614 * Spinning failed. Block until the lock becomes
1615 * available, in order to avoid indefinite priority
1618 _pthread_mutex_lock(lock);
1619 assert((ret << BLOCK_COST_2POW) != 0);
1620 return (ret << BLOCK_COST_2POW);
1628 malloc_spin_unlock(pthread_mutex_t *lock)
1632 _pthread_mutex_unlock(lock);
1639 /******************************************************************************/
1641 * Begin Utility functions/macros.
1644 /* Return the chunk address for allocation address a. */
1645 #define CHUNK_ADDR2BASE(a) \
1646 ((void *)((uintptr_t)(a) & ~chunksize_mask))
1648 /* Return the chunk offset of address a. */
1649 #define CHUNK_ADDR2OFFSET(a) \
1650 ((size_t)((uintptr_t)(a) & chunksize_mask))
1652 /* Return the smallest chunk multiple that is >= s. */
1653 #define CHUNK_CEILING(s) \
1654 (((s) + chunksize_mask) & ~chunksize_mask)
1656 /* Return the smallest cacheline multiple that is >= s. */
1657 #define CACHELINE_CEILING(s) \
1658 (((s) + (CACHELINE - 1)) & ~(CACHELINE - 1))
1660 /* Return the smallest quantum multiple that is >= a. */
1661 #define QUANTUM_CEILING(a) \
1662 (((a) + quantum_mask) & ~quantum_mask)
1664 /* Return the smallest pagesize multiple that is >= s. */
1665 #define PAGE_CEILING(s) \
1666 (((s) + pagesize_mask) & ~pagesize_mask)
1668 /* Compute the smallest power of 2 that is >= x. */
1669 static inline size_t
1679 #if (SIZEOF_PTR == 8)
1686 #ifdef MALLOC_BALANCE
1688 * Use a simple linear congruential pseudo-random number generator:
1690 * prn(y) = (a*x + c) % m
1692 * where the following constants ensure maximal period:
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).
1698 * See Knuth's TAOCP 3rd Ed., Vol. 2, pg. 17 for details on these constraints.
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
1705 # define PRN_DEFINE(suffix, var, a, c) \
1706 static inline void \
1707 sprn_##suffix(uint32_t seed) \
1712 static inline uint32_t \
1713 prn_##suffix(uint32_t lg_range) \
1717 assert(lg_range > 0); \
1718 assert(lg_range <= 32); \
1720 x = (var * (a)) + (c); \
1722 ret = x >> (32 - lg_range); \
1726 # define SPRN(suffix, seed) sprn_##suffix(seed)
1727 # define PRN(suffix, lg_range) prn_##suffix(lg_range)
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)
1736 #ifdef MALLOC_UTRACE
1738 utrace(const void *addr, size_t len)
1740 malloc_utrace_t *ut = (malloc_utrace_t *)addr;
1742 assert(len == sizeof(malloc_utrace_t));
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,
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);
1753 malloc_printf("%d x USER free(%p)\n", getpid(), ut->p);
1759 static inline const char *
1763 return ("<jemalloc>");
1768 * Print to stderr in such a way as to (hopefully) avoid memory allocation.
1771 malloc_printf(const char *format, ...)
1777 va_start(ap, format);
1778 vsnprintf(buf, sizeof(buf), format, ap);
1780 _malloc_message(buf, "", "", "");
1785 /******************************************************************************/
1787 #ifdef MALLOC_DECOMMIT
1789 pages_decommit(void *addr, size_t size)
1792 #ifdef MOZ_MEMORY_WINDOWS
1793 VirtualFree(addr, size, MEM_DECOMMIT);
1795 if (mmap(addr, size, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1,
1802 pages_commit(void *addr, size_t size)
1805 # ifdef MOZ_MEMORY_WINDOWS
1806 VirtualAlloc(addr, size, MEM_COMMIT, PAGE_READWRITE);
1808 if (mmap(addr, size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE |
1809 MAP_ANON, -1, 0) == MAP_FAILED)
1816 base_pages_alloc_mmap(size_t minsize)
1820 #ifdef MALLOC_DECOMMIT
1825 assert(minsize != 0);
1826 csize = CHUNK_CEILING(minsize);
1827 #ifdef MALLOC_PAGEFILE
1829 pfd = pagefile_init(csize);
1835 base_pages = pages_map(NULL, csize, pfd);
1836 if (base_pages == NULL) {
1840 base_next_addr = base_pages;
1841 base_past_addr = (void *)((uintptr_t)base_pages + csize);
1842 #ifdef MALLOC_DECOMMIT
1844 * Leave enough pages for minsize committed, since otherwise they would
1845 * have to be immediately recommitted.
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);
1853 base_mapped += csize;
1858 #ifdef MALLOC_PAGEFILE
1860 pagefile_close(pfd);
1866 base_pages_alloc(size_t minsize)
1869 if (base_pages_alloc_mmap(minsize) == false)
1876 base_alloc(size_t size)
1881 /* Round size up to nearest multiple of the cacheline size. */
1882 csize = CACHELINE_CEILING(size);
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);
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));
1901 pages_commit(base_next_decommitted, (uintptr_t)pbase_next_addr -
1902 (uintptr_t)base_next_decommitted);
1903 base_next_decommitted = pbase_next_addr;
1906 malloc_mutex_unlock(&base_mtx);
1907 VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, false);
1913 base_calloc(size_t number, size_t size)
1917 ret = base_alloc(number * size);
1918 #ifdef MALLOC_VALGRIND
1920 VALGRIND_FREELIKE_BLOCK(ret, 0);
1921 VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, true);
1924 memset(ret, 0, number * size);
1929 static extent_node_t *
1930 base_node_alloc(void)
1934 malloc_mutex_lock(&base_mtx);
1935 if (base_nodes != NULL) {
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);
1942 malloc_mutex_unlock(&base_mtx);
1943 ret = (extent_node_t *)base_alloc(sizeof(extent_node_t));
1950 base_node_dealloc(extent_node_t *node)
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;
1958 malloc_mutex_unlock(&base_mtx);
1961 static reserve_reg_t *
1962 base_reserve_reg_alloc(void)
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);
1974 malloc_mutex_unlock(&base_mtx);
1975 ret = (reserve_reg_t *)base_alloc(sizeof(reserve_reg_t));
1982 base_reserve_reg_dealloc(reserve_reg_t *reg)
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);
1993 /******************************************************************************/
1997 stats_print(arena_t *arena)
1999 unsigned i, gap_start;
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");
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);
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");
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);
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)
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",
2071 /* Gap of one size class. */
2072 malloc_printf("[%u]\n", gap_start);
2074 gap_start = UINT_MAX;
2077 #if defined(MOZ_MEMORY_WINDOWS)
2078 "%13u %1s %4u %4u %3u %9I64u %9I64u"
2079 " %9I64u %7u %7u\n",
2081 "%13u %1s %4u %4u %3u %9llu %9llu"
2082 " %9llu %7lu %7lu\n",
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);
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);
2101 /* Gap of one size class. */
2102 malloc_printf("[%u]\n", gap_start);
2109 * End Utility functions/macros.
2111 /******************************************************************************/
2113 * Begin extent tree code.
2117 extent_szad_comp(extent_node_t *a, extent_node_t *b)
2120 size_t a_size = a->size;
2121 size_t b_size = b->size;
2123 ret = (a_size > b_size) - (a_size < b_size);
2125 uintptr_t a_addr = (uintptr_t)a->addr;
2126 uintptr_t b_addr = (uintptr_t)b->addr;
2128 ret = (a_addr > b_addr) - (a_addr < b_addr);
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)
2139 extent_ad_comp(extent_node_t *a, extent_node_t *b)
2141 uintptr_t a_addr = (uintptr_t)a->addr;
2142 uintptr_t b_addr = (uintptr_t)b->addr;
2144 return ((a_addr > b_addr) - (a_addr < b_addr));
2147 /* Wrap red-black tree macros in functions. */
2148 rb_wrap(static, extent_tree_ad_, extent_tree_t, extent_node_t, link_ad,
2152 * End extent tree code.
2154 /******************************************************************************/
2156 * Begin chunk management functions.
2159 #ifdef MOZ_MEMORY_WINDOWS
2160 #ifdef MOZ_MEMORY_WINCE
2161 #define ALIGN_ADDR2OFFSET(al, ad) \
2162 ((uintptr_t)ad & (al - 1))
2164 pages_map_align(size_t size, int pfd, size_t alignment)
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);
2175 /* try to over allocate by the ammount we're offset */
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,
2185 VirtualFree(tmp, 0, MEM_RELEASE);
2186 offset = ALIGN_ADDR2OFFSET(alignment, ret);
2190 /* over allocate to ensure we have an aligned region */
2191 ret = VirtualAlloc(NULL, size + alignment, MEM_RESERVE,
2193 offset = ALIGN_ADDR2OFFSET(alignment, ret);
2194 ret = VirtualAlloc((void*)((intptr_t)ret +
2195 alignment - offset),
2196 size, MEM_COMMIT, PAGE_READWRITE);
2204 pages_map(void *addr, size_t size, int pfd)
2207 #if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6)
2209 assert(addr == NULL);
2210 va_ret = VirtualAlloc(addr, size, MEM_RESERVE, PAGE_NOACCESS);
2212 ret = VirtualAlloc(va_ret, size, MEM_COMMIT, PAGE_READWRITE);
2213 assert(va_ret == ret);
2215 ret = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE,
2222 pages_unmap(void *addr, size_t size)
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))
2233 _malloc_message(_getprogname(),
2234 ": (malloc) Error in VirtualFree()\n", "", "");
2239 #elif (defined(MOZ_MEMORY_DARWIN))
2241 pages_map(void *addr, size_t size, int pfd)
2251 flags = VM_FLAGS_ANYWHERE;
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)
2258 assert(ret == NULL || (addr == NULL && ret != addr)
2259 || (addr != NULL && ret == addr));
2264 pages_unmap(void *addr, size_t size)
2268 err = vm_deallocate((vm_map_t)mach_task_self(), (vm_address_t)addr,
2270 if (err != KERN_SUCCESS) {
2271 malloc_message(_getprogname(),
2272 ": (malloc) Error in vm_deallocate(): ",
2273 mach_error_string(err), "\n");
2279 #define VM_COPY_MIN (pagesize << 5)
2281 pages_copy(void *dest, const void *src, size_t n)
2284 assert((void *)((uintptr_t)dest & ~pagesize_mask) == dest);
2285 assert(n >= VM_COPY_MIN);
2286 assert((void *)((uintptr_t)src & ~pagesize_mask) == src);
2288 vm_copy(mach_task_self(), (vm_address_t)src, (vm_size_t)n,
2289 (vm_address_t)dest);
2291 #else /* MOZ_MEMORY_DARWIN */
2292 #ifdef JEMALLOC_USES_MAP_ALIGN
2294 pages_map_align(size_t size, int pfd, size_t alignment)
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.
2302 #ifdef MALLOC_PAGEFILE
2304 ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
2305 MAP_NOSYNC | MAP_ALIGN, pfd, 0);
2309 ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
2310 MAP_NOSYNC | MAP_ALIGN | MAP_ANON, -1, 0);
2312 assert(ret != NULL);
2314 if (ret == MAP_FAILED)
2321 pages_map(void *addr, size_t size, int pfd)
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.
2329 #ifdef MALLOC_PAGEFILE
2331 ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
2332 MAP_NOSYNC, pfd, 0);
2336 ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
2339 assert(ret != NULL);
2341 if (ret == MAP_FAILED)
2343 else if (addr != NULL && ret != addr) {
2345 * We succeeded in mapping memory, but not in the right place.
2347 if (munmap(ret, size) == -1) {
2348 char buf[STRERROR_BUF];
2350 strerror_r(errno, buf, sizeof(buf));
2351 _malloc_message(_getprogname(),
2352 ": (malloc) Error in munmap(): ", buf, "\n");
2359 assert(ret == NULL || (addr == NULL && ret != addr)
2360 || (addr != NULL && ret == addr));
2365 pages_unmap(void *addr, size_t size)
2368 if (munmap(addr, size) == -1) {
2369 char buf[STRERROR_BUF];
2371 strerror_r(errno, buf, sizeof(buf));
2372 _malloc_message(_getprogname(),
2373 ": (malloc) Error in munmap(): ", buf, "\n");
2380 #ifdef MALLOC_VALIDATE
2381 static inline malloc_rtree_t *
2382 malloc_rtree_new(unsigned bits)
2384 malloc_rtree_t *ret;
2385 unsigned bits_per_level, height, i;
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)
2392 assert(height * bits_per_level >= bits);
2394 ret = (malloc_rtree_t*)base_calloc(1, sizeof(malloc_rtree_t) + (sizeof(unsigned) *
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;
2404 ret->level2bits[0] = bits_per_level;
2405 for (i = 1; i < height; i++)
2406 ret->level2bits[i] = bits_per_level;
2408 ret->root = (void**)base_calloc(1, sizeof(void *) << ret->level2bits[0]);
2409 if (ret->root == NULL) {
2411 * We leak the rtree here, since there's no generic base
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)
2426 unsigned i, lshift, height, bits;
2427 void **node, **child;
2429 malloc_spin_lock(&rtree->lock);
2430 for (i = lshift = 0, height = rtree->height, node = rtree->root;
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);
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);
2446 malloc_spin_unlock(&rtree->lock);
2452 malloc_rtree_set(malloc_rtree_t *rtree, uintptr_t key, void *val)
2455 unsigned i, lshift, height, bits;
2456 void **node, **child;
2458 malloc_spin_lock(&rtree->lock);
2459 for (i = lshift = 0, height = rtree->height, node = rtree->root;
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);
2472 node[subkey] = child;
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);
2480 malloc_spin_unlock(&rtree->lock);
2487 chunk_alloc_mmap(size_t size, bool pagefile)
2490 #ifndef JEMALLOC_USES_MAP_ALIGN
2495 #ifdef MALLOC_PAGEFILE
2496 if (opt_pagefile && pagefile) {
2497 pfd = pagefile_init(size);
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.
2510 * The MALLOC_PAGEFILE code also benefits from this mapping algorithm,
2511 * since it reduces the number of page files.
2514 #ifdef JEMALLOC_USES_MAP_ALIGN
2515 ret = pages_map_align(size, pfd, chunksize);
2517 ret = pages_map(NULL, size, pfd);
2521 offset = CHUNK_ADDR2OFFSET(ret);
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,
2527 while (ret == NULL) {
2529 * Over-allocate in order to map a memory region that
2530 * is definitely large enough.
2532 ret = pages_map(NULL, size + chunksize, -1);
2536 * Deallocate, then allocate the correct size, within
2537 * the over-sized mapping.
2539 offset = CHUNK_ADDR2OFFSET(ret);
2540 pages_unmap(ret, size + chunksize);
2542 ret = pages_map(ret, size, pfd);
2544 ret = pages_map((void *)((uintptr_t)ret +
2545 chunksize - offset), size, pfd);
2548 * Failure here indicates a race with another thread, so
2555 #ifdef MALLOC_PAGEFILE
2557 pagefile_close(pfd);
2561 stats_chunks.nchunks += (size / chunksize);
2566 #ifdef MALLOC_PAGEFILE
2568 pagefile_init(size_t size)
2572 char pagefile_path[PATH_MAX];
2573 char zbuf[MALLOC_PAGEFILE_WRITE_SIZE];
2576 * Create a temporary file, then immediately unlink it so that it will
2579 strcpy(pagefile_path, pagefile_templ);
2580 ret = mkstemp(pagefile_path);
2583 if (unlink(pagefile_path)) {
2584 char buf[STRERROR_BUF];
2586 strerror_r(errno, buf, sizeof(buf));
2587 _malloc_message(_getprogname(), ": (malloc) Error in unlink(\"",
2588 pagefile_path, "\"):");
2589 _malloc_message(buf, "\n", "", "");
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.
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];
2606 strerror_r(errno, buf, sizeof(buf));
2607 _malloc_message(_getprogname(),
2608 ": (malloc) Error in write(): ", buf, "\n");
2612 pagefile_close(ret);
2621 pagefile_close(int pfd)
2625 char buf[STRERROR_BUF];
2627 strerror_r(errno, buf, sizeof(buf));
2628 _malloc_message(_getprogname(),
2629 ": (malloc) Error in close(): ", buf, "\n");
2637 chunk_recycle_reserve(size_t size, bool zero)
2639 extent_node_t *node, key;
2641 #ifdef MALLOC_DECOMMIT
2642 if (size != chunksize)
2648 malloc_mutex_lock(&reserve_mtx);
2649 node = extent_tree_szad_nsearch(&reserve_chunks_szad, &key);
2651 void *ret = node->addr;
2653 /* Remove node from the tree. */
2654 extent_tree_szad_remove(&reserve_chunks_szad, node);
2655 #ifndef MALLOC_DECOMMIT
2656 if (node->size == size) {
2658 assert(node->size == size);
2660 extent_tree_ad_remove(&reserve_chunks_ad, node);
2661 base_node_dealloc(node);
2662 #ifndef MALLOC_DECOMMIT
2665 * Insert the remainder of node's address range as a
2666 * smaller chunk. Its position within reserve_chunks_ad
2669 assert(node->size > size);
2670 node->addr = (void *)((uintptr_t)node->addr + size);
2672 extent_tree_szad_insert(&reserve_chunks_szad, node);
2675 reserve_cur -= size;
2677 * Try to replenish the reserve if this allocation depleted it.
2679 #ifndef MALLOC_DECOMMIT
2680 if (reserve_cur < reserve_min) {
2681 size_t diff = reserve_min - reserve_cur;
2683 while (reserve_cur < reserve_min) {
2684 # define diff chunksize
2688 malloc_mutex_unlock(&reserve_mtx);
2689 chunk = chunk_alloc_mmap(diff, true);
2690 malloc_mutex_lock(&reserve_mtx);
2691 if (chunk == NULL) {
2695 seq = reserve_notify(RESERVE_CND_LOW,
2699 } while (reserve_cur < reserve_min);
2701 extent_node_t *node;
2703 node = chunk_dealloc_reserve(chunk, diff);
2707 pages_unmap(chunk, diff);
2709 seq = reserve_notify(
2710 RESERVE_CND_LOW, size, seq);
2713 } while (reserve_cur < reserve_min);
2718 malloc_mutex_unlock(&reserve_mtx);
2720 #ifdef MALLOC_DECOMMIT
2721 pages_commit(ret, size);
2725 memset(ret, 0, size);
2729 malloc_mutex_unlock(&reserve_mtx);
2735 chunk_alloc(size_t size, bool zero, bool pagefile)
2740 assert((size & chunksize_mask) == 0);
2742 ret = chunk_recycle_reserve(size, zero);
2746 ret = chunk_alloc_mmap(size, pagefile);
2751 /* All strategies for allocation failed. */
2756 stats_chunks.curchunks += (size / chunksize);
2757 if (stats_chunks.curchunks > stats_chunks.highchunks)
2758 stats_chunks.highchunks = stats_chunks.curchunks;
2761 #ifdef MALLOC_VALIDATE
2763 if (malloc_rtree_set(chunk_rtree, (uintptr_t)ret, ret)) {
2764 chunk_dealloc(ret, size);
2770 assert(CHUNK_ADDR2BASE(ret) == ret);
2774 static extent_node_t *
2775 chunk_dealloc_reserve(void *chunk, size_t size)
2777 extent_node_t *node;
2779 #ifdef MALLOC_DECOMMIT
2780 if (size != chunksize)
2783 extent_node_t *prev, key;
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) {
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.
2794 extent_tree_szad_remove(&reserve_chunks_szad, node);
2797 extent_tree_szad_insert(&reserve_chunks_szad, node);
2800 /* Coalescing forward failed, so insert a new node. */
2801 node = base_node_alloc();
2806 extent_tree_ad_insert(&reserve_chunks_ad, node);
2807 extent_tree_szad_insert(&reserve_chunks_szad, node);
2808 #ifndef MALLOC_DECOMMIT
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) ==
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.
2820 extent_tree_szad_remove(&reserve_chunks_szad, prev);
2821 extent_tree_ad_remove(&reserve_chunks_ad, prev);
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);
2828 base_node_dealloc(prev);
2832 #ifdef MALLOC_DECOMMIT
2833 pages_decommit(chunk, size);
2835 madvise(chunk, size, MADV_FREE);
2838 reserve_cur += size;
2839 if (reserve_cur > reserve_max)
2846 chunk_dealloc_mmap(void *chunk, size_t size)
2849 pages_unmap(chunk, size);
2853 chunk_dealloc(void *chunk, size_t size)
2855 extent_node_t *node;
2857 assert(chunk != NULL);
2858 assert(CHUNK_ADDR2BASE(chunk) == chunk);
2860 assert((size & chunksize_mask) == 0);
2863 stats_chunks.curchunks -= (size / chunksize);
2865 #ifdef MALLOC_VALIDATE
2866 malloc_rtree_set(chunk_rtree, (uintptr_t)chunk, NULL);
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);
2874 chunk_dealloc_mmap(chunk, size);
2878 * End chunk management functions.
2880 /******************************************************************************/
2886 * Choose an arena based on a per-thread value (fast-path code, calls slow-path
2887 * code if necessary).
2889 static inline arena_t *
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.
2900 if (__isthreaded == false) {
2901 /* Avoid the overhead of TLS for single-threaded operation. */
2905 # ifdef MOZ_MEMORY_WINDOWS
2906 ret = (arena_t*)TlsGetValue(tlsIndex);
2912 ret = choose_arena_hard();
2913 assert(ret != NULL);
2916 if (__isthreaded && narenas > 1) {
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.
2927 ind = (unsigned long) _pthread_self() % narenas;
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.
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.
2945 * Avoid races with another thread that may have already
2946 * initialized arenas[ind].
2948 malloc_spin_lock(&arenas_lock);
2949 if (arenas[ind] == NULL)
2950 ret = arenas_extend((unsigned)ind);
2953 malloc_spin_unlock(&arenas_lock);
2959 assert(ret != NULL);
2965 * Choose an arena based on a per-thread value (slow-path code only, called
2966 * only by choose_arena()).
2969 choose_arena_hard(void)
2973 assert(__isthreaded);
2975 #ifdef MALLOC_BALANCE
2976 /* Seed the PRNG used for arena load balancing. */
2977 SPRN(balance, (uint32_t)(uintptr_t)(_pthread_self()));
2981 #ifdef MALLOC_BALANCE
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);
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);
3001 #ifdef MOZ_MEMORY_WINDOWS
3002 TlsSetValue(tlsIndex, ret);
3012 arena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b)
3014 uintptr_t a_chunk = (uintptr_t)a;
3015 uintptr_t b_chunk = (uintptr_t)b;
3020 return ((a_chunk > b_chunk) - (a_chunk < b_chunk));
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)
3028 arena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
3030 uintptr_t a_mapelm = (uintptr_t)a;
3031 uintptr_t b_mapelm = (uintptr_t)b;
3036 return ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm));
3039 /* Wrap red-black tree macros in functions. */
3040 rb_wrap(static, arena_run_tree_, arena_run_tree_t, arena_chunk_map_t, link,
3044 arena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
3047 size_t a_size = a->bits & ~pagesize_mask;
3048 size_t b_size = b->bits & ~pagesize_mask;
3050 ret = (a_size > b_size) - (a_size < b_size);
3052 uintptr_t a_mapelm, b_mapelm;
3054 if ((a->bits & CHUNK_MAP_KEY) == 0)
3055 a_mapelm = (uintptr_t)a;
3058 * Treat keys as though they are lower than anything
3063 b_mapelm = (uintptr_t)b;
3065 ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm);
3071 /* Wrap red-black tree macros in functions. */
3072 rb_wrap(static, arena_avail_tree_, arena_avail_tree_t, arena_chunk_map_t, link,
3075 static inline void *
3076 arena_run_reg_alloc(arena_run_t *run, arena_bin_t *bin)
3079 unsigned i, mask, bit, regind;
3081 assert(run->magic == ARENA_RUN_MAGIC);
3082 assert(run->regs_minelm < bin->regs_mask_nelms);
3085 * Move the first check outside the loop, so that run->regs_minelm can
3086 * be updated unconditionally, without the possibility of updating it
3089 i = run->regs_minelm;
3090 mask = run->regs_mask[i];
3092 /* Usable allocation found. */
3093 bit = ffs((int)mask) - 1;
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));
3101 mask ^= (1U << bit);
3102 run->regs_mask[i] = mask;
3107 for (i++; i < bin->regs_mask_nelms; i++) {
3108 mask = run->regs_mask[i];
3110 /* Usable allocation found. */
3111 bit = ffs((int)mask) - 1;
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));
3119 mask ^= (1U << bit);
3120 run->regs_mask[i] = mask;
3123 * Make a note that nothing before this element
3124 * contains a free region.
3126 run->regs_minelm = i; /* Low payoff: + (mask == 0); */
3137 arena_run_reg_dalloc(arena_run_t *run, arena_bin_t *bin, void *ptr, size_t size)
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.
3147 * (X * size_invs[(D >> QUANTUM_2POW_MIN) - 3]) >> SIZE_INV_SHIFT
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[] = {
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)
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)
3172 unsigned diff, regind, elm, bit;
3174 assert(run->magic == ARENA_RUN_MAGIC);
3175 assert(((sizeof(size_invs)) / sizeof(unsigned)) + 3
3176 >= (SMALL_MAX_DEFAULT >> QUANTUM_2POW_MIN));
3179 * Avoid doing division with a variable divisor if possible. Using
3180 * actual division here can reduce allocator throughput by over 20%!
3182 diff = (unsigned)((uintptr_t)ptr - (uintptr_t)run - bin->reg0_offset);
3183 if ((size & (size - 1)) == 0) {
3185 * log2_table allows fast division of a power of two in the
3188 * (x / divisor) becomes (x >> log2_table[divisor - 1]).
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
3202 regind = (diff >> log2_table[size - 1]);
3203 else if (size <= 32768)
3204 regind = diff >> (8 + log2_table[(size >> 8) - 1]);
3207 * The run size is too large for us to use the lookup
3208 * table. Use real division.
3210 regind = diff / size;
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;
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.
3223 regind = diff / size;
3225 assert(diff == regind * size);
3226 assert(regind < bin->nregs);
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);
3235 #undef SIZE_INV_SHIFT
3239 arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large,
3242 arena_chunk_t *chunk;
3243 size_t old_ndirty, run_ind, total_pages, need_pages, rem_pages, i;
3245 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
3246 old_ndirty = chunk->ndirty;
3247 run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk)
3249 total_pages = (chunk->map[run_ind].bits & ~pagesize_mask) >>
3251 need_pages = (size >> pagesize_2pow);
3252 assert(need_pages > 0);
3253 assert(need_pages <= total_pages);
3254 rem_pages = total_pages - need_pages;
3256 arena_avail_tree_remove(&arena->runs_avail, &chunk->map[run_ind]);
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 &
3263 chunk->map[run_ind+total_pages-1].bits = (rem_pages <<
3264 pagesize_2pow) | (chunk->map[run_ind+total_pages-1].bits &
3266 arena_avail_tree_insert(&arena->runs_avail,
3267 &chunk->map[run_ind+need_pages]);
3270 for (i = 0; i < need_pages; i++) {
3271 #ifdef MALLOC_DECOMMIT
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
3278 if (chunk->map[run_ind + i].bits & CHUNK_MAP_DECOMMITTED) {
3282 * Advance i+j to just past the index of the last page
3283 * to commit. Clear CHUNK_MAP_DECOMMITTED along the
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;
3292 pages_commit((void *)((uintptr_t)chunk + ((run_ind + i)
3293 << pagesize_2pow)), (j << pagesize_2pow));
3294 # ifdef MALLOC_STATS
3295 arena->stats.ncommit++;
3297 } else /* No need to zero since commit zeros. */
3300 /* Zero if necessary. */
3302 if ((chunk->map[run_ind + i].bits & CHUNK_MAP_ZEROED)
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)),
3312 /* CHUNK_MAP_ZEROED is cleared below. */
3316 /* Update dirty page accounting. */
3317 if (chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY) {
3320 /* CHUNK_MAP_DIRTY is cleared below. */
3323 /* Initialize the chunk map. */
3325 chunk->map[run_ind + i].bits = CHUNK_MAP_LARGE
3326 | CHUNK_MAP_ALLOCATED;
3328 chunk->map[run_ind + i].bits = (size_t)run
3329 | CHUNK_MAP_ALLOCATED;
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
3340 chunk->map[run_ind].bits |= size;
3342 if (chunk->ndirty == 0 && old_ndirty > 0)
3343 arena_chunk_tree_dirty_remove(&arena->chunks_dirty, chunk);
3347 arena_chunk_init(arena_t *arena, arena_chunk_t *chunk)
3352 VALGRIND_MALLOCLIKE_BLOCK(chunk, (arena_chunk_header_npages <<
3353 pagesize_2pow), 0, false);
3355 arena->stats.mapped += chunksize;
3358 chunk->arena = arena;
3361 * Claim that no pages are in use, since the header is merely overhead.
3365 /* Initialize the map to contain one maximal free untouched run. */
3366 run = (arena_run_t *)((uintptr_t)chunk + (arena_chunk_header_npages <<
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
3375 for (i++; i < chunk_npages-1; i++) {
3376 chunk->map[i].bits =
3377 #ifdef MALLOC_DECOMMIT
3378 CHUNK_MAP_DECOMMITTED |
3382 chunk->map[chunk_npages-1].bits = arena_maxclass
3383 #ifdef MALLOC_DECOMMIT
3384 | CHUNK_MAP_DECOMMITTED
3388 #ifdef MALLOC_DECOMMIT
3390 * Start out decommitted, in order to force a closer correspondence
3391 * between dirty pages and committed untouched pages.
3393 pages_decommit(run, arena_maxclass);
3394 # ifdef MALLOC_STATS
3395 arena->stats.ndecommit++;
3396 arena->stats.decommitted += (chunk_npages - arena_chunk_header_npages);
3400 /* Insert the run into the runs_avail tree. */
3401 arena_avail_tree_insert(&arena->runs_avail,
3402 &chunk->map[arena_chunk_header_npages]);
3406 arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk)
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;
3415 VALGRIND_FREELIKE_BLOCK(arena->spare, 0);
3416 chunk_dealloc((void *)arena->spare, chunksize);
3418 arena->stats.mapped -= chunksize;
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.
3428 arena_avail_tree_remove(&arena->runs_avail,
3429 &chunk->map[arena_chunk_header_npages]);
3431 arena->spare = chunk;
3434 static arena_run_t *
3435 arena_run_alloc(arena_t *arena, arena_bin_t *bin, size_t size, bool large,
3438 arena_chunk_t *chunk;
3440 arena_chunk_map_t *mapelm, key;
3442 assert(size <= arena_maxclass);
3443 assert((size & pagesize_mask) == 0);
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);
3457 chunk_dealloc(chunk, chunksize);
3458 run = (arena_run_t *)((uintptr_t)run_chunk + (pageind
3460 arena_run_split(arena, run, size, large, zero);
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);
3478 * No usable runs. Create a new chunk from which to allocate
3481 if (chunk == NULL) {
3485 * Record the chunk allocation sequence number in order
3489 chunk_seq = arena->chunk_seq;
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.
3497 malloc_mutex_unlock(&arena->lock);
3498 chunk = (arena_chunk_t *)chunk_alloc(chunksize, true,
3500 malloc_mutex_lock(&arena->lock);
3503 * Check whether a race allowed a usable run to appear.
3505 if (bin != NULL && (run = bin->runcur) != NULL &&
3508 chunk_dealloc(chunk, chunksize);
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.
3517 if (chunk_seq != arena->chunk_seq)
3521 * Check for an error *after* checking for a race,
3522 * since a race could also cause a transient OOM
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);
3539 arena_purge(arena_t *arena)
3541 arena_chunk_t *chunk;
3545 rb_foreach_begin(arena_chunk_t, link_dirty, &arena->chunks_dirty,
3547 ndirty += chunk->ndirty;
3548 } rb_foreach_end(arena_chunk_t, link_dirty, &arena->chunks_dirty, chunk)
3549 assert(ndirty == arena->ndirty);
3551 assert(arena->ndirty > opt_dirty_max);
3554 arena->stats.npurge++;
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
3563 while (arena->ndirty > (opt_dirty_max >> 1)) {
3564 chunk = arena_chunk_tree_dirty_last(&arena->chunks_dirty);
3565 assert(chunk != NULL);
3567 for (i = chunk_npages - 1; chunk->ndirty > 0; i--) {
3568 assert(i >= arena_chunk_header_npages);
3570 if (chunk->map[i].bits & CHUNK_MAP_DIRTY) {
3571 #ifdef MALLOC_DECOMMIT
3572 assert((chunk->map[i].bits &
3573 CHUNK_MAP_DECOMMITTED) == 0);
3575 chunk->map[i].bits ^=
3576 #ifdef MALLOC_DECOMMIT
3577 CHUNK_MAP_DECOMMITTED |
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++) {
3585 #ifdef MALLOC_DECOMMIT
3586 assert((chunk->map[i].bits &
3587 CHUNK_MAP_DECOMMITTED) == 0);
3589 chunk->map[i].bits ^=
3590 #ifdef MALLOC_DECOMMIT
3591 CHUNK_MAP_DECOMMITTED |
3595 chunk->ndirty -= npages;
3596 arena->ndirty -= npages;
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;
3607 madvise((void *)((uintptr_t)chunk + (i <<
3608 pagesize_2pow)), (npages << pagesize_2pow),
3612 arena->stats.nmadvise++;
3613 arena->stats.purged += npages;
3615 if (arena->ndirty <= (opt_dirty_max >> 1))
3620 if (chunk->ndirty == 0) {
3621 arena_chunk_tree_dirty_remove(&arena->chunks_dirty,
3628 arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty)
3630 arena_chunk_t *chunk;
3631 size_t size, run_ind, run_pages;
3633 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
3634 run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk)
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;
3641 size = run->bin->run_size;
3642 run_pages = (size >> pagesize_2pow);
3644 /* Mark pages as unallocated in the chunk map. */
3648 for (i = 0; i < run_pages; i++) {
3649 assert((chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY)
3651 chunk->map[run_ind + i].bits = CHUNK_MAP_DIRTY;
3654 if (chunk->ndirty == 0) {
3655 arena_chunk_tree_dirty_insert(&arena->chunks_dirty,
3658 chunk->ndirty += run_pages;
3659 arena->ndirty += run_pages;
3663 for (i = 0; i < run_pages; i++) {
3664 chunk->map[run_ind + i].bits &= ~(CHUNK_MAP_LARGE |
3665 CHUNK_MAP_ALLOCATED);
3668 chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
3670 chunk->map[run_ind+run_pages-1].bits = size |
3671 (chunk->map[run_ind+run_pages-1].bits & pagesize_mask);
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 &
3680 * Remove successor from runs_avail; the coalesced run is
3683 arena_avail_tree_remove(&arena->runs_avail,
3684 &chunk->map[run_ind+run_pages]);
3687 run_pages = size >> pagesize_2pow;
3689 assert((chunk->map[run_ind+run_pages-1].bits & ~pagesize_mask)
3691 chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
3693 chunk->map[run_ind+run_pages-1].bits = size |
3694 (chunk->map[run_ind+run_pages-1].bits & pagesize_mask);
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;
3702 run_ind -= prun_size >> pagesize_2pow;
3705 * Remove predecessor from runs_avail; the coalesced run is
3708 arena_avail_tree_remove(&arena->runs_avail,
3709 &chunk->map[run_ind]);
3712 run_pages = size >> pagesize_2pow;
3714 assert((chunk->map[run_ind].bits & ~pagesize_mask) ==
3716 chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
3718 chunk->map[run_ind+run_pages-1].bits = size |
3719 (chunk->map[run_ind+run_pages-1].bits & pagesize_mask);
3722 /* Insert into runs_avail, now that coalescing is complete. */
3723 arena_avail_tree_insert(&arena->runs_avail, &chunk->map[run_ind]);
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);
3730 /* Enforce opt_dirty_max. */
3731 if (arena->ndirty > opt_dirty_max)
3736 arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
3737 size_t oldsize, size_t newsize)
3739 size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> pagesize_2pow;
3740 size_t head_npages = (oldsize - newsize) >> pagesize_2pow;
3742 assert(oldsize > newsize);
3745 * Update the chunk map so that arena_run_dalloc() can treat the
3746 * leading run as separately allocated.
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;
3753 arena_run_dalloc(arena, run, false);
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)
3760 size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> pagesize_2pow;
3761 size_t npages = newsize >> pagesize_2pow;
3763 assert(oldsize > newsize);
3766 * Update the chunk map so that arena_run_dalloc() can treat the
3767 * trailing run as separately allocated.
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;
3774 arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize),
3778 static arena_run_t *
3779 arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin)
3781 arena_chunk_map_t *mapelm;
3783 unsigned i, remainder;
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);
3792 bin->stats.reruns++;
3796 /* No existing runs have any space available. */
3798 /* Allocate a new run. */
3799 run = arena_run_alloc(arena, bin, bin->run_size, false, false);
3803 * Don't initialize if a race in arena_run_alloc() allowed an existing
3804 * run to become usable.
3806 if (run == bin->runcur)
3809 VALGRIND_MALLOCLIKE_BLOCK(run, sizeof(arena_run_t) + (sizeof(unsigned) *
3810 (bin->regs_mask_nelms - 1)), 0, false);
3812 /* Initialize run internals. */
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);
3819 run->regs_mask[i] = UINT_MAX;
3821 /* The last element has spare bits that need to be unset. */
3822 run->regs_mask[i] = (UINT_MAX >> ((1U << (SIZEOF_INT_2POW + 3))
3826 run->regs_minelm = 0;
3828 run->nfree = bin->nregs;
3830 run->magic = ARENA_RUN_MAGIC;
3835 bin->stats.curruns++;
3836 if (bin->stats.curruns > bin->stats.highruns)
3837 bin->stats.highruns = bin->stats.curruns;
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)
3848 assert(run->magic == ARENA_RUN_MAGIC);
3849 assert(run->nfree > 0);
3851 ret = arena_run_reg_alloc(run, bin);
3852 assert(ret != NULL);
3858 /* Re-fill bin->runcur, then call arena_bin_malloc_easy(). */
3860 arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)
3863 bin->runcur = arena_bin_nonfull_run_get(arena, bin);
3864 if (bin->runcur == NULL)
3866 assert(bin->runcur->magic == ARENA_RUN_MAGIC);
3867 assert(bin->runcur->nfree > 0);
3869 return (arena_bin_malloc_easy(arena, bin, bin->runcur));
3873 * Calculate bin->run_size such that it meets the following constraints:
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).
3880 * bin->nregs, bin->regs_mask_nelms, and bin->reg0_offset are
3881 * also calculated here, since these settings are all interdependent.
3884 arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size)
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;
3890 assert(min_run_size >= pagesize);
3891 assert(min_run_size <= arena_maxclass);
3892 assert(min_run_size <= RUN_MAX_SMALL);
3895 * Calculate known-valid settings before entering the run_size
3896 * expansion loop, so that the first part of the loop always copies
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.
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. */
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))
3915 /* run_size expansion loop. */
3918 * Copy valid settings before trying more aggressive settings.
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;
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. */
3931 try_mask_nelms = (try_nregs >> (SIZEOF_INT_2POW + 3)) +
3932 ((try_nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1)) ?
3934 try_reg0_offset = try_run_size - (try_nregs *
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);
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);
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;
3952 return (good_run_size);
3955 #ifdef MALLOC_BALANCE
3957 arena_lock_balance(arena_t *arena)
3959 unsigned contention;
3961 contention = malloc_spin_lock(&arena->lock);
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.
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);
3977 arena_lock_balance_hard(arena_t *arena)
3981 arena->contention = 0;
3983 arena->stats.nbalance++;
3985 ind = PRN(balance, narenas_2pow);
3986 if (arenas[ind] != NULL) {
3987 #ifdef MOZ_MEMORY_WINDOWS
3988 TlsSetValue(tlsIndex, arenas[ind]);
3990 arenas_map = arenas[ind];
3993 malloc_spin_lock(&arenas_lock);
3994 if (arenas[ind] != NULL) {
3995 #ifdef MOZ_MEMORY_WINDOWS
3996 TlsSetValue(tlsIndex, arenas[ind]);
3998 arenas_map = arenas[ind];
4001 #ifdef MOZ_MEMORY_WINDOWS
4002 TlsSetValue(tlsIndex, arenas_extend(ind));
4004 arenas_map = arenas_extend(ind);
4007 malloc_spin_unlock(&arenas_lock);
4012 static inline void *
4013 arena_malloc_small(arena_t *arena, size_t size, bool zero)
4019 if (size < small_min) {
4021 size = pow2_ceil(size);
4022 bin = &arena->bins[ffs((int)(size >> (TINY_MIN_2POW +
4024 #if (!defined(NDEBUG) || defined(MALLOC_STATS))
4026 * Bin calculation is always correct, but we may need
4027 * to fix size for the purposes of assertions and/or
4030 if (size < (1U << TINY_MIN_2POW))
4031 size = (1U << TINY_MIN_2POW);
4033 } else if (size <= small_max) {
4034 /* Quantum-spaced. */
4035 size = QUANTUM_CEILING(size);
4036 bin = &arena->bins[ntbins + (size >> opt_quantum_2pow)
4040 size = pow2_ceil(size);
4041 bin = &arena->bins[ntbins + nqbins
4042 + (ffs((int)(size >> opt_small_max_2pow)) - 2)];
4044 assert(size == bin->reg_size);
4046 #ifdef MALLOC_BALANCE
4047 arena_lock_balance(arena);
4049 malloc_spin_lock(&arena->lock);
4051 if ((run = bin->runcur) != NULL && run->nfree > 0)
4052 ret = arena_bin_malloc_easy(arena, bin, run);
4054 ret = arena_bin_malloc_hard(arena, bin);
4057 malloc_spin_unlock(&arena->lock);
4062 bin->stats.nrequests++;
4063 arena->stats.nmalloc_small++;
4064 arena->stats.allocated_small += size;
4066 malloc_spin_unlock(&arena->lock);
4068 VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, zero);
4069 if (zero == false) {
4072 memset(ret, 0xa5, size);
4074 memset(ret, 0, size);
4077 memset(ret, 0, size);
4083 arena_malloc_large(arena_t *arena, size_t size, bool zero)
4087 /* Large allocation. */
4088 size = PAGE_CEILING(size);
4089 #ifdef MALLOC_BALANCE
4090 arena_lock_balance(arena);
4092 malloc_spin_lock(&arena->lock);
4094 ret = (void *)arena_run_alloc(arena, NULL, size, true, zero);
4096 malloc_spin_unlock(&arena->lock);
4100 arena->stats.nmalloc_large++;
4101 arena->stats.allocated_large += size;
4103 malloc_spin_unlock(&arena->lock);
4105 VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, zero);
4106 if (zero == false) {
4109 memset(ret, 0xa5, size);
4111 memset(ret, 0, size);
4118 static inline void *
4119 arena_malloc(arena_t *arena, size_t size, bool zero)
4122 assert(arena != NULL);
4123 assert(arena->magic == ARENA_MAGIC);
4125 assert(QUANTUM_CEILING(size) <= arena_maxclass);
4127 if (size <= bin_maxclass) {
4128 return (arena_malloc_small(arena, size, zero));
4130 return (arena_malloc_large(arena, size, zero));
4133 static inline void *
4134 imalloc(size_t size)
4139 if (size <= arena_maxclass)
4140 return (arena_malloc(choose_arena(), size, false));
4142 return (huge_malloc(size, false));
4145 static inline void *
4146 icalloc(size_t size)
4149 if (size <= arena_maxclass)
4150 return (arena_malloc(choose_arena(), size, true));
4152 return (huge_malloc(size, true));
4155 /* Only handles large allocations that require more than page alignment. */
4157 arena_palloc(arena_t *arena, size_t alignment, size_t size, size_t alloc_size)
4161 arena_chunk_t *chunk;
4163 assert((size & pagesize_mask) == 0);
4164 assert((alignment & pagesize_mask) == 0);
4166 #ifdef MALLOC_BALANCE
4167 arena_lock_balance(arena);
4169 malloc_spin_lock(&arena->lock);
4171 ret = (void *)arena_run_alloc(arena, NULL, alloc_size, true, false);
4173 malloc_spin_unlock(&arena->lock);
4177 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ret);
4179 offset = (uintptr_t)ret & (alignment - 1);
4180 assert((offset & pagesize_mask) == 0);
4181 assert(offset < alloc_size);
4183 arena_run_trim_tail(arena, chunk, (arena_run_t*)ret, alloc_size, size, false);
4185 size_t leadsize, trailsize;
4187 leadsize = alignment - offset;
4189 arena_run_trim_head(arena, chunk, (arena_run_t*)ret, alloc_size,
4190 alloc_size - leadsize);
4191 ret = (void *)((uintptr_t)ret + leadsize);
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,
4204 arena->stats.nmalloc_large++;
4205 arena->stats.allocated_large += size;
4207 malloc_spin_unlock(&arena->lock);
4209 VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, false);
4212 memset(ret, 0xa5, size);
4214 memset(ret, 0, size);
4219 static inline void *
4220 ipalloc(size_t alignment, size_t size)
4226 * Round size up to the nearest multiple of alignment.
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
4233 * Size | Base 2 | Minimum alignment
4234 * -----+----------+------------------
4236 * 144 | 10100000 | 32
4237 * 192 | 11000000 | 64
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.
4243 ceil_size = (size + (alignment - 1)) & (-alignment);
4245 * (ceil_size < size) protects against the combination of maximal
4246 * alignment and size greater than maximal alignment.
4248 if (ceil_size < size) {
4249 /* size_t overflow. */
4253 if (ceil_size <= pagesize || (alignment <= pagesize
4254 && ceil_size <= arena_maxclass))
4255 ret = arena_malloc(choose_arena(), ceil_size, false);
4260 * We can't achieve sub-page alignment, so round up alignment
4261 * permanently; it makes later calculations simpler.
4263 alignment = PAGE_CEILING(alignment);
4264 ceil_size = PAGE_CEILING(size);
4266 * (ceil_size < size) protects against very large sizes within
4267 * pagesize of SIZE_T_MAX.
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.
4277 if (ceil_size < size || ceil_size + alignment < ceil_size) {
4278 /* size_t overflow. */
4283 * Calculate the size of the over-size run that arena_palloc()
4284 * would need to allocate in order to guarantee the alignment.
4286 if (ceil_size >= alignment)
4287 run_size = ceil_size + alignment - pagesize;
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.
4298 run_size = (alignment << 1) - pagesize;
4301 if (run_size <= arena_maxclass) {
4302 ret = arena_palloc(choose_arena(), alignment, ceil_size,
4304 } else if (alignment <= chunksize)
4305 ret = huge_malloc(ceil_size, false);
4307 ret = huge_palloc(alignment, ceil_size);
4310 assert(((uintptr_t)ret & (alignment - 1)) == 0);
4314 /* Return the size of the allocation pointed to by ptr. */
4316 arena_salloc(const void *ptr)
4319 arena_chunk_t *chunk;
4320 size_t pageind, mapbits;
4322 assert(ptr != NULL);
4323 assert(CHUNK_ADDR2BASE(ptr) != ptr);
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;
4334 ret = mapbits & ~pagesize_mask;
4341 #if (defined(MALLOC_VALIDATE) || defined(MOZ_MEMORY_DARWIN))
4343 * Validate ptr before assuming that it points to an allocation. Currently,
4344 * the following validation is performed:
4346 * + Check that ptr is not NULL.
4348 * + Check that ptr lies within a mapped chunk.
4350 static inline size_t
4351 isalloc_validate(const void *ptr)
4353 arena_chunk_t *chunk;
4355 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
4359 if (malloc_rtree_get(chunk_rtree, (uintptr_t)chunk) == NULL)
4363 assert(chunk->arena->magic == ARENA_MAGIC);
4364 return (arena_salloc(ptr));
4367 extent_node_t *node;
4371 key.addr = (void *)chunk;
4372 malloc_mutex_lock(&huge_mtx);
4373 node = extent_tree_ad_search(&huge, &key);
4378 malloc_mutex_unlock(&huge_mtx);
4384 static inline size_t
4385 isalloc(const void *ptr)
4388 arena_chunk_t *chunk;
4390 assert(ptr != NULL);
4392 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
4395 assert(chunk->arena->magic == ARENA_MAGIC);
4397 ret = arena_salloc(ptr);
4399 extent_node_t *node, key;
4401 /* Chunk (huge allocation). */
4403 malloc_mutex_lock(&huge_mtx);
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);
4412 malloc_mutex_unlock(&huge_mtx);
4419 arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,
4420 arena_chunk_map_t *mapelm)
4426 run = (arena_run_t *)(mapelm->bits & ~pagesize_mask);
4427 assert(run->magic == ARENA_RUN_MAGIC);
4429 size = bin->reg_size;
4433 memset(ptr, 0x5a, size);
4436 arena_run_reg_dalloc(run, bin, ptr, size);
4439 if (run->nfree == bin->nregs) {
4440 /* Deallocate run. */
4441 if (run == bin->runcur)
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];
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.
4453 assert(arena_run_tree_search(&bin->runs, run_mapelm) ==
4455 arena_run_tree_remove(&bin->runs, run_mapelm);
4460 VALGRIND_FREELIKE_BLOCK(run, 0);
4461 arena_run_dalloc(arena, run, true);
4463 bin->stats.curruns--;
4465 } else if (run->nfree == 1 && run != bin->runcur) {
4467 * Make sure that bin->runcur always refers to the lowest
4468 * non-full run, if one exists.
4470 if (bin->runcur == NULL)
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];
4483 /* Insert runcur. */
4484 assert(arena_run_tree_search(&bin->runs,
4485 runcur_mapelm) == NULL);
4486 arena_run_tree_insert(&bin->runs,
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];
4496 assert(arena_run_tree_search(&bin->runs, run_mapelm) ==
4498 arena_run_tree_insert(&bin->runs, run_mapelm);
4502 arena->stats.allocated_small -= size;
4503 arena->stats.ndalloc_small++;
4508 arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)
4510 /* Large allocation. */
4511 malloc_spin_lock(&arena->lock);
4514 #ifndef MALLOC_STATS
4519 size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >>
4521 size_t size = chunk->map[pageind].bits & ~pagesize_mask;
4527 memset(ptr, 0x5a, size);
4530 arena->stats.allocated_large -= size;
4534 arena->stats.ndalloc_large++;
4537 arena_run_dalloc(arena, (arena_run_t *)ptr, true);
4538 malloc_spin_unlock(&arena->lock);
4542 arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr)
4545 arena_chunk_map_t *mapelm;
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);
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);
4562 arena_dalloc_large(arena, chunk, ptr);
4563 VALGRIND_FREELIKE_BLOCK(ptr, 0);
4569 arena_chunk_t *chunk;
4571 assert(ptr != NULL);
4573 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
4575 arena_dalloc(chunk->arena, chunk, ptr);
4581 arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr,
4582 size_t size, size_t oldsize)
4585 assert(size < oldsize);
4588 * Shrink the run, and make trailing pages available for other
4591 #ifdef MALLOC_BALANCE
4592 arena_lock_balance(arena);
4594 malloc_spin_lock(&arena->lock);
4596 arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size,
4599 arena->stats.allocated_large -= oldsize - size;
4601 malloc_spin_unlock(&arena->lock);
4605 arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr,
4606 size_t size, size_t oldsize)
4608 size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> pagesize_2pow;
4609 size_t npages = oldsize >> pagesize_2pow;
4611 assert(oldsize == (chunk->map[pageind].bits & ~pagesize_mask));
4613 /* Try to extend the run. */
4614 assert(size > oldsize);
4615 #ifdef MALLOC_BALANCE
4616 arena_lock_balance(arena);
4618 malloc_spin_lock(&arena->lock);
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) {
4624 * The next run is available and sufficiently large. Split the
4625 * following run, then merge the first part with the existing
4628 arena_run_split(arena, (arena_run_t *)((uintptr_t)chunk +
4629 ((pageind+npages) << pagesize_2pow)), size - oldsize, true,
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;
4638 arena->stats.allocated_large += size - oldsize;
4640 malloc_spin_unlock(&arena->lock);
4643 malloc_spin_unlock(&arena->lock);
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.
4653 arena_ralloc_large(void *ptr, size_t size, size_t oldsize)
4657 psize = PAGE_CEILING(size);
4658 if (psize == oldsize) {
4659 /* Same size class. */
4661 if (opt_junk && size < oldsize) {
4662 memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize -
4668 arena_chunk_t *chunk;
4671 chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
4672 arena = chunk->arena;
4673 assert(arena->magic == ARENA_MAGIC);
4675 if (psize < oldsize) {
4677 /* Fill before shrinking in order avoid a race. */
4679 memset((void *)((uintptr_t)ptr + size), 0x5a,
4683 arena_ralloc_large_shrink(arena, chunk, ptr, psize,
4687 bool ret = arena_ralloc_large_grow(arena, chunk, ptr,
4690 if (ret == false && opt_zero) {
4691 memset((void *)((uintptr_t)ptr + oldsize), 0,
4701 arena_ralloc(void *ptr, size_t size, size_t oldsize)
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)
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.
4732 ret = arena_malloc(choose_arena(), size, false);
4736 /* Junk/zero-filling were already done by arena_malloc(). */
4737 copysize = (size < oldsize) ? size : oldsize;
4739 if (copysize >= VM_COPY_MIN)
4740 pages_copy(ret, ptr, copysize);
4743 memcpy(ret, ptr, copysize);
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);
4756 static inline void *
4757 iralloc(void *ptr, size_t size)
4761 assert(ptr != NULL);
4764 oldsize = isalloc(ptr);
4766 #ifndef MALLOC_VALGRIND
4767 if (size <= arena_maxclass)
4768 return (arena_ralloc(ptr, size, oldsize));
4770 return (huge_ralloc(ptr, size, oldsize));
4773 * Valgrind does not provide a public interface for modifying an
4774 * existing allocation, so use malloc/memcpy/free instead.
4777 void *ret = imalloc(size);
4780 memcpy(ret, ptr, oldsize);
4782 memcpy(ret, ptr, size);
4791 arena_new(arena_t *arena)
4795 size_t pow2_size, prev_run_size;
4797 if (malloc_spin_init(&arena->lock))
4801 memset(&arena->stats, 0, sizeof(arena_stats_t));
4804 arena->chunk_seq = 0;
4806 /* Initialize chunks. */
4807 arena_chunk_tree_dirty_new(&arena->chunks_dirty);
4808 arena->spare = NULL;
4812 arena_avail_tree_new(&arena->runs_avail);
4814 #ifdef MALLOC_BALANCE
4815 arena->contention = 0;
4818 /* Initialize bins. */
4819 prev_run_size = pagesize;
4821 /* (2^n)-spaced tiny bins. */
4822 for (i = 0; i < ntbins; i++) {
4823 bin = &arena->bins[i];
4825 arena_run_tree_new(&bin->runs);
4827 bin->reg_size = ((size_t)1 << (TINY_MIN_2POW + i));
4829 prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
4832 memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
4836 /* Quantum-spaced bins. */
4837 for (; i < ntbins + nqbins; i++) {
4838 bin = &arena->bins[i];
4840 arena_run_tree_new(&bin->runs);
4842 bin->reg_size = quantum * (i - ntbins + 1);
4844 pow2_size = pow2_ceil(quantum * (i - ntbins + 1));
4845 prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
4848 memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
4852 /* (2^n)-spaced sub-page bins. */
4853 for (; i < ntbins + nqbins + nsbins; i++) {
4854 bin = &arena->bins[i];
4856 arena_run_tree_new(&bin->runs);
4858 bin->reg_size = (small_max << (i - (ntbins + nqbins) + 1));
4860 prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
4863 memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
4868 arena->magic = ARENA_MAGIC;
4874 /* Create a new arena and insert it into the arenas array at index ind. */
4876 arenas_extend(unsigned ind)
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) {
4887 /* Only reached if there is an OOM error. */
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
4895 _malloc_message(_getprogname(),
4896 ": (malloc) Error initializing arena\n", "", "");
4906 /******************************************************************************/
4908 * Begin general internal functions.
4912 huge_malloc(size_t size, bool zero)
4916 #ifdef MALLOC_DECOMMIT
4919 extent_node_t *node;
4921 /* Allocate one or more contiguous chunks for this request. */
4923 csize = CHUNK_CEILING(size);
4925 /* size is large enough to cause size_t wrap-around. */
4929 /* Allocate an extent node with which to track the chunk. */
4930 node = base_node_alloc();
4934 ret = chunk_alloc(csize, zero, true);
4936 base_node_dealloc(node);
4940 /* Insert node into huge. */
4942 #ifdef MALLOC_DECOMMIT
4943 psize = PAGE_CEILING(size);
4949 malloc_mutex_lock(&huge_mtx);
4950 extent_tree_ad_insert(&huge, node);
4953 # ifdef MALLOC_DECOMMIT
4954 huge_allocated += psize;
4956 huge_allocated += csize;
4959 malloc_mutex_unlock(&huge_mtx);
4961 #ifdef MALLOC_DECOMMIT
4962 if (csize - psize > 0)
4963 pages_decommit((void *)((uintptr_t)ret + psize), csize - psize);
4966 #ifdef MALLOC_DECOMMIT
4967 VALGRIND_MALLOCLIKE_BLOCK(ret, psize, 0, zero);
4969 VALGRIND_MALLOCLIKE_BLOCK(ret, csize, 0, zero);
4973 if (zero == false) {
4975 # ifdef MALLOC_DECOMMIT
4976 memset(ret, 0xa5, psize);
4978 memset(ret, 0xa5, csize);
4981 # ifdef MALLOC_DECOMMIT
4982 memset(ret, 0, psize);
4984 memset(ret, 0, csize);
4992 /* Only handles large allocations that require more than chunk alignment. */
4994 huge_palloc(size_t alignment, size_t size)
4997 size_t alloc_size, chunk_size, offset;
4998 #ifdef MALLOC_DECOMMIT
5001 extent_node_t *node;
5005 * This allocation requires alignment that is even larger than chunk
5006 * alignment. This means that huge_malloc() isn't good enough.
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.
5012 assert(alignment >= chunksize);
5014 chunk_size = CHUNK_CEILING(size);
5016 if (size >= alignment)
5017 alloc_size = chunk_size + alignment - chunksize;
5019 alloc_size = (alignment << 1) - chunksize;
5021 /* Allocate an extent node with which to track the chunk. */
5022 node = base_node_alloc();
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.
5031 * The MALLOC_PAGEFILE code also benefits from this mapping algorithm,
5032 * since it reduces the number of page files.
5034 #ifdef MALLOC_PAGEFILE
5036 pfd = pagefile_init(size);
5042 #ifdef JEMALLOC_USES_MAP_ALIGN
5043 ret = pages_map_align(chunk_size, pfd, alignment);
5048 over = chunk_alloc(alloc_size, false, false);
5050 base_node_dealloc(node);
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);
5062 * Failure here indicates a race with another thread, so try
5065 } while (ret == NULL);
5067 /* Insert node into huge. */
5069 #ifdef MALLOC_DECOMMIT
5070 psize = PAGE_CEILING(size);
5073 node->size = chunk_size;
5076 malloc_mutex_lock(&huge_mtx);
5077 extent_tree_ad_insert(&huge, node);
5080 # ifdef MALLOC_DECOMMIT
5081 huge_allocated += psize;
5083 huge_allocated += chunk_size;
5086 malloc_mutex_unlock(&huge_mtx);
5088 #ifdef MALLOC_DECOMMIT
5089 if (chunk_size - psize > 0) {
5090 pages_decommit((void *)((uintptr_t)ret + psize),
5091 chunk_size - psize);
5095 #ifdef MALLOC_DECOMMIT
5096 VALGRIND_MALLOCLIKE_BLOCK(ret, psize, 0, false);
5098 VALGRIND_MALLOCLIKE_BLOCK(ret, chunk_size, 0, false);
5103 # ifdef MALLOC_DECOMMIT
5104 memset(ret, 0xa5, psize);
5106 memset(ret, 0xa5, chunk_size);
5109 # ifdef MALLOC_DECOMMIT
5110 memset(ret, 0, psize);
5112 memset(ret, 0, chunk_size);
5117 #ifdef MALLOC_PAGEFILE
5119 pagefile_close(pfd);
5125 huge_ralloc(void *ptr, size_t size, size_t oldsize)
5130 /* Avoid moving the allocation if the size class would not change. */
5132 if (oldsize > arena_maxclass &&
5133 CHUNK_CEILING(size) == CHUNK_CEILING(oldsize)) {
5134 #ifdef MALLOC_DECOMMIT
5135 size_t psize = PAGE_CEILING(size);
5138 if (opt_junk && size < oldsize) {
5139 memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize
5143 #ifdef MALLOC_DECOMMIT
5144 if (psize < oldsize) {
5145 extent_node_t *node, key;
5147 pages_decommit((void *)((uintptr_t)ptr + psize),
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;
5160 malloc_mutex_unlock(&huge_mtx);
5161 } else if (psize > oldsize) {
5162 extent_node_t *node, key;
5164 pages_commit((void *)((uintptr_t)ptr + oldsize),
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;
5177 malloc_mutex_unlock(&huge_mtx);
5181 if (opt_zero && size > oldsize) {
5182 memset((void *)((uintptr_t)ptr + oldsize), 0, size
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.
5194 ret = huge_malloc(size, false);
5198 copysize = (size < oldsize) ? size : oldsize;
5200 if (copysize >= VM_COPY_MIN)
5201 pages_copy(ret, ptr, copysize);
5204 memcpy(ret, ptr, copysize);
5210 huge_dalloc(void *ptr)
5212 extent_node_t *node, key;
5214 malloc_mutex_lock(&huge_mtx);
5216 /* Extract from tree of huge allocations. */
5218 node = extent_tree_ad_search(&huge, &key);
5219 assert(node != NULL);
5220 assert(node->addr == ptr);
5221 extent_tree_ad_remove(&huge, node);
5225 huge_allocated -= node->size;
5228 malloc_mutex_unlock(&huge_mtx);
5233 memset(node->addr, 0x5a, node->size);
5235 #ifdef MALLOC_DECOMMIT
5236 chunk_dealloc(node->addr, CHUNK_CEILING(node->size));
5238 chunk_dealloc(node->addr, node->size);
5240 VALGRIND_FREELIKE_BLOCK(node->addr, 0);
5242 base_node_dealloc(node);
5245 #ifdef MOZ_MEMORY_BSD
5246 static inline unsigned
5256 if (sysctl(mib, 2, &ret, &len, (void *) 0, 0) == -1) {
5263 #elif (defined(MOZ_MEMORY_LINUX))
5266 static inline unsigned
5270 int fd, nread, column;
5272 static const char matchstr[] = "processor\t:";
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.
5280 fd = open("/proc/cpuinfo", O_RDONLY);
5282 return (1); /* Error. */
5284 * Count the number of occurrences of matchstr at the beginnings of
5285 * lines. This treats hyperthreaded CPUs as multiple processors.
5290 nread = read(fd, &buf, sizeof(buf));
5292 break; /* EOF or error. */
5293 for (i = 0;i < nread;i++) {
5297 else if (column != -1) {
5298 if (c == matchstr[column]) {
5300 if (column == sizeof(matchstr) - 1) {
5311 ret = 1; /* Something went wrong in the parser. */
5316 #elif (defined(MOZ_MEMORY_DARWIN))
5317 #include <mach/mach_init.h>
5318 #include <mach/mach_host.h>
5320 static inline unsigned
5323 kern_return_t error;
5325 processor_info_array_t pinfo;
5326 mach_msg_type_number_t pinfocnt;
5328 error = host_processor_info(mach_host_self(), PROCESSOR_BASIC_INFO,
5329 &n, &pinfo, &pinfocnt);
5330 if (error != KERN_SUCCESS)
5331 return (1); /* Error. */
5335 #elif (defined(MOZ_MEMORY_SOLARIS))
5337 static inline unsigned
5340 return sysconf(_SC_NPROCESSORS_ONLN);
5343 static inline unsigned
5348 * We lack a way to determine the number of CPUs on this platform, so
5356 malloc_print_stats(void)
5359 if (opt_print_stats) {
5360 char s[UMAX2S_BUFSIZE];
5361 _malloc_message("___ Begin malloc statistics ___\n", "", "",
5363 _malloc_message("Assertions ",
5370 _malloc_message("Boolean MALLOC_OPTIONS: ",
5371 opt_abort ? "A" : "a", "", "");
5373 _malloc_message(opt_junk ? "J" : "j", "", "", "");
5375 #ifdef MALLOC_PAGEFILE
5376 _malloc_message(opt_pagefile ? "o" : "O", "", "", "");
5378 _malloc_message("P", "", "", "");
5379 #ifdef MALLOC_UTRACE
5380 _malloc_message(opt_utrace ? "U" : "u", "", "", "");
5383 _malloc_message(opt_sysv ? "V" : "v", "", "", "");
5385 #ifdef MALLOC_XMALLOC
5386 _malloc_message(opt_xmalloc ? "X" : "x", "", "", "");
5389 _malloc_message(opt_zero ? "Z" : "z", "", "", "");
5391 _malloc_message("\n", "", "", "");
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", "");
5399 _malloc_message("Pointer size: ", umax2s(sizeof(void *), s),
5401 _malloc_message("Quantum size: ", umax2s(quantum, s), "\n", "");
5402 _malloc_message("Max small size: ", umax2s(small_max, s), "\n",
5404 _malloc_message("Max dirty pages per arena: ",
5405 umax2s(opt_dirty_max, s), "\n", "");
5407 _malloc_message("Chunk size: ", umax2s(chunksize, s), "", "");
5408 _malloc_message(" (2^", umax2s(opt_chunk_2pow, s), ")\n", "");
5412 size_t allocated, mapped;
5413 #ifdef MALLOC_BALANCE
5414 uint64_t nbalance = 0;
5419 /* Calculate and print allocated/mapped stats. */
5422 for (i = 0, allocated = 0; i < narenas; i++) {
5423 if (arenas[i] != NULL) {
5424 malloc_spin_lock(&arenas[i]->lock);
5426 arenas[i]->stats.allocated_small;
5428 arenas[i]->stats.allocated_large;
5429 #ifdef MALLOC_BALANCE
5430 nbalance += arenas[i]->stats.nbalance;
5432 malloc_spin_unlock(&arenas[i]->lock);
5437 malloc_mutex_lock(&huge_mtx);
5438 allocated += huge_allocated;
5439 mapped = stats_chunks.curchunks * chunksize;
5440 malloc_mutex_unlock(&huge_mtx);
5442 malloc_mutex_lock(&base_mtx);
5443 mapped += base_mapped;
5444 malloc_mutex_unlock(&base_mtx);
5446 #ifdef MOZ_MEMORY_WINDOWS
5447 malloc_printf("Allocated: %lu, mapped: %lu\n",
5450 malloc_printf("Allocated: %zu, mapped: %zu\n",
5454 malloc_mutex_lock(&reserve_mtx);
5455 malloc_printf("Reserve: min "
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);
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);
5468 malloc_mutex_unlock(&reserve_mtx);
5470 #ifdef MALLOC_BALANCE
5471 malloc_printf("Arena balance reassignments: %llu\n",
5475 /* Print chunk stats. */
5477 chunk_stats_t chunks_stats;
5479 malloc_mutex_lock(&huge_mtx);
5480 chunks_stats = stats_chunks;
5481 malloc_mutex_unlock(&huge_mtx);
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);
5491 /* Print chunk stats. */
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);
5498 malloc_printf(" %12llu %12llu %12zu\n",
5499 huge_nmalloc, huge_ndalloc, huge_allocated);
5501 /* Print stats for each arena. */
5502 for (i = 0; i < narenas; i++) {
5504 if (arena != NULL) {
5506 "\narenas[%u]:\n", i);
5507 malloc_spin_lock(&arena->lock);
5509 malloc_spin_unlock(&arena->lock);
5513 #endif /* #ifdef MALLOC_STATS */
5514 _malloc_message("--- End malloc statistics ---\n", "", "", "");
5519 * FreeBSD's pthreads implementation calls malloc(3), so the malloc
5520 * implementation has to take pains to avoid infinite recursion during
5523 #if (defined(MOZ_MEMORY_WINDOWS) || defined(MOZ_MEMORY_DARWIN)) && !defined(MOZ_MEMORY_WINCE)
5524 #define malloc_init() false
5530 if (malloc_initialized == false)
5531 return (malloc_init_hard());
5537 #if !defined(MOZ_MEMORY_WINDOWS) || defined(MOZ_MEMORY_WINCE)
5541 je_malloc_init_hard(void)
5544 char buf[PATH_MAX + 1];
5547 #ifndef MOZ_MEMORY_WINDOWS
5551 #ifndef MOZ_MEMORY_WINDOWS
5552 malloc_mutex_lock(&init_lock);
5555 if (malloc_initialized) {
5557 * Another thread initialized the allocator before this one
5558 * acquired init_lock.
5560 #ifndef MOZ_MEMORY_WINDOWS
5561 malloc_mutex_unlock(&init_lock);
5566 #ifdef MOZ_MEMORY_WINDOWS
5567 /* get a thread local storage index */
5568 tlsIndex = TlsAlloc();
5571 /* Get page size and number of CPUs */
5572 #ifdef MOZ_MEMORY_WINDOWS
5576 GetSystemInfo(&info);
5577 result = info.dwPageSize;
5579 pagesize = (unsigned) result;
5581 ncpus = info.dwNumberOfProcessors;
5584 ncpus = malloc_ncpus();
5586 result = sysconf(_SC_PAGESIZE);
5587 assert(result != -1);
5589 pagesize = (unsigned) result;
5593 * We assume that pagesize is a power of 2 when calculating
5594 * pagesize_mask and pagesize_2pow.
5596 assert(((result - 1) & result) == 0);
5597 pagesize_mask = result - 1;
5598 pagesize_2pow = ffs((int)result) - 1;
5600 #ifdef MALLOC_PAGEFILE
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:
5614 static const char suffix[] = "/jemalloc.XXXXXX";
5616 if ((s = getenv("MALLOC_TMPDIR")) == NULL && (s =
5617 getenv("TMPDIR")) == NULL)
5620 if (slen + sizeof(suffix) > sizeof(pagefile_templ)) {
5621 _malloc_message(_getprogname(),
5622 ": (malloc) Page file path too long\n",
5626 memcpy(pagefile_templ, s, slen);
5627 memcpy(&pagefile_templ[slen], suffix, sizeof(suffix));
5631 for (i = 0; i < 3; i++) {
5634 /* Get runtime configuration. */
5637 #ifndef MOZ_MEMORY_WINDOWS
5638 if ((linklen = readlink("/etc/malloc.conf", buf,
5639 sizeof(buf) - 1)) != -1) {
5641 * Use the contents of the "/etc/malloc.conf"
5642 * symbolic link's name.
5644 buf[linklen] = '\0';
5649 /* No configuration specified. */
5655 if (issetugid() == 0 && (opts =
5656 getenv("MALLOC_OPTIONS")) != NULL) {
5658 * Do nothing; opts is already initialized to
5659 * the value of the MALLOC_OPTIONS environment
5663 /* No configuration specified. */
5669 if (_malloc_options != NULL) {
5671 * Use options that were compiled into the
5674 opts = _malloc_options;
5676 /* No configuration specified. */
5688 for (j = 0; opts[j] != '\0'; j++) {
5692 /* Parse repetition count, if any. */
5693 for (nreps = 0, nseen = false;; j++, nseen = true) {
5695 case '0': case '1': case '2': case '3':
5696 case '4': case '5': case '6': case '7':
5699 nreps += opts[j] - '0';
5709 for (k = 0; k < nreps; k++) {
5718 #ifdef MALLOC_BALANCE
5719 opt_balance_threshold >>= 1;
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;
5732 opt_dirty_max >>= 1;
5735 if (opt_dirty_max == 0)
5737 else if ((opt_dirty_max << 1) != 0)
5738 opt_dirty_max <<= 1;
5741 opt_reserve_range_lshift--;
5744 opt_reserve_range_lshift++;
5756 * Chunks always require at least one
5757 * header page, so chunks can never be
5758 * smaller than two pages.
5760 if (opt_chunk_2pow > pagesize_2pow + 1)
5764 if (opt_chunk_2pow + 1 <
5765 (sizeof(size_t) << 3))
5769 opt_narenas_lshift--;
5772 opt_narenas_lshift++;
5774 #ifdef MALLOC_PAGEFILE
5776 /* Do not over-commit. */
5777 opt_pagefile = true;
5780 /* Allow over-commit. */
5781 opt_pagefile = false;
5785 opt_print_stats = false;
5788 opt_print_stats = true;
5791 if (opt_quantum_2pow > QUANTUM_2POW_MIN)
5795 if (opt_quantum_2pow < pagesize_2pow -
5800 opt_reserve_min_lshift--;
5803 opt_reserve_min_lshift++;
5806 if (opt_small_max_2pow >
5808 opt_small_max_2pow--;
5811 if (opt_small_max_2pow < pagesize_2pow
5813 opt_small_max_2pow++;
5815 #ifdef MALLOC_UTRACE
5831 #ifdef MALLOC_XMALLOC
5833 opt_xmalloc = false;
5852 _malloc_message(_getprogname(),
5853 ": (malloc) Unsupported character "
5854 "in malloc options: '", cbuf,
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);
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);
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);
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;
5888 /* Set variables according to the value of opt_quantum_2pow. */
5889 quantum = ((size_t)1 << opt_quantum_2pow);
5890 quantum_mask = quantum - 1;
5892 small_min = (quantum >> 1) + 1;
5895 assert(small_min <= quantum);
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);
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.
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);
5916 arena_maxclass = chunksize - (arena_chunk_header_npages <<
5919 #ifdef JEMALLOC_USES_MAP_ALIGN
5921 * When using MAP_ALIGN, the alignment parameter must be a power of two
5922 * multiple of the system pagesize, or mmap will fail.
5924 assert((chunksize % pagesize) == 0);
5925 assert((1 << (ffs(chunksize / pagesize) - 1)) == (chunksize/pagesize));
5931 memset(&stats_chunks, 0, sizeof(chunk_stats_t));
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);
5940 /* Initialize chunks data. */
5941 malloc_mutex_init(&huge_mtx);
5942 extent_tree_ad_new(&huge);
5949 /* Initialize base allocation data structures. */
5954 base_reserve_regs = NULL;
5955 malloc_mutex_init(&base_mtx);
5957 #ifdef MOZ_MEMORY_NARENAS_DEFAULT_ONE
5962 * For SMP systems, create four times as many arenas as there
5963 * are CPUs by default.
5965 opt_narenas_lshift += 2;
5968 /* Determine how many arenas to use. */
5971 if (opt_narenas_lshift > 0) {
5972 if ((narenas << opt_narenas_lshift) > narenas)
5973 narenas <<= opt_narenas_lshift;
5975 * Make sure not to exceed the limits of what base_alloc() can
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. */
5987 #ifdef MALLOC_BALANCE
5988 assert(narenas != 0);
5989 for (narenas_2pow = 0;
5990 (narenas >> (narenas_2pow + 1)) != 0;
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;
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.
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];
6022 # ifndef MALLOC_BALANCE
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);
6036 * Zero the array. In practice, this should always be pre-zeroed,
6037 * since it was just mmap()ed, but let's be sure.
6039 memset(arenas, 0, sizeof(arena_t *) * narenas);
6042 * Initialize one arena here. The rest are lazily created in
6043 * choose_arena_hard().
6046 if (arenas[0] == NULL) {
6047 #ifndef MOZ_MEMORY_WINDOWS
6048 malloc_mutex_unlock(&init_lock);
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
6058 #ifdef MOZ_MEMORY_WINDOWS
6059 TlsSetValue(tlsIndex, arenas[0]);
6061 arenas_map = arenas[0];
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.
6069 #ifdef MALLOC_BALANCE
6073 malloc_spin_init(&arenas_lock);
6075 #ifdef MALLOC_VALIDATE
6076 chunk_rtree = malloc_rtree_new((SIZEOF_PTR << 3) - opt_chunk_2pow);
6077 if (chunk_rtree == NULL)
6082 * Configure and initialize the memory reserve. This needs to happen
6083 * late during initialization, since chunks are allocated.
6085 malloc_mutex_init(&reserve_mtx);
6089 if (RESERVE_RANGE_2POW_DEFAULT + opt_reserve_range_lshift >= 0) {
6090 reserve_max += chunksize << (RESERVE_RANGE_2POW_DEFAULT +
6091 opt_reserve_range_lshift);
6093 ql_new(&reserve_regs);
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));
6102 malloc_initialized = true;
6103 #ifndef MOZ_MEMORY_WINDOWS
6104 malloc_mutex_unlock(&init_lock);
6109 /* XXX Why not just expose malloc_print_stats()? */
6110 #ifdef MOZ_MEMORY_WINDOWS
6115 malloc_print_stats();
6120 * End general internal functions.
6122 /******************************************************************************/
6124 * Begin malloc(3)-compatible functions.
6128 * Inline the standard malloc functions if they are being subsumed by Darwin's
6129 * zone infrastructure.
6131 #ifdef MOZ_MEMORY_DARWIN
6132 # define ZONE_INLINE inline
6134 # define ZONE_INLINE
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
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)
6160 if (malloc_init()) {
6167 if (opt_sysv == false)
6178 ret = imalloc(size);
6182 #ifdef MALLOC_XMALLOC
6184 _malloc_message(_getprogname(),
6185 ": (malloc) Error in malloc(): out of memory\n", "",
6193 UTRACE(0, size, ret);
6197 #ifdef MOZ_MEMORY_SOLARIS
6200 memalign(size_t alignment, size_t size);
6201 #pragma no_inline(memalign)
6202 # elif (defined(__GNU_C__))
6203 __attribute__((noinline))
6209 memalign(size_t alignment, size_t size)
6213 assert(((alignment - 1) & alignment) == 0 && alignment >=
6216 if (malloc_init()) {
6221 ret = ipalloc(alignment, size);
6224 #ifdef MALLOC_XMALLOC
6225 if (opt_xmalloc && ret == NULL) {
6226 _malloc_message(_getprogname(),
6227 ": (malloc) Error in memalign(): out of memory\n", "", "");
6231 UTRACE(0, size, ret);
6237 posix_memalign(void **memptr, size_t alignment, size_t size)
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
6245 _malloc_message(_getprogname(),
6246 ": (malloc) Error in posix_memalign(): "
6247 "invalid alignment\n", "", "");
6254 #ifdef MOZ_MEMORY_DARWIN
6255 result = moz_memalign(alignment, size);
6257 result = memalign(alignment, size);
6270 #ifdef MOZ_MEMORY_DARWIN
6271 return (moz_memalign(pagesize, size));
6273 return (memalign(pagesize, size));
6279 calloc(size_t num, size_t size)
6284 if (malloc_init()) {
6290 num_size = num * size;
6291 if (num_size == 0) {
6293 if ((opt_sysv == false) && ((num == 0) || (size == 0)))
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.
6307 } else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2)))
6308 && (num_size / size != num)) {
6309 /* size_t overflow. */
6314 ret = icalloc(num_size);
6318 #ifdef MALLOC_XMALLOC
6320 _malloc_message(_getprogname(),
6321 ": (malloc) Error in calloc(): out of memory\n", "",
6329 UTRACE(0, num_size, ret);
6335 realloc(void *ptr, size_t size)
6341 if (opt_sysv == false)
6355 assert(malloc_initialized);
6357 ret = iralloc(ptr, size);
6360 #ifdef MALLOC_XMALLOC
6362 _malloc_message(_getprogname(),
6363 ": (malloc) Error in realloc(): out of "
6364 "memory\n", "", "");
6374 ret = imalloc(size);
6377 #ifdef MALLOC_XMALLOC
6379 _malloc_message(_getprogname(),
6380 ": (malloc) Error in realloc(): out of "
6381 "memory\n", "", "");
6392 UTRACE(ptr, size, ret);
6403 assert(malloc_initialized);
6410 * End malloc(3)-compatible functions.
6412 /******************************************************************************/
6414 * Begin non-standard functions.
6418 malloc_usable_size(const void *ptr)
6421 #ifdef MALLOC_VALIDATE
6422 return (isalloc_validate(ptr));
6424 assert(ptr != NULL);
6426 return (isalloc(ptr));
6431 jemalloc_stats(jemalloc_stats_t *stats)
6435 assert(stats != NULL);
6438 * Gather runtime settings.
6440 stats->opt_abort = opt_abort;
6447 #ifdef MALLOC_UTRACE
6456 stats->opt_xmalloc =
6457 #ifdef MALLOC_XMALLOC
6458 opt_xmalloc ? true :
6466 stats->narenas = narenas;
6467 stats->balance_threshold =
6468 #ifdef MALLOC_BALANCE
6469 opt_balance_threshold
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;
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);
6487 * Gather current memory usage statistics.
6490 stats->committed = 0;
6491 stats->allocated = 0;
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;
6500 stats->allocated += huge_allocated;
6501 malloc_mutex_unlock(&huge_mtx);
6503 /* Get base mapped. */
6504 malloc_mutex_lock(&base_mtx);
6505 stats->mapped += base_mapped;
6506 #ifdef MALLOC_DECOMMIT
6507 stats->committed += base_mapped;
6509 malloc_mutex_unlock(&base_mtx);
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;
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) {
6525 for (j = 0; j < chunk_npages; j++) {
6526 if ((chunk->map[j].bits &
6527 CHUNK_MAP_DECOMMITTED) == 0)
6528 stats->committed += pagesize;
6530 } rb_foreach_end(arena_chunk_t, link_dirty,
6531 &arena->chunks_dirty, chunk)
6533 stats->dirty += (arena->ndirty << pagesize_2pow);
6534 malloc_spin_unlock(&arena->lock);
6538 #ifndef MALLOC_DECOMMIT
6539 stats->committed = stats->mapped;
6544 xmalloc(size_t size)
6549 reserve_fail(size, "xmalloc");
6553 if (opt_sysv == false)
6558 _malloc_message(_getprogname(),
6559 ": (malloc) Error in xmalloc(): ",
6560 "invalid size 0", "\n");
6566 ret = imalloc(size);
6571 seq = reserve_crit(size, "xmalloc", seq);
6572 ret = imalloc(size);
6573 } while (ret == NULL);
6576 UTRACE(0, size, ret);
6581 xcalloc(size_t num, size_t size)
6586 num_size = num * size;
6588 reserve_fail(num_size, "xcalloc");
6590 if (num_size == 0) {
6592 if ((opt_sysv == false) && ((num == 0) || (size == 0)))
6597 _malloc_message(_getprogname(),
6598 ": (malloc) Error in xcalloc(): ",
6599 "invalid size 0", "\n");
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.
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");
6617 ret = icalloc(num_size);
6622 seq = reserve_crit(num_size, "xcalloc", seq);
6623 ret = icalloc(num_size);
6624 } while (ret == NULL);
6627 UTRACE(0, num_size, ret);
6632 xrealloc(void *ptr, size_t size)
6638 if (opt_sysv == false)
6645 _malloc_message(_getprogname(),
6646 ": (malloc) Error in xrealloc(): ",
6647 "invalid size 0", "\n");
6654 assert(malloc_initialized);
6656 ret = iralloc(ptr, size);
6661 seq = reserve_crit(size, "xrealloc", seq);
6662 ret = iralloc(ptr, size);
6663 } while (ret == NULL);
6667 reserve_fail(size, "xrealloc");
6669 ret = imalloc(size);
6674 seq = reserve_crit(size, "xrealloc", seq);
6675 ret = imalloc(size);
6676 } while (ret == NULL);
6680 UTRACE(ptr, size, ret);
6685 xmemalign(size_t alignment, size_t size)
6689 assert(((alignment - 1) & alignment) == 0 && alignment >=
6693 reserve_fail(size, "xmemalign");
6695 ret = ipalloc(alignment, size);
6700 seq = reserve_crit(size, "xmemalign", seq);
6701 ret = ipalloc(alignment, size);
6702 } while (ret == NULL);
6705 UTRACE(0, size, ret);
6710 reserve_shrink(void)
6712 extent_node_t *node;
6714 assert(reserve_cur > reserve_max);
6717 extent_node_t *node;
6718 size_t reserve_size;
6721 rb_foreach_begin(extent_node_t, link_szad, &reserve_chunks_szad,
6723 reserve_size += node->size;
6724 } rb_foreach_end(extent_node_t, link_szad, &reserve_chunks_szad,
6726 assert(reserve_size == reserve_cur);
6729 rb_foreach_begin(extent_node_t, link_ad, &reserve_chunks_ad,
6731 reserve_size += node->size;
6732 } rb_foreach_end(extent_node_t, link_ad, &reserve_chunks_ad,
6734 assert(reserve_size == reserve_cur);
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,
6741 #ifndef MALLOC_DECOMMIT
6742 if (node->size <= reserve_cur - reserve_max) {
6744 extent_node_t *tnode = extent_tree_ad_prev(
6745 &reserve_chunks_ad, node);
6747 #ifdef MALLOC_DECOMMIT
6748 assert(node->size <= reserve_cur - reserve_max);
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);
6757 stats_chunks.curchunks -= (node->size / chunksize);
6759 base_node_dealloc(node);
6760 if (reserve_cur == reserve_max)
6763 rb_foreach_reverse_prev(extent_node_t, link_ad,
6764 extent_ad_comp, &reserve_chunks_ad, tnode);
6765 #ifndef MALLOC_DECOMMIT
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);
6774 stats_chunks.curchunks -= ((reserve_cur - reserve_max) /
6777 reserve_cur = reserve_max;
6781 assert(reserve_cur > reserve_max);
6782 } rb_foreach_reverse_end(extent_node_t, link_ad, &reserve_chunks_ad,
6786 /* Send a condition notification. */
6788 reserve_notify(reserve_cnd_t cnd, size_t size, uint64_t seq)
6792 /* seq is used to keep track of distinct condition-causing events. */
6794 /* Allocate new sequence number. */
6800 * Advance to the next callback registration and send a notification,
6801 * unless one has already been sent for this condition-causing event.
6803 reg = ql_first(&reserve_regs);
6806 ql_first(&reserve_regs) = ql_next(&reserve_regs, reg, link);
6807 if (reg->seq == seq)
6810 malloc_mutex_unlock(&reserve_mtx);
6811 reg->cb(reg->ctx, cnd, size);
6812 malloc_mutex_lock(&reserve_mtx);
6817 /* Allocation failure due to OOM. Try to free some memory via callbacks. */
6819 reserve_crit(size_t size, const char *fname, uint64_t seq)
6823 * Send one condition notification. Iteration is handled by the
6824 * caller of this function.
6826 malloc_mutex_lock(&reserve_mtx);
6827 seq = reserve_notify(RESERVE_CND_CRIT, size, seq);
6828 malloc_mutex_unlock(&reserve_mtx);
6830 /* If no notification could be sent, then no further recourse exists. */
6832 reserve_fail(size, fname);
6837 /* Permanent allocation failure due to OOM. */
6839 reserve_fail(size_t size, const char *fname)
6843 /* Send fail notifications. */
6844 malloc_mutex_lock(&reserve_mtx);
6846 seq = reserve_notify(RESERVE_CND_FAIL, size, seq);
6848 malloc_mutex_unlock(&reserve_mtx);
6850 /* Terminate the application. */
6851 _malloc_message(_getprogname(),
6852 ": (malloc) Error in ", fname, "(): out of memory\n");
6857 reserve_cb_register(reserve_cb_t *cb, void *ctx)
6859 reserve_reg_t *reg = base_reserve_reg_alloc();
6863 ql_elm_new(reg, link);
6868 malloc_mutex_lock(&reserve_mtx);
6869 ql_head_insert(&reserve_regs, reg, link);
6870 malloc_mutex_unlock(&reserve_mtx);
6876 reserve_cb_unregister(reserve_cb_t *cb, void *ctx)
6878 reserve_reg_t *reg = NULL;
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);
6887 malloc_mutex_unlock(&reserve_mtx);
6890 base_reserve_reg_dealloc(reg);
6896 reserve_cur_get(void)
6900 malloc_mutex_lock(&reserve_mtx);
6902 malloc_mutex_unlock(&reserve_mtx);
6908 reserve_min_get(void)
6912 malloc_mutex_lock(&reserve_mtx);
6914 malloc_mutex_unlock(&reserve_mtx);
6920 reserve_min_set(size_t min)
6923 min = CHUNK_CEILING(min);
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;
6931 /* Protect against wrap-around. */
6932 if (reserve_max + min - reserve_min < reserve_max) {
6933 reserve_min = SIZE_T_MAX - (reserve_max - reserve_min)
6935 reserve_max = SIZE_T_MAX - chunksize + 1;
6937 reserve_max += min - reserve_min;
6942 /* Resize the reserve if necessary. */
6943 if (reserve_cur < reserve_min) {
6944 size_t size = reserve_min - reserve_cur;
6946 /* Force the reserve to grow by allocating/deallocating. */
6947 malloc_mutex_unlock(&reserve_mtx);
6948 #ifdef MALLOC_DECOMMIT
6953 n = size >> opt_chunk_2pow;
6954 chunks = (void**)imalloc(n * sizeof(void *));
6957 for (i = 0; i < n; i++) {
6958 chunks[i] = huge_malloc(chunksize, false);
6959 if (chunks[i] == NULL) {
6962 for (j = 0; j < i; j++) {
6963 huge_dalloc(chunks[j]);
6969 for (i = 0; i < n; i++)
6970 huge_dalloc(chunks[i]);
6975 void *x = huge_malloc(size, false);
6982 } else if (reserve_cur > reserve_max) {
6984 malloc_mutex_unlock(&reserve_mtx);
6986 malloc_mutex_unlock(&reserve_mtx);
6991 #ifdef MOZ_MEMORY_WINDOWS
6993 _recalloc(void *ptr, size_t count, size_t size)
6995 size_t oldsize = (ptr != NULL) ? isalloc(ptr) : 0;
6996 size_t newsize = count * size;
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
7006 ptr = realloc(ptr, newsize);
7007 if (ptr != NULL && oldsize < newsize) {
7008 memset((void *)((uintptr_t)ptr + oldsize), 0, newsize -
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.
7020 _expand(void *ptr, size_t newsize)
7022 if (isalloc(ptr) >= newsize)
7029 _msize(const void *ptr)
7031 return malloc_usable_size(ptr);
7036 * End non-standard functions.
7038 /******************************************************************************/
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
7047 _malloc_prefork(void)
7051 /* Acquire all mutexes in a safe order. */
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);
7058 malloc_spin_unlock(&arenas_lock);
7060 malloc_mutex_lock(&base_mtx);
7062 malloc_mutex_lock(&huge_mtx);
7066 _malloc_postfork(void)
7070 /* Release all mutexes, now that fork() has completed. */
7072 malloc_mutex_unlock(&huge_mtx);
7074 malloc_mutex_unlock(&base_mtx);
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);
7081 malloc_spin_unlock(&arenas_lock);
7085 * End library-private functions.
7087 /******************************************************************************/
7093 #ifdef MOZ_MEMORY_DARWIN
7094 static malloc_zone_t zone;
7095 static struct malloc_introspection_t zone_introspect;
7098 zone_size(malloc_zone_t *zone, void *ptr)
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.
7110 return (isalloc_validate(ptr));
7114 zone_malloc(malloc_zone_t *zone, size_t size)
7117 return (malloc(size));
7121 zone_calloc(malloc_zone_t *zone, size_t num, size_t size)
7124 return (calloc(num, size));
7128 zone_valloc(malloc_zone_t *zone, size_t size)
7130 void *ret = NULL; /* Assignment avoids useless compiler warning. */
7132 posix_memalign(&ret, pagesize, size);
7138 zone_free(malloc_zone_t *zone, void *ptr)
7145 zone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
7148 return (realloc(ptr, size));
7152 zone_destroy(malloc_zone_t *zone)
7155 /* This function should never be called. */
7161 zone_good_size(malloc_zone_t *zone, size_t size)
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
7182 zone_force_lock(malloc_zone_t *zone)
7189 zone_force_unlock(malloc_zone_t *zone)
7195 static malloc_zone_t *
7199 assert(malloc_initialized);
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;
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;
7225 __attribute__((constructor))
7227 jemalloc_darwin_init(void)
7229 extern unsigned malloc_num_zones;
7230 extern malloc_zone_t **malloc_zones;
7232 if (malloc_init_hard())
7236 * The following code is *not* thread-safe, so it's critical that
7237 * initialization be manually triggered.
7240 /* Register the custom zones. */
7241 malloc_zone_register(create_zone());
7242 assert(malloc_zones[malloc_num_zones - 1] == &zone);
7245 * Shift malloc_zones around so that zone is first, which makes it the
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;
7254 #elif defined(__GLIBC__) && !defined(__UCLIBC__)
7256 * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible
7257 * to inconsistently reference libc's malloc(3)-compatible functions
7260 * These definitions interpose hooks in glibc. The functions are actually
7261 * passed an extra argument for the caller return address, which will be
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;
7269 #elif defined(RTLD_DEEPBIND)
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?
7275 # error "Interposing malloc is unsafe on this system without libc malloc hooks."