summaryrefslogtreecommitdiff
path: root/examples/redis-unstable/deps/jemalloc/test/unit/arena_reset.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/redis-unstable/deps/jemalloc/test/unit/arena_reset.c')
-rw-r--r--examples/redis-unstable/deps/jemalloc/test/unit/arena_reset.c361
1 files changed, 361 insertions, 0 deletions
diff --git a/examples/redis-unstable/deps/jemalloc/test/unit/arena_reset.c b/examples/redis-unstable/deps/jemalloc/test/unit/arena_reset.c
new file mode 100644
index 0000000..8ef0786
--- /dev/null
+++ b/examples/redis-unstable/deps/jemalloc/test/unit/arena_reset.c
@@ -0,0 +1,361 @@
1#ifndef ARENA_RESET_PROF_C_
2#include "test/jemalloc_test.h"
3#endif
4
5#include "jemalloc/internal/extent_mmap.h"
6#include "jemalloc/internal/rtree.h"
7
8#include "test/extent_hooks.h"
9
10static unsigned
11get_nsizes_impl(const char *cmd) {
12 unsigned ret;
13 size_t z;
14
15 z = sizeof(unsigned);
16 expect_d_eq(mallctl(cmd, (void *)&ret, &z, NULL, 0), 0,
17 "Unexpected mallctl(\"%s\", ...) failure", cmd);
18
19 return ret;
20}
21
22static unsigned
23get_nsmall(void) {
24 return get_nsizes_impl("arenas.nbins");
25}
26
27static unsigned
28get_nlarge(void) {
29 return get_nsizes_impl("arenas.nlextents");
30}
31
32static size_t
33get_size_impl(const char *cmd, size_t ind) {
34 size_t ret;
35 size_t z;
36 size_t mib[4];
37 size_t miblen = 4;
38
39 z = sizeof(size_t);
40 expect_d_eq(mallctlnametomib(cmd, mib, &miblen),
41 0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
42 mib[2] = ind;
43 z = sizeof(size_t);
44 expect_d_eq(mallctlbymib(mib, miblen, (void *)&ret, &z, NULL, 0),
45 0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
46
47 return ret;
48}
49
50static size_t
51get_small_size(size_t ind) {
52 return get_size_impl("arenas.bin.0.size", ind);
53}
54
55static size_t
56get_large_size(size_t ind) {
57 return get_size_impl("arenas.lextent.0.size", ind);
58}
59
60/* Like ivsalloc(), but safe to call on discarded allocations. */
61static size_t
62vsalloc(tsdn_t *tsdn, const void *ptr) {
63 emap_full_alloc_ctx_t full_alloc_ctx;
64 bool missing = emap_full_alloc_ctx_try_lookup(tsdn, &arena_emap_global,
65 ptr, &full_alloc_ctx);
66 if (missing) {
67 return 0;
68 }
69
70 if (full_alloc_ctx.edata == NULL) {
71 return 0;
72 }
73 if (edata_state_get(full_alloc_ctx.edata) != extent_state_active) {
74 return 0;
75 }
76
77 if (full_alloc_ctx.szind == SC_NSIZES) {
78 return 0;
79 }
80
81 return sz_index2size(full_alloc_ctx.szind);
82}
83
84static unsigned
85do_arena_create(extent_hooks_t *h) {
86 unsigned arena_ind;
87 size_t sz = sizeof(unsigned);
88 expect_d_eq(mallctl("arenas.create", (void *)&arena_ind, &sz,
89 (void *)(h != NULL ? &h : NULL), (h != NULL ? sizeof(h) : 0)), 0,
90 "Unexpected mallctl() failure");
91 return arena_ind;
92}
93
94static void
95do_arena_reset_pre(unsigned arena_ind, void ***ptrs, unsigned *nptrs) {
96#define NLARGE 32
97 unsigned nsmall, nlarge, i;
98 size_t sz;
99 int flags;
100 tsdn_t *tsdn;
101
102 flags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE;
103
104 nsmall = get_nsmall();
105 nlarge = get_nlarge() > NLARGE ? NLARGE : get_nlarge();
106 *nptrs = nsmall + nlarge;
107 *ptrs = (void **)malloc(*nptrs * sizeof(void *));
108 expect_ptr_not_null(*ptrs, "Unexpected malloc() failure");
109
110 /* Allocate objects with a wide range of sizes. */
111 for (i = 0; i < nsmall; i++) {
112 sz = get_small_size(i);
113 (*ptrs)[i] = mallocx(sz, flags);
114 expect_ptr_not_null((*ptrs)[i],
115 "Unexpected mallocx(%zu, %#x) failure", sz, flags);
116 }
117 for (i = 0; i < nlarge; i++) {
118 sz = get_large_size(i);
119 (*ptrs)[nsmall + i] = mallocx(sz, flags);
120 expect_ptr_not_null((*ptrs)[i],
121 "Unexpected mallocx(%zu, %#x) failure", sz, flags);
122 }
123
124 tsdn = tsdn_fetch();
125
126 /* Verify allocations. */
127 for (i = 0; i < *nptrs; i++) {
128 expect_zu_gt(ivsalloc(tsdn, (*ptrs)[i]), 0,
129 "Allocation should have queryable size");
130 }
131}
132
133static void
134do_arena_reset_post(void **ptrs, unsigned nptrs, unsigned arena_ind) {
135 tsdn_t *tsdn;
136 unsigned i;
137
138 tsdn = tsdn_fetch();
139
140 if (have_background_thread) {
141 malloc_mutex_lock(tsdn,
142 &background_thread_info_get(arena_ind)->mtx);
143 }
144 /* Verify allocations no longer exist. */
145 for (i = 0; i < nptrs; i++) {
146 expect_zu_eq(vsalloc(tsdn, ptrs[i]), 0,
147 "Allocation should no longer exist");
148 }
149 if (have_background_thread) {
150 malloc_mutex_unlock(tsdn,
151 &background_thread_info_get(arena_ind)->mtx);
152 }
153
154 free(ptrs);
155}
156
157static void
158do_arena_reset_destroy(const char *name, unsigned arena_ind) {
159 size_t mib[3];
160 size_t miblen;
161
162 miblen = sizeof(mib)/sizeof(size_t);
163 expect_d_eq(mallctlnametomib(name, mib, &miblen), 0,
164 "Unexpected mallctlnametomib() failure");
165 mib[1] = (size_t)arena_ind;
166 expect_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,
167 "Unexpected mallctlbymib() failure");
168}
169
170static void
171do_arena_reset(unsigned arena_ind) {
172 do_arena_reset_destroy("arena.0.reset", arena_ind);
173}
174
175static void
176do_arena_destroy(unsigned arena_ind) {
177 do_arena_reset_destroy("arena.0.destroy", arena_ind);
178}
179
180TEST_BEGIN(test_arena_reset) {
181 unsigned arena_ind;
182 void **ptrs;
183 unsigned nptrs;
184
185 arena_ind = do_arena_create(NULL);
186 do_arena_reset_pre(arena_ind, &ptrs, &nptrs);
187 do_arena_reset(arena_ind);
188 do_arena_reset_post(ptrs, nptrs, arena_ind);
189}
190TEST_END
191
192static bool
193arena_i_initialized(unsigned arena_ind, bool refresh) {
194 bool initialized;
195 size_t mib[3];
196 size_t miblen, sz;
197
198 if (refresh) {
199 uint64_t epoch = 1;
200 expect_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch,
201 sizeof(epoch)), 0, "Unexpected mallctl() failure");
202 }
203
204 miblen = sizeof(mib)/sizeof(size_t);
205 expect_d_eq(mallctlnametomib("arena.0.initialized", mib, &miblen), 0,
206 "Unexpected mallctlnametomib() failure");
207 mib[1] = (size_t)arena_ind;
208 sz = sizeof(initialized);
209 expect_d_eq(mallctlbymib(mib, miblen, (void *)&initialized, &sz, NULL,
210 0), 0, "Unexpected mallctlbymib() failure");
211
212 return initialized;
213}
214
215TEST_BEGIN(test_arena_destroy_initial) {
216 expect_false(arena_i_initialized(MALLCTL_ARENAS_DESTROYED, false),
217 "Destroyed arena stats should not be initialized");
218}
219TEST_END
220
221TEST_BEGIN(test_arena_destroy_hooks_default) {
222 unsigned arena_ind, arena_ind_another, arena_ind_prev;
223 void **ptrs;
224 unsigned nptrs;
225
226 arena_ind = do_arena_create(NULL);
227 do_arena_reset_pre(arena_ind, &ptrs, &nptrs);
228
229 expect_false(arena_i_initialized(arena_ind, false),
230 "Arena stats should not be initialized");
231 expect_true(arena_i_initialized(arena_ind, true),
232 "Arena stats should be initialized");
233
234 /*
235 * Create another arena before destroying one, to better verify arena
236 * index reuse.
237 */
238 arena_ind_another = do_arena_create(NULL);
239
240 do_arena_destroy(arena_ind);
241
242 expect_false(arena_i_initialized(arena_ind, true),
243 "Arena stats should not be initialized");
244 expect_true(arena_i_initialized(MALLCTL_ARENAS_DESTROYED, false),
245 "Destroyed arena stats should be initialized");
246
247 do_arena_reset_post(ptrs, nptrs, arena_ind);
248
249 arena_ind_prev = arena_ind;
250 arena_ind = do_arena_create(NULL);
251 do_arena_reset_pre(arena_ind, &ptrs, &nptrs);
252 expect_u_eq(arena_ind, arena_ind_prev,
253 "Arena index should have been recycled");
254 do_arena_destroy(arena_ind);
255 do_arena_reset_post(ptrs, nptrs, arena_ind);
256
257 do_arena_destroy(arena_ind_another);
258
259 /* Try arena.create with custom hooks. */
260 size_t sz = sizeof(extent_hooks_t *);
261 extent_hooks_t *a0_default_hooks;
262 expect_d_eq(mallctl("arena.0.extent_hooks", (void *)&a0_default_hooks,
263 &sz, NULL, 0), 0, "Unexpected mallctlnametomib() failure");
264
265 /* Default impl; but wrapped as "customized". */
266 extent_hooks_t new_hooks = *a0_default_hooks;
267 extent_hooks_t *hook = &new_hooks;
268 sz = sizeof(unsigned);
269 expect_d_eq(mallctl("arenas.create", (void *)&arena_ind, &sz,
270 (void *)&hook, sizeof(void *)), 0,
271 "Unexpected mallctl() failure");
272 do_arena_destroy(arena_ind);
273}
274TEST_END
275
276/*
277 * Actually unmap extents, regardless of opt_retain, so that attempts to access
278 * a destroyed arena's memory will segfault.
279 */
280static bool
281extent_dalloc_unmap(extent_hooks_t *extent_hooks, void *addr, size_t size,
282 bool committed, unsigned arena_ind) {
283 TRACE_HOOK("%s(extent_hooks=%p, addr=%p, size=%zu, committed=%s, "
284 "arena_ind=%u)\n", __func__, extent_hooks, addr, size, committed ?
285 "true" : "false", arena_ind);
286 expect_ptr_eq(extent_hooks, &hooks,
287 "extent_hooks should be same as pointer used to set hooks");
288 expect_ptr_eq(extent_hooks->dalloc, extent_dalloc_unmap,
289 "Wrong hook function");
290 called_dalloc = true;
291 if (!try_dalloc) {
292 return true;
293 }
294 did_dalloc = true;
295 if (!maps_coalesce && opt_retain) {
296 return true;
297 }
298 pages_unmap(addr, size);
299 return false;
300}
301
302static extent_hooks_t hooks_orig;
303
304static extent_hooks_t hooks_unmap = {
305 extent_alloc_hook,
306 extent_dalloc_unmap, /* dalloc */
307 extent_destroy_hook,
308 extent_commit_hook,
309 extent_decommit_hook,
310 extent_purge_lazy_hook,
311 extent_purge_forced_hook,
312 extent_split_hook,
313 extent_merge_hook
314};
315
316TEST_BEGIN(test_arena_destroy_hooks_unmap) {
317 unsigned arena_ind;
318 void **ptrs;
319 unsigned nptrs;
320
321 extent_hooks_prep();
322 if (maps_coalesce) {
323 try_decommit = false;
324 }
325 memcpy(&hooks_orig, &hooks, sizeof(extent_hooks_t));
326 memcpy(&hooks, &hooks_unmap, sizeof(extent_hooks_t));
327
328 did_alloc = false;
329 arena_ind = do_arena_create(&hooks);
330 do_arena_reset_pre(arena_ind, &ptrs, &nptrs);
331
332 expect_true(did_alloc, "Expected alloc");
333
334 expect_false(arena_i_initialized(arena_ind, false),
335 "Arena stats should not be initialized");
336 expect_true(arena_i_initialized(arena_ind, true),
337 "Arena stats should be initialized");
338
339 did_dalloc = false;
340 do_arena_destroy(arena_ind);
341 expect_true(did_dalloc, "Expected dalloc");
342
343 expect_false(arena_i_initialized(arena_ind, true),
344 "Arena stats should not be initialized");
345 expect_true(arena_i_initialized(MALLCTL_ARENAS_DESTROYED, false),
346 "Destroyed arena stats should be initialized");
347
348 do_arena_reset_post(ptrs, nptrs, arena_ind);
349
350 memcpy(&hooks, &hooks_orig, sizeof(extent_hooks_t));
351}
352TEST_END
353
354int
355main(void) {
356 return test(
357 test_arena_reset,
358 test_arena_destroy_initial,
359 test_arena_destroy_hooks_default,
360 test_arena_destroy_hooks_unmap);
361}