arena.c revision 41631d00618d7262125e501c91d31b4d70e605fa
1e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	JEMALLOC_ARENA_C_
2b0fd5016db74678476868abb380170b319a50480Jason Evans#include "internal/jemalloc_internal.h"
3e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
4e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/******************************************************************************/
5e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Data. */
6e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
7e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t	opt_lg_qspace_max = LG_QSPACE_MAX_DEFAULT;
8e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t	opt_lg_cspace_max = LG_CSPACE_MAX_DEFAULT;
9e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t	opt_lg_medium_max = LG_MEDIUM_MAX_DEFAULT;
10e476f8a161d445211fd6e54fe370275196e66bcbJason Evansssize_t		opt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT;
11e476f8a161d445211fd6e54fe370275196e66bcbJason Evansuint8_t const	*small_size2bin;
12e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
13e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Various bin-related settings. */
14e476f8a161d445211fd6e54fe370275196e66bcbJason Evansunsigned	nqbins;
15e476f8a161d445211fd6e54fe370275196e66bcbJason Evansunsigned	ncbins;
16e476f8a161d445211fd6e54fe370275196e66bcbJason Evansunsigned	nsbins;
17e476f8a161d445211fd6e54fe370275196e66bcbJason Evansunsigned	nmbins;
18e476f8a161d445211fd6e54fe370275196e66bcbJason Evansunsigned	nbins;
19e476f8a161d445211fd6e54fe370275196e66bcbJason Evansunsigned	mbin0;
20e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t		qspace_max;
21e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t		cspace_min;
22e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t		cspace_max;
23e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t		sspace_min;
24e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t		sspace_max;
25e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t		medium_max;
26e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
27e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t		lg_mspace;
28e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t		mspace_mask;
29e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
30e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/*
31e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * const_small_size2bin is a static constant lookup table that in the common
32e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * case can be used as-is for small_size2bin.  For dynamically linked programs,
33e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * this avoids a page of memory overhead per process.
34e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */
35e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_1(i)	i,
36e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_2(i)	S2B_1(i) S2B_1(i)
37e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_4(i)	S2B_2(i) S2B_2(i)
38e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_8(i)	S2B_4(i) S2B_4(i)
39e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_16(i)	S2B_8(i) S2B_8(i)
40e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_32(i)	S2B_16(i) S2B_16(i)
41e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_64(i)	S2B_32(i) S2B_32(i)
42e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_128(i)	S2B_64(i) S2B_64(i)
43e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_256(i)	S2B_128(i) S2B_128(i)
44e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/*
45e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * The number of elements in const_small_size2bin is dependent on page size
46e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * and on the definition for SUBPAGE.  If SUBPAGE changes, the '- 255' must also
47e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * change, along with the addition/removal of static lookup table element
48e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * definitions.
49e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */
50e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic const uint8_t	const_small_size2bin[STATIC_PAGE_SIZE - 255] = {
51e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_1(0xffU)		/*    0 */
52e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#if (LG_QUANTUM == 4)
53e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* 64-bit system ************************/
54e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  ifdef JEMALLOC_TINY
55e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_2(0)		/*    2 */
56e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_2(1)		/*    4 */
57e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_4(2)		/*    8 */
58e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(3)		/*   16 */
59e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#    define S2B_QMIN 3
60e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  else
61e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_16(0)		/*   16 */
62e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#    define S2B_QMIN 0
63e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  endif
64e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_16(S2B_QMIN + 1)	/*   32 */
65e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_16(S2B_QMIN + 2)	/*   48 */
66e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_16(S2B_QMIN + 3)	/*   64 */
67e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_16(S2B_QMIN + 4)	/*   80 */
68e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_16(S2B_QMIN + 5)	/*   96 */
69e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_16(S2B_QMIN + 6)	/*  112 */
70e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_16(S2B_QMIN + 7)	/*  128 */
71e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  define S2B_CMIN (S2B_QMIN + 8)
72e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#else
73e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* 32-bit system ************************/
74e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  ifdef JEMALLOC_TINY
75e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_2(0)		/*    2 */
76e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_2(1)		/*    4 */
77e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_4(2)		/*    8 */
78e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#    define S2B_QMIN 2
79e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  else
80e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(0)		/*    8 */
81e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#    define S2B_QMIN 0
82e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  endif
83e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 1)	/*   16 */
84e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 2)	/*   24 */
85e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 3)	/*   32 */
86e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 4)	/*   40 */
87e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 5)	/*   48 */
88e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 6)	/*   56 */
89e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 7)	/*   64 */
90e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 8)	/*   72 */
91e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 9)	/*   80 */
92e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 10)	/*   88 */
93e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 11)	/*   96 */
94e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 12)	/*  104 */
95e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 13)	/*  112 */
96e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 14)	/*  120 */
97e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_8(S2B_QMIN + 15)	/*  128 */
98e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  define S2B_CMIN (S2B_QMIN + 16)
99e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
100e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/****************************************/
101e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_64(S2B_CMIN + 0)	/*  192 */
102e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_64(S2B_CMIN + 1)	/*  256 */
103e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_64(S2B_CMIN + 2)	/*  320 */
104e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_64(S2B_CMIN + 3)	/*  384 */
105e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_64(S2B_CMIN + 4)	/*  448 */
106e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_64(S2B_CMIN + 5)	/*  512 */
107e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  define S2B_SMIN (S2B_CMIN + 6)
108e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 0)	/*  768 */
109e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 1)	/* 1024 */
110e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 2)	/* 1280 */
111e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 3)	/* 1536 */
112e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 4)	/* 1792 */
113e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 5)	/* 2048 */
114e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 6)	/* 2304 */
115e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 7)	/* 2560 */
116e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 8)	/* 2816 */
117e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 9)	/* 3072 */
118e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 10)	/* 3328 */
119e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 11)	/* 3584 */
120e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 12)	/* 3840 */
121e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#if (STATIC_PAGE_SHIFT == 13)
122e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 13)	/* 4096 */
123e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 14)	/* 4352 */
124e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 15)	/* 4608 */
125e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 16)	/* 4864 */
126e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 17)	/* 5120 */
127e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 18)	/* 5376 */
128e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 19)	/* 5632 */
129e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 20)	/* 5888 */
130e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 21)	/* 6144 */
131e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 22)	/* 6400 */
132e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 23)	/* 6656 */
133e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 24)	/* 6912 */
134e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 25)	/* 7168 */
135e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 26)	/* 7424 */
136e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 27)	/* 7680 */
137e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	S2B_256(S2B_SMIN + 28)	/* 7936 */
138e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
139e476f8a161d445211fd6e54fe370275196e66bcbJason Evans};
140e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_1
141e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_2
142e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_4
143e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_8
144e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_16
145e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_32
146e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_64
147e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_128
148e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_256
149e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_QMIN
150e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_CMIN
151e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_SMIN
152e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
153e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/******************************************************************************/
154e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Function prototypes for non-inline static functions. */
155e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
156e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_run_split(arena_t *arena, arena_run_t *run, size_t size,
157e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    bool large, bool zero);
158e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_chunk_t *arena_chunk_alloc(arena_t *arena);
159e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk);
160e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t *arena_run_alloc(arena_t *arena, size_t size, bool large,
161e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    bool zero);
162e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_purge(arena_t *arena);
163e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty);
164e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk,
165e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    arena_run_t *run, size_t oldsize, size_t newsize);
166e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk,
167e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    arena_run_t *run, size_t oldsize, size_t newsize, bool dirty);
168e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin);
169e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	*arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin);
170e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic size_t	arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size);
171e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	*arena_malloc_large(arena_t *arena, size_t size, bool zero);
172e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool	arena_is_large(const void *ptr);
173e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk,
174e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    arena_run_t *run, arena_bin_t *bin);
175b34e8684ec025aa780997c11f847c19fb269755bJason Evans#ifdef JEMALLOC_STATS
176b34e8684ec025aa780997c11f847c19fb269755bJason Evansstatic void	arena_stats_aprint(size_t nactive, size_t ndirty,
177b34e8684ec025aa780997c11f847c19fb269755bJason Evans    const arena_stats_t *astats,
178ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    void (*write4)(void *, const char *, const char *, const char *,
179ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    const char *), void *w4opaque);
180b34e8684ec025aa780997c11f847c19fb269755bJason Evansstatic void	arena_stats_bprint(arena_t *arena,
181b34e8684ec025aa780997c11f847c19fb269755bJason Evans    const malloc_bin_stats_t *bstats,
182ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    void (*write4)(void *, const char *, const char *, const char *,
183ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    const char *), void *w4opaque);
184b34e8684ec025aa780997c11f847c19fb269755bJason Evansstatic void	arena_stats_lprint(const malloc_large_stats_t *lstats,
185ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    void (*write4)(void *, const char *, const char *, const char *,
186ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    const char *), void *w4opaque);
187b34e8684ec025aa780997c11f847c19fb269755bJason Evans#endif
188e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk,
189e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    void *ptr, size_t size, size_t oldsize);
190e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool	arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk,
191e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    void *ptr, size_t size, size_t oldsize);
192e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool	arena_ralloc_large(void *ptr, size_t size, size_t oldsize);
193e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TINY
194e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic size_t	pow2_ceil(size_t x);
195e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
196e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool	small_size2bin_init(void);
197e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG
198e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	small_size2bin_validate(void);
199e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
200e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool	small_size2bin_init_hard(void);
201e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
202e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/******************************************************************************/
203e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
204e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline int
205e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b)
206e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
207e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	uintptr_t a_chunk = (uintptr_t)a;
208e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	uintptr_t b_chunk = (uintptr_t)b;
209e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
210e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(a != NULL);
211e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(b != NULL);
212e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
213e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return ((a_chunk > b_chunk) - (a_chunk < b_chunk));
214e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
215e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
216e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Wrap red-black tree macros in functions. */
217e476f8a161d445211fd6e54fe370275196e66bcbJason Evansrb_wrap(static JEMALLOC_ATTR(unused), arena_chunk_tree_dirty_,
218e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    arena_chunk_tree_t, arena_chunk_t, link_dirty, arena_chunk_comp)
219e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
220e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline int
221e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
222e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
223e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	uintptr_t a_mapelm = (uintptr_t)a;
224e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	uintptr_t b_mapelm = (uintptr_t)b;
225e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
226e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(a != NULL);
227e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(b != NULL);
228e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
229e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm));
230e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
231e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
232e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Wrap red-black tree macros in functions. */
233e476f8a161d445211fd6e54fe370275196e66bcbJason Evansrb_wrap(static JEMALLOC_ATTR(unused), arena_run_tree_, arena_run_tree_t,
234e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    arena_chunk_map_t, link, arena_run_comp)
235e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
236e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline int
237e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
238e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
239e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	int ret;
240e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t a_size = a->bits & ~PAGE_MASK;
241e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t b_size = b->bits & ~PAGE_MASK;
242e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
243e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	ret = (a_size > b_size) - (a_size < b_size);
244e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (ret == 0) {
245e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		uintptr_t a_mapelm, b_mapelm;
246e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
247e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if ((a->bits & CHUNK_MAP_KEY) != CHUNK_MAP_KEY)
248e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			a_mapelm = (uintptr_t)a;
249e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		else {
250e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			/*
251e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 * Treat keys as though they are lower than anything
252e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 * else.
253e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 */
254e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			a_mapelm = 0;
255e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
256e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		b_mapelm = (uintptr_t)b;
257e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
258e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm);
259e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
260e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
261e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ret);
262e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
263e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
264e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Wrap red-black tree macros in functions. */
265e476f8a161d445211fd6e54fe370275196e66bcbJason Evansrb_wrap(static JEMALLOC_ATTR(unused), arena_avail_tree_, arena_avail_tree_t,
266e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    arena_chunk_map_t, link, arena_avail_comp)
267e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
268e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline void
269e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_rc_incr(arena_run_t *run, arena_bin_t *bin, const void *ptr)
270e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
271e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
272e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_t *arena;
273e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t pagebeg, pageend, i;
274e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
275e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
276e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena = chunk->arena;
277e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	pagebeg = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT;
278e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	pageend = ((uintptr_t)ptr + (uintptr_t)(bin->reg_size - 1) -
279e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    (uintptr_t)chunk) >> PAGE_SHIFT;
280e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
281e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (i = pagebeg; i <= pageend; i++) {
282e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size_t mapbits = chunk->map[i].bits;
283e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
284e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (mapbits & CHUNK_MAP_DIRTY) {
285e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			assert((mapbits & CHUNK_MAP_RC_MASK) == 0);
286e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->ndirty--;
287e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena->ndirty--;
288e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			mapbits ^= CHUNK_MAP_DIRTY;
289e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
290e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert((mapbits & CHUNK_MAP_RC_MASK) != CHUNK_MAP_RC_MASK);
291e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		mapbits += CHUNK_MAP_RC_ONE;
292e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->map[i].bits = mapbits;
293e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
294e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
295e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
296e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline void
297e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_rc_decr(arena_run_t *run, arena_bin_t *bin, const void *ptr)
298e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
299e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
300e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_t *arena;
301e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t pagebeg, pageend, mapbits, i;
302e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bool dirtier = false;
303e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
304e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
305e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena = chunk->arena;
306e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	pagebeg = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT;
307e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	pageend = ((uintptr_t)ptr + (uintptr_t)(bin->reg_size - 1) -
308e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    (uintptr_t)chunk) >> PAGE_SHIFT;
309e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
310e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* First page. */
311e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	mapbits = chunk->map[pagebeg].bits;
312e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	mapbits -= CHUNK_MAP_RC_ONE;
313e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if ((mapbits & CHUNK_MAP_RC_MASK) == 0) {
314e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		dirtier = true;
315e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert((mapbits & CHUNK_MAP_DIRTY) == 0);
316e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		mapbits |= CHUNK_MAP_DIRTY;
317e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->ndirty++;
318e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->ndirty++;
319e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
320e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk->map[pagebeg].bits = mapbits;
321e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
322e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (pageend - pagebeg >= 1) {
323e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
324e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Interior pages are completely consumed by the object being
325e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * deallocated, which means that the pages can be
326e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * unconditionally marked dirty.
327e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
328e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		for (i = pagebeg + 1; i < pageend; i++) {
329e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			mapbits = chunk->map[i].bits;
330e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			mapbits -= CHUNK_MAP_RC_ONE;
331e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			assert((mapbits & CHUNK_MAP_RC_MASK) == 0);
332e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			dirtier = true;
333e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			assert((mapbits & CHUNK_MAP_DIRTY) == 0);
334e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			mapbits |= CHUNK_MAP_DIRTY;
335e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->ndirty++;
336e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena->ndirty++;
337e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->map[i].bits = mapbits;
338e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
339e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
340e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* Last page. */
341e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		mapbits = chunk->map[pageend].bits;
342e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		mapbits -= CHUNK_MAP_RC_ONE;
343e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if ((mapbits & CHUNK_MAP_RC_MASK) == 0) {
344e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			dirtier = true;
345e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			assert((mapbits & CHUNK_MAP_DIRTY) == 0);
346e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			mapbits |= CHUNK_MAP_DIRTY;
347e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->ndirty++;
348e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena->ndirty++;
349e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
350e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->map[pageend].bits = mapbits;
351e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
352e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
353e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (dirtier) {
354e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (chunk->dirtied == false) {
355e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena_chunk_tree_dirty_insert(&arena->chunks_dirty,
356e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    chunk);
357e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->dirtied = true;
358e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
359e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
360e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* Enforce opt_lg_dirty_mult. */
361e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (opt_lg_dirty_mult >= 0 && (arena->nactive >>
362e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    opt_lg_dirty_mult) < arena->ndirty)
363e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena_purge(arena);
364e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
365e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
366e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
367e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline void *
368e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_reg_alloc(arena_run_t *run, arena_bin_t *bin)
369e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
370e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	void *ret;
371e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	unsigned i, mask, bit, regind;
372e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
373e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(run->magic == ARENA_RUN_MAGIC);
374e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(run->regs_minelm < bin->regs_mask_nelms);
375e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
376e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
377e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Move the first check outside the loop, so that run->regs_minelm can
378e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * be updated unconditionally, without the possibility of updating it
379e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * multiple times.
380e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
381e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	i = run->regs_minelm;
382e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	mask = run->regs_mask[i];
383e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (mask != 0) {
384e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* Usable allocation found. */
385e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bit = ffs((int)mask) - 1;
386e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
387e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		regind = ((i << (LG_SIZEOF_INT + 3)) + bit);
388e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert(regind < bin->nregs);
389e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		ret = (void *)(((uintptr_t)run) + bin->reg0_offset
390e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    + (bin->reg_size * regind));
391e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
392e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* Clear bit. */
393e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		mask ^= (1U << bit);
394e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		run->regs_mask[i] = mask;
395e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
396e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_rc_incr(run, bin, ret);
397e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
398e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (ret);
399e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
400e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
401e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (i++; i < bin->regs_mask_nelms; i++) {
402e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		mask = run->regs_mask[i];
403e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (mask != 0) {
404e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			/* Usable allocation found. */
405e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			bit = ffs((int)mask) - 1;
406e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
407e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			regind = ((i << (LG_SIZEOF_INT + 3)) + bit);
408e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			assert(regind < bin->nregs);
409e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			ret = (void *)(((uintptr_t)run) + bin->reg0_offset
410e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    + (bin->reg_size * regind));
411e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
412e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			/* Clear bit. */
413e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			mask ^= (1U << bit);
414e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			run->regs_mask[i] = mask;
415e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
416e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			/*
417e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 * Make a note that nothing before this element
418e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 * contains a free region.
419e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 */
420e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			run->regs_minelm = i; /* Low payoff: + (mask == 0); */
421e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
422e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena_run_rc_incr(run, bin, ret);
423e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
424e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			return (ret);
425e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
426e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
427e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Not reached. */
428e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(0);
429e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (NULL);
430e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
431e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
432e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline void
433e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_reg_dalloc(arena_run_t *run, arena_bin_t *bin, void *ptr, size_t size)
434e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
435e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	unsigned shift, diff, regind, elm, bit;
436e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
437e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(run->magic == ARENA_RUN_MAGIC);
438e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
439e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
440e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Avoid doing division with a variable divisor if possible.  Using
441e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * actual division here can reduce allocator throughput by over 20%!
442e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
443e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	diff = (unsigned)((uintptr_t)ptr - (uintptr_t)run - bin->reg0_offset);
444e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
445e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Rescale (factor powers of 2 out of the numerator and denominator). */
446e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	shift = ffs(size) - 1;
447e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	diff >>= shift;
448e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size >>= shift;
449e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
450e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (size == 1) {
451e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* The divisor was a power of 2. */
452e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		regind = diff;
453e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else {
454e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
455e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * To divide by a number D that is not a power of two we
456e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * multiply by (2^21 / D) and then right shift by 21 positions.
457e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 *
458e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 *   X / D
459e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 *
460e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * becomes
461e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 *
462e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 *   (X * size_invs[D - 3]) >> SIZE_INV_SHIFT
463e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 *
464e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * We can omit the first three elements, because we never
465e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * divide by 0, and 1 and 2 are both powers of two, which are
466e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * handled above.
467e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
468e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	SIZE_INV_SHIFT 21
469e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	SIZE_INV(s) (((1U << SIZE_INV_SHIFT) / (s)) + 1)
470e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		static const unsigned size_invs[] = {
471e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    SIZE_INV(3),
472e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7),
473e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11),
474e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    SIZE_INV(12), SIZE_INV(13), SIZE_INV(14), SIZE_INV(15),
475e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    SIZE_INV(16), SIZE_INV(17), SIZE_INV(18), SIZE_INV(19),
476e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    SIZE_INV(20), SIZE_INV(21), SIZE_INV(22), SIZE_INV(23),
477e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    SIZE_INV(24), SIZE_INV(25), SIZE_INV(26), SIZE_INV(27),
478e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    SIZE_INV(28), SIZE_INV(29), SIZE_INV(30), SIZE_INV(31)
479e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		};
480e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
481e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (size <= ((sizeof(size_invs) / sizeof(unsigned)) + 2))
482e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			regind = (diff * size_invs[size - 3]) >> SIZE_INV_SHIFT;
483e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		else
484e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			regind = diff / size;
485e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef SIZE_INV
486e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef SIZE_INV_SHIFT
487e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
488e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(diff == regind * size);
489e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(regind < bin->nregs);
490e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
491e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	elm = regind >> (LG_SIZEOF_INT + 3);
492e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (elm < run->regs_minelm)
493e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		run->regs_minelm = elm;
494e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bit = regind - (elm << (LG_SIZEOF_INT + 3));
495e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((run->regs_mask[elm] & (1U << bit)) == 0);
496e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run->regs_mask[elm] |= (1U << bit);
497e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
498e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_rc_decr(run, bin, ptr);
499e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
500e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
501e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
502e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large,
503e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    bool zero)
504e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
505e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
506e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t old_ndirty, run_ind, total_pages, need_pages, rem_pages, i;
507e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
508e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
509e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	old_ndirty = chunk->ndirty;
510e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk)
511e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    >> PAGE_SHIFT);
512e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	total_pages = (chunk->map[run_ind].bits & ~PAGE_MASK) >>
513e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    PAGE_SHIFT;
514e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	need_pages = (size >> PAGE_SHIFT);
515e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(need_pages > 0);
516e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(need_pages <= total_pages);
517e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	rem_pages = total_pages - need_pages;
518e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
519e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_avail_tree_remove(&arena->runs_avail, &chunk->map[run_ind]);
520e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->nactive += need_pages;
521e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
522e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Keep track of trailing unused pages for later use. */
523e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (rem_pages > 0) {
524e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->map[run_ind+need_pages].bits = (rem_pages <<
525e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    PAGE_SHIFT) | (chunk->map[run_ind+need_pages].bits &
526e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    CHUNK_MAP_FLAGS_MASK);
527e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->map[run_ind+total_pages-1].bits = (rem_pages <<
528e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    PAGE_SHIFT) | (chunk->map[run_ind+total_pages-1].bits &
529e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    CHUNK_MAP_FLAGS_MASK);
530e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_avail_tree_insert(&arena->runs_avail,
531e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    &chunk->map[run_ind+need_pages]);
532e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
533e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
534e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (i = 0; i < need_pages; i++) {
535e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* Zero if necessary. */
536e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (zero) {
537e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			if ((chunk->map[run_ind + i].bits & CHUNK_MAP_ZEROED)
538e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    == 0) {
539e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				memset((void *)((uintptr_t)chunk + ((run_ind
540e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    + i) << PAGE_SHIFT)), 0, PAGE_SIZE);
541e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				/* CHUNK_MAP_ZEROED is cleared below. */
542e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			}
543e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
544e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
545e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* Update dirty page accounting. */
546e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY) {
547e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->ndirty--;
548e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena->ndirty--;
549e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			/* CHUNK_MAP_DIRTY is cleared below. */
550e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
551e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
552e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* Initialize the chunk map. */
553e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (large) {
554e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->map[run_ind + i].bits = CHUNK_MAP_LARGE
555e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    | CHUNK_MAP_ALLOCATED;
556e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		} else {
557e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->map[run_ind + i].bits = (i << CHUNK_MAP_PG_SHIFT)
558e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    | CHUNK_MAP_ALLOCATED;
559e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
560e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
561e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
562e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (large) {
563e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
564e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Set the run size only in the first element for large runs.
565e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * This is primarily a debugging aid, since the lack of size
566e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * info for trailing pages only matters if the application
567e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * tries to operate on an interior pointer.
568e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
569e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->map[run_ind].bits |= size;
570e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else {
571e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
572e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Initialize the first page's refcount to 1, so that the run
573e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * header is protected from dirty page purging.
574e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
575e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->map[run_ind].bits += CHUNK_MAP_RC_ONE;
576e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
577e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
578e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
579e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_chunk_t *
580e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_chunk_alloc(arena_t *arena)
581e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
582e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
583e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t i;
584e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
585e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (arena->spare != NULL) {
586e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk = arena->spare;
587e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->spare = NULL;
588e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else {
58941631d00618d7262125e501c91d31b4d70e605faJason Evans		bool zero;
59041631d00618d7262125e501c91d31b4d70e605faJason Evans		size_t zeroed;
59141631d00618d7262125e501c91d31b4d70e605faJason Evans
59241631d00618d7262125e501c91d31b4d70e605faJason Evans		zero = false;
59341631d00618d7262125e501c91d31b4d70e605faJason Evans		chunk = (arena_chunk_t *)chunk_alloc(chunksize, &zero);
594e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (chunk == NULL)
595e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			return (NULL);
596e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
597e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.mapped += chunksize;
598e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
599e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
600e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->arena = arena;
601e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->dirtied = false;
602e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
603e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
604e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Claim that no pages are in use, since the header is merely
605e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * overhead.
606e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
607e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->ndirty = 0;
608e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
609e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
610e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Initialize the map to contain one maximal free untouched run.
61141631d00618d7262125e501c91d31b4d70e605faJason Evans		 * Mark the pages as zeroed iff chunk_alloc() returned a zeroed
61241631d00618d7262125e501c91d31b4d70e605faJason Evans		 * chunk.
613e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
61441631d00618d7262125e501c91d31b4d70e605faJason Evans		zeroed = zero ? CHUNK_MAP_ZEROED : 0;
615e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		for (i = 0; i < arena_chunk_header_npages; i++)
616e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->map[i].bits = 0;
61741631d00618d7262125e501c91d31b4d70e605faJason Evans		chunk->map[i].bits = arena_maxclass | zeroed;
61841631d00618d7262125e501c91d31b4d70e605faJason Evans		for (i++; i < chunk_npages-1; i++)
61941631d00618d7262125e501c91d31b4d70e605faJason Evans			chunk->map[i].bits = zeroed;
62041631d00618d7262125e501c91d31b4d70e605faJason Evans		chunk->map[chunk_npages-1].bits = arena_maxclass | zeroed;
621e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
622e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
623e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Insert the run into the runs_avail tree. */
624e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_avail_tree_insert(&arena->runs_avail,
625e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    &chunk->map[arena_chunk_header_npages]);
626e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
627e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (chunk);
628e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
629e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
630e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
631e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk)
632e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
633e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
634e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (arena->spare != NULL) {
635e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (arena->spare->dirtied) {
636e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena_chunk_tree_dirty_remove(
637e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    &chunk->arena->chunks_dirty, arena->spare);
638e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena->ndirty -= arena->spare->ndirty;
639e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
640e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk_dealloc((void *)arena->spare, chunksize);
641e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
642e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.mapped -= chunksize;
643e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
644e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
645e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
646e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
647e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Remove run from runs_avail, regardless of whether this chunk
648e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * will be cached, so that the arena does not use it.  Dirty page
649e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * flushing only uses the chunks_dirty tree, so leaving this chunk in
650e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * the chunks_* trees is sufficient for that purpose.
651e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
652e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_avail_tree_remove(&arena->runs_avail,
653e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    &chunk->map[arena_chunk_header_npages]);
654e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
655e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->spare = chunk;
656e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
657e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
658e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t *
659e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_alloc(arena_t *arena, size_t size, bool large, bool zero)
660e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
661e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
662e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_t *run;
663e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_map_t *mapelm, key;
664e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
665e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(size <= arena_maxclass);
666e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((size & PAGE_MASK) == 0);
667e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
668e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Search the arena's chunks for the lowest best fit. */
669e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	key.bits = size | CHUNK_MAP_KEY;
670e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key);
671e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (mapelm != NULL) {
672e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm);
673e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size_t pageind = ((uintptr_t)mapelm - (uintptr_t)run_chunk->map)
674e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    / sizeof(arena_chunk_map_t);
675e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
676e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		run = (arena_run_t *)((uintptr_t)run_chunk + (pageind
677e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    << PAGE_SHIFT));
678e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_split(arena, run, size, large, zero);
679e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (run);
680e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
681e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
682e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
683e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * No usable runs.  Create a new chunk from which to allocate the run.
684e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
685e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk = arena_chunk_alloc(arena);
686e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (chunk == NULL)
687e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (NULL);
688e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run = (arena_run_t *)((uintptr_t)chunk + (arena_chunk_header_npages <<
689e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    PAGE_SHIFT));
690e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Update page map. */
691e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_split(arena, run, size, large, zero);
692e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (run);
693e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
694e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
695e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
696e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_purge(arena_t *arena)
697e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
698e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
699e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t i, npages;
700e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG
701e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t ndirty = 0;
702e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
703e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	rb_foreach_begin(arena_chunk_t, link_dirty, &arena->chunks_dirty,
704e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    chunk) {
705e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert(chunk->dirtied);
706e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		ndirty += chunk->ndirty;
707e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} rb_foreach_end(arena_chunk_t, link_dirty, &arena->chunks_dirty, chunk)
708e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(ndirty == arena->ndirty);
709e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
710e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((arena->nactive >> opt_lg_dirty_mult) < arena->ndirty);
711e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
712e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
713e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.npurge++;
714e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
715e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
716e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
717e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Iterate downward through chunks until enough dirty memory has been
718e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * purged.  Terminate as soon as possible in order to minimize the
719e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * number of system calls, even if a chunk has only been partially
720e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * purged.
721e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
722e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
723e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	while ((arena->nactive >> (opt_lg_dirty_mult + 1)) < arena->ndirty) {
724e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk = arena_chunk_tree_dirty_last(&arena->chunks_dirty);
725e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert(chunk != NULL);
726e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
727e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		for (i = chunk_npages - 1; chunk->ndirty > 0; i--) {
728e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			assert(i >= arena_chunk_header_npages);
729e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			if (chunk->map[i].bits & CHUNK_MAP_DIRTY) {
730e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				chunk->map[i].bits ^= CHUNK_MAP_DIRTY;
731e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				/* Find adjacent dirty run(s). */
732e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				for (npages = 1; i > arena_chunk_header_npages
733e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    && (chunk->map[i - 1].bits &
734e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    CHUNK_MAP_DIRTY); npages++) {
735e476f8a161d445211fd6e54fe370275196e66bcbJason Evans					i--;
736e476f8a161d445211fd6e54fe370275196e66bcbJason Evans					chunk->map[i].bits ^= CHUNK_MAP_DIRTY;
737e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				}
738e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				chunk->ndirty -= npages;
739e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				arena->ndirty -= npages;
740e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
741e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				madvise((void *)((uintptr_t)chunk + (i <<
742e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    PAGE_SHIFT)), (npages << PAGE_SHIFT),
743e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    MADV_DONTNEED);
744e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
745e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				arena->stats.nmadvise++;
746e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				arena->stats.purged += npages;
747e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
748e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				if ((arena->nactive >> (opt_lg_dirty_mult + 1))
749e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    >= arena->ndirty)
750e476f8a161d445211fd6e54fe370275196e66bcbJason Evans					break;
751e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			}
752e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
753e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
754e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (chunk->ndirty == 0) {
755e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena_chunk_tree_dirty_remove(&arena->chunks_dirty,
756e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    chunk);
757e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->dirtied = false;
758e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
759e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
760e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
761e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
762e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
763e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty)
764e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
765e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
766e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t size, run_ind, run_pages;
767e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
768e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
769e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk)
770e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    >> PAGE_SHIFT);
771e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(run_ind >= arena_chunk_header_npages);
772e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(run_ind < chunk_npages);
773e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if ((chunk->map[run_ind].bits & CHUNK_MAP_LARGE) != 0)
774e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size = chunk->map[run_ind].bits & ~PAGE_MASK;
775e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	else
776e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size = run->bin->run_size;
777e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run_pages = (size >> PAGE_SHIFT);
778e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->nactive -= run_pages;
779e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
780e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Mark pages as unallocated in the chunk map. */
781e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (dirty) {
782e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size_t i;
783e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
784e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		for (i = 0; i < run_pages; i++) {
785e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			/*
786e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 * When (dirty == true), *all* pages within the run
787e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 * need to have their dirty bits set, because only
788e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 * small runs can create a mixture of clean/dirty
789e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 * pages, but such runs are passed to this function
790e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 * with (dirty == false).
791e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 */
792e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			assert((chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY)
793e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    == 0);
794e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->ndirty++;
795e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena->ndirty++;
796e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->map[run_ind + i].bits = CHUNK_MAP_DIRTY;
797e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
798e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else {
799e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size_t i;
800e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
801e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		for (i = 0; i < run_pages; i++) {
802e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->map[run_ind + i].bits &= ~(CHUNK_MAP_LARGE |
803e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    CHUNK_MAP_ALLOCATED);
804e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
805e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
806e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
807e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    CHUNK_MAP_FLAGS_MASK);
808e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk->map[run_ind+run_pages-1].bits = size |
809e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    (chunk->map[run_ind+run_pages-1].bits & CHUNK_MAP_FLAGS_MASK);
810e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
811e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Try to coalesce forward. */
812e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (run_ind + run_pages < chunk_npages &&
813e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    (chunk->map[run_ind+run_pages].bits & CHUNK_MAP_ALLOCATED) == 0) {
814e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size_t nrun_size = chunk->map[run_ind+run_pages].bits &
815e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    ~PAGE_MASK;
816e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
817e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
818e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Remove successor from runs_avail; the coalesced run is
819e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * inserted later.
820e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
821e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_avail_tree_remove(&arena->runs_avail,
822e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    &chunk->map[run_ind+run_pages]);
823e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
824e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size += nrun_size;
825e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		run_pages = size >> PAGE_SHIFT;
826e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
827e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert((chunk->map[run_ind+run_pages-1].bits & ~PAGE_MASK)
828e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    == nrun_size);
829e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
830e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    CHUNK_MAP_FLAGS_MASK);
831e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->map[run_ind+run_pages-1].bits = size |
832e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    (chunk->map[run_ind+run_pages-1].bits &
833e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    CHUNK_MAP_FLAGS_MASK);
834e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
835e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
836e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Try to coalesce backward. */
837e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (run_ind > arena_chunk_header_npages && (chunk->map[run_ind-1].bits &
838e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    CHUNK_MAP_ALLOCATED) == 0) {
839e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size_t prun_size = chunk->map[run_ind-1].bits & ~PAGE_MASK;
840e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
841e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		run_ind -= prun_size >> PAGE_SHIFT;
842e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
843e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
844e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Remove predecessor from runs_avail; the coalesced run is
845e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * inserted later.
846e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
847e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_avail_tree_remove(&arena->runs_avail,
848e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    &chunk->map[run_ind]);
849e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
850e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size += prun_size;
851e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		run_pages = size >> PAGE_SHIFT;
852e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
853e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert((chunk->map[run_ind].bits & ~PAGE_MASK) == prun_size);
854e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
855e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    CHUNK_MAP_FLAGS_MASK);
856e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->map[run_ind+run_pages-1].bits = size |
857e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    (chunk->map[run_ind+run_pages-1].bits &
858e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    CHUNK_MAP_FLAGS_MASK);
859e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
860e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
861e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Insert into runs_avail, now that coalescing is complete. */
862e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_avail_tree_insert(&arena->runs_avail, &chunk->map[run_ind]);
863e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
864e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Deallocate chunk if it is now completely unused. */
865e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if ((chunk->map[arena_chunk_header_npages].bits & (~PAGE_MASK |
866e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    CHUNK_MAP_ALLOCATED)) == arena_maxclass)
867e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_chunk_dealloc(arena, chunk);
868e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
869e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (dirty) {
870e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (chunk->dirtied == false) {
871e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena_chunk_tree_dirty_insert(&arena->chunks_dirty,
872e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    chunk);
873e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->dirtied = true;
874e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
875e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
876e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* Enforce opt_lg_dirty_mult. */
877e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (opt_lg_dirty_mult >= 0 && (arena->nactive >>
878e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    opt_lg_dirty_mult) < arena->ndirty)
879e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena_purge(arena);
880e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
881e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
882e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
883e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
884e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
885e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    size_t oldsize, size_t newsize)
886e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
887e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT;
888e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t head_npages = (oldsize - newsize) >> PAGE_SHIFT;
889e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
890e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(oldsize > newsize);
891e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
892e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
893e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Update the chunk map so that arena_run_dalloc() can treat the
894e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * leading run as separately allocated.
895e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
896e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((chunk->map[pageind].bits & CHUNK_MAP_DIRTY) == 0);
897e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk->map[pageind].bits = (oldsize - newsize) | CHUNK_MAP_LARGE |
898e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    CHUNK_MAP_ALLOCATED;
899e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((chunk->map[pageind+head_npages].bits & CHUNK_MAP_DIRTY) == 0);
900e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk->map[pageind+head_npages].bits = newsize | CHUNK_MAP_LARGE |
901e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    CHUNK_MAP_ALLOCATED;
902e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
903e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_dalloc(arena, run, false);
904e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
905e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
906e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
907e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
908e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    size_t oldsize, size_t newsize, bool dirty)
909e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
910e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT;
911e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t npages = newsize >> PAGE_SHIFT;
912e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
913e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(oldsize > newsize);
914e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
915e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
916e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Update the chunk map so that arena_run_dalloc() can treat the
917e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * trailing run as separately allocated.
918e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
919e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((chunk->map[pageind].bits & CHUNK_MAP_DIRTY) == 0);
920e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk->map[pageind].bits = newsize | CHUNK_MAP_LARGE |
921e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    CHUNK_MAP_ALLOCATED;
922e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((chunk->map[pageind+npages].bits & CHUNK_MAP_DIRTY) == 0);
923e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk->map[pageind+npages].bits = (oldsize - newsize) | CHUNK_MAP_LARGE
924e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    | CHUNK_MAP_ALLOCATED;
925e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
926e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize),
927e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    dirty);
928e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
929e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
930e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t *
931e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin)
932e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
933e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_map_t *mapelm;
934e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_t *run;
935e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	unsigned i, remainder;
936e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
937e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Look for a usable run. */
938e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	mapelm = arena_run_tree_first(&bin->runs);
939e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (mapelm != NULL) {
940e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_chunk_t *chunk;
941e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size_t pageind;
942e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
943e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* run is guaranteed to have available space. */
944e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_tree_remove(&bin->runs, mapelm);
945e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
946e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm);
947e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) /
948e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    sizeof(arena_chunk_map_t));
949e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -
950e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    ((mapelm->bits & CHUNK_MAP_PG_MASK) >> CHUNK_MAP_PG_SHIFT))
951e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    << PAGE_SHIFT));
952e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
953e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->stats.reruns++;
954e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
955e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (run);
956e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
957e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* No existing runs have any space available. */
958e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
959e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Allocate a new run. */
960e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run = arena_run_alloc(arena, bin->run_size, false, false);
961e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (run == NULL)
962e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (NULL);
963e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
964e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Initialize run internals. */
965e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run->bin = bin;
966e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
967e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (i = 0; i < bin->regs_mask_nelms - 1; i++)
968e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		run->regs_mask[i] = UINT_MAX;
969e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	remainder = bin->nregs & ((1U << (LG_SIZEOF_INT + 3)) - 1);
970e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (remainder == 0)
971e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		run->regs_mask[i] = UINT_MAX;
972e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	else {
973e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* The last element has spare bits that need to be unset. */
974e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		run->regs_mask[i] = (UINT_MAX >> ((1U << (LG_SIZEOF_INT + 3))
975e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    - remainder));
976e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
977e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
978e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run->regs_minelm = 0;
979e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
980e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run->nfree = bin->nregs;
981e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG
982e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run->magic = ARENA_RUN_MAGIC;
983e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
984e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
985e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
986e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin->stats.nruns++;
987e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin->stats.curruns++;
988e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (bin->stats.curruns > bin->stats.highruns)
989e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->stats.highruns = bin->stats.curruns;
990e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
991e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (run);
992e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
993e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
994e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* bin->runcur must have space available before this function is called. */
995e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline void *
996e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_bin_malloc_easy(arena_t *arena, arena_bin_t *bin, arena_run_t *run)
997e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
998e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	void *ret;
999e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1000e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(run->magic == ARENA_RUN_MAGIC);
1001e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(run->nfree > 0);
1002e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1003e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	ret = arena_run_reg_alloc(run, bin);
1004e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(ret != NULL);
1005e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run->nfree--;
1006e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1007e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ret);
1008e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1009e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1010e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Re-fill bin->runcur, then call arena_bin_malloc_easy(). */
1011e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void *
1012e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)
1013e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1014e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1015e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin->runcur = arena_bin_nonfull_run_get(arena, bin);
1016e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (bin->runcur == NULL)
1017e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (NULL);
1018e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(bin->runcur->magic == ARENA_RUN_MAGIC);
1019e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(bin->runcur->nfree > 0);
1020e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1021e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (arena_bin_malloc_easy(arena, bin, bin->runcur));
1022e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1023e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1024e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TCACHE
1025e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid
1026e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_tcache_fill(arena_t *arena, tcache_bin_t *tbin, size_t binind)
1027e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1028e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	unsigned i, nfill;
1029e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_bin_t *bin;
1030e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_t *run;
1031e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	void *ptr;
1032e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1033e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(tbin->ncached == 0);
1034e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1035e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin = &arena->bins[binind];
1036e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_lock(&arena->lock);
1037e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (i = 0, nfill = (tcache_nslots >> 1); i < nfill; i++) {
1038e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if ((run = bin->runcur) != NULL && run->nfree > 0)
1039e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			ptr = arena_bin_malloc_easy(arena, bin, run);
1040e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		else
1041e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			ptr = arena_bin_malloc_hard(arena, bin);
1042e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (ptr == NULL) {
1043e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			if (i > 0) {
1044e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				/*
1045e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				 * Move valid pointers to the base of
1046e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				 * tbin->slots.
1047e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				 */
1048e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				memmove(&tbin->slots[0],
1049e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    &tbin->slots[nfill - i],
1050e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    i * sizeof(void *));
1051e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			}
1052e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			break;
1053e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1054e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
1055e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Fill slots such that the objects lowest in memory come last.
1056e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * This causes tcache to use low objects first.
1057e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
1058e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		tbin->slots[nfill - 1 - i] = ptr;
1059e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1060e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
1061e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin->stats.nfills++;
1062e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin->stats.nrequests += tbin->tstats.nrequests;
1063e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (bin->reg_size <= small_maxclass) {
1064e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.nmalloc_small += (i - tbin->ncached);
1065e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.allocated_small += (i - tbin->ncached) *
1066e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    bin->reg_size;
1067e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.nmalloc_small += tbin->tstats.nrequests;
1068e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else {
1069e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.nmalloc_medium += (i - tbin->ncached);
1070e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.allocated_medium += (i - tbin->ncached) *
1071e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    bin->reg_size;
1072e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.nmalloc_medium += tbin->tstats.nrequests;
1073e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1074e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	tbin->tstats.nrequests = 0;
1075e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1076e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_unlock(&arena->lock);
1077e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	tbin->ncached = i;
1078e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (tbin->ncached > tbin->high_water)
1079e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		tbin->high_water = tbin->ncached;
1080e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1081e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1082e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1083e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/*
1084e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Calculate bin->run_size such that it meets the following constraints:
1085e476f8a161d445211fd6e54fe370275196e66bcbJason Evans *
1086e476f8a161d445211fd6e54fe370275196e66bcbJason Evans *   *) bin->run_size >= min_run_size
1087e476f8a161d445211fd6e54fe370275196e66bcbJason Evans *   *) bin->run_size <= arena_maxclass
1088e476f8a161d445211fd6e54fe370275196e66bcbJason Evans *   *) bin->run_size <= RUN_MAX_SMALL
1089e476f8a161d445211fd6e54fe370275196e66bcbJason Evans *   *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed).
1090e476f8a161d445211fd6e54fe370275196e66bcbJason Evans *   *) run header size < PAGE_SIZE
1091e476f8a161d445211fd6e54fe370275196e66bcbJason Evans *
1092e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * bin->nregs, bin->regs_mask_nelms, and bin->reg0_offset are
1093e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * also calculated here, since these settings are all interdependent.
1094e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */
1095e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic size_t
1096e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size)
1097e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1098e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t try_run_size, good_run_size;
1099e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	unsigned good_nregs, good_mask_nelms, good_reg0_offset;
1100e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	unsigned try_nregs, try_mask_nelms, try_reg0_offset;
1101e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1102e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(min_run_size >= PAGE_SIZE);
1103e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(min_run_size <= arena_maxclass);
1104e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(min_run_size <= RUN_MAX_SMALL);
1105e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1106e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
1107e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Calculate known-valid settings before entering the run_size
1108e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * expansion loop, so that the first part of the loop always copies
1109e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * valid settings.
1110e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 *
1111e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * The do..while loop iteratively reduces the number of regions until
1112e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * the run header and the regions no longer overlap.  A closed formula
1113e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * would be quite messy, since there is an interdependency between the
1114e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * header's mask length and the number of regions.
1115e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
1116e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	try_run_size = min_run_size;
1117e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	try_nregs = ((try_run_size - sizeof(arena_run_t)) / bin->reg_size)
1118e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    + 1; /* Counter-act try_nregs-- in loop. */
1119e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	do {
1120e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		try_nregs--;
1121e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		try_mask_nelms = (try_nregs >> (LG_SIZEOF_INT + 3)) +
1122e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    ((try_nregs & ((1U << (LG_SIZEOF_INT + 3)) - 1)) ? 1 : 0);
1123e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		try_reg0_offset = try_run_size - (try_nregs * bin->reg_size);
1124e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} while (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1))
1125e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    > try_reg0_offset);
1126e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1127e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* run_size expansion loop. */
1128e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	do {
1129e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
1130e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Copy valid settings before trying more aggressive settings.
1131e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
1132e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		good_run_size = try_run_size;
1133e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		good_nregs = try_nregs;
1134e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		good_mask_nelms = try_mask_nelms;
1135e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		good_reg0_offset = try_reg0_offset;
1136e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1137e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* Try more aggressive settings. */
1138e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		try_run_size += PAGE_SIZE;
1139e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		try_nregs = ((try_run_size - sizeof(arena_run_t)) /
1140e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    bin->reg_size) + 1; /* Counter-act try_nregs-- in loop. */
1141e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		do {
1142e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			try_nregs--;
1143e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			try_mask_nelms = (try_nregs >> (LG_SIZEOF_INT + 3)) +
1144e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    ((try_nregs & ((1U << (LG_SIZEOF_INT + 3)) - 1)) ?
1145e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    1 : 0);
1146e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			try_reg0_offset = try_run_size - (try_nregs *
1147e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    bin->reg_size);
1148e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		} while (sizeof(arena_run_t) + (sizeof(unsigned) *
1149e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    (try_mask_nelms - 1)) > try_reg0_offset);
1150e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} while (try_run_size <= arena_maxclass && try_run_size <= RUN_MAX_SMALL
1151e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    && RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX
1152e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    && (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size
1153e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    && (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1)))
1154e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    < PAGE_SIZE);
1155e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1156e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1))
1157e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    <= good_reg0_offset);
1158e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((good_mask_nelms << (LG_SIZEOF_INT + 3)) >= good_nregs);
1159e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1160e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Copy final settings. */
1161e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin->run_size = good_run_size;
1162e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin->nregs = good_nregs;
1163e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin->regs_mask_nelms = good_mask_nelms;
1164e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin->reg0_offset = good_reg0_offset;
1165e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1166e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (good_run_size);
1167e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1168e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1169e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid *
1170e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_malloc_small(arena_t *arena, size_t size, bool zero)
1171e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1172e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	void *ret;
1173e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_bin_t *bin;
1174e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_t *run;
1175e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t binind;
1176e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1177e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	binind = small_size2bin[size];
1178e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(binind < mbin0);
1179e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin = &arena->bins[binind];
1180e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size = bin->reg_size;
1181e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1182e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_lock(&arena->lock);
1183e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if ((run = bin->runcur) != NULL && run->nfree > 0)
1184e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		ret = arena_bin_malloc_easy(arena, bin, run);
1185e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	else
1186e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		ret = arena_bin_malloc_hard(arena, bin);
1187e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1188e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (ret == NULL) {
1189e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		malloc_mutex_unlock(&arena->lock);
1190e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (NULL);
1191e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1192e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1193e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
1194e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  ifdef JEMALLOC_TCACHE
1195e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (isthreaded == false) {
1196e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  endif
1197e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->stats.nrequests++;
1198e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.nmalloc_small++;
1199e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  ifdef JEMALLOC_TCACHE
1200e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1201e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  endif
1202e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.allocated_small += size;
1203e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1204e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_unlock(&arena->lock);
1205e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1206e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (zero == false) {
1207e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL
1208e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (opt_junk)
1209e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			memset(ret, 0xa5, size);
1210e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		else if (opt_zero)
1211e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			memset(ret, 0, size);
1212e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1213e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else
1214e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memset(ret, 0, size);
1215e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1216e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ret);
1217e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1218e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1219e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid *
1220e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_malloc_medium(arena_t *arena, size_t size, bool zero)
1221e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1222e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	void *ret;
1223e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_bin_t *bin;
1224e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_t *run;
1225e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t binind;
1226e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1227e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size = MEDIUM_CEILING(size);
1228e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	binind = mbin0 + ((size - medium_min) >> lg_mspace);
1229e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(binind < nbins);
1230e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin = &arena->bins[binind];
1231e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(bin->reg_size == size);
1232e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1233e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_lock(&arena->lock);
1234e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if ((run = bin->runcur) != NULL && run->nfree > 0)
1235e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		ret = arena_bin_malloc_easy(arena, bin, run);
1236e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	else
1237e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		ret = arena_bin_malloc_hard(arena, bin);
1238e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1239e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (ret == NULL) {
1240e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		malloc_mutex_unlock(&arena->lock);
1241e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (NULL);
1242e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1243e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1244e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
1245e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  ifdef JEMALLOC_TCACHE
1246e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (isthreaded == false) {
1247e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  endif
1248e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->stats.nrequests++;
1249e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.nmalloc_medium++;
1250e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  ifdef JEMALLOC_TCACHE
1251e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1252e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  endif
1253e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.allocated_medium += size;
1254e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1255e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_unlock(&arena->lock);
1256e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1257e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (zero == false) {
1258e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL
1259e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (opt_junk)
1260e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			memset(ret, 0xa5, size);
1261e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		else if (opt_zero)
1262e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			memset(ret, 0, size);
1263e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1264e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else
1265e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memset(ret, 0, size);
1266e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1267e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ret);
1268e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1269e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1270e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void *
1271e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_malloc_large(arena_t *arena, size_t size, bool zero)
1272e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1273e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	void *ret;
1274e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1275e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Large allocation. */
1276e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size = PAGE_CEILING(size);
1277e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_lock(&arena->lock);
1278e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	ret = (void *)arena_run_alloc(arena, size, true, zero);
1279e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (ret == NULL) {
1280e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		malloc_mutex_unlock(&arena->lock);
1281e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (NULL);
1282e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1283e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
1284e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.nmalloc_large++;
1285e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.allocated_large += size;
1286e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++;
1287e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++;
1288e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns >
1289e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) {
1290e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns =
1291e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns;
1292e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1293e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1294e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_unlock(&arena->lock);
1295e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1296e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (zero == false) {
1297e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL
1298e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (opt_junk)
1299e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			memset(ret, 0xa5, size);
1300e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		else if (opt_zero)
1301e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			memset(ret, 0, size);
1302e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1303e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1304e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1305e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ret);
1306e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1307e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1308e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid *
1309e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_malloc(size_t size, bool zero)
1310e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1311e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1312e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(size != 0);
1313e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(QUANTUM_CEILING(size) <= arena_maxclass);
1314e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1315e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (size <= bin_maxclass) {
1316e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TCACHE
1317e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		tcache_t *tcache;
1318e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1319e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if ((tcache = tcache_get()) != NULL)
1320e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			return (tcache_alloc(tcache, size, zero));
1321e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1322e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (size <= small_maxclass)
1323e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			return (arena_malloc_small(choose_arena(), size, zero));
1324e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		else {
1325e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			return (arena_malloc_medium(choose_arena(), size,
1326e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    zero));
1327e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1328e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else
1329e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (arena_malloc_large(choose_arena(), size, zero));
1330e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1331e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1332e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Only handles large allocations that require more than page alignment. */
1333e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid *
1334e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_palloc(arena_t *arena, size_t alignment, size_t size, size_t alloc_size)
1335e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1336e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	void *ret;
1337e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t offset;
1338e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
1339e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1340e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((size & PAGE_MASK) == 0);
1341e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((alignment & PAGE_MASK) == 0);
1342e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1343e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_lock(&arena->lock);
1344e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	ret = (void *)arena_run_alloc(arena, alloc_size, true, false);
1345e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (ret == NULL) {
1346e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		malloc_mutex_unlock(&arena->lock);
1347e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (NULL);
1348e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1349e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1350e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ret);
1351e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1352e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	offset = (uintptr_t)ret & (alignment - 1);
1353e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((offset & PAGE_MASK) == 0);
1354e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(offset < alloc_size);
1355e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (offset == 0)
1356e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_trim_tail(arena, chunk, ret, alloc_size, size, false);
1357e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	else {
1358e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size_t leadsize, trailsize;
1359e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1360e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		leadsize = alignment - offset;
1361e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (leadsize > 0) {
1362e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena_run_trim_head(arena, chunk, ret, alloc_size,
1363e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    alloc_size - leadsize);
1364e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			ret = (void *)((uintptr_t)ret + leadsize);
1365e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1366e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1367e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		trailsize = alloc_size - leadsize - size;
1368e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (trailsize != 0) {
1369e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			/* Trim trailing space. */
1370e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			assert(trailsize < alloc_size);
1371e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena_run_trim_tail(arena, chunk, ret, size + trailsize,
1372e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    size, false);
1373e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1374e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1375e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1376e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
1377e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.nmalloc_large++;
1378e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.allocated_large += size;
1379e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++;
1380e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++;
1381e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns >
1382e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) {
1383e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns =
1384e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns;
1385e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1386e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1387e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_unlock(&arena->lock);
1388e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1389e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL
1390e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (opt_junk)
1391e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memset(ret, 0xa5, size);
1392e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	else if (opt_zero)
1393e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memset(ret, 0, size);
1394e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1395e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ret);
1396e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1397e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1398e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool
1399e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_is_large(const void *ptr)
1400e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1401e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
1402e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t pageind, mapbits;
1403e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1404e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(ptr != NULL);
1405e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(CHUNK_ADDR2BASE(ptr) != ptr);
1406e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1407e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
1408e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT);
1409e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	mapbits = chunk->map[pageind].bits;
1410e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((mapbits & CHUNK_MAP_ALLOCATED) != 0);
1411e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return ((mapbits & CHUNK_MAP_LARGE) != 0);
1412e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1413e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1414e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Return the size of the allocation pointed to by ptr. */
1415e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t
1416e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_salloc(const void *ptr)
1417e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1418e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t ret;
1419e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
1420e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t pageind, mapbits;
1421e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1422e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(ptr != NULL);
1423e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(CHUNK_ADDR2BASE(ptr) != ptr);
1424e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1425e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
1426e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT);
1427e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	mapbits = chunk->map[pageind].bits;
1428e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((mapbits & CHUNK_MAP_ALLOCATED) != 0);
1429e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if ((mapbits & CHUNK_MAP_LARGE) == 0) {
1430e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_t *run = (arena_run_t *)((uintptr_t)chunk +
1431e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    (uintptr_t)((pageind - ((mapbits & CHUNK_MAP_PG_MASK) >>
1432e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    CHUNK_MAP_PG_SHIFT)) << PAGE_SHIFT));
1433e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert(run->magic == ARENA_RUN_MAGIC);
1434e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		ret = run->bin->reg_size;
1435e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else {
1436e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		ret = mapbits & ~PAGE_MASK;
1437e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert(ret != 0);
1438e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1439e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1440e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ret);
1441e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1442e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1443e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
1444e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
1445e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    arena_bin_t *bin)
1446e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1447e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t run_ind;
1448e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1449e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Deallocate run. */
1450e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (run == bin->runcur)
1451e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->runcur = NULL;
1452e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	else if (bin->nregs != 1) {
1453e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size_t run_pageind = (((uintptr_t)run -
1454e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    (uintptr_t)chunk)) >> PAGE_SHIFT;
1455e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_chunk_map_t *run_mapelm =
1456e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    &chunk->map[run_pageind];
1457e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
1458e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * This block's conditional is necessary because if the
1459e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * run only contains one region, then it never gets
1460e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * inserted into the non-full runs tree.
1461e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
1462e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_tree_remove(&bin->runs, run_mapelm);
1463e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1464e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
1465e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Mark the first page as dirty.  The dirty bit for every other page in
1466e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * the run is already properly set, which means we can call
1467e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * arena_run_dalloc(..., false), thus potentially avoiding the needless
1468e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * creation of many dirty pages.
1469e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
1470e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT);
1471e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((chunk->map[run_ind].bits & CHUNK_MAP_DIRTY) == 0);
1472e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk->map[run_ind].bits |= CHUNK_MAP_DIRTY;
1473e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk->ndirty++;
1474e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->ndirty++;
1475e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1476e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG
1477e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run->magic = 0;
1478e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1479e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_dalloc(arena, run, false);
1480e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
1481e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin->stats.curruns--;
1482e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1483e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1484e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (chunk->dirtied == false) {
1485e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_chunk_tree_dirty_insert(&arena->chunks_dirty, chunk);
1486e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->dirtied = true;
1487e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1488e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Enforce opt_lg_dirty_mult. */
1489e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (opt_lg_dirty_mult >= 0 && (arena->nactive >> opt_lg_dirty_mult) <
1490e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    arena->ndirty)
1491e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_purge(arena);
1492e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1493e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1494e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid
1495e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,
1496e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    arena_chunk_map_t *mapelm)
1497e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1498e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t pageind;
1499e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_t *run;
1500e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_bin_t *bin;
1501e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t size;
1502e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1503e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT);
1504e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -
1505e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    ((mapelm->bits & CHUNK_MAP_PG_MASK) >> CHUNK_MAP_PG_SHIFT)) <<
1506e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    PAGE_SHIFT));
1507e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(run->magic == ARENA_RUN_MAGIC);
1508e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin = run->bin;
1509e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size = bin->reg_size;
1510e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1511e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL
1512e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (opt_junk)
1513e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memset(ptr, 0x5a, size);
1514e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1515e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1516e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_reg_dalloc(run, bin, ptr, size);
1517e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	run->nfree++;
1518e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1519e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (run->nfree == bin->nregs)
1520e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_dalloc_bin_run(arena, chunk, run, bin);
1521e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	else if (run->nfree == 1 && run != bin->runcur) {
1522e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
1523e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Make sure that bin->runcur always refers to the lowest
1524e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * non-full run, if one exists.
1525e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
1526e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (bin->runcur == NULL)
1527e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			bin->runcur = run;
1528e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		else if ((uintptr_t)run < (uintptr_t)bin->runcur) {
1529e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			/* Switch runcur. */
1530e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			if (bin->runcur->nfree > 0) {
1531e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				arena_chunk_t *runcur_chunk =
1532e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    CHUNK_ADDR2BASE(bin->runcur);
1533e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				size_t runcur_pageind =
1534e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    (((uintptr_t)bin->runcur -
1535e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    (uintptr_t)runcur_chunk)) >> PAGE_SHIFT;
1536e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				arena_chunk_map_t *runcur_mapelm =
1537e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    &runcur_chunk->map[runcur_pageind];
1538e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1539e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				/* Insert runcur. */
1540e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				arena_run_tree_insert(&bin->runs,
1541e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    runcur_mapelm);
1542e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			}
1543e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			bin->runcur = run;
1544e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		} else {
1545e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			size_t run_pageind = (((uintptr_t)run -
1546e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    (uintptr_t)chunk)) >> PAGE_SHIFT;
1547e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena_chunk_map_t *run_mapelm =
1548e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    &chunk->map[run_pageind];
1549e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1550e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			assert(arena_run_tree_search(&bin->runs, run_mapelm) ==
1551e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    NULL);
1552e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena_run_tree_insert(&bin->runs, run_mapelm);
1553e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1554e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1555e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1556e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
1557e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (size <= small_maxclass) {
1558e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.allocated_small -= size;
1559e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.ndalloc_small++;
1560e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else {
1561e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.allocated_medium -= size;
1562e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.ndalloc_medium++;
1563e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1564e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1565e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1566e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1567e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
1568e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid
1569b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_merge(arena_t *arena, size_t *nactive, size_t *ndirty,
1570b34e8684ec025aa780997c11f847c19fb269755bJason Evans    arena_stats_t *astats, malloc_bin_stats_t *bstats,
1571b34e8684ec025aa780997c11f847c19fb269755bJason Evans    malloc_large_stats_t *lstats)
1572b34e8684ec025aa780997c11f847c19fb269755bJason Evans{
1573b34e8684ec025aa780997c11f847c19fb269755bJason Evans	unsigned i, nlclasses;
1574b34e8684ec025aa780997c11f847c19fb269755bJason Evans
1575b34e8684ec025aa780997c11f847c19fb269755bJason Evans	*nactive += arena->nactive;
1576b34e8684ec025aa780997c11f847c19fb269755bJason Evans	*ndirty += arena->ndirty;
1577b34e8684ec025aa780997c11f847c19fb269755bJason Evans
15784201af05425b69ee37ffca437aca0cdd604d1e51Jason Evans	astats->mapped += arena->stats.mapped;
1579b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->npurge += arena->stats.npurge;
1580b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->nmadvise += arena->stats.nmadvise;
1581b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->purged += arena->stats.purged;
1582b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->allocated_small += arena->stats.allocated_small;
1583b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->nmalloc_small += arena->stats.nmalloc_small;
1584b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->ndalloc_small += arena->stats.ndalloc_small;
1585b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->allocated_medium += arena->stats.allocated_medium;
1586b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->nmalloc_medium += arena->stats.nmalloc_medium;
1587b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->ndalloc_medium += arena->stats.ndalloc_medium;
1588b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->allocated_large += arena->stats.allocated_large;
1589b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->nmalloc_large += arena->stats.nmalloc_large;
1590b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->ndalloc_large += arena->stats.ndalloc_large;
1591b34e8684ec025aa780997c11f847c19fb269755bJason Evans
1592b34e8684ec025aa780997c11f847c19fb269755bJason Evans	for (i = 0; i < nbins; i++) {
1593b34e8684ec025aa780997c11f847c19fb269755bJason Evans		bstats[i].nrequests += arena->bins[i].stats.nrequests;
1594b34e8684ec025aa780997c11f847c19fb269755bJason Evans#ifdef JEMALLOC_TCACHE
1595b34e8684ec025aa780997c11f847c19fb269755bJason Evans		bstats[i].nfills += arena->bins[i].stats.nfills;
1596b34e8684ec025aa780997c11f847c19fb269755bJason Evans		bstats[i].nflushes += arena->bins[i].stats.nflushes;
1597b34e8684ec025aa780997c11f847c19fb269755bJason Evans#endif
1598b34e8684ec025aa780997c11f847c19fb269755bJason Evans		bstats[i].nruns += arena->bins[i].stats.nruns;
1599b34e8684ec025aa780997c11f847c19fb269755bJason Evans		bstats[i].reruns += arena->bins[i].stats.reruns;
1600b34e8684ec025aa780997c11f847c19fb269755bJason Evans		bstats[i].highruns += arena->bins[i].stats.highruns;
1601b34e8684ec025aa780997c11f847c19fb269755bJason Evans		bstats[i].curruns += arena->bins[i].stats.curruns;
1602b34e8684ec025aa780997c11f847c19fb269755bJason Evans	}
1603b34e8684ec025aa780997c11f847c19fb269755bJason Evans
1604b34e8684ec025aa780997c11f847c19fb269755bJason Evans	for (i = 0, nlclasses = (chunksize - PAGE_SIZE) >> PAGE_SHIFT;
1605b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    i < nlclasses;
1606b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    i++) {
1607b34e8684ec025aa780997c11f847c19fb269755bJason Evans		lstats[i].nrequests += arena->stats.lstats[i].nrequests;
1608b34e8684ec025aa780997c11f847c19fb269755bJason Evans		lstats[i].highruns += arena->stats.lstats[i].highruns;
1609b34e8684ec025aa780997c11f847c19fb269755bJason Evans		lstats[i].curruns += arena->stats.lstats[i].curruns;
1610b34e8684ec025aa780997c11f847c19fb269755bJason Evans	}
1611b34e8684ec025aa780997c11f847c19fb269755bJason Evans}
1612b34e8684ec025aa780997c11f847c19fb269755bJason Evans
1613b34e8684ec025aa780997c11f847c19fb269755bJason Evansstatic void
1614b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_aprint(size_t nactive, size_t ndirty, const arena_stats_t *astats,
1615ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    void (*write4)(void *, const char *, const char *, const char *,
1616ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    const char *), void *w4opaque)
1617e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1618e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1619ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans	malloc_cprintf(write4, w4opaque,
1620bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans	    "dirty pages: %zu:%zu active:dirty, %"PRIu64" sweep%s,"
1621bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans	    " %"PRIu64" madvise%s, %"PRIu64" purged\n",
1622b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    nactive, ndirty,
1623b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->npurge, astats->npurge == 1 ? "" : "s",
1624b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->nmadvise, astats->nmadvise == 1 ? "" : "s",
1625b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->purged);
1626e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1627ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans	malloc_cprintf(write4, w4opaque,
162800b5c9334701d10a798ae86cd142df882f28519cJason Evans	    "            allocated      nmalloc      ndalloc\n");
1629bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans	malloc_cprintf(write4, w4opaque,
1630bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans	    "small:   %12zu %12"PRIu64" %12"PRIu64"\n",
1631b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->allocated_small, astats->nmalloc_small,
1632b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->ndalloc_small);
1633bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans	malloc_cprintf(write4, w4opaque,
1634bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans	    "medium:  %12zu %12"PRIu64" %12"PRIu64"\n",
1635b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->allocated_medium, astats->nmalloc_medium,
1636b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->ndalloc_medium);
1637bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans	malloc_cprintf(write4, w4opaque,
1638bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans	    "large:   %12zu %12"PRIu64" %12"PRIu64"\n",
1639b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->allocated_large, astats->nmalloc_large,
1640b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->ndalloc_large);
1641bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans	malloc_cprintf(write4, w4opaque,
1642bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans	    "total:   %12zu %12"PRIu64" %12"PRIu64"\n",
1643b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->allocated_small + astats->allocated_medium +
1644b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->allocated_large, astats->nmalloc_small +
1645b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->nmalloc_medium + astats->nmalloc_large,
1646b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->ndalloc_small + astats->ndalloc_medium +
1647b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    astats->ndalloc_large);
1648ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans	malloc_cprintf(write4, w4opaque, "mapped:  %12zu\n", astats->mapped);
1649b34e8684ec025aa780997c11f847c19fb269755bJason Evans}
1650b34e8684ec025aa780997c11f847c19fb269755bJason Evans
1651b34e8684ec025aa780997c11f847c19fb269755bJason Evansstatic void
1652b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_bprint(arena_t *arena, const malloc_bin_stats_t *bstats,
1653ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    void (*write4)(void *, const char *, const char *, const char *,
1654ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    const char *), void *w4opaque)
1655b34e8684ec025aa780997c11f847c19fb269755bJason Evans{
1656b34e8684ec025aa780997c11f847c19fb269755bJason Evans	unsigned i, gap_start;
1657b34e8684ec025aa780997c11f847c19fb269755bJason Evans
1658e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TCACHE
1659ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans	malloc_cprintf(write4, w4opaque,
1660b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    "bins:     bin    size regs pgs  requests    "
1661b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    "nfills  nflushes   newruns    reruns maxruns curruns\n");
1662e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#else
1663ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans	malloc_cprintf(write4, w4opaque,
1664b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    "bins:     bin    size regs pgs  requests   "
1665b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    "newruns    reruns maxruns curruns\n");
1666e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1667b34e8684ec025aa780997c11f847c19fb269755bJason Evans	for (i = 0, gap_start = UINT_MAX; i < nbins; i++) {
1668b34e8684ec025aa780997c11f847c19fb269755bJason Evans		if (bstats[i].nruns == 0) {
1669b34e8684ec025aa780997c11f847c19fb269755bJason Evans			if (gap_start == UINT_MAX)
1670b34e8684ec025aa780997c11f847c19fb269755bJason Evans				gap_start = i;
1671b34e8684ec025aa780997c11f847c19fb269755bJason Evans		} else {
1672b34e8684ec025aa780997c11f847c19fb269755bJason Evans			if (gap_start != UINT_MAX) {
1673b34e8684ec025aa780997c11f847c19fb269755bJason Evans				if (i > gap_start + 1) {
1674b34e8684ec025aa780997c11f847c19fb269755bJason Evans					/* Gap of more than one size class. */
1675ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans					malloc_cprintf(write4, w4opaque,
1676b34e8684ec025aa780997c11f847c19fb269755bJason Evans					    "[%u..%u]\n", gap_start,
1677b34e8684ec025aa780997c11f847c19fb269755bJason Evans					    i - 1);
1678b34e8684ec025aa780997c11f847c19fb269755bJason Evans				} else {
1679b34e8684ec025aa780997c11f847c19fb269755bJason Evans					/* Gap of one size class. */
1680ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans					malloc_cprintf(write4, w4opaque,
1681ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans					    "[%u]\n", gap_start);
1682e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				}
1683b34e8684ec025aa780997c11f847c19fb269755bJason Evans				gap_start = UINT_MAX;
1684b34e8684ec025aa780997c11f847c19fb269755bJason Evans			}
1685ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans			malloc_cprintf(write4, w4opaque,
1686bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans			    "%13u %1s %5u %4u %3u %9"PRIu64" %9"PRIu64
1687e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TCACHE
1688bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans			    " %9"PRIu64" %9"PRIu64""
1689e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1690bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans			    " %9"PRIu64" %7zu %7zu\n",
1691b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    i,
1692b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    i < ntbins ? "T" : i < ntbins + nqbins ?
1693b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    "Q" : i < ntbins + nqbins + ncbins ? "C" :
1694b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    i < ntbins + nqbins + ncbins + nsbins ? "S"
1695b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    : "M",
1696b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    arena->bins[i].reg_size,
1697b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    arena->bins[i].nregs,
1698b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    arena->bins[i].run_size >> PAGE_SHIFT,
1699b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    bstats[i].nrequests,
1700e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TCACHE
1701b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    bstats[i].nfills,
1702b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    bstats[i].nflushes,
1703e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1704b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    bstats[i].nruns,
1705b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    bstats[i].reruns,
1706b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    bstats[i].highruns,
1707b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    bstats[i].curruns);
1708e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1709b34e8684ec025aa780997c11f847c19fb269755bJason Evans	}
1710b34e8684ec025aa780997c11f847c19fb269755bJason Evans	if (gap_start != UINT_MAX) {
1711b34e8684ec025aa780997c11f847c19fb269755bJason Evans		if (i > gap_start + 1) {
1712b34e8684ec025aa780997c11f847c19fb269755bJason Evans			/* Gap of more than one size class. */
1713ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans			malloc_cprintf(write4, w4opaque, "[%u..%u]\n",
1714ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans			    gap_start, i - 1);
1715b34e8684ec025aa780997c11f847c19fb269755bJason Evans		} else {
1716b34e8684ec025aa780997c11f847c19fb269755bJason Evans			/* Gap of one size class. */
1717ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans			malloc_cprintf(write4, w4opaque, "[%u]\n", gap_start);
1718e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1719e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1720b34e8684ec025aa780997c11f847c19fb269755bJason Evans}
1721e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1722b34e8684ec025aa780997c11f847c19fb269755bJason Evansstatic void
1723b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_lprint(const malloc_large_stats_t *lstats,
1724ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    void (*write4)(void *, const char *, const char *, const char *,
1725ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    const char *), void *w4opaque)
1726b34e8684ec025aa780997c11f847c19fb269755bJason Evans{
1727b34e8684ec025aa780997c11f847c19fb269755bJason Evans	size_t i;
1728b34e8684ec025aa780997c11f847c19fb269755bJason Evans	ssize_t gap_start;
1729b34e8684ec025aa780997c11f847c19fb269755bJason Evans	size_t nlclasses = (chunksize - PAGE_SIZE) >> PAGE_SHIFT;
1730b34e8684ec025aa780997c11f847c19fb269755bJason Evans
1731ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans	malloc_cprintf(write4, w4opaque,
1732b34e8684ec025aa780997c11f847c19fb269755bJason Evans	    "large:   size pages nrequests   maxruns   curruns\n");
1733b34e8684ec025aa780997c11f847c19fb269755bJason Evans
1734b34e8684ec025aa780997c11f847c19fb269755bJason Evans	for (i = 0, gap_start = -1; i < nlclasses; i++) {
1735b34e8684ec025aa780997c11f847c19fb269755bJason Evans		if (lstats[i].nrequests == 0) {
1736b34e8684ec025aa780997c11f847c19fb269755bJason Evans			if (gap_start == -1)
1737b34e8684ec025aa780997c11f847c19fb269755bJason Evans				gap_start = i;
1738b34e8684ec025aa780997c11f847c19fb269755bJason Evans		} else {
1739b34e8684ec025aa780997c11f847c19fb269755bJason Evans			if (gap_start != -1) {
1740ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans				malloc_cprintf(write4, w4opaque, "[%zu]\n",
1741b34e8684ec025aa780997c11f847c19fb269755bJason Evans				    i - gap_start);
1742b34e8684ec025aa780997c11f847c19fb269755bJason Evans				gap_start = -1;
1743e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			}
1744ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans			malloc_cprintf(write4, w4opaque,
1745bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans			    "%13zu %5zu %9"PRIu64" %9zu %9zu\n",
1746b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    (i+1) << PAGE_SHIFT, i+1,
1747b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    lstats[i].nrequests,
1748b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    lstats[i].highruns,
1749b34e8684ec025aa780997c11f847c19fb269755bJason Evans			    lstats[i].curruns);
1750e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1751e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1752b34e8684ec025aa780997c11f847c19fb269755bJason Evans	if (gap_start != -1)
1753ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans		malloc_cprintf(write4, w4opaque, "[%zu]\n", i - gap_start);
1754b34e8684ec025aa780997c11f847c19fb269755bJason Evans}
1755b34e8684ec025aa780997c11f847c19fb269755bJason Evans
1756b34e8684ec025aa780997c11f847c19fb269755bJason Evansvoid
1757b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_mprint(arena_t *arena, size_t nactive, size_t ndirty,
1758b34e8684ec025aa780997c11f847c19fb269755bJason Evans    const arena_stats_t *astats, const malloc_bin_stats_t *bstats,
1759b34e8684ec025aa780997c11f847c19fb269755bJason Evans    const malloc_large_stats_t *lstats, bool bins, bool large,
1760ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    void (*write4)(void *, const char *, const char *, const char *,
1761ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    const char *), void *w4opaque)
1762b34e8684ec025aa780997c11f847c19fb269755bJason Evans{
1763b34e8684ec025aa780997c11f847c19fb269755bJason Evans
1764ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans	arena_stats_aprint(nactive, ndirty, astats, write4, w4opaque);
1765b34e8684ec025aa780997c11f847c19fb269755bJason Evans	if (bins && astats->nmalloc_small + astats->nmalloc_medium > 0)
1766ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans		arena_stats_bprint(arena, bstats, write4, w4opaque);
1767b34e8684ec025aa780997c11f847c19fb269755bJason Evans	if (large && astats->nmalloc_large > 0)
1768ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans		arena_stats_lprint(lstats, write4, w4opaque);
1769b34e8684ec025aa780997c11f847c19fb269755bJason Evans}
1770b34e8684ec025aa780997c11f847c19fb269755bJason Evans
1771b34e8684ec025aa780997c11f847c19fb269755bJason Evansvoid
1772b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_print(arena_t *arena, bool bins, bool large,
1773ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    void (*write4)(void *, const char *, const char *, const char *,
1774ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans    const char *), void *w4opaque)
1775b34e8684ec025aa780997c11f847c19fb269755bJason Evans{
1776b34e8684ec025aa780997c11f847c19fb269755bJason Evans	size_t nactive, ndirty;
1777b34e8684ec025aa780997c11f847c19fb269755bJason Evans	arena_stats_t astats;
1778b34e8684ec025aa780997c11f847c19fb269755bJason Evans	malloc_bin_stats_t bstats[nbins];
1779b34e8684ec025aa780997c11f847c19fb269755bJason Evans	malloc_large_stats_t lstats[((chunksize - PAGE_SIZE) >> PAGE_SHIFT)];
1780b34e8684ec025aa780997c11f847c19fb269755bJason Evans
1781b34e8684ec025aa780997c11f847c19fb269755bJason Evans	nactive = 0;
1782b34e8684ec025aa780997c11f847c19fb269755bJason Evans	ndirty = 0;
1783b34e8684ec025aa780997c11f847c19fb269755bJason Evans	memset(&astats, 0, sizeof(astats));
1784b34e8684ec025aa780997c11f847c19fb269755bJason Evans	memset(bstats, 0, sizeof(bstats));
1785b34e8684ec025aa780997c11f847c19fb269755bJason Evans	memset(lstats, 0, sizeof(lstats));
1786b34e8684ec025aa780997c11f847c19fb269755bJason Evans
1787b34e8684ec025aa780997c11f847c19fb269755bJason Evans	arena_stats_merge(arena, &nactive, &ndirty, &astats, bstats, lstats);
1788b34e8684ec025aa780997c11f847c19fb269755bJason Evans	arena_stats_mprint(arena, nactive, ndirty, &astats, bstats, lstats,
1789ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans	    bins, large, write4, w4opaque);
1790e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1791e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1792e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1793e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid
1794e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)
1795e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1796e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Large allocation. */
1797e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_lock(&arena->lock);
1798e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1799e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL
1800e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifndef JEMALLOC_STATS
1801e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (opt_junk)
1802e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1803e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1804e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	{
1805e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#if (defined(JEMALLOC_FILL) || defined(JEMALLOC_STATS))
1806e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >>
1807e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    PAGE_SHIFT;
1808e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size_t size = chunk->map[pageind].bits & ~PAGE_MASK;
1809e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1810e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1811e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL
1812e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
1813e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (opt_junk)
1814e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1815e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			memset(ptr, 0x5a, size);
1816e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1817e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
1818e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.allocated_large -= size;
1819e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns--;
1820e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1821e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1822e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
1823e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.ndalloc_large++;
1824e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1825e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1826e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_dalloc(arena, (arena_run_t *)ptr, true);
1827e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_unlock(&arena->lock);
1828e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1829e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1830e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
1831e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr,
1832e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    size_t size, size_t oldsize)
1833e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1834e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1835e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(size < oldsize);
1836e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1837e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
1838e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Shrink the run, and make trailing pages available for other
1839e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * allocations.
1840e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
1841e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_lock(&arena->lock);
1842e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size,
1843e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    true);
1844e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
1845e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.allocated_large -= oldsize - size;
1846e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.lstats[size >> PAGE_SHIFT].nrequests++;
1847e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.lstats[size >> PAGE_SHIFT].curruns++;
1848e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (arena->stats.lstats[size >> PAGE_SHIFT].curruns >
1849e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    arena->stats.lstats[size >> PAGE_SHIFT].highruns) {
1850e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.lstats[size >> PAGE_SHIFT].highruns =
1851e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    arena->stats.lstats[size >> PAGE_SHIFT].curruns;
1852e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1853e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.lstats[oldsize >> PAGE_SHIFT].curruns--;
1854e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1855e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_unlock(&arena->lock);
1856e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1857e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1858e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool
1859e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr,
1860e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    size_t size, size_t oldsize)
1861e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1862e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT;
1863e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t npages = oldsize >> PAGE_SHIFT;
1864e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1865e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(oldsize == (chunk->map[pageind].bits & ~PAGE_MASK));
1866e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1867e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Try to extend the run. */
1868e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(size > oldsize);
1869e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_lock(&arena->lock);
1870e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (pageind + npages < chunk_npages && (chunk->map[pageind+npages].bits
1871e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    & CHUNK_MAP_ALLOCATED) == 0 && (chunk->map[pageind+npages].bits &
1872e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    ~PAGE_MASK) >= size - oldsize) {
1873e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
1874e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * The next run is available and sufficiently large.  Split the
1875e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * following run, then merge the first part with the existing
1876e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * allocation.
1877e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
1878e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_split(arena, (arena_run_t *)((uintptr_t)chunk +
1879e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    ((pageind+npages) << PAGE_SHIFT)), size - oldsize, true,
1880e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    false);
1881e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1882e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->map[pageind].bits = size | CHUNK_MAP_LARGE |
1883e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    CHUNK_MAP_ALLOCATED;
1884e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->map[pageind+npages].bits = CHUNK_MAP_LARGE |
1885e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    CHUNK_MAP_ALLOCATED;
1886e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1887e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
1888e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.allocated_large += size - oldsize;
1889e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.lstats[size >> PAGE_SHIFT].nrequests++;
1890e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.lstats[size >> PAGE_SHIFT].curruns++;
1891e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (arena->stats.lstats[size >> PAGE_SHIFT].curruns >
1892e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    arena->stats.lstats[size >> PAGE_SHIFT].highruns) {
1893e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena->stats.lstats[size >> PAGE_SHIFT].highruns =
1894e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    arena->stats.lstats[size >> PAGE_SHIFT].curruns;
1895e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1896e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->stats.lstats[oldsize >> PAGE_SHIFT].curruns--;
1897e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1898e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		malloc_mutex_unlock(&arena->lock);
1899e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (false);
1900e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1901e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_unlock(&arena->lock);
1902e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1903e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (true);
1904e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1905e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1906e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/*
1907e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Try to resize a large allocation, in order to avoid copying.  This will
1908e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * always fail if growing an object, and the following run is already in use.
1909e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */
1910e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool
1911e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_ralloc_large(void *ptr, size_t size, size_t oldsize)
1912e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1913e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t psize;
1914e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1915e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	psize = PAGE_CEILING(size);
1916e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (psize == oldsize) {
1917e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* Same size class. */
1918e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL
1919e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (opt_junk && size < oldsize) {
1920e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize -
1921e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    size);
1922e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1923e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1924e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (false);
1925e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else {
1926e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_chunk_t *chunk;
1927e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_t *arena;
1928e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1929e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
1930e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena = chunk->arena;
1931e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert(arena->magic == ARENA_MAGIC);
1932e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1933e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (psize < oldsize) {
1934e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL
1935e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			/* Fill before shrinking in order avoid a race. */
1936e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			if (opt_junk) {
1937e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				memset((void *)((uintptr_t)ptr + size), 0x5a,
1938e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    oldsize - size);
1939e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			}
1940e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1941e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			arena_ralloc_large_shrink(arena, chunk, ptr, psize,
1942e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    oldsize);
1943e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			return (false);
1944e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		} else {
1945e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			bool ret = arena_ralloc_large_grow(arena, chunk, ptr,
1946e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    psize, oldsize);
1947e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL
1948e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			if (ret == false && opt_zero) {
1949e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				memset((void *)((uintptr_t)ptr + oldsize), 0,
1950e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    size - oldsize);
1951e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			}
1952e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
1953e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			return (ret);
1954e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1955e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1956e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1957e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1958e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid *
1959e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_ralloc(void *ptr, size_t size, size_t oldsize)
1960e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1961e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	void *ret;
1962e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t copysize;
1963e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1964e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
1965e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Try to avoid moving the allocation.
1966e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 *
1967e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * posix_memalign() can cause allocation of "large" objects that are
1968e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * smaller than bin_maxclass (in order to meet alignment requirements).
1969e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Therefore, do not assume that (oldsize <= bin_maxclass) indicates
1970e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * ptr refers to a bin-allocated object.
1971e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
1972e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (oldsize <= arena_maxclass) {
1973e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (arena_is_large(ptr) == false ) {
1974e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			if (size <= small_maxclass) {
1975e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				if (oldsize <= small_maxclass &&
1976e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    small_size2bin[size] ==
1977e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    small_size2bin[oldsize])
1978e476f8a161d445211fd6e54fe370275196e66bcbJason Evans					goto IN_PLACE;
1979e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			} else if (size <= bin_maxclass) {
1980e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				if (small_maxclass < oldsize && oldsize <=
1981e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    bin_maxclass && MEDIUM_CEILING(size) ==
1982e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    MEDIUM_CEILING(oldsize))
1983e476f8a161d445211fd6e54fe370275196e66bcbJason Evans					goto IN_PLACE;
1984e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			}
1985e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		} else {
1986e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			assert(size <= arena_maxclass);
1987e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			if (size > bin_maxclass) {
1988e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				if (arena_ralloc_large(ptr, size, oldsize) ==
1989e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    false)
1990e476f8a161d445211fd6e54fe370275196e66bcbJason Evans					return (ptr);
1991e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			}
1992e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1993e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1994e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1995e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Try to avoid moving the allocation. */
1996e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (size <= small_maxclass) {
1997e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (oldsize <= small_maxclass && small_size2bin[size] ==
1998e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    small_size2bin[oldsize])
1999e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			goto IN_PLACE;
2000e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else if (size <= bin_maxclass) {
2001e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (small_maxclass < oldsize && oldsize <= bin_maxclass &&
2002e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    MEDIUM_CEILING(size) == MEDIUM_CEILING(oldsize))
2003e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			goto IN_PLACE;
2004e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else {
2005e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (bin_maxclass < oldsize && oldsize <= arena_maxclass) {
2006e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			assert(size > bin_maxclass);
2007e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			if (arena_ralloc_large(ptr, size, oldsize) == false)
2008e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				return (ptr);
2009e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
2010e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2011e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2012e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
2013e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * If we get here, then size and oldsize are different enough that we
2014e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * need to move the object.  In that case, fall back to allocating new
2015e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * space and copying.
2016e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
2017e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	ret = arena_malloc(size, false);
2018e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (ret == NULL)
2019e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (NULL);
2020e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2021e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Junk/zero-filling were already done by arena_malloc(). */
2022e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	copysize = (size < oldsize) ? size : oldsize;
2023e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	memcpy(ret, ptr, copysize);
2024e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	idalloc(ptr);
2025e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ret);
2026e476f8a161d445211fd6e54fe370275196e66bcbJason EvansIN_PLACE:
2027e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL
2028e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (opt_junk && size < oldsize)
2029e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size);
2030e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	else if (opt_zero && size > oldsize)
2031e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memset((void *)((uintptr_t)ptr + oldsize), 0, size - oldsize);
2032e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2033e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ptr);
2034e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
2035e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2036e476f8a161d445211fd6e54fe370275196e66bcbJason Evansbool
2037e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_new(arena_t *arena, unsigned ind)
2038e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
2039e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	unsigned i;
2040e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_bin_t *bin;
2041e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t prev_run_size;
2042e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2043e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (malloc_mutex_init(&arena->lock))
2044e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (true);
2045e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2046e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
2047e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	memset(&arena->stats, 0, sizeof(arena_stats_t));
2048e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->stats.lstats = (malloc_large_stats_t *)base_alloc(
2049e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    sizeof(malloc_large_stats_t) * ((chunksize - PAGE_SIZE) >>
2050e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	        PAGE_SHIFT));
2051e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (arena->stats.lstats == NULL)
2052e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (true);
2053e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	memset(arena->stats.lstats, 0, sizeof(malloc_large_stats_t) *
2054e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    ((chunksize - PAGE_SIZE) >> PAGE_SHIFT));
2055e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  ifdef JEMALLOC_TCACHE
2056e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	ql_new(&arena->tcache_ql);
2057e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  endif
2058e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2059e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2060e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TRACE
2061e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (opt_trace) {
2062e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* "jemtr.<pid>.<arena>" */
2063e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		char buf[UMAX2S_BUFSIZE];
2064e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		char filename[6 + UMAX2S_BUFSIZE + 1 + UMAX2S_BUFSIZE + 1];
2065e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		char *s;
2066e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		unsigned i, slen;
2067e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2068e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->trace_buf_end = 0;
2069e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2070e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		i = 0;
2071e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2072e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		s = "jemtr.";
2073e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		slen = strlen(s);
2074e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memcpy(&filename[i], s, slen);
2075e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		i += slen;
2076e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2077e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		s = umax2s(getpid(), 10, buf);
2078e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		slen = strlen(s);
2079e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memcpy(&filename[i], s, slen);
2080e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		i += slen;
2081e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2082e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		s = ".";
2083e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		slen = strlen(s);
2084e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memcpy(&filename[i], s, slen);
2085e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		i += slen;
2086e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2087e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		s = umax2s(ind, 10, buf);
2088e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		slen = strlen(s);
2089e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memcpy(&filename[i], s, slen);
2090e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		i += slen;
2091e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2092e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		filename[i] = '\0';
2093e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2094e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->trace_fd = creat(filename, 0644);
2095e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (arena->trace_fd == -1) {
2096e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			malloc_write4("<jemalloc>",
2097e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    ": creat(\"", filename, "\", O_RDWR) failed\n");
2098e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			abort();
2099e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
2100e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2101e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2102e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2103e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Initialize chunks. */
2104e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_tree_dirty_new(&arena->chunks_dirty);
2105e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->spare = NULL;
2106e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2107e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->nactive = 0;
2108e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->ndirty = 0;
2109e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2110e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_avail_tree_new(&arena->runs_avail);
2111e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2112e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Initialize bins. */
2113e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	prev_run_size = PAGE_SIZE;
2114e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2115e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	i = 0;
2116e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TINY
2117e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* (2^n)-spaced tiny bins. */
2118e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i < ntbins; i++) {
2119e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin = &arena->bins[i];
2120e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->runcur = NULL;
2121e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_tree_new(&bin->runs);
2122e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2123e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->reg_size = (1U << (LG_TINY_MIN + i));
2124e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2125e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
2126e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2127e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
2128e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
2129e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2130e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2131e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2132e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2133e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Quantum-spaced bins. */
2134e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i < ntbins + nqbins; i++) {
2135e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin = &arena->bins[i];
2136e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->runcur = NULL;
2137e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_tree_new(&bin->runs);
2138e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2139e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->reg_size = (i - ntbins + 1) << LG_QUANTUM;
2140e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2141e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
2142e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2143e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
2144e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
2145e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2146e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2147e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2148e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Cacheline-spaced bins. */
2149e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i < ntbins + nqbins + ncbins; i++) {
2150e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin = &arena->bins[i];
2151e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->runcur = NULL;
2152e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_tree_new(&bin->runs);
2153e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2154e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->reg_size = cspace_min + ((i - (ntbins + nqbins)) <<
2155e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    LG_CACHELINE);
2156e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2157e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
2158e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2159e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
2160e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
2161e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2162e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2163e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2164e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Subpage-spaced bins. */
2165e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i < ntbins + nqbins + ncbins + nsbins; i++) {
2166e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin = &arena->bins[i];
2167e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->runcur = NULL;
2168e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_tree_new(&bin->runs);
2169e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2170e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->reg_size = sspace_min + ((i - (ntbins + nqbins + ncbins))
2171e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    << LG_SUBPAGE);
2172e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2173e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
2174e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2175e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
2176e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
2177e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2178e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2179e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2180e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Medium bins. */
2181e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i < nbins; i++) {
2182e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin = &arena->bins[i];
2183e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->runcur = NULL;
2184e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_tree_new(&bin->runs);
2185e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2186e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->reg_size = medium_min + ((i - (ntbins + nqbins + ncbins +
2187e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    nsbins)) << lg_mspace);
2188e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2189e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
2190e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2191e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS
2192e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
2193e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2194e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2195e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2196e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG
2197e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->magic = ARENA_MAGIC;
2198e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2199e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2200e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (false);
2201e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
2202e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2203e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TINY
2204e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Compute the smallest power of 2 that is >= x. */
2205e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic size_t
2206e476f8a161d445211fd6e54fe370275196e66bcbJason Evanspow2_ceil(size_t x)
2207e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
2208e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2209e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	x--;
2210e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	x |= x >> 1;
2211e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	x |= x >> 2;
2212e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	x |= x >> 4;
2213e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	x |= x >> 8;
2214e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	x |= x >> 16;
2215e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#if (SIZEOF_PTR == 8)
2216e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	x |= x >> 32;
2217e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2218e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	x++;
2219e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (x);
2220e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
2221e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2222e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2223e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG
2224e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
2225e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssmall_size2bin_validate(void)
2226e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
2227e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t i, size, binind;
2228e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2229e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(small_size2bin[0] == 0xffU);
2230e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	i = 1;
2231e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  ifdef JEMALLOC_TINY
2232e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Tiny. */
2233e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i < (1U << LG_TINY_MIN); i++) {
2234e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size = pow2_ceil(1U << LG_TINY_MIN);
2235e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		binind = ffs((int)(size >> (LG_TINY_MIN + 1)));
2236e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert(small_size2bin[i] == binind);
2237e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2238e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i < qspace_min; i++) {
2239e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size = pow2_ceil(i);
2240e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		binind = ffs((int)(size >> (LG_TINY_MIN + 1)));
2241e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert(small_size2bin[i] == binind);
2242e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2243e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#  endif
2244e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Quantum-spaced. */
2245e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i <= qspace_max; i++) {
2246e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size = QUANTUM_CEILING(i);
2247e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		binind = ntbins + (size >> LG_QUANTUM) - 1;
2248e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert(small_size2bin[i] == binind);
2249e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2250e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Cacheline-spaced. */
2251e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i <= cspace_max; i++) {
2252e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size = CACHELINE_CEILING(i);
2253e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		binind = ntbins + nqbins + ((size - cspace_min) >>
2254e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    LG_CACHELINE);
2255e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert(small_size2bin[i] == binind);
2256e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2257e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Sub-page. */
2258e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i <= sspace_max; i++) {
2259e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size = SUBPAGE_CEILING(i);
2260e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		binind = ntbins + nqbins + ncbins + ((size - sspace_min)
2261e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    >> LG_SUBPAGE);
2262e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		assert(small_size2bin[i] == binind);
2263e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2264e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
2265e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2266e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2267e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool
2268e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssmall_size2bin_init(void)
2269e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
2270e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2271e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (opt_lg_qspace_max != LG_QSPACE_MAX_DEFAULT
2272e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    || opt_lg_cspace_max != LG_CSPACE_MAX_DEFAULT
2273e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    || sizeof(const_small_size2bin) != small_maxclass + 1)
2274e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (small_size2bin_init_hard());
2275e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2276e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	small_size2bin = const_small_size2bin;
2277e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG
2278e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(sizeof(const_small_size2bin) == small_maxclass + 1);
2279e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	small_size2bin_validate();
2280e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2281e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (false);
2282e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
2283e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2284e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool
2285e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssmall_size2bin_init_hard(void)
2286e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
2287e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t i, size, binind;
2288e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	uint8_t *custom_small_size2bin;
2289e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2290e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(opt_lg_qspace_max != LG_QSPACE_MAX_DEFAULT
2291e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    || opt_lg_cspace_max != LG_CSPACE_MAX_DEFAULT
2292e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    || sizeof(const_small_size2bin) != small_maxclass + 1);
2293e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2294e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	custom_small_size2bin = (uint8_t *)base_alloc(small_maxclass + 1);
2295e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (custom_small_size2bin == NULL)
2296e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (true);
2297e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2298e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	custom_small_size2bin[0] = 0xffU;
2299e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	i = 1;
2300e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TINY
2301e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Tiny. */
2302e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i < (1U << LG_TINY_MIN); i++) {
2303e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size = pow2_ceil(1U << LG_TINY_MIN);
2304e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		binind = ffs((int)(size >> (LG_TINY_MIN + 1)));
2305e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		custom_small_size2bin[i] = binind;
2306e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2307e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i < qspace_min; i++) {
2308e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size = pow2_ceil(i);
2309e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		binind = ffs((int)(size >> (LG_TINY_MIN + 1)));
2310e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		custom_small_size2bin[i] = binind;
2311e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2312e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2313e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Quantum-spaced. */
2314e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i <= qspace_max; i++) {
2315e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size = QUANTUM_CEILING(i);
2316e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		binind = ntbins + (size >> LG_QUANTUM) - 1;
2317e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		custom_small_size2bin[i] = binind;
2318e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2319e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Cacheline-spaced. */
2320e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i <= cspace_max; i++) {
2321e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size = CACHELINE_CEILING(i);
2322e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		binind = ntbins + nqbins + ((size - cspace_min) >>
2323e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    LG_CACHELINE);
2324e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		custom_small_size2bin[i] = binind;
2325e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2326e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Sub-page. */
2327e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	for (; i <= sspace_max; i++) {
2328e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size = SUBPAGE_CEILING(i);
2329e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		binind = ntbins + nqbins + ncbins + ((size - sspace_min) >>
2330e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    LG_SUBPAGE);
2331e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		custom_small_size2bin[i] = binind;
2332e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2333e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2334e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	small_size2bin = custom_small_size2bin;
2335e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG
2336e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	small_size2bin_validate();
2337e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2338e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (false);
2339e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
2340e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2341e476f8a161d445211fd6e54fe370275196e66bcbJason Evansbool
2342e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_boot0(void)
2343e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
2344e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2345e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Set variables according to the value of opt_lg_[qc]space_max. */
2346e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	qspace_max = (1U << opt_lg_qspace_max);
2347e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	cspace_min = CACHELINE_CEILING(qspace_max);
2348e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (cspace_min == qspace_max)
2349e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		cspace_min += CACHELINE;
2350e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	cspace_max = (1U << opt_lg_cspace_max);
2351e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	sspace_min = SUBPAGE_CEILING(cspace_max);
2352e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (sspace_min == cspace_max)
2353e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		sspace_min += SUBPAGE;
2354e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(sspace_min < PAGE_SIZE);
2355e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	sspace_max = PAGE_SIZE - SUBPAGE;
2356e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	medium_max = (1U << opt_lg_medium_max);
2357e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2358e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TINY
2359e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(LG_QUANTUM >= LG_TINY_MIN);
2360e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif
2361e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(ntbins <= LG_QUANTUM);
2362e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	nqbins = qspace_max >> LG_QUANTUM;
2363e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	ncbins = ((cspace_max - cspace_min) >> LG_CACHELINE) + 1;
2364e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	nsbins = ((sspace_max - sspace_min) >> LG_SUBPAGE) + 1;
2365e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2366e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
2367e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Compute medium size class spacing and the number of medium size
2368e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * classes.  Limit spacing to no more than pagesize, but if possible
2369e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * use the smallest spacing that does not exceed NMBINS_MAX medium size
2370e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * classes.
2371e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
2372e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	lg_mspace = LG_SUBPAGE;
2373e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	nmbins = ((medium_max - medium_min) >> lg_mspace) + 1;
2374e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	while (lg_mspace < PAGE_SHIFT && nmbins > NMBINS_MAX) {
2375e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		lg_mspace = lg_mspace + 1;
2376e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		nmbins = ((medium_max - medium_min) >> lg_mspace) + 1;
2377e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2378e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	mspace_mask = (1U << lg_mspace) - 1U;
2379e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2380e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	mbin0 = ntbins + nqbins + ncbins + nsbins;
2381e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	nbins = mbin0 + nmbins;
2382e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
2383e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * The small_size2bin lookup table uses uint8_t to encode each bin
2384e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * index, so we cannot support more than 256 small size classes.  This
2385e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * limit is difficult to exceed (not even possible with 16B quantum and
2386e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * 4KiB pages), and such configurations are impractical, but
2387e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * nonetheless we need to protect against this case in order to avoid
2388e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * undefined behavior.
2389e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
2390e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (mbin0 > 256) {
2391e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    char line_buf[UMAX2S_BUFSIZE];
2392e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    malloc_write4("<jemalloc>: Too many small size classes (",
2393e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	        umax2s(mbin0, 10, line_buf), " > max 256)\n", "");
2394e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    abort();
2395e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
2396e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2397e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (small_size2bin_init())
2398e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (true);
2399e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2400e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (false);
2401e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
2402e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2403e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid
2404e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_boot1(void)
2405e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
2406e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t header_size;
2407e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2408e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
2409e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Compute the header size such that it is large enough to contain the
2410e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * page map.
2411e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
2412e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	header_size = sizeof(arena_chunk_t) +
2413e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    (sizeof(arena_chunk_map_t) * (chunk_npages - 1));
2414e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_header_npages = (header_size >> PAGE_SHIFT) +
2415e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    ((header_size & PAGE_MASK) != 0);
2416e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_maxclass = chunksize - (arena_chunk_header_npages << PAGE_SHIFT);
2417e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
2418