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