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