]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | #include "test/jemalloc_test.h" |
2 | ||
3 | TEST_BEGIN(test_mallctl_errors) | |
4 | { | |
5 | uint64_t epoch; | |
6 | size_t sz; | |
7 | ||
8 | assert_d_eq(mallctl("no_such_name", NULL, NULL, NULL, 0), ENOENT, | |
9 | "mallctl() should return ENOENT for non-existent names"); | |
10 | ||
11 | assert_d_eq(mallctl("version", NULL, NULL, "0.0.0", strlen("0.0.0")), | |
12 | EPERM, "mallctl() should return EPERM on attempt to write " | |
13 | "read-only value"); | |
14 | ||
15 | assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)-1), | |
16 | EINVAL, "mallctl() should return EINVAL for input size mismatch"); | |
17 | assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)+1), | |
18 | EINVAL, "mallctl() should return EINVAL for input size mismatch"); | |
19 | ||
20 | sz = sizeof(epoch)-1; | |
21 | assert_d_eq(mallctl("epoch", &epoch, &sz, NULL, 0), EINVAL, | |
22 | "mallctl() should return EINVAL for output size mismatch"); | |
23 | sz = sizeof(epoch)+1; | |
24 | assert_d_eq(mallctl("epoch", &epoch, &sz, NULL, 0), EINVAL, | |
25 | "mallctl() should return EINVAL for output size mismatch"); | |
26 | } | |
27 | TEST_END | |
28 | ||
29 | TEST_BEGIN(test_mallctlnametomib_errors) | |
30 | { | |
31 | size_t mib[1]; | |
32 | size_t miblen; | |
33 | ||
34 | miblen = sizeof(mib)/sizeof(size_t); | |
35 | assert_d_eq(mallctlnametomib("no_such_name", mib, &miblen), ENOENT, | |
36 | "mallctlnametomib() should return ENOENT for non-existent names"); | |
37 | } | |
38 | TEST_END | |
39 | ||
40 | TEST_BEGIN(test_mallctlbymib_errors) | |
41 | { | |
42 | uint64_t epoch; | |
43 | size_t sz; | |
44 | size_t mib[1]; | |
45 | size_t miblen; | |
46 | ||
47 | miblen = sizeof(mib)/sizeof(size_t); | |
48 | assert_d_eq(mallctlnametomib("version", mib, &miblen), 0, | |
49 | "Unexpected mallctlnametomib() failure"); | |
50 | ||
51 | assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, "0.0.0", | |
52 | strlen("0.0.0")), EPERM, "mallctl() should return EPERM on " | |
53 | "attempt to write read-only value"); | |
54 | ||
55 | miblen = sizeof(mib)/sizeof(size_t); | |
56 | assert_d_eq(mallctlnametomib("epoch", mib, &miblen), 0, | |
57 | "Unexpected mallctlnametomib() failure"); | |
58 | ||
59 | assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch, | |
60 | sizeof(epoch)-1), EINVAL, | |
61 | "mallctlbymib() should return EINVAL for input size mismatch"); | |
62 | assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch, | |
63 | sizeof(epoch)+1), EINVAL, | |
64 | "mallctlbymib() should return EINVAL for input size mismatch"); | |
65 | ||
66 | sz = sizeof(epoch)-1; | |
67 | assert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL, | |
68 | "mallctlbymib() should return EINVAL for output size mismatch"); | |
69 | sz = sizeof(epoch)+1; | |
70 | assert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL, | |
71 | "mallctlbymib() should return EINVAL for output size mismatch"); | |
72 | } | |
73 | TEST_END | |
74 | ||
75 | TEST_BEGIN(test_mallctl_read_write) | |
76 | { | |
77 | uint64_t old_epoch, new_epoch; | |
78 | size_t sz = sizeof(old_epoch); | |
79 | ||
80 | /* Blind. */ | |
81 | assert_d_eq(mallctl("epoch", NULL, NULL, NULL, 0), 0, | |
82 | "Unexpected mallctl() failure"); | |
83 | assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); | |
84 | ||
85 | /* Read. */ | |
86 | assert_d_eq(mallctl("epoch", &old_epoch, &sz, NULL, 0), 0, | |
87 | "Unexpected mallctl() failure"); | |
88 | assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); | |
89 | ||
90 | /* Write. */ | |
91 | assert_d_eq(mallctl("epoch", NULL, NULL, &new_epoch, sizeof(new_epoch)), | |
92 | 0, "Unexpected mallctl() failure"); | |
93 | assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); | |
94 | ||
95 | /* Read+write. */ | |
96 | assert_d_eq(mallctl("epoch", &old_epoch, &sz, &new_epoch, | |
97 | sizeof(new_epoch)), 0, "Unexpected mallctl() failure"); | |
98 | assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); | |
99 | } | |
100 | TEST_END | |
101 | ||
102 | TEST_BEGIN(test_mallctlnametomib_short_mib) | |
103 | { | |
104 | size_t mib[4]; | |
105 | size_t miblen; | |
106 | ||
107 | miblen = 3; | |
108 | mib[3] = 42; | |
109 | assert_d_eq(mallctlnametomib("arenas.bin.0.nregs", mib, &miblen), 0, | |
110 | "Unexpected mallctlnametomib() failure"); | |
111 | assert_zu_eq(miblen, 3, "Unexpected mib output length"); | |
112 | assert_zu_eq(mib[3], 42, | |
113 | "mallctlnametomib() wrote past the end of the input mib"); | |
114 | } | |
115 | TEST_END | |
116 | ||
117 | TEST_BEGIN(test_mallctl_config) | |
118 | { | |
119 | ||
54a0048b SL |
120 | #define TEST_MALLCTL_CONFIG(config, t) do { \ |
121 | t oldval; \ | |
1a4d82fc JJ |
122 | size_t sz = sizeof(oldval); \ |
123 | assert_d_eq(mallctl("config."#config, &oldval, &sz, NULL, 0), \ | |
124 | 0, "Unexpected mallctl() failure"); \ | |
125 | assert_b_eq(oldval, config_##config, "Incorrect config value"); \ | |
126 | assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \ | |
127 | } while (0) | |
128 | ||
54a0048b SL |
129 | TEST_MALLCTL_CONFIG(cache_oblivious, bool); |
130 | TEST_MALLCTL_CONFIG(debug, bool); | |
131 | TEST_MALLCTL_CONFIG(fill, bool); | |
132 | TEST_MALLCTL_CONFIG(lazy_lock, bool); | |
133 | TEST_MALLCTL_CONFIG(malloc_conf, const char *); | |
134 | TEST_MALLCTL_CONFIG(munmap, bool); | |
135 | TEST_MALLCTL_CONFIG(prof, bool); | |
136 | TEST_MALLCTL_CONFIG(prof_libgcc, bool); | |
137 | TEST_MALLCTL_CONFIG(prof_libunwind, bool); | |
138 | TEST_MALLCTL_CONFIG(stats, bool); | |
139 | TEST_MALLCTL_CONFIG(tcache, bool); | |
140 | TEST_MALLCTL_CONFIG(tls, bool); | |
141 | TEST_MALLCTL_CONFIG(utrace, bool); | |
142 | TEST_MALLCTL_CONFIG(valgrind, bool); | |
143 | TEST_MALLCTL_CONFIG(xmalloc, bool); | |
1a4d82fc JJ |
144 | |
145 | #undef TEST_MALLCTL_CONFIG | |
146 | } | |
147 | TEST_END | |
148 | ||
149 | TEST_BEGIN(test_mallctl_opt) | |
150 | { | |
151 | bool config_always = true; | |
152 | ||
153 | #define TEST_MALLCTL_OPT(t, opt, config) do { \ | |
154 | t oldval; \ | |
155 | size_t sz = sizeof(oldval); \ | |
156 | int expected = config_##config ? 0 : ENOENT; \ | |
157 | int result = mallctl("opt."#opt, &oldval, &sz, NULL, 0); \ | |
158 | assert_d_eq(result, expected, \ | |
159 | "Unexpected mallctl() result for opt."#opt); \ | |
160 | assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \ | |
161 | } while (0) | |
162 | ||
163 | TEST_MALLCTL_OPT(bool, abort, always); | |
164 | TEST_MALLCTL_OPT(size_t, lg_chunk, always); | |
165 | TEST_MALLCTL_OPT(const char *, dss, always); | |
54a0048b SL |
166 | TEST_MALLCTL_OPT(unsigned, narenas, always); |
167 | TEST_MALLCTL_OPT(const char *, purge, always); | |
1a4d82fc | 168 | TEST_MALLCTL_OPT(ssize_t, lg_dirty_mult, always); |
54a0048b | 169 | TEST_MALLCTL_OPT(ssize_t, decay_time, always); |
1a4d82fc | 170 | TEST_MALLCTL_OPT(bool, stats_print, always); |
54a0048b | 171 | TEST_MALLCTL_OPT(const char *, junk, fill); |
1a4d82fc JJ |
172 | TEST_MALLCTL_OPT(size_t, quarantine, fill); |
173 | TEST_MALLCTL_OPT(bool, redzone, fill); | |
174 | TEST_MALLCTL_OPT(bool, zero, fill); | |
175 | TEST_MALLCTL_OPT(bool, utrace, utrace); | |
176 | TEST_MALLCTL_OPT(bool, xmalloc, xmalloc); | |
177 | TEST_MALLCTL_OPT(bool, tcache, tcache); | |
178 | TEST_MALLCTL_OPT(size_t, lg_tcache_max, tcache); | |
179 | TEST_MALLCTL_OPT(bool, prof, prof); | |
180 | TEST_MALLCTL_OPT(const char *, prof_prefix, prof); | |
181 | TEST_MALLCTL_OPT(bool, prof_active, prof); | |
182 | TEST_MALLCTL_OPT(ssize_t, lg_prof_sample, prof); | |
183 | TEST_MALLCTL_OPT(bool, prof_accum, prof); | |
184 | TEST_MALLCTL_OPT(ssize_t, lg_prof_interval, prof); | |
185 | TEST_MALLCTL_OPT(bool, prof_gdump, prof); | |
186 | TEST_MALLCTL_OPT(bool, prof_final, prof); | |
187 | TEST_MALLCTL_OPT(bool, prof_leak, prof); | |
188 | ||
189 | #undef TEST_MALLCTL_OPT | |
190 | } | |
191 | TEST_END | |
192 | ||
193 | TEST_BEGIN(test_manpage_example) | |
194 | { | |
195 | unsigned nbins, i; | |
196 | size_t mib[4]; | |
197 | size_t len, miblen; | |
198 | ||
199 | len = sizeof(nbins); | |
200 | assert_d_eq(mallctl("arenas.nbins", &nbins, &len, NULL, 0), 0, | |
201 | "Unexpected mallctl() failure"); | |
202 | ||
203 | miblen = 4; | |
204 | assert_d_eq(mallctlnametomib("arenas.bin.0.size", mib, &miblen), 0, | |
205 | "Unexpected mallctlnametomib() failure"); | |
206 | for (i = 0; i < nbins; i++) { | |
207 | size_t bin_size; | |
208 | ||
209 | mib[2] = i; | |
210 | len = sizeof(bin_size); | |
211 | assert_d_eq(mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0), | |
212 | 0, "Unexpected mallctlbymib() failure"); | |
213 | /* Do something with bin_size... */ | |
214 | } | |
215 | } | |
216 | TEST_END | |
217 | ||
54a0048b SL |
218 | TEST_BEGIN(test_tcache_none) |
219 | { | |
220 | void *p0, *q, *p1; | |
221 | ||
222 | test_skip_if(!config_tcache); | |
223 | ||
224 | /* Allocate p and q. */ | |
225 | p0 = mallocx(42, 0); | |
226 | assert_ptr_not_null(p0, "Unexpected mallocx() failure"); | |
227 | q = mallocx(42, 0); | |
228 | assert_ptr_not_null(q, "Unexpected mallocx() failure"); | |
229 | ||
230 | /* Deallocate p and q, but bypass the tcache for q. */ | |
231 | dallocx(p0, 0); | |
232 | dallocx(q, MALLOCX_TCACHE_NONE); | |
233 | ||
234 | /* Make sure that tcache-based allocation returns p, not q. */ | |
235 | p1 = mallocx(42, 0); | |
236 | assert_ptr_not_null(p1, "Unexpected mallocx() failure"); | |
237 | assert_ptr_eq(p0, p1, "Expected tcache to allocate cached region"); | |
238 | ||
239 | /* Clean up. */ | |
240 | dallocx(p1, MALLOCX_TCACHE_NONE); | |
241 | } | |
242 | TEST_END | |
243 | ||
244 | TEST_BEGIN(test_tcache) | |
245 | { | |
246 | #define NTCACHES 10 | |
247 | unsigned tis[NTCACHES]; | |
248 | void *ps[NTCACHES]; | |
249 | void *qs[NTCACHES]; | |
250 | unsigned i; | |
251 | size_t sz, psz, qsz; | |
252 | ||
253 | test_skip_if(!config_tcache); | |
254 | ||
255 | psz = 42; | |
256 | qsz = nallocx(psz, 0) + 1; | |
257 | ||
258 | /* Create tcaches. */ | |
259 | for (i = 0; i < NTCACHES; i++) { | |
260 | sz = sizeof(unsigned); | |
261 | assert_d_eq(mallctl("tcache.create", &tis[i], &sz, NULL, 0), 0, | |
262 | "Unexpected mallctl() failure, i=%u", i); | |
263 | } | |
264 | ||
265 | /* Exercise tcache ID recycling. */ | |
266 | for (i = 0; i < NTCACHES; i++) { | |
267 | assert_d_eq(mallctl("tcache.destroy", NULL, NULL, &tis[i], | |
268 | sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u", | |
269 | i); | |
270 | } | |
271 | for (i = 0; i < NTCACHES; i++) { | |
272 | sz = sizeof(unsigned); | |
273 | assert_d_eq(mallctl("tcache.create", &tis[i], &sz, NULL, 0), 0, | |
274 | "Unexpected mallctl() failure, i=%u", i); | |
275 | } | |
276 | ||
277 | /* Flush empty tcaches. */ | |
278 | for (i = 0; i < NTCACHES; i++) { | |
279 | assert_d_eq(mallctl("tcache.flush", NULL, NULL, &tis[i], | |
280 | sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u", | |
281 | i); | |
282 | } | |
283 | ||
284 | /* Cache some allocations. */ | |
285 | for (i = 0; i < NTCACHES; i++) { | |
286 | ps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i])); | |
287 | assert_ptr_not_null(ps[i], "Unexpected mallocx() failure, i=%u", | |
288 | i); | |
289 | dallocx(ps[i], MALLOCX_TCACHE(tis[i])); | |
290 | ||
291 | qs[i] = mallocx(qsz, MALLOCX_TCACHE(tis[i])); | |
292 | assert_ptr_not_null(qs[i], "Unexpected mallocx() failure, i=%u", | |
293 | i); | |
294 | dallocx(qs[i], MALLOCX_TCACHE(tis[i])); | |
295 | } | |
296 | ||
297 | /* Verify that tcaches allocate cached regions. */ | |
298 | for (i = 0; i < NTCACHES; i++) { | |
299 | void *p0 = ps[i]; | |
300 | ps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i])); | |
301 | assert_ptr_not_null(ps[i], "Unexpected mallocx() failure, i=%u", | |
302 | i); | |
303 | assert_ptr_eq(ps[i], p0, | |
304 | "Expected mallocx() to allocate cached region, i=%u", i); | |
305 | } | |
306 | ||
307 | /* Verify that reallocation uses cached regions. */ | |
308 | for (i = 0; i < NTCACHES; i++) { | |
309 | void *q0 = qs[i]; | |
310 | qs[i] = rallocx(ps[i], qsz, MALLOCX_TCACHE(tis[i])); | |
311 | assert_ptr_not_null(qs[i], "Unexpected rallocx() failure, i=%u", | |
312 | i); | |
313 | assert_ptr_eq(qs[i], q0, | |
314 | "Expected rallocx() to allocate cached region, i=%u", i); | |
315 | /* Avoid undefined behavior in case of test failure. */ | |
316 | if (qs[i] == NULL) | |
317 | qs[i] = ps[i]; | |
318 | } | |
319 | for (i = 0; i < NTCACHES; i++) | |
320 | dallocx(qs[i], MALLOCX_TCACHE(tis[i])); | |
321 | ||
322 | /* Flush some non-empty tcaches. */ | |
323 | for (i = 0; i < NTCACHES/2; i++) { | |
324 | assert_d_eq(mallctl("tcache.flush", NULL, NULL, &tis[i], | |
325 | sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u", | |
326 | i); | |
327 | } | |
328 | ||
329 | /* Destroy tcaches. */ | |
330 | for (i = 0; i < NTCACHES; i++) { | |
331 | assert_d_eq(mallctl("tcache.destroy", NULL, NULL, &tis[i], | |
332 | sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u", | |
333 | i); | |
334 | } | |
335 | } | |
336 | TEST_END | |
337 | ||
1a4d82fc JJ |
338 | TEST_BEGIN(test_thread_arena) |
339 | { | |
340 | unsigned arena_old, arena_new, narenas; | |
341 | size_t sz = sizeof(unsigned); | |
342 | ||
343 | assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, | |
344 | "Unexpected mallctl() failure"); | |
345 | assert_u_eq(narenas, opt_narenas, "Number of arenas incorrect"); | |
346 | arena_new = narenas - 1; | |
347 | assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new, | |
348 | sizeof(unsigned)), 0, "Unexpected mallctl() failure"); | |
349 | arena_new = 0; | |
350 | assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new, | |
351 | sizeof(unsigned)), 0, "Unexpected mallctl() failure"); | |
352 | } | |
353 | TEST_END | |
354 | ||
54a0048b SL |
355 | TEST_BEGIN(test_arena_i_lg_dirty_mult) |
356 | { | |
357 | ssize_t lg_dirty_mult, orig_lg_dirty_mult, prev_lg_dirty_mult; | |
358 | size_t sz = sizeof(ssize_t); | |
359 | ||
360 | test_skip_if(opt_purge != purge_mode_ratio); | |
361 | ||
362 | assert_d_eq(mallctl("arena.0.lg_dirty_mult", &orig_lg_dirty_mult, &sz, | |
363 | NULL, 0), 0, "Unexpected mallctl() failure"); | |
364 | ||
365 | lg_dirty_mult = -2; | |
366 | assert_d_eq(mallctl("arena.0.lg_dirty_mult", NULL, NULL, | |
367 | &lg_dirty_mult, sizeof(ssize_t)), EFAULT, | |
368 | "Unexpected mallctl() success"); | |
369 | ||
370 | lg_dirty_mult = (sizeof(size_t) << 3); | |
371 | assert_d_eq(mallctl("arena.0.lg_dirty_mult", NULL, NULL, | |
372 | &lg_dirty_mult, sizeof(ssize_t)), EFAULT, | |
373 | "Unexpected mallctl() success"); | |
374 | ||
375 | for (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1; | |
376 | lg_dirty_mult < (ssize_t)(sizeof(size_t) << 3); prev_lg_dirty_mult | |
377 | = lg_dirty_mult, lg_dirty_mult++) { | |
378 | ssize_t old_lg_dirty_mult; | |
379 | ||
380 | assert_d_eq(mallctl("arena.0.lg_dirty_mult", &old_lg_dirty_mult, | |
381 | &sz, &lg_dirty_mult, sizeof(ssize_t)), 0, | |
382 | "Unexpected mallctl() failure"); | |
383 | assert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult, | |
384 | "Unexpected old arena.0.lg_dirty_mult"); | |
385 | } | |
386 | } | |
387 | TEST_END | |
388 | ||
389 | TEST_BEGIN(test_arena_i_decay_time) | |
390 | { | |
391 | ssize_t decay_time, orig_decay_time, prev_decay_time; | |
392 | size_t sz = sizeof(ssize_t); | |
393 | ||
394 | test_skip_if(opt_purge != purge_mode_decay); | |
395 | ||
396 | assert_d_eq(mallctl("arena.0.decay_time", &orig_decay_time, &sz, | |
397 | NULL, 0), 0, "Unexpected mallctl() failure"); | |
398 | ||
399 | decay_time = -2; | |
400 | assert_d_eq(mallctl("arena.0.decay_time", NULL, NULL, | |
401 | &decay_time, sizeof(ssize_t)), EFAULT, | |
402 | "Unexpected mallctl() success"); | |
403 | ||
404 | decay_time = 0x7fffffff; | |
405 | assert_d_eq(mallctl("arena.0.decay_time", NULL, NULL, | |
406 | &decay_time, sizeof(ssize_t)), 0, | |
407 | "Unexpected mallctl() failure"); | |
408 | ||
409 | for (prev_decay_time = decay_time, decay_time = -1; | |
410 | decay_time < 20; prev_decay_time = decay_time, decay_time++) { | |
411 | ssize_t old_decay_time; | |
412 | ||
413 | assert_d_eq(mallctl("arena.0.decay_time", &old_decay_time, | |
414 | &sz, &decay_time, sizeof(ssize_t)), 0, | |
415 | "Unexpected mallctl() failure"); | |
416 | assert_zd_eq(old_decay_time, prev_decay_time, | |
417 | "Unexpected old arena.0.decay_time"); | |
418 | } | |
419 | } | |
420 | TEST_END | |
421 | ||
1a4d82fc JJ |
422 | TEST_BEGIN(test_arena_i_purge) |
423 | { | |
424 | unsigned narenas; | |
425 | size_t sz = sizeof(unsigned); | |
426 | size_t mib[3]; | |
427 | size_t miblen = 3; | |
428 | ||
429 | assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0, | |
430 | "Unexpected mallctl() failure"); | |
431 | ||
432 | assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, | |
433 | "Unexpected mallctl() failure"); | |
434 | assert_d_eq(mallctlnametomib("arena.0.purge", mib, &miblen), 0, | |
435 | "Unexpected mallctlnametomib() failure"); | |
436 | mib[1] = narenas; | |
437 | assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0, | |
438 | "Unexpected mallctlbymib() failure"); | |
439 | } | |
440 | TEST_END | |
441 | ||
54a0048b SL |
442 | TEST_BEGIN(test_arena_i_decay) |
443 | { | |
444 | unsigned narenas; | |
445 | size_t sz = sizeof(unsigned); | |
446 | size_t mib[3]; | |
447 | size_t miblen = 3; | |
448 | ||
449 | assert_d_eq(mallctl("arena.0.decay", NULL, NULL, NULL, 0), 0, | |
450 | "Unexpected mallctl() failure"); | |
451 | ||
452 | assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, | |
453 | "Unexpected mallctl() failure"); | |
454 | assert_d_eq(mallctlnametomib("arena.0.decay", mib, &miblen), 0, | |
455 | "Unexpected mallctlnametomib() failure"); | |
456 | mib[1] = narenas; | |
457 | assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0, | |
458 | "Unexpected mallctlbymib() failure"); | |
459 | } | |
460 | TEST_END | |
461 | ||
1a4d82fc JJ |
462 | TEST_BEGIN(test_arena_i_dss) |
463 | { | |
464 | const char *dss_prec_old, *dss_prec_new; | |
465 | size_t sz = sizeof(dss_prec_old); | |
466 | size_t mib[3]; | |
467 | size_t miblen; | |
468 | ||
469 | miblen = sizeof(mib)/sizeof(size_t); | |
470 | assert_d_eq(mallctlnametomib("arena.0.dss", mib, &miblen), 0, | |
471 | "Unexpected mallctlnametomib() error"); | |
472 | ||
473 | dss_prec_new = "disabled"; | |
474 | assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new, | |
475 | sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure"); | |
476 | assert_str_ne(dss_prec_old, "primary", | |
477 | "Unexpected default for dss precedence"); | |
478 | ||
479 | assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old, | |
480 | sizeof(dss_prec_old)), 0, "Unexpected mallctl() failure"); | |
481 | ||
482 | assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, NULL, 0), 0, | |
483 | "Unexpected mallctl() failure"); | |
484 | assert_str_ne(dss_prec_old, "primary", | |
485 | "Unexpected value for dss precedence"); | |
486 | ||
487 | mib[1] = narenas_total_get(); | |
488 | dss_prec_new = "disabled"; | |
489 | assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new, | |
490 | sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure"); | |
491 | assert_str_ne(dss_prec_old, "primary", | |
492 | "Unexpected default for dss precedence"); | |
493 | ||
494 | assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old, | |
495 | sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure"); | |
496 | ||
497 | assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, NULL, 0), 0, | |
498 | "Unexpected mallctl() failure"); | |
499 | assert_str_ne(dss_prec_old, "primary", | |
500 | "Unexpected value for dss precedence"); | |
501 | } | |
502 | TEST_END | |
503 | ||
504 | TEST_BEGIN(test_arenas_initialized) | |
505 | { | |
506 | unsigned narenas; | |
507 | size_t sz = sizeof(narenas); | |
508 | ||
509 | assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, | |
510 | "Unexpected mallctl() failure"); | |
511 | { | |
512 | VARIABLE_ARRAY(bool, initialized, narenas); | |
513 | ||
514 | sz = narenas * sizeof(bool); | |
515 | assert_d_eq(mallctl("arenas.initialized", initialized, &sz, | |
516 | NULL, 0), 0, "Unexpected mallctl() failure"); | |
517 | } | |
518 | } | |
519 | TEST_END | |
520 | ||
54a0048b SL |
521 | TEST_BEGIN(test_arenas_lg_dirty_mult) |
522 | { | |
523 | ssize_t lg_dirty_mult, orig_lg_dirty_mult, prev_lg_dirty_mult; | |
524 | size_t sz = sizeof(ssize_t); | |
525 | ||
526 | test_skip_if(opt_purge != purge_mode_ratio); | |
527 | ||
528 | assert_d_eq(mallctl("arenas.lg_dirty_mult", &orig_lg_dirty_mult, &sz, | |
529 | NULL, 0), 0, "Unexpected mallctl() failure"); | |
530 | ||
531 | lg_dirty_mult = -2; | |
532 | assert_d_eq(mallctl("arenas.lg_dirty_mult", NULL, NULL, | |
533 | &lg_dirty_mult, sizeof(ssize_t)), EFAULT, | |
534 | "Unexpected mallctl() success"); | |
535 | ||
536 | lg_dirty_mult = (sizeof(size_t) << 3); | |
537 | assert_d_eq(mallctl("arenas.lg_dirty_mult", NULL, NULL, | |
538 | &lg_dirty_mult, sizeof(ssize_t)), EFAULT, | |
539 | "Unexpected mallctl() success"); | |
540 | ||
541 | for (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1; | |
542 | lg_dirty_mult < (ssize_t)(sizeof(size_t) << 3); prev_lg_dirty_mult = | |
543 | lg_dirty_mult, lg_dirty_mult++) { | |
544 | ssize_t old_lg_dirty_mult; | |
545 | ||
546 | assert_d_eq(mallctl("arenas.lg_dirty_mult", &old_lg_dirty_mult, | |
547 | &sz, &lg_dirty_mult, sizeof(ssize_t)), 0, | |
548 | "Unexpected mallctl() failure"); | |
549 | assert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult, | |
550 | "Unexpected old arenas.lg_dirty_mult"); | |
551 | } | |
552 | } | |
553 | TEST_END | |
554 | ||
555 | TEST_BEGIN(test_arenas_decay_time) | |
556 | { | |
557 | ssize_t decay_time, orig_decay_time, prev_decay_time; | |
558 | size_t sz = sizeof(ssize_t); | |
559 | ||
560 | test_skip_if(opt_purge != purge_mode_decay); | |
561 | ||
562 | assert_d_eq(mallctl("arenas.decay_time", &orig_decay_time, &sz, | |
563 | NULL, 0), 0, "Unexpected mallctl() failure"); | |
564 | ||
565 | decay_time = -2; | |
566 | assert_d_eq(mallctl("arenas.decay_time", NULL, NULL, | |
567 | &decay_time, sizeof(ssize_t)), EFAULT, | |
568 | "Unexpected mallctl() success"); | |
569 | ||
570 | decay_time = 0x7fffffff; | |
571 | assert_d_eq(mallctl("arenas.decay_time", NULL, NULL, | |
572 | &decay_time, sizeof(ssize_t)), 0, | |
573 | "Expected mallctl() failure"); | |
574 | ||
575 | for (prev_decay_time = decay_time, decay_time = -1; | |
576 | decay_time < 20; prev_decay_time = decay_time, decay_time++) { | |
577 | ssize_t old_decay_time; | |
578 | ||
579 | assert_d_eq(mallctl("arenas.decay_time", &old_decay_time, | |
580 | &sz, &decay_time, sizeof(ssize_t)), 0, | |
581 | "Unexpected mallctl() failure"); | |
582 | assert_zd_eq(old_decay_time, prev_decay_time, | |
583 | "Unexpected old arenas.decay_time"); | |
584 | } | |
585 | } | |
586 | TEST_END | |
587 | ||
1a4d82fc JJ |
588 | TEST_BEGIN(test_arenas_constants) |
589 | { | |
590 | ||
591 | #define TEST_ARENAS_CONSTANT(t, name, expected) do { \ | |
592 | t name; \ | |
593 | size_t sz = sizeof(t); \ | |
594 | assert_d_eq(mallctl("arenas."#name, &name, &sz, NULL, 0), 0, \ | |
595 | "Unexpected mallctl() failure"); \ | |
596 | assert_zu_eq(name, expected, "Incorrect "#name" size"); \ | |
597 | } while (0) | |
598 | ||
599 | TEST_ARENAS_CONSTANT(size_t, quantum, QUANTUM); | |
600 | TEST_ARENAS_CONSTANT(size_t, page, PAGE); | |
601 | TEST_ARENAS_CONSTANT(unsigned, nbins, NBINS); | |
54a0048b SL |
602 | TEST_ARENAS_CONSTANT(unsigned, nlruns, nlclasses); |
603 | TEST_ARENAS_CONSTANT(unsigned, nhchunks, nhclasses); | |
1a4d82fc JJ |
604 | |
605 | #undef TEST_ARENAS_CONSTANT | |
606 | } | |
607 | TEST_END | |
608 | ||
609 | TEST_BEGIN(test_arenas_bin_constants) | |
610 | { | |
611 | ||
612 | #define TEST_ARENAS_BIN_CONSTANT(t, name, expected) do { \ | |
613 | t name; \ | |
614 | size_t sz = sizeof(t); \ | |
615 | assert_d_eq(mallctl("arenas.bin.0."#name, &name, &sz, NULL, 0), \ | |
616 | 0, "Unexpected mallctl() failure"); \ | |
617 | assert_zu_eq(name, expected, "Incorrect "#name" size"); \ | |
618 | } while (0) | |
619 | ||
620 | TEST_ARENAS_BIN_CONSTANT(size_t, size, arena_bin_info[0].reg_size); | |
621 | TEST_ARENAS_BIN_CONSTANT(uint32_t, nregs, arena_bin_info[0].nregs); | |
622 | TEST_ARENAS_BIN_CONSTANT(size_t, run_size, arena_bin_info[0].run_size); | |
623 | ||
624 | #undef TEST_ARENAS_BIN_CONSTANT | |
625 | } | |
626 | TEST_END | |
627 | ||
628 | TEST_BEGIN(test_arenas_lrun_constants) | |
629 | { | |
630 | ||
631 | #define TEST_ARENAS_LRUN_CONSTANT(t, name, expected) do { \ | |
632 | t name; \ | |
633 | size_t sz = sizeof(t); \ | |
634 | assert_d_eq(mallctl("arenas.lrun.0."#name, &name, &sz, NULL, \ | |
635 | 0), 0, "Unexpected mallctl() failure"); \ | |
636 | assert_zu_eq(name, expected, "Incorrect "#name" size"); \ | |
637 | } while (0) | |
638 | ||
54a0048b | 639 | TEST_ARENAS_LRUN_CONSTANT(size_t, size, LARGE_MINCLASS); |
1a4d82fc JJ |
640 | |
641 | #undef TEST_ARENAS_LRUN_CONSTANT | |
642 | } | |
643 | TEST_END | |
644 | ||
54a0048b SL |
645 | TEST_BEGIN(test_arenas_hchunk_constants) |
646 | { | |
647 | ||
648 | #define TEST_ARENAS_HCHUNK_CONSTANT(t, name, expected) do { \ | |
649 | t name; \ | |
650 | size_t sz = sizeof(t); \ | |
651 | assert_d_eq(mallctl("arenas.hchunk.0."#name, &name, &sz, NULL, \ | |
652 | 0), 0, "Unexpected mallctl() failure"); \ | |
653 | assert_zu_eq(name, expected, "Incorrect "#name" size"); \ | |
654 | } while (0) | |
655 | ||
656 | TEST_ARENAS_HCHUNK_CONSTANT(size_t, size, chunksize); | |
657 | ||
658 | #undef TEST_ARENAS_HCHUNK_CONSTANT | |
659 | } | |
660 | TEST_END | |
661 | ||
1a4d82fc JJ |
662 | TEST_BEGIN(test_arenas_extend) |
663 | { | |
664 | unsigned narenas_before, arena, narenas_after; | |
665 | size_t sz = sizeof(unsigned); | |
666 | ||
667 | assert_d_eq(mallctl("arenas.narenas", &narenas_before, &sz, NULL, 0), 0, | |
668 | "Unexpected mallctl() failure"); | |
669 | assert_d_eq(mallctl("arenas.extend", &arena, &sz, NULL, 0), 0, | |
670 | "Unexpected mallctl() failure"); | |
671 | assert_d_eq(mallctl("arenas.narenas", &narenas_after, &sz, NULL, 0), 0, | |
672 | "Unexpected mallctl() failure"); | |
673 | ||
674 | assert_u_eq(narenas_before+1, narenas_after, | |
675 | "Unexpected number of arenas before versus after extension"); | |
676 | assert_u_eq(arena, narenas_after-1, "Unexpected arena index"); | |
677 | } | |
678 | TEST_END | |
679 | ||
680 | TEST_BEGIN(test_stats_arenas) | |
681 | { | |
682 | ||
683 | #define TEST_STATS_ARENAS(t, name) do { \ | |
684 | t name; \ | |
685 | size_t sz = sizeof(t); \ | |
686 | assert_d_eq(mallctl("stats.arenas.0."#name, &name, &sz, NULL, \ | |
687 | 0), 0, "Unexpected mallctl() failure"); \ | |
688 | } while (0) | |
689 | ||
1a4d82fc | 690 | TEST_STATS_ARENAS(unsigned, nthreads); |
54a0048b SL |
691 | TEST_STATS_ARENAS(const char *, dss); |
692 | TEST_STATS_ARENAS(ssize_t, lg_dirty_mult); | |
693 | TEST_STATS_ARENAS(ssize_t, decay_time); | |
1a4d82fc JJ |
694 | TEST_STATS_ARENAS(size_t, pactive); |
695 | TEST_STATS_ARENAS(size_t, pdirty); | |
696 | ||
697 | #undef TEST_STATS_ARENAS | |
698 | } | |
699 | TEST_END | |
700 | ||
701 | int | |
702 | main(void) | |
703 | { | |
704 | ||
705 | return (test( | |
706 | test_mallctl_errors, | |
707 | test_mallctlnametomib_errors, | |
708 | test_mallctlbymib_errors, | |
709 | test_mallctl_read_write, | |
710 | test_mallctlnametomib_short_mib, | |
711 | test_mallctl_config, | |
712 | test_mallctl_opt, | |
713 | test_manpage_example, | |
54a0048b SL |
714 | test_tcache_none, |
715 | test_tcache, | |
1a4d82fc | 716 | test_thread_arena, |
54a0048b SL |
717 | test_arena_i_lg_dirty_mult, |
718 | test_arena_i_decay_time, | |
1a4d82fc | 719 | test_arena_i_purge, |
54a0048b | 720 | test_arena_i_decay, |
1a4d82fc JJ |
721 | test_arena_i_dss, |
722 | test_arenas_initialized, | |
54a0048b SL |
723 | test_arenas_lg_dirty_mult, |
724 | test_arenas_decay_time, | |
1a4d82fc JJ |
725 | test_arenas_constants, |
726 | test_arenas_bin_constants, | |
727 | test_arenas_lrun_constants, | |
54a0048b | 728 | test_arenas_hchunk_constants, |
1a4d82fc JJ |
729 | test_arenas_extend, |
730 | test_stats_arenas)); | |
731 | } |