Better installation info inside README file.
[redis.git] / deps / jemalloc / src / chunk.c
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 }