xref: /redis-3.2.3/deps/jemalloc/src/chunk.c (revision c9d0c362)
1 #define	JEMALLOC_CHUNK_C_
2 #include "jemalloc/internal/jemalloc_internal.h"
3 
4 /******************************************************************************/
5 /* Data. */
6 
7 size_t	opt_lg_chunk = LG_CHUNK_DEFAULT;
8 #ifdef JEMALLOC_SWAP
9 bool	opt_overcommit = true;
10 #endif
11 
12 #if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
13 malloc_mutex_t	chunks_mtx;
14 chunk_stats_t	stats_chunks;
15 #endif
16 
17 #ifdef JEMALLOC_IVSALLOC
18 rtree_t		*chunks_rtree;
19 #endif
20 
21 /* Various chunk-related settings. */
22 size_t		chunksize;
23 size_t		chunksize_mask; /* (chunksize - 1). */
24 size_t		chunk_npages;
25 size_t		map_bias;
26 size_t		arena_maxclass; /* Max size class for arenas. */
27 
28 /******************************************************************************/
29 
30 /*
31  * If the caller specifies (*zero == false), it is still possible to receive
32  * zeroed memory, in which case *zero is toggled to true.  arena_chunk_alloc()
33  * takes advantage of this to avoid demanding zeroed chunks, but taking
34  * advantage of them if they are returned.
35  */
36 void *
37 chunk_alloc(size_t size, bool base, bool *zero)
38 {
39 	void *ret;
40 
41 	assert(size != 0);
42 	assert((size & chunksize_mask) == 0);
43 
44 #ifdef JEMALLOC_SWAP
45 	if (swap_enabled) {
46 		ret = chunk_alloc_swap(size, zero);
47 		if (ret != NULL)
48 			goto RETURN;
49 	}
50 
51 	if (swap_enabled == false || opt_overcommit) {
52 #endif
53 #ifdef JEMALLOC_DSS
54 		ret = chunk_alloc_dss(size, zero);
55 		if (ret != NULL)
56 			goto RETURN;
57 #endif
58 		ret = chunk_alloc_mmap(size);
59 		if (ret != NULL) {
60 			*zero = true;
61 			goto RETURN;
62 		}
63 #ifdef JEMALLOC_SWAP
64 	}
65 #endif
66 
67 	/* All strategies for allocation failed. */
68 	ret = NULL;
69 RETURN:
70 #ifdef JEMALLOC_IVSALLOC
71 	if (base == false && ret != NULL) {
72 		if (rtree_set(chunks_rtree, (uintptr_t)ret, ret)) {
73 			chunk_dealloc(ret, size);
74 			return (NULL);
75 		}
76 	}
77 #endif
78 #if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
79 	if (ret != NULL) {
80 #  ifdef JEMALLOC_PROF
81 		bool gdump;
82 #  endif
83 		malloc_mutex_lock(&chunks_mtx);
84 #  ifdef JEMALLOC_STATS
85 		stats_chunks.nchunks += (size / chunksize);
86 #  endif
87 		stats_chunks.curchunks += (size / chunksize);
88 		if (stats_chunks.curchunks > stats_chunks.highchunks) {
89 			stats_chunks.highchunks = stats_chunks.curchunks;
90 #  ifdef JEMALLOC_PROF
91 			gdump = true;
92 #  endif
93 		}
94 #  ifdef JEMALLOC_PROF
95 		else
96 			gdump = false;
97 #  endif
98 		malloc_mutex_unlock(&chunks_mtx);
99 #  ifdef JEMALLOC_PROF
100 		if (opt_prof && opt_prof_gdump && gdump)
101 			prof_gdump();
102 #  endif
103 	}
104 #endif
105 
106 	assert(CHUNK_ADDR2BASE(ret) == ret);
107 	return (ret);
108 }
109 
110 void
111 chunk_dealloc(void *chunk, size_t size)
112 {
113 
114 	assert(chunk != NULL);
115 	assert(CHUNK_ADDR2BASE(chunk) == chunk);
116 	assert(size != 0);
117 	assert((size & chunksize_mask) == 0);
118 
119 #ifdef JEMALLOC_IVSALLOC
120 	rtree_set(chunks_rtree, (uintptr_t)chunk, NULL);
121 #endif
122 #if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
123 	malloc_mutex_lock(&chunks_mtx);
124 	stats_chunks.curchunks -= (size / chunksize);
125 	malloc_mutex_unlock(&chunks_mtx);
126 #endif
127 
128 #ifdef JEMALLOC_SWAP
129 	if (swap_enabled && chunk_dealloc_swap(chunk, size) == false)
130 		return;
131 #endif
132 #ifdef JEMALLOC_DSS
133 	if (chunk_dealloc_dss(chunk, size) == false)
134 		return;
135 #endif
136 	chunk_dealloc_mmap(chunk, size);
137 }
138 
139 bool
140 chunk_boot(void)
141 {
142 
143 	/* Set variables according to the value of opt_lg_chunk. */
144 	chunksize = (ZU(1) << opt_lg_chunk);
145 	assert(chunksize >= PAGE_SIZE);
146 	chunksize_mask = chunksize - 1;
147 	chunk_npages = (chunksize >> PAGE_SHIFT);
148 
149 #if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
150 	if (malloc_mutex_init(&chunks_mtx))
151 		return (true);
152 	memset(&stats_chunks, 0, sizeof(chunk_stats_t));
153 #endif
154 #ifdef JEMALLOC_SWAP
155 	if (chunk_swap_boot())
156 		return (true);
157 #endif
158 	if (chunk_mmap_boot())
159 		return (true);
160 #ifdef JEMALLOC_DSS
161 	if (chunk_dss_boot())
162 		return (true);
163 #endif
164 #ifdef JEMALLOC_IVSALLOC
165 	chunks_rtree = rtree_new((ZU(1) << (LG_SIZEOF_PTR+3)) - opt_lg_chunk);
166 	if (chunks_rtree == NULL)
167 		return (true);
168 #endif
169 
170 	return (false);
171 }
172