arena.c revision f54166e7ef5313c3b5c773cbb0ca2af95f5a15ae
1e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	JEMALLOC_ARENA_C_
2376b1529a383c39adf4674baf6db83a5e63f97acJason Evans#include "jemalloc/internal/jemalloc_internal.h"
3e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
4e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/******************************************************************************/
5e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Data. */
6e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
7e476f8a161d445211fd6e54fe370275196e66bcbJason Evansssize_t		opt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT;
8b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evansarena_bin_info_t	arena_bin_info[NBINS];
9e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
10b172610317babc7f365584ddd7fdaf4eb8d9d04cJason EvansJEMALLOC_ATTR(aligned(CACHELINE))
11b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evansconst uint8_t	small_size2bin[] = {
1241ade967c29ea9312c0b7390ee43bc0c63373f39Jason Evans#define	S2B_8(i)	i,
13e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_16(i)	S2B_8(i) S2B_8(i)
14e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_32(i)	S2B_16(i) S2B_16(i)
15e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_64(i)	S2B_32(i) S2B_32(i)
16e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_128(i)	S2B_64(i) S2B_64(i)
17e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define	S2B_256(i)	S2B_128(i) S2B_128(i)
18b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define	S2B_512(i)	S2B_256(i) S2B_256(i)
19b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define	S2B_1024(i)	S2B_512(i) S2B_512(i)
20b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define	S2B_2048(i)	S2B_1024(i) S2B_1024(i)
21b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define	S2B_4096(i)	S2B_2048(i) S2B_2048(i)
22b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define	S2B_8192(i)	S2B_4096(i) S2B_4096(i)
23b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define	SIZE_CLASS(bin, delta, size)					\
24b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans	S2B_##delta(bin)
25b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans	SIZE_CLASSES
26e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_8
27e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_16
28e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_32
29e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_64
30e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_128
31e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_256
32b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef S2B_512
33b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef S2B_1024
34b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef S2B_2048
35b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef S2B_4096
36b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef S2B_8192
37b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef SIZE_CLASS
38b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans};
39e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
40e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/******************************************************************************/
41e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Function prototypes for non-inline static functions. */
42e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
43e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_run_split(arena_t *arena, arena_run_t *run, size_t size,
44e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    bool large, bool zero);
45e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_chunk_t *arena_chunk_alloc(arena_t *arena);
46e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk);
47e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t *arena_run_alloc(arena_t *arena, size_t size, bool large,
48e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    bool zero);
496005f0710cf07d60659d91b20b7ff5592d310027Jason Evansstatic void	arena_purge(arena_t *arena, bool all);
50e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty);
51e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk,
52e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    arena_run_t *run, size_t oldsize, size_t newsize);
53e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk,
54e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    arena_run_t *run, size_t oldsize, size_t newsize, bool dirty);
55e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic arena_run_t	*arena_bin_runs_first(arena_bin_t *bin);
56e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic void	arena_bin_runs_insert(arena_bin_t *bin, arena_run_t *run);
57e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic void	arena_bin_runs_remove(arena_bin_t *bin, arena_run_t *run);
58e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic arena_run_t *arena_bin_nonfull_run_tryget(arena_bin_t *bin);
59e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin);
60e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	*arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin);
61088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evansstatic void	arena_dissociate_bin_run(arena_chunk_t *chunk, arena_run_t *run,
62088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans    arena_bin_t *bin);
63e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk,
64e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    arena_run_t *run, arena_bin_t *bin);
65940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evansstatic void	arena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk,
66940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans    arena_run_t *run, arena_bin_t *bin);
67e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void	arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk,
688e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans    void *ptr, size_t oldsize, size_t size);
69e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool	arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk,
708e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans    void *ptr, size_t oldsize, size_t size, size_t extra, bool zero);
718e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evansstatic bool	arena_ralloc_large(void *ptr, size_t oldsize, size_t size,
728e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans    size_t extra, bool zero);
7349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evansstatic size_t	bin_info_run_size_calc(arena_bin_info_t *bin_info,
7449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans    size_t min_run_size);
75b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evansstatic void	bin_info_init(void);
76e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
77e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/******************************************************************************/
78e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
79e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline int
80e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
81e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
82e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	uintptr_t a_mapelm = (uintptr_t)a;
83e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	uintptr_t b_mapelm = (uintptr_t)b;
84e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
85e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(a != NULL);
86e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(b != NULL);
87e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
88e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm));
89e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
90e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
91f3ff75289be32382fa455b4436871e4958fe6bf9Jason Evans/* Generate red-black tree functions. */
927372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evansrb_gen(static UNUSED, arena_run_tree_, arena_run_tree_t, arena_chunk_map_t,
937372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans    u.rb_link, arena_run_comp)
94e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
95e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline int
96e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
97e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
98e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	int ret;
99e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t a_size = a->bits & ~PAGE_MASK;
100e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t b_size = b->bits & ~PAGE_MASK;
101e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1020b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans	assert((a->bits & CHUNK_MAP_KEY) == CHUNK_MAP_KEY || (a->bits &
1030b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans	    CHUNK_MAP_DIRTY) == (b->bits & CHUNK_MAP_DIRTY));
10419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans
105e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	ret = (a_size > b_size) - (a_size < b_size);
106e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (ret == 0) {
107e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		uintptr_t a_mapelm, b_mapelm;
108e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
109e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if ((a->bits & CHUNK_MAP_KEY) != CHUNK_MAP_KEY)
110e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			a_mapelm = (uintptr_t)a;
111e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		else {
112e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			/*
113e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 * Treat keys as though they are lower than anything
114e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 * else.
115e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			 */
116e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			a_mapelm = 0;
117e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
118e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		b_mapelm = (uintptr_t)b;
119e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
120e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm);
121e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
122e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
123e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ret);
124e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
125e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
126f3ff75289be32382fa455b4436871e4958fe6bf9Jason Evans/* Generate red-black tree functions. */
1277372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evansrb_gen(static UNUSED, arena_avail_tree_, arena_avail_tree_t, arena_chunk_map_t,
1287372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans    u.rb_link, arena_avail_comp)
129e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
130e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline void *
13149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evansarena_run_reg_alloc(arena_run_t *run, arena_bin_info_t *bin_info)
132e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
133e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	void *ret;
13484c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	unsigned regind;
13584c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run +
13684c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	    (uintptr_t)bin_info->bitmap_offset);
137e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1381e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans	assert(run->nfree > 0);
13984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	assert(bitmap_full(bitmap, &bin_info->bitmap_info) == false);
140e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
14184c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	regind = bitmap_sfu(bitmap, &bin_info->bitmap_info);
14284c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	ret = (void *)((uintptr_t)run + (uintptr_t)bin_info->reg0_offset +
143122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	    (uintptr_t)(bin_info->reg_interval * regind));
1441e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans	run->nfree--;
14584c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	if (regind == run->nextind)
14684c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans		run->nextind++;
14784c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	assert(regind < run->nextind);
1481e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans	return (ret);
1496109fe07a14b7a619365977d9523db9f8b333792Jason Evans}
1506109fe07a14b7a619365977d9523db9f8b333792Jason Evans
1516109fe07a14b7a619365977d9523db9f8b333792Jason Evansstatic inline void
1521e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evansarena_run_reg_dalloc(arena_run_t *run, void *ptr)
1536109fe07a14b7a619365977d9523db9f8b333792Jason Evans{
15449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
15549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	size_t binind = arena_bin_index(chunk->arena, run->bin);
15649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	arena_bin_info_t *bin_info = &arena_bin_info[binind];
15784c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	unsigned regind = arena_run_regind(run, bin_info, ptr);
15884c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run +
15984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	    (uintptr_t)bin_info->bitmap_offset);
16084c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans
16149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	assert(run->nfree < bin_info->nregs);
1621e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans	/* Freeing an interior pointer can cause assertion failure. */
1631e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans	assert(((uintptr_t)ptr - ((uintptr_t)run +
164122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	    (uintptr_t)bin_info->reg0_offset)) %
165122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	    (uintptr_t)bin_info->reg_interval == 0);
16621fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans	assert((uintptr_t)ptr >= (uintptr_t)run +
16749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	    (uintptr_t)bin_info->reg0_offset);
16884c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	/* Freeing an unallocated pointer can cause assertion failure. */
16984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	assert(bitmap_get(bitmap, &bin_info->bitmap_info, regind));
170e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
17184c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	bitmap_unset(bitmap, &bin_info->bitmap_info, regind);
1721e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans	run->nfree++;
173e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
174e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
17521fb95bba6ea922e0523f269c0d9a32640047a29Jason Evansstatic inline void
17621fb95bba6ea922e0523f269c0d9a32640047a29Jason Evansarena_chunk_validate_zeroed(arena_chunk_t *chunk, size_t run_ind)
17721fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans{
178d4bab21756279db540866998099522dbd39c05f7Jason Evans	size_t i;
179ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	UNUSED size_t *p = (size_t *)((uintptr_t)chunk + (run_ind << LG_PAGE));
180d4bab21756279db540866998099522dbd39c05f7Jason Evans
181ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	for (i = 0; i < PAGE / sizeof(size_t); i++)
18221fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans		assert(p[i] == 0);
18321fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans}
18421fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans
185e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
186e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large,
187e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    bool zero)
188e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
189e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
190bdcadf41e961a3c6bbb37d8d24e4b68a27f2b952Jason Evans	size_t run_ind, total_pages, need_pages, rem_pages, i;
19119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	size_t flag_dirty;
19219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	arena_avail_tree_t *runs_avail;
193e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
194e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
195ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE);
1967393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	flag_dirty = chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY;
19719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	runs_avail = (flag_dirty != 0) ? &arena->runs_avail_dirty :
19819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	    &arena->runs_avail_clean;
1997393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	total_pages = (chunk->map[run_ind-map_bias].bits & ~PAGE_MASK) >>
200ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	    LG_PAGE;
2017393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	assert((chunk->map[run_ind+total_pages-1-map_bias].bits &
2027393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	    CHUNK_MAP_DIRTY) == flag_dirty);
203ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	need_pages = (size >> LG_PAGE);
204e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(need_pages > 0);
205e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(need_pages <= total_pages);
206e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	rem_pages = total_pages - need_pages;
207e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2087393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	arena_avail_tree_remove(runs_avail, &chunk->map[run_ind-map_bias]);
2097372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats) {
2107372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		/*
2117372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		 * Update stats_cactive if nactive is crossing a chunk
2127372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		 * multiple.
2137372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		 */
2147372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		size_t cactive_diff = CHUNK_CEILING((arena->nactive +
215ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    need_pages) << LG_PAGE) - CHUNK_CEILING(arena->nactive <<
216ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    LG_PAGE);
2177372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (cactive_diff != 0)
2187372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			stats_cactive_add(cactive_diff);
2197372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	}
220e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->nactive += need_pages;
221e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
222e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Keep track of trailing unused pages for later use. */
223e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (rem_pages > 0) {
22419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		if (flag_dirty != 0) {
2257393f44ff025ca67716fc53b68003fd65122fd97Jason Evans			chunk->map[run_ind+need_pages-map_bias].bits =
226ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans			    (rem_pages << LG_PAGE) | CHUNK_MAP_DIRTY;
2277393f44ff025ca67716fc53b68003fd65122fd97Jason Evans			chunk->map[run_ind+total_pages-1-map_bias].bits =
228ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans			    (rem_pages << LG_PAGE) | CHUNK_MAP_DIRTY;
22919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		} else {
2307393f44ff025ca67716fc53b68003fd65122fd97Jason Evans			chunk->map[run_ind+need_pages-map_bias].bits =
231ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans			    (rem_pages << LG_PAGE) |
2327393f44ff025ca67716fc53b68003fd65122fd97Jason Evans			    (chunk->map[run_ind+need_pages-map_bias].bits &
2333377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans			    CHUNK_MAP_UNZEROED);
2347393f44ff025ca67716fc53b68003fd65122fd97Jason Evans			chunk->map[run_ind+total_pages-1-map_bias].bits =
235ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans			    (rem_pages << LG_PAGE) |
2367393f44ff025ca67716fc53b68003fd65122fd97Jason Evans			    (chunk->map[run_ind+total_pages-1-map_bias].bits &
2373377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans			    CHUNK_MAP_UNZEROED);
23819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		}
23919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		arena_avail_tree_insert(runs_avail,
2407393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    &chunk->map[run_ind+need_pages-map_bias]);
241e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
242e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
24319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	/* Update dirty page accounting. */
24419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	if (flag_dirty != 0) {
24519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		chunk->ndirty -= need_pages;
24619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		arena->ndirty -= need_pages;
24719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	}
24819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans
24919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	/*
25019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * Update the page map separately for large vs. small runs, since it is
25119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * possible to avoid iteration for large mallocs.
25219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 */
25319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	if (large) {
254e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (zero) {
25519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans			if (flag_dirty == 0) {
25619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				/*
25719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				 * The run is clean, so some pages may be
25819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				 * zeroed (i.e. never before touched).
25919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				 */
26019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				for (i = 0; i < need_pages; i++) {
2617393f44ff025ca67716fc53b68003fd65122fd97Jason Evans					if ((chunk->map[run_ind+i-map_bias].bits
2623377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans					    & CHUNK_MAP_UNZEROED) != 0) {
263122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans						VALGRIND_MAKE_MEM_UNDEFINED(
264122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans						    (void *)((uintptr_t)
265122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans						    chunk + ((run_ind+i) <<
266122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans						    LG_PAGE)), PAGE);
26719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans						memset((void *)((uintptr_t)
26821fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans						    chunk + ((run_ind+i) <<
269ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans						    LG_PAGE)), 0, PAGE);
2707372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans					} else if (config_debug) {
271122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans						VALGRIND_MAKE_MEM_DEFINED(
272122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans						    (void *)((uintptr_t)
273122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans						    chunk + ((run_ind+i) <<
274122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans						    LG_PAGE)), PAGE);
27521fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans						arena_chunk_validate_zeroed(
27621fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans						    chunk, run_ind+i);
277940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans					}
27819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				}
27919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans			} else {
28019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				/*
28119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				 * The run is dirty, so all pages must be
28219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				 * zeroed.
28319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				 */
284122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans				VALGRIND_MAKE_MEM_UNDEFINED((void
285122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans				    *)((uintptr_t)chunk + (run_ind <<
286122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans				    LG_PAGE)), (need_pages << LG_PAGE));
28719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				memset((void *)((uintptr_t)chunk + (run_ind <<
288ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans				    LG_PAGE)), 0, (need_pages << LG_PAGE));
289e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			}
290e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
291e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
292e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
29319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		 * Set the last element first, in case the run only contains one
29419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		 * page (i.e. both statements set the same element).
295e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
2967393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		chunk->map[run_ind+need_pages-1-map_bias].bits =
2977393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED | flag_dirty;
298e4f7846f1fd279a039ffa2a41707348187219de4Jason Evans		chunk->map[run_ind-map_bias].bits = size | flag_dirty |
299e4f7846f1fd279a039ffa2a41707348187219de4Jason Evans		    CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED;
30019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	} else {
30119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		assert(zero == false);
30219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		/*
303940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		 * Propagate the dirty and unzeroed flags to the allocated
304940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		 * small run, so that arena_dalloc_bin_run() has the ability to
305940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		 * conditionally trim clean pages.
30619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		 */
307397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans		chunk->map[run_ind-map_bias].bits =
308397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans		    (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_UNZEROED) |
309397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans		    CHUNK_MAP_ALLOCATED | flag_dirty;
31021fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans		/*
31121fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans		 * The first page will always be dirtied during small run
31221fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans		 * initialization, so a validation failure here would not
31321fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans		 * actually cause an observable failure.
31421fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans		 */
3157372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_debug && flag_dirty == 0 &&
31621fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans		    (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_UNZEROED)
31721fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans		    == 0)
31821fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans			arena_chunk_validate_zeroed(chunk, run_ind);
31919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		for (i = 1; i < need_pages - 1; i++) {
320ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans			chunk->map[run_ind+i-map_bias].bits = (i << LG_PAGE)
321397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans			    | (chunk->map[run_ind+i-map_bias].bits &
322397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans			    CHUNK_MAP_UNZEROED) | CHUNK_MAP_ALLOCATED;
3237372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			if (config_debug && flag_dirty == 0 &&
32421fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans			    (chunk->map[run_ind+i-map_bias].bits &
32521fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans			    CHUNK_MAP_UNZEROED) == 0)
32621fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans				arena_chunk_validate_zeroed(chunk, run_ind+i);
32719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		}
328004ed142a66529ecf4a55e8f4fa42ff2e535f586Jason Evans		chunk->map[run_ind+need_pages-1-map_bias].bits = ((need_pages
329ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    - 1) << LG_PAGE) |
330397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans		    (chunk->map[run_ind+need_pages-1-map_bias].bits &
331397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans		    CHUNK_MAP_UNZEROED) | CHUNK_MAP_ALLOCATED | flag_dirty;
3327372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_debug && flag_dirty == 0 &&
33321fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans		    (chunk->map[run_ind+need_pages-1-map_bias].bits &
33421fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans		    CHUNK_MAP_UNZEROED) == 0) {
33521fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans			arena_chunk_validate_zeroed(chunk,
33621fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans			    run_ind+need_pages-1);
33721fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans		}
338e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
339e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
340e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
341e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_chunk_t *
342e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_chunk_alloc(arena_t *arena)
343e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
344e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
345e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t i;
346e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
347e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (arena->spare != NULL) {
34819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		arena_avail_tree_t *runs_avail;
34919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans
350e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk = arena->spare;
351e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena->spare = NULL;
35219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans
35319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		/* Insert the run into the appropriate runs_avail_* tree. */
3547393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		if ((chunk->map[0].bits & CHUNK_MAP_DIRTY) == 0)
35519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans			runs_avail = &arena->runs_avail_clean;
35619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		else
35719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans			runs_avail = &arena->runs_avail_dirty;
3588de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans		assert((chunk->map[0].bits & ~PAGE_MASK) == arena_maxclass);
3598de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans		assert((chunk->map[chunk_npages-1-map_bias].bits & ~PAGE_MASK)
3608de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans		    == arena_maxclass);
3618de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans		assert((chunk->map[0].bits & CHUNK_MAP_DIRTY) ==
3628de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans		    (chunk->map[chunk_npages-1-map_bias].bits &
3638de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans		    CHUNK_MAP_DIRTY));
3647393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		arena_avail_tree_insert(runs_avail, &chunk->map[0]);
365e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else {
36641631d00618d7262125e501c91d31b4d70e605faJason Evans		bool zero;
3673377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans		size_t unzeroed;
36841631d00618d7262125e501c91d31b4d70e605faJason Evans
36941631d00618d7262125e501c91d31b4d70e605faJason Evans		zero = false;
370e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		malloc_mutex_unlock(&arena->lock);
371eae269036c9f702d9fa9be497a1a2aa1be13a29eMike Hommey		chunk = (arena_chunk_t *)chunk_alloc(chunksize, chunksize,
372eae269036c9f702d9fa9be497a1a2aa1be13a29eMike Hommey		    false, &zero);
373e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		malloc_mutex_lock(&arena->lock);
374e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (chunk == NULL)
375e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			return (NULL);
3767372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_stats)
3777372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			arena->stats.mapped += chunksize;
378e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
379e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->arena = arena;
3802caa4715ed4f787f263239ff97dd824636289286Jason Evans		ql_elm_new(chunk, link_dirty);
381e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->dirtied = false;
382e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
383e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
384e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Claim that no pages are in use, since the header is merely
385e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * overhead.
386e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
387e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk->ndirty = 0;
388e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
389e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
390e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Initialize the map to contain one maximal free untouched run.
39141631d00618d7262125e501c91d31b4d70e605faJason Evans		 * Mark the pages as zeroed iff chunk_alloc() returned a zeroed
39241631d00618d7262125e501c91d31b4d70e605faJason Evans		 * chunk.
393e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
3943377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans		unzeroed = zero ? 0 : CHUNK_MAP_UNZEROED;
3953377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans		chunk->map[0].bits = arena_maxclass | unzeroed;
3963377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans		/*
3973377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans		 * There is no need to initialize the internal page map entries
3983377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans		 * unless the chunk is not zeroed.
3993377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans		 */
4003377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans		if (zero == false) {
4013377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans			for (i = map_bias+1; i < chunk_npages-1; i++)
4023377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans				chunk->map[i-map_bias].bits = unzeroed;
4037372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		} else if (config_debug) {
404940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans			for (i = map_bias+1; i < chunk_npages-1; i++)
405940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans				assert(chunk->map[i-map_bias].bits == unzeroed);
406940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		}
407004ed142a66529ecf4a55e8f4fa42ff2e535f586Jason Evans		chunk->map[chunk_npages-1-map_bias].bits = arena_maxclass |
408004ed142a66529ecf4a55e8f4fa42ff2e535f586Jason Evans		    unzeroed;
409e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
41019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		/* Insert the run into the runs_avail_clean tree. */
41119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		arena_avail_tree_insert(&arena->runs_avail_clean,
4127393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    &chunk->map[0]);
41319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	}
414e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
415e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (chunk);
416e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
417e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
418e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
419e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk)
420e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
42119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	arena_avail_tree_t *runs_avail;
422e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
4238d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans	/*
4248d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans	 * Remove run from the appropriate runs_avail_* tree, so that the arena
4258d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans	 * does not use it.
4268d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans	 */
4277393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	if ((chunk->map[0].bits & CHUNK_MAP_DIRTY) == 0)
4288d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans		runs_avail = &arena->runs_avail_clean;
4298d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans	else
4308d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans		runs_avail = &arena->runs_avail_dirty;
4317393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	arena_avail_tree_remove(runs_avail, &chunk->map[0]);
4328d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans
4338d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans	if (arena->spare != NULL) {
434e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		arena_chunk_t *spare = arena->spare;
435e00572b384c81bd2aba57fac32f7077a34388915Jason Evans
4368d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans		arena->spare = chunk;
437e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		if (spare->dirtied) {
438e00572b384c81bd2aba57fac32f7077a34388915Jason Evans			ql_remove(&chunk->arena->chunks_dirty, spare,
4392caa4715ed4f787f263239ff97dd824636289286Jason Evans			    link_dirty);
440e00572b384c81bd2aba57fac32f7077a34388915Jason Evans			arena->ndirty -= spare->ndirty;
441e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
442e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		malloc_mutex_unlock(&arena->lock);
44312a488782681cbd740a5f54e0b7e74ea84858e21Jason Evans		chunk_dealloc((void *)spare, chunksize, true);
444e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		malloc_mutex_lock(&arena->lock);
4457372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_stats)
4467372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			arena->stats.mapped -= chunksize;
4478d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans	} else
4488d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans		arena->spare = chunk;
449e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
450e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
451e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t *
452e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_alloc(arena_t *arena, size_t size, bool large, bool zero)
453e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
454e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
455e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_t *run;
456e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_map_t *mapelm, key;
457e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
458e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(size <= arena_maxclass);
459e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((size & PAGE_MASK) == 0);
460e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
461e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Search the arena's chunks for the lowest best fit. */
462e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	key.bits = size | CHUNK_MAP_KEY;
46319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	mapelm = arena_avail_tree_nsearch(&arena->runs_avail_dirty, &key);
46419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	if (mapelm != NULL) {
46519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm);
4667393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		size_t pageind = (((uintptr_t)mapelm -
4677393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t))
4687393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    + map_bias;
46919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans
47019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		run = (arena_run_t *)((uintptr_t)run_chunk + (pageind <<
471ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    LG_PAGE));
47219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		arena_run_split(arena, run, size, large, zero);
47319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		return (run);
47419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	}
47519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	mapelm = arena_avail_tree_nsearch(&arena->runs_avail_clean, &key);
476e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (mapelm != NULL) {
477e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm);
4787393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		size_t pageind = (((uintptr_t)mapelm -
4797393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t))
4807393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    + map_bias;
481e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
482e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		run = (arena_run_t *)((uintptr_t)run_chunk + (pageind <<
483ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    LG_PAGE));
484e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_split(arena, run, size, large, zero);
485e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (run);
486e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
487e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
488e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
489e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * No usable runs.  Create a new chunk from which to allocate the run.
490e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
491e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk = arena_chunk_alloc(arena);
492e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	if (chunk != NULL) {
493ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		run = (arena_run_t *)((uintptr_t)chunk + (map_bias << LG_PAGE));
494e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		arena_run_split(arena, run, size, large, zero);
495e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		return (run);
496e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	}
497e00572b384c81bd2aba57fac32f7077a34388915Jason Evans
498e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	/*
499e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	 * arena_chunk_alloc() failed, but another thread may have made
500e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	 * sufficient memory available while this one dropped arena->lock in
501e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	 * arena_chunk_alloc(), so search one more time.
502e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	 */
50319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	mapelm = arena_avail_tree_nsearch(&arena->runs_avail_dirty, &key);
50419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	if (mapelm != NULL) {
50519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm);
5067393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		size_t pageind = (((uintptr_t)mapelm -
5077393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t))
5087393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    + map_bias;
50919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans
51019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		run = (arena_run_t *)((uintptr_t)run_chunk + (pageind <<
511ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    LG_PAGE));
51219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		arena_run_split(arena, run, size, large, zero);
51319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		return (run);
51419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	}
51519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	mapelm = arena_avail_tree_nsearch(&arena->runs_avail_clean, &key);
516e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	if (mapelm != NULL) {
517e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm);
5187393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		size_t pageind = (((uintptr_t)mapelm -
5197393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t))
5207393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    + map_bias;
521e00572b384c81bd2aba57fac32f7077a34388915Jason Evans
522e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		run = (arena_run_t *)((uintptr_t)run_chunk + (pageind <<
523ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    LG_PAGE));
524e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		arena_run_split(arena, run, size, large, zero);
525e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		return (run);
526e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	}
527e00572b384c81bd2aba57fac32f7077a34388915Jason Evans
528e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	return (NULL);
529e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
530e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
53105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evansstatic inline void
53205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evansarena_maybe_purge(arena_t *arena)
53305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans{
53405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans
53505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	/* Enforce opt_lg_dirty_mult. */
536799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans	if (opt_lg_dirty_mult >= 0 && arena->ndirty > arena->npurgatory &&
537799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans	    (arena->ndirty - arena->npurgatory) > chunk_npages &&
538799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans	    (arena->nactive >> opt_lg_dirty_mult) < (arena->ndirty -
539799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans	    arena->npurgatory))
5406005f0710cf07d60659d91b20b7ff5592d310027Jason Evans		arena_purge(arena, false);
54105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans}
54205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans
54305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evansstatic inline void
54405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evansarena_chunk_purge(arena_t *arena, arena_chunk_t *chunk)
54505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans{
54605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	ql_head(arena_chunk_map_t) mapelms;
54705b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	arena_chunk_map_t *mapelm;
5483377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans	size_t pageind, flag_unzeroed;
54905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	size_t ndirty;
55005b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	size_t nmadvise;
55105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans
55205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	ql_new(&mapelms);
55305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans
5543377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans	flag_unzeroed =
5552dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans#ifdef JEMALLOC_PURGE_MADVISE_DONTNEED
5562dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans   /*
5572dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans    * madvise(..., MADV_DONTNEED) results in zero-filled pages for anonymous
5582dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans    * mappings, but not for file-backed mappings.
5592dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans    */
5604162627757889ea999264c2ddbc3c354768774e2Jason Evans	    0
5613377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans#else
5624162627757889ea999264c2ddbc3c354768774e2Jason Evans	    CHUNK_MAP_UNZEROED
5632dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans#endif
5644162627757889ea999264c2ddbc3c354768774e2Jason Evans	    ;
565c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans
56605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	/*
56705b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	 * If chunk is the spare, temporarily re-allocate it, 1) so that its
56819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * run is reinserted into runs_avail_dirty, and 2) so that it cannot be
56905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	 * completely discarded by another thread while arena->lock is dropped
57005b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	 * by this thread.  Note that the arena_run_dalloc() call will
57105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	 * implicitly deallocate the chunk, so no explicit action is required
57205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	 * in this function to deallocate the chunk.
57319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 *
57419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * Note that once a chunk contains dirty pages, it cannot again contain
57519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * a single run unless 1) it is a dirty run, or 2) this function purges
57619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * dirty pages and causes the transition to a single clean run.  Thus
57719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * (chunk == arena->spare) is possible, but it is not possible for
57819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * this function to be called on the spare unless it contains a dirty
57919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * run.
58005b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	 */
58119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	if (chunk == arena->spare) {
5827393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		assert((chunk->map[0].bits & CHUNK_MAP_DIRTY) != 0);
58305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans		arena_chunk_alloc(arena);
58419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	}
58505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans
58619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	/* Temporarily allocate all free dirty runs within chunk. */
5877393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	for (pageind = map_bias; pageind < chunk_npages;) {
5887393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		mapelm = &chunk->map[pageind-map_bias];
58905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans		if ((mapelm->bits & CHUNK_MAP_ALLOCATED) == 0) {
59019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans			size_t npages;
59105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans
592ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans			npages = mapelm->bits >> LG_PAGE;
593e69bee01de62b56d3e585042d341743239568043Jason Evans			assert(pageind + npages <= chunk_npages);
59419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans			if (mapelm->bits & CHUNK_MAP_DIRTY) {
595c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans				size_t i;
596c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans
59719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				arena_avail_tree_remove(
59819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				    &arena->runs_avail_dirty, mapelm);
599c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans
600ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans				mapelm->bits = (npages << LG_PAGE) |
6018de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans				    flag_unzeroed | CHUNK_MAP_LARGE |
6028de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans				    CHUNK_MAP_ALLOCATED;
603c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans				/*
604c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans				 * Update internal elements in the page map, so
6053377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans				 * that CHUNK_MAP_UNZEROED is properly set.
606c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans				 */
607c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans				for (i = 1; i < npages - 1; i++) {
6087393f44ff025ca67716fc53b68003fd65122fd97Jason Evans					chunk->map[pageind+i-map_bias].bits =
6093377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans					    flag_unzeroed;
610c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans				}
611c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans				if (npages > 1) {
6127393f44ff025ca67716fc53b68003fd65122fd97Jason Evans					chunk->map[
6137393f44ff025ca67716fc53b68003fd65122fd97Jason Evans					    pageind+npages-1-map_bias].bits =
6148de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans					    flag_unzeroed | CHUNK_MAP_LARGE |
6158de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans					    CHUNK_MAP_ALLOCATED;
616c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans				}
617c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans
6187372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans				if (config_stats) {
6197372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans					/*
6207372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans					 * Update stats_cactive if nactive is
6217372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans					 * crossing a chunk multiple.
6227372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans					 */
6237372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans					size_t cactive_diff =
6247372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans					    CHUNK_CEILING((arena->nactive +
625ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans					    npages) << LG_PAGE) -
6267372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans					    CHUNK_CEILING(arena->nactive <<
627ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans					    LG_PAGE);
6287372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans					if (cactive_diff != 0)
6297372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans						stats_cactive_add(cactive_diff);
6307372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans				}
63119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				arena->nactive += npages;
63219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				/* Append to list for later processing. */
63319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				ql_elm_new(mapelm, u.ql_link);
63419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans				ql_tail_insert(&mapelms, mapelm, u.ql_link);
63505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans			}
63619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans
63705b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans			pageind += npages;
63805b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans		} else {
63905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans			/* Skip allocated run. */
640c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans			if (mapelm->bits & CHUNK_MAP_LARGE)
641ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans				pageind += mapelm->bits >> LG_PAGE;
642c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans			else {
64305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans				arena_run_t *run = (arena_run_t *)((uintptr_t)
644ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans				    chunk + (uintptr_t)(pageind << LG_PAGE));
645e69bee01de62b56d3e585042d341743239568043Jason Evans
646ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans				assert((mapelm->bits >> LG_PAGE) == 0);
64749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans				size_t binind = arena_bin_index(arena,
64849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans				    run->bin);
64949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans				arena_bin_info_t *bin_info =
65049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans				    &arena_bin_info[binind];
651ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans				pageind += bin_info->run_size >> LG_PAGE;
65205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans			}
65305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans		}
65405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	}
655e69bee01de62b56d3e585042d341743239568043Jason Evans	assert(pageind == chunk_npages);
65605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans
6577372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_debug)
6587372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		ndirty = chunk->ndirty;
6597372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats)
6607372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.purged += chunk->ndirty;
66105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	arena->ndirty -= chunk->ndirty;
66205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	chunk->ndirty = 0;
66305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	ql_remove(&arena->chunks_dirty, chunk, link_dirty);
66405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	chunk->dirtied = false;
66505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans
66605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	malloc_mutex_unlock(&arena->lock);
6677372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats)
6687372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		nmadvise = 0;
66905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	ql_foreach(mapelm, &mapelms, u.ql_link) {
6707393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		size_t pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) /
6717393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    sizeof(arena_chunk_map_t)) + map_bias;
672ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		size_t npages = mapelm->bits >> LG_PAGE;
67305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans
674e69bee01de62b56d3e585042d341743239568043Jason Evans		assert(pageind + npages <= chunk_npages);
67519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		assert(ndirty >= npages);
6767372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_debug)
6777372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			ndirty -= npages;
6782dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans
679666c5bf7a8baaa842da69cb402948411432a9d00Mike Hommey		pages_purge((void *)((uintptr_t)chunk + (pageind << LG_PAGE)),
680666c5bf7a8baaa842da69cb402948411432a9d00Mike Hommey		    (npages << LG_PAGE));
6817372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_stats)
6827372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			nmadvise++;
68305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	}
68405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	assert(ndirty == 0);
68505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	malloc_mutex_lock(&arena->lock);
6867372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats)
6877372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.nmadvise += nmadvise;
68805b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans
68905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	/* Deallocate runs. */
69005b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	for (mapelm = ql_first(&mapelms); mapelm != NULL;
69105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	    mapelm = ql_first(&mapelms)) {
6927393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		size_t pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) /
6937393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    sizeof(arena_chunk_map_t)) + map_bias;
69405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans		arena_run_t *run = (arena_run_t *)((uintptr_t)chunk +
695ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    (uintptr_t)(pageind << LG_PAGE));
69605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans
69705b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans		ql_remove(&mapelms, mapelm, u.ql_link);
69805b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans		arena_run_dalloc(arena, run, false);
69905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	}
70005b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans}
70105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans
702e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
7036005f0710cf07d60659d91b20b7ff5592d310027Jason Evansarena_purge(arena_t *arena, bool all)
704e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
705e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
70605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	size_t npurgatory;
7077372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_debug) {
7087372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		size_t ndirty = 0;
709e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
7107372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		ql_foreach(chunk, &arena->chunks_dirty, link_dirty) {
7117372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		    assert(chunk->dirtied);
7127372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		    ndirty += chunk->ndirty;
7137372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		}
7147372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		assert(ndirty == arena->ndirty);
7152caa4715ed4f787f263239ff97dd824636289286Jason Evans	}
716af8ad3ec6abe9840bd503535a604a6173ce73515Jason Evans	assert(arena->ndirty > arena->npurgatory || all);
717f9a8edbb50f8cbcaf8ed62b36e8d7191ed223d2aJason Evans	assert(arena->ndirty - arena->npurgatory > chunk_npages || all);
718af8ad3ec6abe9840bd503535a604a6173ce73515Jason Evans	assert((arena->nactive >> opt_lg_dirty_mult) < (arena->ndirty -
719f9a8edbb50f8cbcaf8ed62b36e8d7191ed223d2aJason Evans	    arena->npurgatory) || all);
720e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
7217372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats)
7227372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.npurge++;
723e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
724e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
72505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	 * Compute the minimum number of pages that this thread should try to
726799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans	 * purge, and add the result to arena->npurgatory.  This will keep
727799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans	 * multiple threads from racing to reduce ndirty below the threshold.
728e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
7296005f0710cf07d60659d91b20b7ff5592d310027Jason Evans	npurgatory = arena->ndirty - arena->npurgatory;
730af8ad3ec6abe9840bd503535a604a6173ce73515Jason Evans	if (all == false) {
731af8ad3ec6abe9840bd503535a604a6173ce73515Jason Evans		assert(npurgatory >= arena->nactive >> opt_lg_dirty_mult);
7326005f0710cf07d60659d91b20b7ff5592d310027Jason Evans		npurgatory -= arena->nactive >> opt_lg_dirty_mult;
733af8ad3ec6abe9840bd503535a604a6173ce73515Jason Evans	}
734799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans	arena->npurgatory += npurgatory;
735799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans
73605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans	while (npurgatory > 0) {
73705b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans		/* Get next chunk with dirty pages. */
7382caa4715ed4f787f263239ff97dd824636289286Jason Evans		chunk = ql_first(&arena->chunks_dirty);
73905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans		if (chunk == NULL) {
74005b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans			/*
74105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans			 * This thread was unable to purge as many pages as
74205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans			 * originally intended, due to races with other threads
743799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 * that either did some of the purging work, or re-used
744799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 * dirty pages.
74505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans			 */
746799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			arena->npurgatory -= npurgatory;
747799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			return;
748e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
74905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans		while (chunk->ndirty == 0) {
7502caa4715ed4f787f263239ff97dd824636289286Jason Evans			ql_remove(&arena->chunks_dirty, chunk, link_dirty);
751e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			chunk->dirtied = false;
75205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans			chunk = ql_first(&arena->chunks_dirty);
75305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans			if (chunk == NULL) {
75405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans				/* Same logic as for above. */
755799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans				arena->npurgatory -= npurgatory;
756799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans				return;
75705b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans			}
758e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
75905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans
760799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans		if (chunk->ndirty > npurgatory) {
761799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			/*
762799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 * This thread will, at a minimum, purge all the dirty
763799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 * pages in chunk, so set npurgatory to reflect this
764799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 * thread's commitment to purge the pages.  This tends
765799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 * to reduce the chances of the following scenario:
766799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 *
767799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 * 1) This thread sets arena->npurgatory such that
768799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 *    (arena->ndirty - arena->npurgatory) is at the
769799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 *    threshold.
770799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 * 2) This thread drops arena->lock.
771799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 * 3) Another thread causes one or more pages to be
772799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 *    dirtied, and immediately determines that it must
773799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 *    purge dirty pages.
774799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 *
775799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 * If this scenario *does* play out, that's okay,
776799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 * because all of the purging work being done really
777799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 * needs to happen.
778799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			 */
779799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			arena->npurgatory += chunk->ndirty - npurgatory;
780799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans			npurgatory = chunk->ndirty;
781799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans		}
782799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans
783799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans		arena->npurgatory -= chunk->ndirty;
784799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans		npurgatory -= chunk->ndirty;
78505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans		arena_chunk_purge(arena, chunk);
786e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
787e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
788e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
7896005f0710cf07d60659d91b20b7ff5592d310027Jason Evansvoid
7906005f0710cf07d60659d91b20b7ff5592d310027Jason Evansarena_purge_all(arena_t *arena)
7916005f0710cf07d60659d91b20b7ff5592d310027Jason Evans{
7926005f0710cf07d60659d91b20b7ff5592d310027Jason Evans
7936005f0710cf07d60659d91b20b7ff5592d310027Jason Evans	malloc_mutex_lock(&arena->lock);
7946005f0710cf07d60659d91b20b7ff5592d310027Jason Evans	arena_purge(arena, true);
7956005f0710cf07d60659d91b20b7ff5592d310027Jason Evans	malloc_mutex_unlock(&arena->lock);
7966005f0710cf07d60659d91b20b7ff5592d310027Jason Evans}
7976005f0710cf07d60659d91b20b7ff5592d310027Jason Evans
798e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
799e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty)
800e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
801e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
80219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	size_t size, run_ind, run_pages, flag_dirty;
80319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	arena_avail_tree_t *runs_avail;
804e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
805e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
806ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE);
8077393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	assert(run_ind >= map_bias);
808e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(run_ind < chunk_npages);
8098de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans	if ((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_LARGE) != 0) {
8107393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		size = chunk->map[run_ind-map_bias].bits & ~PAGE_MASK;
811ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		assert(size == PAGE ||
812ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    (chunk->map[run_ind+(size>>LG_PAGE)-1-map_bias].bits &
8138de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans		    ~PAGE_MASK) == 0);
814ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		assert((chunk->map[run_ind+(size>>LG_PAGE)-1-map_bias].bits &
8158de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans		    CHUNK_MAP_LARGE) != 0);
816ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		assert((chunk->map[run_ind+(size>>LG_PAGE)-1-map_bias].bits &
8178de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans		    CHUNK_MAP_ALLOCATED) != 0);
81849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	} else {
81949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		size_t binind = arena_bin_index(arena, run->bin);
82049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		arena_bin_info_t *bin_info = &arena_bin_info[binind];
82149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		size = bin_info->run_size;
82249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	}
823ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	run_pages = (size >> LG_PAGE);
8247372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats) {
8257372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		/*
8267372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		 * Update stats_cactive if nactive is crossing a chunk
8277372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		 * multiple.
8287372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		 */
829ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		size_t cactive_diff = CHUNK_CEILING(arena->nactive << LG_PAGE) -
830ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    CHUNK_CEILING((arena->nactive - run_pages) << LG_PAGE);
8317372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (cactive_diff != 0)
8327372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			stats_cactive_sub(cactive_diff);
8337372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	}
834e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->nactive -= run_pages;
835e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
83619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	/*
83719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * The run is dirty if the caller claims to have dirtied it, as well as
83819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * if it was already dirty before being allocated.
83919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 */
8407393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	if ((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY) != 0)
84119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		dirty = true;
84219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	flag_dirty = dirty ? CHUNK_MAP_DIRTY : 0;
84319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	runs_avail = dirty ? &arena->runs_avail_dirty :
84419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	    &arena->runs_avail_clean;
84519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans
846e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Mark pages as unallocated in the chunk map. */
847e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (dirty) {
848940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		chunk->map[run_ind-map_bias].bits = size | CHUNK_MAP_DIRTY;
8497393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		chunk->map[run_ind+run_pages-1-map_bias].bits = size |
850940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		    CHUNK_MAP_DIRTY;
851e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
85219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		chunk->ndirty += run_pages;
85319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		arena->ndirty += run_pages;
854e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else {
8557393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		chunk->map[run_ind-map_bias].bits = size |
8563377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans		    (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_UNZEROED);
8577393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		chunk->map[run_ind+run_pages-1-map_bias].bits = size |
8587393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    (chunk->map[run_ind+run_pages-1-map_bias].bits &
8593377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans		    CHUNK_MAP_UNZEROED);
860e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
861e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
862e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Try to coalesce forward. */
863e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (run_ind + run_pages < chunk_npages &&
8647393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	    (chunk->map[run_ind+run_pages-map_bias].bits & CHUNK_MAP_ALLOCATED)
8657393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	    == 0 && (chunk->map[run_ind+run_pages-map_bias].bits &
8667393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	    CHUNK_MAP_DIRTY) == flag_dirty) {
8677393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		size_t nrun_size = chunk->map[run_ind+run_pages-map_bias].bits &
868e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    ~PAGE_MASK;
869ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		size_t nrun_pages = nrun_size >> LG_PAGE;
870e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
871e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
872e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Remove successor from runs_avail; the coalesced run is
873e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * inserted later.
874e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
87512ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		assert((chunk->map[run_ind+run_pages+nrun_pages-1-map_bias].bits
87612ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		    & ~PAGE_MASK) == nrun_size);
87712ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		assert((chunk->map[run_ind+run_pages+nrun_pages-1-map_bias].bits
87812ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		    & CHUNK_MAP_ALLOCATED) == 0);
87912ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		assert((chunk->map[run_ind+run_pages+nrun_pages-1-map_bias].bits
88012ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		    & CHUNK_MAP_DIRTY) == flag_dirty);
88119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		arena_avail_tree_remove(runs_avail,
8827393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    &chunk->map[run_ind+run_pages-map_bias]);
883e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
884e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size += nrun_size;
88512ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		run_pages += nrun_pages;
886e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
8877393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		chunk->map[run_ind-map_bias].bits = size |
8887393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_FLAGS_MASK);
8897393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		chunk->map[run_ind+run_pages-1-map_bias].bits = size |
8907393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    (chunk->map[run_ind+run_pages-1-map_bias].bits &
891e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    CHUNK_MAP_FLAGS_MASK);
892e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
893e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
894e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Try to coalesce backward. */
8957393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	if (run_ind > map_bias && (chunk->map[run_ind-1-map_bias].bits &
8967393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	    CHUNK_MAP_ALLOCATED) == 0 && (chunk->map[run_ind-1-map_bias].bits &
89719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	    CHUNK_MAP_DIRTY) == flag_dirty) {
8987393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		size_t prun_size = chunk->map[run_ind-1-map_bias].bits &
8997393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    ~PAGE_MASK;
900ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		size_t prun_pages = prun_size >> LG_PAGE;
901e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
90212ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		run_ind -= prun_pages;
903e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
904e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
905e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * Remove predecessor from runs_avail; the coalesced run is
906e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * inserted later.
907e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
90812ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		assert((chunk->map[run_ind-map_bias].bits & ~PAGE_MASK)
90912ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		    == prun_size);
91012ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		assert((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_ALLOCATED)
91112ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		    == 0);
91212ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		assert((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY)
91312ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		    == flag_dirty);
9147393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		arena_avail_tree_remove(runs_avail,
9157393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    &chunk->map[run_ind-map_bias]);
916e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
917e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size += prun_size;
91812ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans		run_pages += prun_pages;
919e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
9207393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		chunk->map[run_ind-map_bias].bits = size |
9217393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_FLAGS_MASK);
9227393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		chunk->map[run_ind+run_pages-1-map_bias].bits = size |
9237393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    (chunk->map[run_ind+run_pages-1-map_bias].bits &
924e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		    CHUNK_MAP_FLAGS_MASK);
925e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
926e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
927e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Insert into runs_avail, now that coalescing is complete. */
9288de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans	assert((chunk->map[run_ind-map_bias].bits & ~PAGE_MASK) ==
9298de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans	    (chunk->map[run_ind+run_pages-1-map_bias].bits & ~PAGE_MASK));
9308de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans	assert((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY) ==
9318de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans	    (chunk->map[run_ind+run_pages-1-map_bias].bits & CHUNK_MAP_DIRTY));
9327393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	arena_avail_tree_insert(runs_avail, &chunk->map[run_ind-map_bias]);
933e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
9348d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans	if (dirty) {
9358d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans		/*
9368d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans		 * Insert into chunks_dirty before potentially calling
9378d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans		 * arena_chunk_dealloc(), so that chunks_dirty and
9388d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans		 * arena->ndirty are consistent.
9398d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans		 */
9408d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans		if (chunk->dirtied == false) {
9418d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans			ql_tail_insert(&arena->chunks_dirty, chunk, link_dirty);
9428d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans			chunk->dirtied = true;
9438d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans		}
9448d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans	}
9458d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans
9464fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans	/*
9474fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans	 * Deallocate chunk if it is now completely unused.  The bit
9484fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans	 * manipulation checks whether the first run is unallocated and extends
9494fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans	 * to the end of the chunk.
9504fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans	 */
9517393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	if ((chunk->map[0].bits & (~PAGE_MASK | CHUNK_MAP_ALLOCATED)) ==
9527393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	    arena_maxclass)
953e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_chunk_dealloc(arena, chunk);
954e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
9554fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans	/*
9568d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans	 * It is okay to do dirty page processing here even if the chunk was
9574fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans	 * deallocated above, since in that case it is the spare.  Waiting
9584fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans	 * until after possible chunk deallocation to do dirty processing
9594fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans	 * allows for an old spare to be fully deallocated, thus decreasing the
9604fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans	 * chances of spuriously crossing the dirty page purging threshold.
9614fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans	 */
9628d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans	if (dirty)
96305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans		arena_maybe_purge(arena);
964e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
965e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
966e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
967e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
968e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    size_t oldsize, size_t newsize)
969e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
970ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE;
971ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	size_t head_npages = (oldsize - newsize) >> LG_PAGE;
972940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	size_t flag_dirty = chunk->map[pageind-map_bias].bits & CHUNK_MAP_DIRTY;
973e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
974e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(oldsize > newsize);
975e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
976e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
977e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Update the chunk map so that arena_run_dalloc() can treat the
978940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	 * leading run as separately allocated.  Set the last element of each
979940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	 * run first, in case of single-page runs.
980e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
981940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	assert((chunk->map[pageind-map_bias].bits & CHUNK_MAP_LARGE) != 0);
982940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	assert((chunk->map[pageind-map_bias].bits & CHUNK_MAP_ALLOCATED) != 0);
983940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	chunk->map[pageind+head_npages-1-map_bias].bits = flag_dirty |
984940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    (chunk->map[pageind+head_npages-1-map_bias].bits &
985940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED;
986940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	chunk->map[pageind-map_bias].bits = (oldsize - newsize)
987940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    | flag_dirty | (chunk->map[pageind-map_bias].bits &
988940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED;
989940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans
9907372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_debug) {
991ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		UNUSED size_t tail_npages = newsize >> LG_PAGE;
992940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias]
993940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		    .bits & ~PAGE_MASK) == 0);
994940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias]
995940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		    .bits & CHUNK_MAP_DIRTY) == flag_dirty);
996940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias]
997940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		    .bits & CHUNK_MAP_LARGE) != 0);
998940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias]
999940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		    .bits & CHUNK_MAP_ALLOCATED) != 0);
1000940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	}
1001940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	chunk->map[pageind+head_npages-map_bias].bits = newsize | flag_dirty |
1002940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    (chunk->map[pageind+head_npages-map_bias].bits &
1003940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    CHUNK_MAP_FLAGS_MASK) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED;
1004e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1005e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_dalloc(arena, run, false);
1006e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1007e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1008e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
1009e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
1010e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    size_t oldsize, size_t newsize, bool dirty)
1011e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1012ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE;
1013ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	size_t head_npages = newsize >> LG_PAGE;
1014ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	size_t tail_npages = (oldsize - newsize) >> LG_PAGE;
1015940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	size_t flag_dirty = chunk->map[pageind-map_bias].bits &
1016940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    CHUNK_MAP_DIRTY;
1017e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1018e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(oldsize > newsize);
1019e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1020e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
1021e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Update the chunk map so that arena_run_dalloc() can treat the
1022940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	 * trailing run as separately allocated.  Set the last element of each
1023940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	 * run first, in case of single-page runs.
1024e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
1025940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	assert((chunk->map[pageind-map_bias].bits & CHUNK_MAP_LARGE) != 0);
1026940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	assert((chunk->map[pageind-map_bias].bits & CHUNK_MAP_ALLOCATED) != 0);
1027940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	chunk->map[pageind+head_npages-1-map_bias].bits = flag_dirty |
1028940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    (chunk->map[pageind+head_npages-1-map_bias].bits &
1029940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED;
1030940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	chunk->map[pageind-map_bias].bits = newsize | flag_dirty |
1031940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    (chunk->map[pageind-map_bias].bits & CHUNK_MAP_UNZEROED) |
1032940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED;
1033940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans
1034940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits &
1035940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    ~PAGE_MASK) == 0);
1036940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits &
1037940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    CHUNK_MAP_LARGE) != 0);
1038940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits &
1039940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    CHUNK_MAP_ALLOCATED) != 0);
1040940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits =
1041940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    flag_dirty |
1042940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    (chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits &
1043940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED;
1044940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	chunk->map[pageind+head_npages-map_bias].bits = (oldsize - newsize) |
1045940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    flag_dirty | (chunk->map[pageind+head_npages-map_bias].bits &
1046940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	    CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED;
1047e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1048e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize),
1049e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    dirty);
1050e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1051e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1052e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t *
1053e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansarena_bin_runs_first(arena_bin_t *bin)
1054e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1055e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	arena_chunk_map_t *mapelm = arena_run_tree_first(&bin->runs);
1056e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (mapelm != NULL) {
1057e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_chunk_t *chunk;
1058e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		size_t pageind;
1059e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1060e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm);
10617393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		pageind = ((((uintptr_t)mapelm - (uintptr_t)chunk->map) /
10627393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    sizeof(arena_chunk_map_t))) + map_bias;
1063e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans		arena_run_t *run = (arena_run_t *)((uintptr_t)chunk +
1064ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    (uintptr_t)((pageind - (mapelm->bits >> LG_PAGE)) <<
1065ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    LG_PAGE));
1066e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans		return (run);
1067e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	}
1068e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans
1069e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	return (NULL);
1070e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans}
1071e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans
1072e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic void
1073e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansarena_bin_runs_insert(arena_bin_t *bin, arena_run_t *run)
1074e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans{
1075e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	arena_chunk_t *chunk = CHUNK_ADDR2BASE(run);
1076ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE;
1077e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	arena_chunk_map_t *mapelm = &chunk->map[pageind-map_bias];
1078e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans
1079e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	assert(arena_run_tree_search(&bin->runs, mapelm) == NULL);
1080e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans
1081e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	arena_run_tree_insert(&bin->runs, mapelm);
1082e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans}
1083e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans
1084e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic void
1085e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansarena_bin_runs_remove(arena_bin_t *bin, arena_run_t *run)
1086e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans{
1087e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
1088ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE;
1089e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	arena_chunk_map_t *mapelm = &chunk->map[pageind-map_bias];
1090e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans
1091e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	assert(arena_run_tree_search(&bin->runs, mapelm) != NULL);
1092e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans
1093e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	arena_run_tree_remove(&bin->runs, mapelm);
1094e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans}
1095e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans
1096e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic arena_run_t *
1097e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansarena_bin_nonfull_run_tryget(arena_bin_t *bin)
1098e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans{
1099e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	arena_run_t *run = arena_bin_runs_first(bin);
1100e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	if (run != NULL) {
1101e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans		arena_bin_runs_remove(bin, run);
11027372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_stats)
11037372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			bin->stats.reruns++;
1104e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1105e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	return (run);
1106e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans}
1107e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans
1108e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic arena_run_t *
1109e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansarena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin)
1110e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans{
1111e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	arena_run_t *run;
1112e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	size_t binind;
1113e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	arena_bin_info_t *bin_info;
1114e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans
1115e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	/* Look for a usable run. */
1116e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	run = arena_bin_nonfull_run_tryget(bin);
1117e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	if (run != NULL)
1118e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans		return (run);
1119e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* No existing runs have any space available. */
1120e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
112149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	binind = arena_bin_index(arena, bin);
112249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	bin_info = &arena_bin_info[binind];
112349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans
1124e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Allocate a new run. */
1125e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	malloc_mutex_unlock(&bin->lock);
1126e69bee01de62b56d3e585042d341743239568043Jason Evans	/******************************/
112786815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans	malloc_mutex_lock(&arena->lock);
112849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	run = arena_run_alloc(arena, bin_info->run_size, false, false);
1129e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	if (run != NULL) {
113084c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans		bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run +
113184c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans		    (uintptr_t)bin_info->bitmap_offset);
113284c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans
1133e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		/* Initialize run internals. */
1134f54166e7ef5313c3b5c773cbb0ca2af95f5a15aeJason Evans		VALGRIND_MAKE_MEM_UNDEFINED(run, bin_info->reg0_offset -
1135f54166e7ef5313c3b5c773cbb0ca2af95f5a15aeJason Evans		    bin_info->redzone_size);
1136e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		run->bin = bin;
113784c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans		run->nextind = 0;
113849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		run->nfree = bin_info->nregs;
113984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans		bitmap_init(bitmap, &bin_info->bitmap_info);
1140e69bee01de62b56d3e585042d341743239568043Jason Evans	}
1141e69bee01de62b56d3e585042d341743239568043Jason Evans	malloc_mutex_unlock(&arena->lock);
1142e69bee01de62b56d3e585042d341743239568043Jason Evans	/********************************/
1143e69bee01de62b56d3e585042d341743239568043Jason Evans	malloc_mutex_lock(&bin->lock);
1144e69bee01de62b56d3e585042d341743239568043Jason Evans	if (run != NULL) {
11457372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_stats) {
11467372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			bin->stats.nruns++;
11477372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			bin->stats.curruns++;
11487372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		}
1149e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		return (run);
1150e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	}
1151e00572b384c81bd2aba57fac32f7077a34388915Jason Evans
1152e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	/*
1153e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	 * arena_run_alloc() failed, but another thread may have made
1154940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	 * sufficient memory available while this one dropped bin->lock above,
1155e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	 * so search one more time.
1156e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	 */
1157e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	run = arena_bin_nonfull_run_tryget(bin);
1158e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	if (run != NULL)
1159e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		return (run);
1160e00572b384c81bd2aba57fac32f7077a34388915Jason Evans
1161e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	return (NULL);
1162e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1163e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
11641e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans/* Re-fill bin->runcur, then call arena_run_reg_alloc(). */
1165e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void *
1166e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)
1167e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1168e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	void *ret;
116949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	size_t binind;
117049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	arena_bin_info_t *bin_info;
1171e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	arena_run_t *run;
1172e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
117349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	binind = arena_bin_index(arena, bin);
117449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	bin_info = &arena_bin_info[binind];
1175e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	bin->runcur = NULL;
1176e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	run = arena_bin_nonfull_run_get(arena, bin);
1177e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	if (bin->runcur != NULL && bin->runcur->nfree > 0) {
1178e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		/*
1179e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		 * Another thread updated runcur while this one ran without the
1180e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		 * bin lock in arena_bin_nonfull_run_get().
1181e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		 */
1182e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		assert(bin->runcur->nfree > 0);
118349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		ret = arena_run_reg_alloc(bin->runcur, bin_info);
1184e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		if (run != NULL) {
1185940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans			arena_chunk_t *chunk;
1186940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans
1187940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans			/*
1188940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans			 * arena_run_alloc() may have allocated run, or it may
118984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans			 * have pulled run from the bin's run tree.  Therefore
1190940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans			 * it is unsafe to make any assumptions about how run
1191940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans			 * has previously been used, and arena_bin_lower_run()
1192940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans			 * must be called, as if a region were just deallocated
1193940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans			 * from the run.
1194940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans			 */
1195940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans			chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
119649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			if (run->nfree == bin_info->nregs)
11978de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans				arena_dalloc_bin_run(arena, chunk, run, bin);
11988de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans			else
11998de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans				arena_bin_lower_run(arena, chunk, run, bin);
1200e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		}
1201e00572b384c81bd2aba57fac32f7077a34388915Jason Evans		return (ret);
1202e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	}
1203e00572b384c81bd2aba57fac32f7077a34388915Jason Evans
1204e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	if (run == NULL)
1205e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (NULL);
1206e00572b384c81bd2aba57fac32f7077a34388915Jason Evans
1207e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	bin->runcur = run;
1208e00572b384c81bd2aba57fac32f7077a34388915Jason Evans
1209e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(bin->runcur->nfree > 0);
1210e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
121149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	return (arena_run_reg_alloc(bin->runcur, bin_info));
1212e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1213e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
121486815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evansvoid
121586815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evansarena_prof_accum(arena_t *arena, uint64_t accumbytes)
121686815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans{
121786815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans
121878f7352259768f670f8e1f9b000388dd32b62493Jason Evans	cassert(config_prof);
121978f7352259768f670f8e1f9b000388dd32b62493Jason Evans
122078f7352259768f670f8e1f9b000388dd32b62493Jason Evans	if (config_prof && prof_interval != 0) {
122186815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		arena->prof_accumbytes += accumbytes;
122286815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		if (arena->prof_accumbytes >= prof_interval) {
122386815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans			prof_idump();
122486815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans			arena->prof_accumbytes -= prof_interval;
122586815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		}
122686815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans	}
122786815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans}
122886815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans
1229e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid
12307372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evansarena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind,
12317372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans    uint64_t prof_accumbytes)
1232e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1233e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	unsigned i, nfill;
1234e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_bin_t *bin;
1235e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_t *run;
1236e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	void *ptr;
1237e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1238e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(tbin->ncached == 0);
1239e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
12407372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_prof) {
12417372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		malloc_mutex_lock(&arena->lock);
12427372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena_prof_accum(arena, prof_accumbytes);
12437372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		malloc_mutex_unlock(&arena->lock);
12447372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	}
1245e69bee01de62b56d3e585042d341743239568043Jason Evans	bin = &arena->bins[binind];
1246e69bee01de62b56d3e585042d341743239568043Jason Evans	malloc_mutex_lock(&bin->lock);
12471dcb4f86b23a5760f5a717ace716360b63b33fadJason Evans	for (i = 0, nfill = (tcache_bin_info[binind].ncached_max >>
12481dcb4f86b23a5760f5a717ace716360b63b33fadJason Evans	    tbin->lg_fill_div); i < nfill; i++) {
1249e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if ((run = bin->runcur) != NULL && run->nfree > 0)
125049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			ptr = arena_run_reg_alloc(run, &arena_bin_info[binind]);
1251e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		else
1252e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			ptr = arena_bin_malloc_hard(arena, bin);
12533fa9a2fad83a3014d5069b5a2530a0cfb8d8d197Jason Evans		if (ptr == NULL)
1254e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			break;
1255122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		if (config_fill && opt_junk) {
1256122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			arena_alloc_junk_small(ptr, &arena_bin_info[binind],
1257122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			    true);
1258122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		}
12599c43c13a35220c10d97a886616899189daceb359Jason Evans		/* Insert such that low regions get used first. */
12609c43c13a35220c10d97a886616899189daceb359Jason Evans		tbin->avail[nfill - 1 - i] = ptr;
1261e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
12627372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats) {
12637372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		bin->stats.allocated += i * arena_bin_info[binind].reg_size;
12647372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		bin->stats.nmalloc += i;
12657372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		bin->stats.nrequests += tbin->tstats.nrequests;
12667372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		bin->stats.nfills++;
12677372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		tbin->tstats.nrequests = 0;
12687372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	}
126986815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans	malloc_mutex_unlock(&bin->lock);
1270e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	tbin->ncached = i;
1271e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1272e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1273122449b073bcbaa504c4f592ea2d733503c272d2Jason Evansvoid
1274122449b073bcbaa504c4f592ea2d733503c272d2Jason Evansarena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info, bool zero)
1275122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans{
1276122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans
1277122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	if (zero) {
1278122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		size_t redzone_size = bin_info->redzone_size;
1279122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		memset((void *)((uintptr_t)ptr - redzone_size), 0xa5,
1280122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		    redzone_size);
1281122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		memset((void *)((uintptr_t)ptr + bin_info->reg_size), 0xa5,
1282122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		    redzone_size);
1283122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	} else {
1284122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		memset((void *)((uintptr_t)ptr - bin_info->redzone_size), 0xa5,
1285122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		    bin_info->reg_interval);
1286122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	}
1287122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans}
1288122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans
1289122449b073bcbaa504c4f592ea2d733503c272d2Jason Evansvoid
1290122449b073bcbaa504c4f592ea2d733503c272d2Jason Evansarena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info)
1291122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans{
1292122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	size_t size = bin_info->reg_size;
1293122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	size_t redzone_size = bin_info->redzone_size;
1294122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	size_t i;
1295122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	bool error = false;
1296122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans
1297122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	for (i = 1; i <= redzone_size; i++) {
1298122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		unsigned byte;
1299122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		if ((byte = *(uint8_t *)((uintptr_t)ptr - i)) != 0xa5) {
1300122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			error = true;
1301122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			malloc_printf("<jemalloc>: Corrupt redzone "
1302122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			    "%zu byte%s before %p (size %zu), byte=%#x\n", i,
1303122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			    (i == 1) ? "" : "s", ptr, size, byte);
1304122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		}
1305122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	}
1306122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	for (i = 0; i < redzone_size; i++) {
1307122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		unsigned byte;
1308122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		if ((byte = *(uint8_t *)((uintptr_t)ptr + size + i)) != 0xa5) {
1309122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			error = true;
1310122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			malloc_printf("<jemalloc>: Corrupt redzone "
1311122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			    "%zu byte%s after end of %p (size %zu), byte=%#x\n",
1312122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			    i, (i == 1) ? "" : "s", ptr, size, byte);
1313122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		}
1314122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	}
1315122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	if (opt_abort && error)
1316122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		abort();
1317122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans
1318122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	memset((void *)((uintptr_t)ptr - redzone_size), 0x5a,
1319122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	    bin_info->reg_interval);
1320122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans}
1321122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans
1322e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid *
1323e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_malloc_small(arena_t *arena, size_t size, bool zero)
1324e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1325e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	void *ret;
1326e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_bin_t *bin;
1327e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_t *run;
1328e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t binind;
1329e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
133041ade967c29ea9312c0b7390ee43bc0c63373f39Jason Evans	binind = SMALL_SIZE2BIN(size);
1331b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans	assert(binind < NBINS);
1332e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	bin = &arena->bins[binind];
133349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	size = arena_bin_info[binind].reg_size;
1334e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
133586815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans	malloc_mutex_lock(&bin->lock);
1336e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if ((run = bin->runcur) != NULL && run->nfree > 0)
133749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		ret = arena_run_reg_alloc(run, &arena_bin_info[binind]);
1338e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	else
1339e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		ret = arena_bin_malloc_hard(arena, bin);
1340e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1341e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (ret == NULL) {
134286815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		malloc_mutex_unlock(&bin->lock);
1343e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (NULL);
1344e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1345e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
13467372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats) {
13477372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		bin->stats.allocated += size;
13487372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		bin->stats.nmalloc++;
13497372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		bin->stats.nrequests++;
13507372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	}
135186815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans	malloc_mutex_unlock(&bin->lock);
13527372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_prof && isthreaded == false) {
135386815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		malloc_mutex_lock(&arena->lock);
1354d34f9e7e9306698e298a703c28526cd6bfc073ecJason Evans		arena_prof_accum(arena, size);
135586815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		malloc_mutex_unlock(&arena->lock);
135686815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans	}
1357e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1358e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (zero == false) {
13597372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_fill) {
1360122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			if (opt_junk) {
1361122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans				arena_alloc_junk_small(ret,
1362122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans				    &arena_bin_info[binind], false);
1363122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			} else if (opt_zero)
13647372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans				memset(ret, 0, size);
13657372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		}
1366122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	} else {
1367122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		if (config_fill && opt_junk) {
1368122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			arena_alloc_junk_small(ret, &arena_bin_info[binind],
1369122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			    true);
1370122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		}
1371122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
1372e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		memset(ret, 0, size);
1373122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	}
1374e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1375e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ret);
1376e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1377e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1378e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid *
1379e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_malloc_large(arena_t *arena, size_t size, bool zero)
1380e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1381e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	void *ret;
1382e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1383e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Large allocation. */
1384e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size = PAGE_CEILING(size);
1385e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_lock(&arena->lock);
1386e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	ret = (void *)arena_run_alloc(arena, size, true, zero);
1387e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (ret == NULL) {
1388e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		malloc_mutex_unlock(&arena->lock);
1389e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (NULL);
1390e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
13917372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats) {
13927372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.nmalloc_large++;
13937372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.nrequests_large++;
13947372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.allocated_large += size;
1395ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++;
1396ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++;
1397ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++;
1398e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
13997372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_prof)
14007372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena_prof_accum(arena, size);
1401e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_unlock(&arena->lock);
1402e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1403e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (zero == false) {
14047372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_fill) {
14057372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			if (opt_junk)
14067372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans				memset(ret, 0xa5, size);
14077372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			else if (opt_zero)
14087372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans				memset(ret, 0, size);
14097372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		}
1410e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1411e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1412e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ret);
1413e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1414e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1415e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Only handles large allocations that require more than page alignment. */
1416e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid *
14175ff709c264e52651de25b788692c62ff1f6f389cJason Evansarena_palloc(arena_t *arena, size_t size, size_t alignment, bool zero)
1418e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1419e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	void *ret;
14205ff709c264e52651de25b788692c62ff1f6f389cJason Evans	size_t alloc_size, leadsize, trailsize;
14215ff709c264e52651de25b788692c62ff1f6f389cJason Evans	arena_run_t *run;
1422e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_chunk_t *chunk;
1423e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1424e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert((size & PAGE_MASK) == 0);
142593443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
142693443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans	alignment = PAGE_CEILING(alignment);
14275ff709c264e52651de25b788692c62ff1f6f389cJason Evans	alloc_size = size + alignment - PAGE;
1428e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1429e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_lock(&arena->lock);
14305ff709c264e52651de25b788692c62ff1f6f389cJason Evans	run = arena_run_alloc(arena, alloc_size, true, zero);
14315ff709c264e52651de25b788692c62ff1f6f389cJason Evans	if (run == NULL) {
1432e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		malloc_mutex_unlock(&arena->lock);
1433e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (NULL);
1434e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
14355ff709c264e52651de25b788692c62ff1f6f389cJason Evans	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
1436e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
14375ff709c264e52651de25b788692c62ff1f6f389cJason Evans	leadsize = ALIGNMENT_CEILING((uintptr_t)run, alignment) -
14385ff709c264e52651de25b788692c62ff1f6f389cJason Evans	    (uintptr_t)run;
14395ff709c264e52651de25b788692c62ff1f6f389cJason Evans	assert(alloc_size >= leadsize + size);
14405ff709c264e52651de25b788692c62ff1f6f389cJason Evans	trailsize = alloc_size - leadsize - size;
14415ff709c264e52651de25b788692c62ff1f6f389cJason Evans	ret = (void *)((uintptr_t)run + leadsize);
14425ff709c264e52651de25b788692c62ff1f6f389cJason Evans	if (leadsize != 0) {
14435ff709c264e52651de25b788692c62ff1f6f389cJason Evans		arena_run_trim_head(arena, chunk, run, alloc_size, alloc_size -
14445ff709c264e52651de25b788692c62ff1f6f389cJason Evans		    leadsize);
14455ff709c264e52651de25b788692c62ff1f6f389cJason Evans	}
14465ff709c264e52651de25b788692c62ff1f6f389cJason Evans	if (trailsize != 0) {
14475ff709c264e52651de25b788692c62ff1f6f389cJason Evans		arena_run_trim_tail(arena, chunk, ret, size + trailsize, size,
14485ff709c264e52651de25b788692c62ff1f6f389cJason Evans		    false);
1449e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1450e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
14517372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats) {
14527372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.nmalloc_large++;
14537372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.nrequests_large++;
14547372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.allocated_large += size;
1455ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++;
1456ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++;
1457ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++;
1458e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1459e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_unlock(&arena->lock);
1460e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
14617372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_fill && zero == false) {
14628e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans		if (opt_junk)
14638e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans			memset(ret, 0xa5, size);
14648e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans		else if (opt_zero)
14658e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans			memset(ret, 0, size);
14668e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	}
1467e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ret);
1468e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1469e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
14700b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evansvoid
14710b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evansarena_prof_promoted(const void *ptr, size_t size)
14720b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans{
14730b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans	arena_chunk_t *chunk;
14740b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans	size_t pageind, binind;
14750b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans
147678f7352259768f670f8e1f9b000388dd32b62493Jason Evans	cassert(config_prof);
14770b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans	assert(ptr != NULL);
14780b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans	assert(CHUNK_ADDR2BASE(ptr) != ptr);
1479122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	assert(isalloc(ptr, false) == PAGE);
1480122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	assert(isalloc(ptr, true) == PAGE);
1481b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans	assert(size <= SMALL_MAXCLASS);
14820b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans
14830b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
1484ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
148541ade967c29ea9312c0b7390ee43bc0c63373f39Jason Evans	binind = SMALL_SIZE2BIN(size);
1486b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans	assert(binind < NBINS);
14877393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	chunk->map[pageind-map_bias].bits = (chunk->map[pageind-map_bias].bits &
1488e4f7846f1fd279a039ffa2a41707348187219de4Jason Evans	    ~CHUNK_MAP_CLASS_MASK) | ((binind+1) << CHUNK_MAP_CLASS_SHIFT);
14890b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans
1490122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	assert(isalloc(ptr, false) == PAGE);
1491122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	assert(isalloc(ptr, true) == size);
14920b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans}
14936109fe07a14b7a619365977d9523db9f8b333792Jason Evans
1494e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
1495088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evansarena_dissociate_bin_run(arena_chunk_t *chunk, arena_run_t *run,
1496e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    arena_bin_t *bin)
1497e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1498e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
149919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	/* Dissociate run from bin. */
1500e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (run == bin->runcur)
1501e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->runcur = NULL;
150249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	else {
150349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		size_t binind = arena_bin_index(chunk->arena, bin);
150449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		arena_bin_info_t *bin_info = &arena_bin_info[binind];
150549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans
150649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		if (bin_info->nregs != 1) {
150749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			/*
150849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			 * This block's conditional is necessary because if the
150949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			 * run only contains one region, then it never gets
151049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			 * inserted into the non-full runs tree.
151149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			 */
1512e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans			arena_bin_runs_remove(bin, run);
151349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		}
1514e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1515088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans}
1516088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans
1517088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evansstatic void
1518088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evansarena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
1519088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans    arena_bin_t *bin)
1520088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans{
152149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	size_t binind;
152249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	arena_bin_info_t *bin_info;
1523088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans	size_t npages, run_ind, past;
1524088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans
1525088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans	assert(run != bin->runcur);
1526088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans	assert(arena_run_tree_search(&bin->runs, &chunk->map[
1527ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	    (((uintptr_t)run-(uintptr_t)chunk)>>LG_PAGE)-map_bias]) == NULL);
152886815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans
152949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	binind = arena_bin_index(chunk->arena, run->bin);
153049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	bin_info = &arena_bin_info[binind];
153149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans
1532e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	malloc_mutex_unlock(&bin->lock);
1533e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	/******************************/
1534ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	npages = bin_info->run_size >> LG_PAGE;
1535ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE);
153684c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	past = (size_t)(PAGE_CEILING((uintptr_t)run +
153784c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	    (uintptr_t)bin_info->reg0_offset + (uintptr_t)(run->nextind *
1538122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	    bin_info->reg_interval - bin_info->redzone_size) -
1539122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	    (uintptr_t)chunk) >> LG_PAGE);
154086815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans	malloc_mutex_lock(&arena->lock);
154119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans
154219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	/*
154319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * If the run was originally clean, and some pages were never touched,
154419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * trim the clean pages before deallocating the dirty portion of the
154519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 * run.
154619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	 */
15477393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	if ((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY) == 0 && past
15487393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	    - run_ind < npages) {
154919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		/*
155019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		 * Trim clean pages.  Convert to large run beforehand.  Set the
155119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		 * last map element first, in case this is a one-page run.
155219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans		 */
15537393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		chunk->map[run_ind+npages-1-map_bias].bits = CHUNK_MAP_LARGE |
1554940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		    (chunk->map[run_ind+npages-1-map_bias].bits &
1555940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		    CHUNK_MAP_FLAGS_MASK);
155649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		chunk->map[run_ind-map_bias].bits = bin_info->run_size |
15577393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    CHUNK_MAP_LARGE | (chunk->map[run_ind-map_bias].bits &
15587393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		    CHUNK_MAP_FLAGS_MASK);
1559ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		arena_run_trim_tail(arena, chunk, run, (npages << LG_PAGE),
1560ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    ((past - run_ind) << LG_PAGE), false);
1561940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		/* npages = past - run_ind; */
15621e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans	}
156319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	arena_run_dalloc(arena, run, true);
156486815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans	malloc_mutex_unlock(&arena->lock);
1565e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	/****************************/
1566e00572b384c81bd2aba57fac32f7077a34388915Jason Evans	malloc_mutex_lock(&bin->lock);
15677372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats)
15687372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		bin->stats.curruns--;
1569e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1570e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1571940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evansstatic void
1572940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evansarena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
1573940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans    arena_bin_t *bin)
1574e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1575e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
15768de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans	/*
1577e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	 * Make sure that if bin->runcur is non-NULL, it refers to the lowest
1578e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	 * non-full run.  It is okay to NULL runcur out rather than proactively
1579e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	 * keeping it pointing at the lowest non-full run.
15808de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans	 */
1581e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	if ((uintptr_t)run < (uintptr_t)bin->runcur) {
15828de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans		/* Switch runcur. */
1583e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans		if (bin->runcur->nfree > 0)
1584e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans			arena_bin_runs_insert(bin, bin->runcur);
15858de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans		bin->runcur = run;
1586e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans		if (config_stats)
1587e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans			bin->stats.reruns++;
1588e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans	} else
1589e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans		arena_bin_runs_insert(bin, run);
1590940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans}
1591940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans
1592940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evansvoid
1593940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evansarena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,
1594940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans    arena_chunk_map_t *mapelm)
1595940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans{
1596940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	size_t pageind;
1597940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	arena_run_t *run;
1598940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	arena_bin_t *bin;
1599940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	size_t size;
1600940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans
1601ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
1602940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -
1603ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	    (mapelm->bits >> LG_PAGE)) << LG_PAGE));
1604940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	bin = run->bin;
160549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	size_t binind = arena_bin_index(arena, bin);
160649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	arena_bin_info_t *bin_info = &arena_bin_info[binind];
16077372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_fill || config_stats)
16087372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		size = bin_info->reg_size;
1609940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans
16107372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_fill && opt_junk)
1611122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		arena_dalloc_junk_small(ptr, bin_info);
1612940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans
1613940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans	arena_run_reg_dalloc(run, ptr);
161449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	if (run->nfree == bin_info->nregs) {
1615088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans		arena_dissociate_bin_run(chunk, run, bin);
16168de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans		arena_dalloc_bin_run(arena, chunk, run, bin);
1617088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans	} else if (run->nfree == 1 && run != bin->runcur)
16188de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans		arena_bin_lower_run(arena, chunk, run, bin);
1619e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
16207372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats) {
16217372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		bin->stats.allocated -= size;
16227372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		bin->stats.ndalloc++;
16237372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	}
1624e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1625e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1626e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid
1627b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_merge(arena_t *arena, size_t *nactive, size_t *ndirty,
1628b34e8684ec025aa780997c11f847c19fb269755bJason Evans    arena_stats_t *astats, malloc_bin_stats_t *bstats,
1629b34e8684ec025aa780997c11f847c19fb269755bJason Evans    malloc_large_stats_t *lstats)
1630b34e8684ec025aa780997c11f847c19fb269755bJason Evans{
16313c2343518c2b1fbbd66065c75a3c19f908de1d78Jason Evans	unsigned i;
1632b34e8684ec025aa780997c11f847c19fb269755bJason Evans
163386815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans	malloc_mutex_lock(&arena->lock);
1634b34e8684ec025aa780997c11f847c19fb269755bJason Evans	*nactive += arena->nactive;
1635b34e8684ec025aa780997c11f847c19fb269755bJason Evans	*ndirty += arena->ndirty;
1636b34e8684ec025aa780997c11f847c19fb269755bJason Evans
16374201af05425b69ee37ffca437aca0cdd604d1e51Jason Evans	astats->mapped += arena->stats.mapped;
1638b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->npurge += arena->stats.npurge;
1639b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->nmadvise += arena->stats.nmadvise;
1640b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->purged += arena->stats.purged;
1641b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->allocated_large += arena->stats.allocated_large;
1642b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->nmalloc_large += arena->stats.nmalloc_large;
1643b34e8684ec025aa780997c11f847c19fb269755bJason Evans	astats->ndalloc_large += arena->stats.ndalloc_large;
1644dafde14e08ddfda747aabb2045b350848b601b2eJason Evans	astats->nrequests_large += arena->stats.nrequests_large;
1645b34e8684ec025aa780997c11f847c19fb269755bJason Evans
16463c2343518c2b1fbbd66065c75a3c19f908de1d78Jason Evans	for (i = 0; i < nlclasses; i++) {
1647dafde14e08ddfda747aabb2045b350848b601b2eJason Evans		lstats[i].nmalloc += arena->stats.lstats[i].nmalloc;
1648dafde14e08ddfda747aabb2045b350848b601b2eJason Evans		lstats[i].ndalloc += arena->stats.lstats[i].ndalloc;
1649b34e8684ec025aa780997c11f847c19fb269755bJason Evans		lstats[i].nrequests += arena->stats.lstats[i].nrequests;
1650b34e8684ec025aa780997c11f847c19fb269755bJason Evans		lstats[i].curruns += arena->stats.lstats[i].curruns;
1651b34e8684ec025aa780997c11f847c19fb269755bJason Evans	}
165286815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans	malloc_mutex_unlock(&arena->lock);
165386815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans
1654b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans	for (i = 0; i < NBINS; i++) {
165586815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		arena_bin_t *bin = &arena->bins[i];
165686815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans
165786815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		malloc_mutex_lock(&bin->lock);
165886815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		bstats[i].allocated += bin->stats.allocated;
165986815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		bstats[i].nmalloc += bin->stats.nmalloc;
166086815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		bstats[i].ndalloc += bin->stats.ndalloc;
166186815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		bstats[i].nrequests += bin->stats.nrequests;
16627372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_tcache) {
16637372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			bstats[i].nfills += bin->stats.nfills;
16647372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			bstats[i].nflushes += bin->stats.nflushes;
16657372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		}
166686815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		bstats[i].nruns += bin->stats.nruns;
166786815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		bstats[i].reruns += bin->stats.reruns;
166886815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		bstats[i].curruns += bin->stats.curruns;
166986815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		malloc_mutex_unlock(&bin->lock);
167086815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans	}
1671b34e8684ec025aa780997c11f847c19fb269755bJason Evans}
1672e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1673e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid
1674e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)
1675e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
167613668262d17fb5950e2441bc9d56a15db9c93877Jason Evans
16777372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_fill || config_stats) {
1678ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
16797393f44ff025ca67716fc53b68003fd65122fd97Jason Evans		size_t size = chunk->map[pageind-map_bias].bits & ~PAGE_MASK;
1680e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
16817372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_fill && config_stats && opt_junk)
1682e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			memset(ptr, 0x5a, size);
16837372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_stats) {
16847372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			arena->stats.ndalloc_large++;
16857372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			arena->stats.allocated_large -= size;
1686ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans			arena->stats.lstats[(size >> LG_PAGE) - 1].ndalloc++;
1687ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans			arena->stats.lstats[(size >> LG_PAGE) - 1].curruns--;
16887372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		}
1689e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1690e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1691e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_dalloc(arena, (arena_run_t *)ptr, true);
1692e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1693e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1694e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void
1695e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr,
16968e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans    size_t oldsize, size_t size)
1697e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1698e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1699e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	assert(size < oldsize);
1700e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1701e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
1702e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Shrink the run, and make trailing pages available for other
1703e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * allocations.
1704e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
1705e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_lock(&arena->lock);
1706e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size,
1707e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	    true);
17087372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats) {
17097372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.ndalloc_large++;
17107372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.allocated_large -= oldsize;
1711ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		arena->stats.lstats[(oldsize >> LG_PAGE) - 1].ndalloc++;
1712ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		arena->stats.lstats[(oldsize >> LG_PAGE) - 1].curruns--;
17137372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans
17147372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.nmalloc_large++;
17157372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.nrequests_large++;
17167372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.allocated_large += size;
1717ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++;
1718ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++;
1719ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++;
1720e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1721e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_unlock(&arena->lock);
1722e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1723e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1724e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool
1725e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr,
17268e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans    size_t oldsize, size_t size, size_t extra, bool zero)
1727e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1728ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
1729ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	size_t npages = oldsize >> LG_PAGE;
17308e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	size_t followsize;
1731e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
17327393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	assert(oldsize == (chunk->map[pageind-map_bias].bits & ~PAGE_MASK));
1733e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1734e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Try to extend the run. */
17358e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	assert(size + extra > oldsize);
1736e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_lock(&arena->lock);
17377393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	if (pageind + npages < chunk_npages &&
17387393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	    (chunk->map[pageind+npages-map_bias].bits
17398e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	    & CHUNK_MAP_ALLOCATED) == 0 && (followsize =
17407393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	    chunk->map[pageind+npages-map_bias].bits & ~PAGE_MASK) >= size -
17417393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	    oldsize) {
1742e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/*
1743e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * The next run is available and sufficiently large.  Split the
1744e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * following run, then merge the first part with the existing
1745e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 * allocation.
1746e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		 */
1747940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		size_t flag_dirty;
17488e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans		size_t splitsize = (oldsize + followsize <= size + extra)
17498e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans		    ? followsize : size + extra - oldsize;
1750e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_split(arena, (arena_run_t *)((uintptr_t)chunk +
1751ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    ((pageind+npages) << LG_PAGE)), splitsize, true, zero);
1752e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1753088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans		size = oldsize + splitsize;
1754ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		npages = size >> LG_PAGE;
1755e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1756940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		/*
1757940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		 * Mark the extended run as dirty if either portion of the run
1758940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		 * was dirty before allocation.  This is rather pedantic,
1759940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		 * because there's not actually any sequence of events that
1760940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		 * could cause the resulting run to be passed to
1761940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		 * arena_run_dalloc() with the dirty argument set to false
1762940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		 * (which is when dirty flag consistency would really matter).
1763940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		 */
1764940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		flag_dirty = (chunk->map[pageind-map_bias].bits &
1765940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		    CHUNK_MAP_DIRTY) |
1766940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		    (chunk->map[pageind+npages-1-map_bias].bits &
1767940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		    CHUNK_MAP_DIRTY);
1768940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		chunk->map[pageind-map_bias].bits = size | flag_dirty
1769940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		    | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED;
1770940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		chunk->map[pageind+npages-1-map_bias].bits = flag_dirty |
1771940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		    CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED;
1772990d10cefb4b2ff4458086aedba8fc70975a9adcJason Evans
17737372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_stats) {
17747372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			arena->stats.ndalloc_large++;
17757372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			arena->stats.allocated_large -= oldsize;
1776ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans			arena->stats.lstats[(oldsize >> LG_PAGE)
17777372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			    - 1].ndalloc++;
1778ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans			arena->stats.lstats[(oldsize >> LG_PAGE)
17797372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			    - 1].curruns--;
17807372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans
17817372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			arena->stats.nmalloc_large++;
17827372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			arena->stats.nrequests_large++;
17837372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			arena->stats.allocated_large += size;
1784ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans			arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++;
1785ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans			arena->stats.lstats[(size >> LG_PAGE)
17867372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			    - 1].nrequests++;
1787ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans			arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++;
1788940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans		}
1789e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		malloc_mutex_unlock(&arena->lock);
1790e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (false);
1791e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1792e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	malloc_mutex_unlock(&arena->lock);
1793e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1794e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (true);
1795e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1796e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1797e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/*
1798e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Try to resize a large allocation, in order to avoid copying.  This will
1799e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * always fail if growing an object, and the following run is already in use.
1800e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */
1801e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool
18028e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evansarena_ralloc_large(void *ptr, size_t oldsize, size_t size, size_t extra,
18038e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans    bool zero)
1804e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1805e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	size_t psize;
1806e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
18078e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	psize = PAGE_CEILING(size + extra);
1808e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (psize == oldsize) {
1809e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		/* Same size class. */
18107372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_fill && opt_junk && size < oldsize) {
1811e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize -
1812e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			    size);
1813e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1814e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (false);
1815e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	} else {
1816e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_chunk_t *chunk;
1817e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_t *arena;
1818e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1819e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
1820e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena = chunk->arena;
1821e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1822e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		if (psize < oldsize) {
1823e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			/* Fill before shrinking in order avoid a race. */
18247372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			if (config_fill && opt_junk) {
1825e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				memset((void *)((uintptr_t)ptr + size), 0x5a,
1826e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    oldsize - size);
1827e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			}
18288e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans			arena_ralloc_large_shrink(arena, chunk, ptr, oldsize,
18298e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans			    psize);
1830e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			return (false);
1831e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		} else {
1832e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			bool ret = arena_ralloc_large_grow(arena, chunk, ptr,
18338e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans			    oldsize, PAGE_CEILING(size),
18348e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans			    psize - PAGE_CEILING(size), zero);
18357372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			if (config_fill && ret == false && zero == false &&
18367372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			    opt_zero) {
1837e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				memset((void *)((uintptr_t)ptr + oldsize), 0,
1838e476f8a161d445211fd6e54fe370275196e66bcbJason Evans				    size - oldsize);
1839e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			}
1840e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			return (ret);
1841e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1842e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1843e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1844e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1845e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid *
18468e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evansarena_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra,
18478e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans    bool zero)
1848e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1849e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
18508e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	/*
18518e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	 * Avoid moving the allocation if the size class can be left the same.
18528e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	 */
1853e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (oldsize <= arena_maxclass) {
1854b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans		if (oldsize <= SMALL_MAXCLASS) {
185549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			assert(arena_bin_info[SMALL_SIZE2BIN(oldsize)].reg_size
185649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			    == oldsize);
1857b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans			if ((size + extra <= SMALL_MAXCLASS &&
185841ade967c29ea9312c0b7390ee43bc0c63373f39Jason Evans			    SMALL_SIZE2BIN(size + extra) ==
185941ade967c29ea9312c0b7390ee43bc0c63373f39Jason Evans			    SMALL_SIZE2BIN(oldsize)) || (size <= oldsize &&
18608e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans			    size + extra >= oldsize)) {
18617372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans				if (config_fill && opt_junk && size < oldsize) {
18628e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans					memset((void *)((uintptr_t)ptr + size),
18638e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans					    0x5a, oldsize - size);
18648e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans				}
18658e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans				return (ptr);
18668e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans			}
1867e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		} else {
1868e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			assert(size <= arena_maxclass);
1869b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans			if (size + extra > SMALL_MAXCLASS) {
18708e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans				if (arena_ralloc_large(ptr, oldsize, size,
18718e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans				    extra, zero) == false)
1872e476f8a161d445211fd6e54fe370275196e66bcbJason Evans					return (ptr);
1873e476f8a161d445211fd6e54fe370275196e66bcbJason Evans			}
1874e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		}
1875e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1876e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
18778e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	/* Reallocation would require a move. */
18788e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	return (NULL);
18798e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans}
18808e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans
18818e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evansvoid *
18828e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evansarena_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
188301b3fe55ff3ac8e4aa689f09fcb0729da8037638Jason Evans    size_t alignment, bool zero, bool try_tcache)
18848e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans{
18858e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	void *ret;
18868e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	size_t copysize;
18878e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans
18888e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	/* Try to avoid moving the allocation. */
18898e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	ret = arena_ralloc_no_move(ptr, oldsize, size, extra, zero);
18908e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	if (ret != NULL)
18918e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans		return (ret);
18928e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans
1893e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
18948e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	 * size and oldsize are different enough that we need to move the
18958e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	 * object.  In that case, fall back to allocating new space and
18968e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	 * copying.
1897e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
189838d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans	if (alignment != 0) {
18995ff709c264e52651de25b788692c62ff1f6f389cJason Evans		size_t usize = sa2u(size + extra, alignment);
190038d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans		if (usize == 0)
190138d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans			return (NULL);
190238d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans		ret = ipalloc(usize, alignment, zero);
190338d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans	} else
190401b3fe55ff3ac8e4aa689f09fcb0729da8037638Jason Evans		ret = arena_malloc(NULL, size + extra, zero, try_tcache);
1905e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
19068e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	if (ret == NULL) {
19078e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans		if (extra == 0)
19088e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans			return (NULL);
19098e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans		/* Try again, this time without extra. */
191038d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans		if (alignment != 0) {
19115ff709c264e52651de25b788692c62ff1f6f389cJason Evans			size_t usize = sa2u(size, alignment);
191238d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans			if (usize == 0)
191338d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans				return (NULL);
191438d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans			ret = ipalloc(usize, alignment, zero);
191538d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans		} else
191601b3fe55ff3ac8e4aa689f09fcb0729da8037638Jason Evans			ret = arena_malloc(NULL, size, zero, try_tcache);
19178e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans
19188e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans		if (ret == NULL)
19198e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans			return (NULL);
19208e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	}
19218e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans
19228e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	/* Junk/zero-filling were already done by ipalloc()/arena_malloc(). */
19238e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans
19248e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	/*
19258e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	 * Copy at most size bytes (not size+extra), since the caller has no
19268e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	 * expectation that the extra bytes will be reliably preserved.
19278e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans	 */
1928e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	copysize = (size < oldsize) ? size : oldsize;
1929f54166e7ef5313c3b5c773cbb0ca2af95f5a15aeJason Evans	VALGRIND_MAKE_MEM_UNDEFINED(ret, copysize);
1930e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	memcpy(ret, ptr, copysize);
1931122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	iqalloc(ptr);
1932e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (ret);
1933e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1934e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1935e476f8a161d445211fd6e54fe370275196e66bcbJason Evansbool
1936e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_new(arena_t *arena, unsigned ind)
1937e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
1938e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	unsigned i;
1939e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena_bin_t *bin;
1940e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
19416109fe07a14b7a619365977d9523db9f8b333792Jason Evans	arena->ind = ind;
1942597632be188d2bcc135dad2145cc46ef44897aadJason Evans	arena->nthreads = 0;
19436109fe07a14b7a619365977d9523db9f8b333792Jason Evans
1944e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	if (malloc_mutex_init(&arena->lock))
1945e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		return (true);
1946e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
19477372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_stats) {
19487372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		memset(&arena->stats, 0, sizeof(arena_stats_t));
19497372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->stats.lstats =
19507372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		    (malloc_large_stats_t *)base_alloc(nlclasses *
19517372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		    sizeof(malloc_large_stats_t));
19527372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (arena->stats.lstats == NULL)
19537372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			return (true);
19547372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		memset(arena->stats.lstats, 0, nlclasses *
19557372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		    sizeof(malloc_large_stats_t));
19567372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_tcache)
19577372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			ql_new(&arena->tcache_ql);
19587372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	}
1959e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
19607372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans	if (config_prof)
19617372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		arena->prof_accumbytes = 0;
1962d34f9e7e9306698e298a703c28526cd6bfc073ecJason Evans
1963e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Initialize chunks. */
19642caa4715ed4f787f263239ff97dd824636289286Jason Evans	ql_new(&arena->chunks_dirty);
1965e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->spare = NULL;
1966e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1967e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->nactive = 0;
1968e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	arena->ndirty = 0;
1969799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans	arena->npurgatory = 0;
1970e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
197119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	arena_avail_tree_new(&arena->runs_avail_clean);
197219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans	arena_avail_tree_new(&arena->runs_avail_dirty);
1973e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1974e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/* Initialize bins. */
1975b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans	for (i = 0; i < NBINS; i++) {
1976e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin = &arena->bins[i];
197786815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans		if (malloc_mutex_init(&bin->lock))
197886815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans			return (true);
1979e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		bin->runcur = NULL;
1980e476f8a161d445211fd6e54fe370275196e66bcbJason Evans		arena_run_tree_new(&bin->runs);
19817372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_stats)
19827372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
1983e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	}
1984e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
1985e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	return (false);
1986e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
1987e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
198849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans/*
198949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * Calculate bin_info->run_size such that it meets the following constraints:
199049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans *
199149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans *   *) bin_info->run_size >= min_run_size
199249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans *   *) bin_info->run_size <= arena_maxclass
199349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans *   *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed).
199447e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans *   *) bin_info->nregs <= RUN_MAXREGS
199549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans *
199684c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans * bin_info->nregs, bin_info->bitmap_offset, and bin_info->reg0_offset are also
199784c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans * calculated here, since these settings are all interdependent.
199849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans */
199949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evansstatic size_t
200049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evansbin_info_run_size_calc(arena_bin_info_t *bin_info, size_t min_run_size)
200149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans{
2002122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	size_t pad_size;
200349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	size_t try_run_size, good_run_size;
200449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	uint32_t try_nregs, good_nregs;
200549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	uint32_t try_hdr_size, good_hdr_size;
200684c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	uint32_t try_bitmap_offset, good_bitmap_offset;
200749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	uint32_t try_ctx0_offset, good_ctx0_offset;
2008122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	uint32_t try_redzone0_offset, good_redzone0_offset;
200949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans
2010ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	assert(min_run_size >= PAGE);
201149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	assert(min_run_size <= arena_maxclass);
201249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans
201349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	/*
2014122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	 * Determine redzone size based on minimum alignment and minimum
2015122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	 * redzone size.  Add padding to the end of the run if it is needed to
2016122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	 * align the regions.  The padding allows each redzone to be half the
2017122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	 * minimum alignment; without the padding, each redzone would have to
2018122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	 * be twice as large in order to maintain alignment.
2019122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	 */
2020122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	if (config_fill && opt_redzone) {
2021122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		size_t align_min = ZU(1) << (ffs(bin_info->reg_size) - 1);
2022122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		if (align_min <= REDZONE_MINSIZE) {
2023122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			bin_info->redzone_size = REDZONE_MINSIZE;
2024122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			pad_size = 0;
2025122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		} else {
2026122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			bin_info->redzone_size = align_min >> 1;
2027122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			pad_size = bin_info->redzone_size;
2028122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		}
2029122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	} else {
2030122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		bin_info->redzone_size = 0;
2031122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		pad_size = 0;
2032122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	}
2033122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	bin_info->reg_interval = bin_info->reg_size +
2034122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	    (bin_info->redzone_size << 1);
2035122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans
2036122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	/*
203749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	 * Calculate known-valid settings before entering the run_size
203849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	 * expansion loop, so that the first part of the loop always copies
203949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	 * valid settings.
204049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	 *
204149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	 * The do..while loop iteratively reduces the number of regions until
204249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	 * the run header and the regions no longer overlap.  A closed formula
204349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	 * would be quite messy, since there is an interdependency between the
204449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	 * header's mask length and the number of regions.
204549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	 */
204649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	try_run_size = min_run_size;
2047122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	try_nregs = ((try_run_size - sizeof(arena_run_t)) /
2048122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	    bin_info->reg_interval)
204949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	    + 1; /* Counter-act try_nregs-- in loop. */
205047e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans	if (try_nregs > RUN_MAXREGS) {
205147e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans		try_nregs = RUN_MAXREGS
205247e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans		    + 1; /* Counter-act try_nregs-- in loop. */
205347e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans	}
205449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	do {
205549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		try_nregs--;
205649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		try_hdr_size = sizeof(arena_run_t);
205784c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans		/* Pad to a long boundary. */
205884c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans		try_hdr_size = LONG_CEILING(try_hdr_size);
205984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans		try_bitmap_offset = try_hdr_size;
206084c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans		/* Add space for bitmap. */
206184c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans		try_hdr_size += bitmap_size(try_nregs);
20627372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans		if (config_prof && opt_prof && prof_promote == false) {
206349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			/* Pad to a quantum boundary. */
206449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			try_hdr_size = QUANTUM_CEILING(try_hdr_size);
206549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			try_ctx0_offset = try_hdr_size;
206649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			/* Add space for one (prof_ctx_t *) per region. */
206749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			try_hdr_size += try_nregs * sizeof(prof_ctx_t *);
206849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		} else
206949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			try_ctx0_offset = 0;
2070122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		try_redzone0_offset = try_run_size - (try_nregs *
2071122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		    bin_info->reg_interval) - pad_size;
2072122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	} while (try_hdr_size > try_redzone0_offset);
207349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans
207449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	/* run_size expansion loop. */
207549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	do {
207649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		/*
207749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		 * Copy valid settings before trying more aggressive settings.
207849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		 */
207949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		good_run_size = try_run_size;
208049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		good_nregs = try_nregs;
208149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		good_hdr_size = try_hdr_size;
208284c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans		good_bitmap_offset = try_bitmap_offset;
208349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		good_ctx0_offset = try_ctx0_offset;
2084122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		good_redzone0_offset = try_redzone0_offset;
208549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans
208649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		/* Try more aggressive settings. */
2087ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		try_run_size += PAGE;
2088122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		try_nregs = ((try_run_size - sizeof(arena_run_t) - pad_size) /
2089122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		    bin_info->reg_interval)
209049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		    + 1; /* Counter-act try_nregs-- in loop. */
209147e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans		if (try_nregs > RUN_MAXREGS) {
209247e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans			try_nregs = RUN_MAXREGS
209347e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans			    + 1; /* Counter-act try_nregs-- in loop. */
209447e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans		}
209549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans		do {
209649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			try_nregs--;
209749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			try_hdr_size = sizeof(arena_run_t);
209884c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans			/* Pad to a long boundary. */
209984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans			try_hdr_size = LONG_CEILING(try_hdr_size);
210084c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans			try_bitmap_offset = try_hdr_size;
210184c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans			/* Add space for bitmap. */
210284c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans			try_hdr_size += bitmap_size(try_nregs);
21037372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans			if (config_prof && opt_prof && prof_promote == false) {
210449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans				/* Pad to a quantum boundary. */
210549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans				try_hdr_size = QUANTUM_CEILING(try_hdr_size);
210649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans				try_ctx0_offset = try_hdr_size;
210749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans				/*
210849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans				 * Add space for one (prof_ctx_t *) per region.
210949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans				 */
211049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans				try_hdr_size += try_nregs *
211149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans				    sizeof(prof_ctx_t *);
211249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans			}
2113122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			try_redzone0_offset = try_run_size - (try_nregs *
2114122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans			    bin_info->reg_interval) - pad_size;
2115122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans		} while (try_hdr_size > try_redzone0_offset);
211649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	} while (try_run_size <= arena_maxclass
211749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	    && try_run_size <= arena_maxclass
2118122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	    && RUN_MAX_OVRHD * (bin_info->reg_interval << 3) >
2119122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	    RUN_MAX_OVRHD_RELAX
2120122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	    && (try_redzone0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size
212147e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans	    && try_nregs < RUN_MAXREGS);
212249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans
2123122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	assert(good_hdr_size <= good_redzone0_offset);
212449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans
212549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	/* Copy final settings. */
212649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	bin_info->run_size = good_run_size;
212749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	bin_info->nregs = good_nregs;
212884c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans	bin_info->bitmap_offset = good_bitmap_offset;
212949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	bin_info->ctx0_offset = good_ctx0_offset;
2130122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	bin_info->reg0_offset = good_redzone0_offset + bin_info->redzone_size;
2131122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans
2132122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	assert(bin_info->reg0_offset - bin_info->redzone_size + (bin_info->nregs
2133122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans	    * bin_info->reg_interval) + pad_size == bin_info->run_size);
213449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans
213549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	return (good_run_size);
213649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans}
213749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans
2138b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evansstatic void
213949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evansbin_info_init(void)
214049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans{
214149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans	arena_bin_info_t *bin_info;
2142ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	size_t prev_run_size = PAGE;
2143b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans
2144b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define	SIZE_CLASS(bin, delta, size)					\
2145b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans	bin_info = &arena_bin_info[bin];				\
2146b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans	bin_info->reg_size = size;					\
2147b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans	prev_run_size = bin_info_run_size_calc(bin_info, prev_run_size);\
2148b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans	bitmap_info_init(&bin_info->bitmap_info, bin_info->nregs);
2149b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans	SIZE_CLASSES
2150b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef SIZE_CLASS
215149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans}
215249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans
2153b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evansvoid
2154a0bf242230be117a3e54a7d1fc3f11e5a83606ecJason Evansarena_boot(void)
2155e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
2156a0bf242230be117a3e54a7d1fc3f11e5a83606ecJason Evans	size_t header_size;
21577393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	unsigned i;
2158e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
2159e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	/*
2160e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 * Compute the header size such that it is large enough to contain the
21617393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	 * page map.  The page map is biased to omit entries for the header
21627393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	 * itself, so some iteration is necessary to compute the map bias.
21637393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	 *
21647393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	 * 1) Compute safe header_size and map_bias values that include enough
21657393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	 *    space for an unbiased page map.
21667393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	 * 2) Refine map_bias based on (1) to omit the header pages in the page
21677393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	 *    map.  The resulting map_bias may be one too small.
21687393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	 * 3) Refine map_bias based on (2).  The result will be >= the result
21697393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	 *    from (2), and will always be correct.
2170e476f8a161d445211fd6e54fe370275196e66bcbJason Evans	 */
21717393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	map_bias = 0;
21727393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	for (i = 0; i < 3; i++) {
2173ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		header_size = offsetof(arena_chunk_t, map) +
2174ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    (sizeof(arena_chunk_map_t) * (chunk_npages-map_bias));
2175ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		map_bias = (header_size >> LG_PAGE) + ((header_size & PAGE_MASK)
2176ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans		    != 0);
21777393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	}
21787393f44ff025ca67716fc53b68003fd65122fd97Jason Evans	assert(map_bias > 0);
21797393f44ff025ca67716fc53b68003fd65122fd97Jason Evans
2180ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans	arena_maxclass = chunksize - (map_bias << LG_PAGE);
2181a0bf242230be117a3e54a7d1fc3f11e5a83606ecJason Evans
2182b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans	bin_info_init();
2183e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
21844e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans
21854e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evansvoid
21864e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evansarena_prefork(arena_t *arena)
21874e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans{
21884e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans	unsigned i;
21894e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans
21904e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans	malloc_mutex_prefork(&arena->lock);
21914e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans	for (i = 0; i < NBINS; i++)
21924e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans		malloc_mutex_prefork(&arena->bins[i].lock);
21934e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans}
21944e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans
21954e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evansvoid
21964e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evansarena_postfork_parent(arena_t *arena)
21974e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans{
21984e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans	unsigned i;
21994e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans
22004e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans	for (i = 0; i < NBINS; i++)
22014e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans		malloc_mutex_postfork_parent(&arena->bins[i].lock);
22024e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans	malloc_mutex_postfork_parent(&arena->lock);
22034e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans}
22044e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans
22054e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evansvoid
22064e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evansarena_postfork_child(arena_t *arena)
22074e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans{
22084e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans	unsigned i;
22094e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans
22104e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans	for (i = 0; i < NBINS; i++)
22114e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans		malloc_mutex_postfork_child(&arena->bins[i].lock);
22124e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans	malloc_mutex_postfork_child(&arena->lock);
22134e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans}
2214