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 #define TEST_MALLCTL_CONFIG(config, t) do { \
125 t oldval; \
126 size_t sz = sizeof(oldval); \
127 assert_d_eq(mallctl("config."#config, (void *)&oldval, &sz, \
128 NULL, 0), 0, "Unexpected mallctl() failure"); \
129 assert_b_eq(oldval, config_##config, "Incorrect config value"); \
130 assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \
131 } while (0)
132
133 TEST_MALLCTL_CONFIG(cache_oblivious, bool);
134 TEST_MALLCTL_CONFIG(debug, bool);
135 TEST_MALLCTL_CONFIG(fill, bool);
136 TEST_MALLCTL_CONFIG(lazy_lock, bool);
137 TEST_MALLCTL_CONFIG(malloc_conf, const char *);
138 TEST_MALLCTL_CONFIG(munmap, bool);
139 TEST_MALLCTL_CONFIG(prof, bool);
140 TEST_MALLCTL_CONFIG(prof_libgcc, bool);
141 TEST_MALLCTL_CONFIG(prof_libunwind, bool);
142 TEST_MALLCTL_CONFIG(stats, bool);
143 TEST_MALLCTL_CONFIG(tcache, bool);
144 TEST_MALLCTL_CONFIG(tls, bool);
145 TEST_MALLCTL_CONFIG(utrace, bool);
146 TEST_MALLCTL_CONFIG(xmalloc, bool);
147
148 #undef TEST_MALLCTL_CONFIG
149 }
150 TEST_END
151
TEST_BEGIN(test_mallctl_opt)152 TEST_BEGIN(test_mallctl_opt)
153 {
154 bool config_always = true;
155
156 #define TEST_MALLCTL_OPT(t, opt, config) do { \
157 t oldval; \
158 size_t sz = sizeof(oldval); \
159 int expected = config_##config ? 0 : ENOENT; \
160 int result = mallctl("opt."#opt, (void *)&oldval, &sz, NULL, \
161 0); \
162 assert_d_eq(result, expected, \
163 "Unexpected mallctl() result for opt."#opt); \
164 assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \
165 } while (0)
166
167 TEST_MALLCTL_OPT(bool, abort, always);
168 TEST_MALLCTL_OPT(const char *, dss, always);
169 TEST_MALLCTL_OPT(unsigned, narenas, always);
170 TEST_MALLCTL_OPT(ssize_t, decay_time, always);
171 TEST_MALLCTL_OPT(bool, stats_print, always);
172 TEST_MALLCTL_OPT(const char *, junk, fill);
173 TEST_MALLCTL_OPT(bool, zero, fill);
174 TEST_MALLCTL_OPT(bool, utrace, utrace);
175 TEST_MALLCTL_OPT(bool, xmalloc, xmalloc);
176 TEST_MALLCTL_OPT(bool, tcache, tcache);
177 TEST_MALLCTL_OPT(size_t, lg_tcache_max, tcache);
178 TEST_MALLCTL_OPT(bool, prof, prof);
179 TEST_MALLCTL_OPT(const char *, prof_prefix, prof);
180 TEST_MALLCTL_OPT(bool, prof_active, prof);
181 TEST_MALLCTL_OPT(ssize_t, lg_prof_sample, prof);
182 TEST_MALLCTL_OPT(bool, prof_accum, prof);
183 TEST_MALLCTL_OPT(ssize_t, lg_prof_interval, prof);
184 TEST_MALLCTL_OPT(bool, prof_gdump, prof);
185 TEST_MALLCTL_OPT(bool, prof_final, prof);
186 TEST_MALLCTL_OPT(bool, prof_leak, prof);
187
188 #undef TEST_MALLCTL_OPT
189 }
190 TEST_END
191
TEST_BEGIN(test_manpage_example)192 TEST_BEGIN(test_manpage_example)
193 {
194 unsigned nbins, i;
195 size_t mib[4];
196 size_t len, miblen;
197
198 len = sizeof(nbins);
199 assert_d_eq(mallctl("arenas.nbins", (void *)&nbins, &len, NULL, 0), 0,
200 "Unexpected mallctl() failure");
201
202 miblen = 4;
203 assert_d_eq(mallctlnametomib("arenas.bin.0.size", mib, &miblen), 0,
204 "Unexpected mallctlnametomib() failure");
205 for (i = 0; i < nbins; i++) {
206 size_t bin_size;
207
208 mib[2] = i;
209 len = sizeof(bin_size);
210 assert_d_eq(mallctlbymib(mib, miblen, (void *)&bin_size, &len,
211 NULL, 0), 0, "Unexpected mallctlbymib() failure");
212 /* Do something with bin_size... */
213 }
214 }
215 TEST_END
216
TEST_BEGIN(test_tcache_none)217 TEST_BEGIN(test_tcache_none)
218 {
219 void *p0, *q, *p1;
220
221 test_skip_if(!config_tcache);
222
223 /* Allocate p and q. */
224 p0 = mallocx(42, 0);
225 assert_ptr_not_null(p0, "Unexpected mallocx() failure");
226 q = mallocx(42, 0);
227 assert_ptr_not_null(q, "Unexpected mallocx() failure");
228
229 /* Deallocate p and q, but bypass the tcache for q. */
230 dallocx(p0, 0);
231 dallocx(q, MALLOCX_TCACHE_NONE);
232
233 /* Make sure that tcache-based allocation returns p, not q. */
234 p1 = mallocx(42, 0);
235 assert_ptr_not_null(p1, "Unexpected mallocx() failure");
236 assert_ptr_eq(p0, p1, "Expected tcache to allocate cached region");
237
238 /* Clean up. */
239 dallocx(p1, MALLOCX_TCACHE_NONE);
240 }
241 TEST_END
242
TEST_BEGIN(test_tcache)243 TEST_BEGIN(test_tcache)
244 {
245 #define NTCACHES 10
246 unsigned tis[NTCACHES];
247 void *ps[NTCACHES];
248 void *qs[NTCACHES];
249 unsigned i;
250 size_t sz, psz, qsz;
251
252 test_skip_if(!config_tcache);
253
254 psz = 42;
255 qsz = nallocx(psz, 0) + 1;
256
257 /* Create tcaches. */
258 for (i = 0; i < NTCACHES; i++) {
259 sz = sizeof(unsigned);
260 assert_d_eq(mallctl("tcache.create", (void *)&tis[i], &sz, NULL,
261 0), 0, "Unexpected mallctl() failure, i=%u", i);
262 }
263
264 /* Exercise tcache ID recycling. */
265 for (i = 0; i < NTCACHES; i++) {
266 assert_d_eq(mallctl("tcache.destroy", NULL, NULL,
267 (void *)&tis[i], sizeof(unsigned)), 0,
268 "Unexpected mallctl() failure, i=%u", i);
269 }
270 for (i = 0; i < NTCACHES; i++) {
271 sz = sizeof(unsigned);
272 assert_d_eq(mallctl("tcache.create", (void *)&tis[i], &sz, NULL,
273 0), 0, "Unexpected mallctl() failure, i=%u", i);
274 }
275
276 /* Flush empty tcaches. */
277 for (i = 0; i < NTCACHES; i++) {
278 assert_d_eq(mallctl("tcache.flush", NULL, NULL, (void *)&tis[i],
279 sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
280 i);
281 }
282
283 /* Cache some allocations. */
284 for (i = 0; i < NTCACHES; i++) {
285 ps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i]));
286 assert_ptr_not_null(ps[i], "Unexpected mallocx() failure, i=%u",
287 i);
288 dallocx(ps[i], MALLOCX_TCACHE(tis[i]));
289
290 qs[i] = mallocx(qsz, MALLOCX_TCACHE(tis[i]));
291 assert_ptr_not_null(qs[i], "Unexpected mallocx() failure, i=%u",
292 i);
293 dallocx(qs[i], MALLOCX_TCACHE(tis[i]));
294 }
295
296 /* Verify that tcaches allocate cached regions. */
297 for (i = 0; i < NTCACHES; i++) {
298 void *p0 = ps[i];
299 ps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i]));
300 assert_ptr_not_null(ps[i], "Unexpected mallocx() failure, i=%u",
301 i);
302 assert_ptr_eq(ps[i], p0,
303 "Expected mallocx() to allocate cached region, i=%u", i);
304 }
305
306 /* Verify that reallocation uses cached regions. */
307 for (i = 0; i < NTCACHES; i++) {
308 void *q0 = qs[i];
309 qs[i] = rallocx(ps[i], qsz, MALLOCX_TCACHE(tis[i]));
310 assert_ptr_not_null(qs[i], "Unexpected rallocx() failure, i=%u",
311 i);
312 assert_ptr_eq(qs[i], q0,
313 "Expected rallocx() to allocate cached region, i=%u", i);
314 /* Avoid undefined behavior in case of test failure. */
315 if (qs[i] == NULL)
316 qs[i] = ps[i];
317 }
318 for (i = 0; i < NTCACHES; i++)
319 dallocx(qs[i], MALLOCX_TCACHE(tis[i]));
320
321 /* Flush some non-empty tcaches. */
322 for (i = 0; i < NTCACHES/2; i++) {
323 assert_d_eq(mallctl("tcache.flush", NULL, NULL, (void *)&tis[i],
324 sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
325 i);
326 }
327
328 /* Destroy tcaches. */
329 for (i = 0; i < NTCACHES; i++) {
330 assert_d_eq(mallctl("tcache.destroy", NULL, NULL,
331 (void *)&tis[i], sizeof(unsigned)), 0,
332 "Unexpected mallctl() failure, i=%u", i);
333 }
334 }
335 TEST_END
336
TEST_BEGIN(test_thread_arena)337 TEST_BEGIN(test_thread_arena)
338 {
339 unsigned arena_old, arena_new, narenas;
340 size_t sz = sizeof(unsigned);
341
342 assert_d_eq(mallctl("arenas.narenas", (void *)&narenas, &sz, NULL, 0),
343 0, "Unexpected mallctl() failure");
344 assert_u_eq(narenas, opt_narenas, "Number of arenas incorrect");
345 arena_new = narenas - 1;
346 assert_d_eq(mallctl("thread.arena", (void *)&arena_old, &sz,
347 (void *)&arena_new, sizeof(unsigned)), 0,
348 "Unexpected mallctl() failure");
349 arena_new = 0;
350 assert_d_eq(mallctl("thread.arena", (void *)&arena_old, &sz,
351 (void *)&arena_new, sizeof(unsigned)), 0,
352 "Unexpected mallctl() failure");
353 }
354 TEST_END
355
TEST_BEGIN(test_arena_i_initialized)356 TEST_BEGIN(test_arena_i_initialized)
357 {
358 unsigned narenas, i;
359 size_t sz;
360 size_t mib[3];
361 size_t miblen = sizeof(mib) / sizeof(size_t);
362 bool initialized;
363
364 sz = sizeof(narenas);
365 assert_d_eq(mallctl("arenas.narenas", (void *)&narenas, &sz, NULL, 0),
366 0, "Unexpected mallctl() failure");
367
368 assert_d_eq(mallctlnametomib("arena.0.initialized", mib, &miblen), 0,
369 "Unexpected mallctlnametomib() failure");
370 for (i = 0; i < narenas; i++) {
371 mib[1] = i;
372 sz = sizeof(initialized);
373 assert_d_eq(mallctlbymib(mib, miblen, &initialized, &sz, NULL,
374 0), 0, "Unexpected mallctl() failure");
375 }
376
377 mib[1] = MALLCTL_ARENAS_ALL;
378 sz = sizeof(initialized);
379 assert_d_eq(mallctlbymib(mib, miblen, &initialized, &sz, NULL, 0), 0,
380 "Unexpected mallctl() failure");
381 assert_true(initialized,
382 "Merged arena statistics should always be initialized");
383
384 /* Equivalent to the above but using mallctl() directly. */
385 sz = sizeof(initialized);
386 assert_d_eq(mallctl(
387 "arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".initialized",
388 (void *)&initialized, &sz, NULL, 0), 0,
389 "Unexpected mallctl() failure");
390 assert_true(initialized,
391 "Merged arena statistics should always be initialized");
392 }
393 TEST_END
394
TEST_BEGIN(test_arena_i_decay_time)395 TEST_BEGIN(test_arena_i_decay_time)
396 {
397 ssize_t decay_time, orig_decay_time, prev_decay_time;
398 size_t sz = sizeof(ssize_t);
399
400 assert_d_eq(mallctl("arena.0.decay_time", (void *)&orig_decay_time, &sz,
401 NULL, 0), 0, "Unexpected mallctl() failure");
402
403 decay_time = -2;
404 assert_d_eq(mallctl("arena.0.decay_time", NULL, NULL,
405 (void *)&decay_time, sizeof(ssize_t)), EFAULT,
406 "Unexpected mallctl() success");
407
408 decay_time = 0x7fffffff;
409 assert_d_eq(mallctl("arena.0.decay_time", NULL, NULL,
410 (void *)&decay_time, sizeof(ssize_t)), 0,
411 "Unexpected mallctl() failure");
412
413 for (prev_decay_time = decay_time, decay_time = -1;
414 decay_time < 20; prev_decay_time = decay_time, decay_time++) {
415 ssize_t old_decay_time;
416
417 assert_d_eq(mallctl("arena.0.decay_time", (void *)&old_decay_time,
418 &sz, (void *)&decay_time, sizeof(ssize_t)), 0,
419 "Unexpected mallctl() failure");
420 assert_zd_eq(old_decay_time, prev_decay_time,
421 "Unexpected old arena.0.decay_time");
422 }
423 }
424 TEST_END
425
TEST_BEGIN(test_arena_i_purge)426 TEST_BEGIN(test_arena_i_purge)
427 {
428 unsigned narenas;
429 size_t sz = sizeof(unsigned);
430 size_t mib[3];
431 size_t miblen = 3;
432
433 assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
434 "Unexpected mallctl() failure");
435
436 assert_d_eq(mallctl("arenas.narenas", (void *)&narenas, &sz, NULL, 0),
437 0, "Unexpected mallctl() failure");
438 assert_d_eq(mallctlnametomib("arena.0.purge", mib, &miblen), 0,
439 "Unexpected mallctlnametomib() failure");
440 mib[1] = narenas;
441 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,
442 "Unexpected mallctlbymib() failure");
443
444 mib[1] = MALLCTL_ARENAS_ALL;
445 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,
446 "Unexpected mallctlbymib() failure");
447 }
448 TEST_END
449
TEST_BEGIN(test_arena_i_decay)450 TEST_BEGIN(test_arena_i_decay)
451 {
452 unsigned narenas;
453 size_t sz = sizeof(unsigned);
454 size_t mib[3];
455 size_t miblen = 3;
456
457 assert_d_eq(mallctl("arena.0.decay", NULL, NULL, NULL, 0), 0,
458 "Unexpected mallctl() failure");
459
460 assert_d_eq(mallctl("arenas.narenas", (void *)&narenas, &sz, NULL, 0),
461 0, "Unexpected mallctl() failure");
462 assert_d_eq(mallctlnametomib("arena.0.decay", mib, &miblen), 0,
463 "Unexpected mallctlnametomib() failure");
464 mib[1] = narenas;
465 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,
466 "Unexpected mallctlbymib() failure");
467
468 mib[1] = MALLCTL_ARENAS_ALL;
469 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,
470 "Unexpected mallctlbymib() failure");
471 }
472 TEST_END
473
TEST_BEGIN(test_arena_i_dss)474 TEST_BEGIN(test_arena_i_dss)
475 {
476 const char *dss_prec_old, *dss_prec_new;
477 size_t sz = sizeof(dss_prec_old);
478 size_t mib[3];
479 size_t miblen;
480
481 miblen = sizeof(mib)/sizeof(size_t);
482 assert_d_eq(mallctlnametomib("arena.0.dss", mib, &miblen), 0,
483 "Unexpected mallctlnametomib() error");
484
485 dss_prec_new = "disabled";
486 assert_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_old, &sz,
487 (void *)&dss_prec_new, sizeof(dss_prec_new)), 0,
488 "Unexpected mallctl() failure");
489 assert_str_ne(dss_prec_old, "primary",
490 "Unexpected default for dss precedence");
491
492 assert_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_new, &sz,
493 (void *)&dss_prec_old, sizeof(dss_prec_old)), 0,
494 "Unexpected mallctl() failure");
495
496 assert_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_old, &sz, NULL,
497 0), 0, "Unexpected mallctl() failure");
498 assert_str_ne(dss_prec_old, "primary",
499 "Unexpected value for dss precedence");
500
501 mib[1] = narenas_total_get();
502 dss_prec_new = "disabled";
503 assert_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_old, &sz,
504 (void *)&dss_prec_new, sizeof(dss_prec_new)), 0,
505 "Unexpected mallctl() failure");
506 assert_str_ne(dss_prec_old, "primary",
507 "Unexpected default for dss precedence");
508
509 assert_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_new, &sz,
510 (void *)&dss_prec_old, sizeof(dss_prec_new)), 0,
511 "Unexpected mallctl() failure");
512
513 assert_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_old, &sz, NULL,
514 0), 0, "Unexpected mallctl() failure");
515 assert_str_ne(dss_prec_old, "primary",
516 "Unexpected value for dss precedence");
517 }
518 TEST_END
519
TEST_BEGIN(test_arenas_decay_time)520 TEST_BEGIN(test_arenas_decay_time)
521 {
522 ssize_t decay_time, orig_decay_time, prev_decay_time;
523 size_t sz = sizeof(ssize_t);
524
525 assert_d_eq(mallctl("arenas.decay_time", (void *)&orig_decay_time, &sz,
526 NULL, 0), 0, "Unexpected mallctl() failure");
527
528 decay_time = -2;
529 assert_d_eq(mallctl("arenas.decay_time", NULL, NULL,
530 (void *)&decay_time, sizeof(ssize_t)), EFAULT,
531 "Unexpected mallctl() success");
532
533 decay_time = 0x7fffffff;
534 assert_d_eq(mallctl("arenas.decay_time", NULL, NULL,
535 (void *)&decay_time, sizeof(ssize_t)), 0,
536 "Expected mallctl() failure");
537
538 for (prev_decay_time = decay_time, decay_time = -1;
539 decay_time < 20; prev_decay_time = decay_time, decay_time++) {
540 ssize_t old_decay_time;
541
542 assert_d_eq(mallctl("arenas.decay_time",
543 (void *)&old_decay_time, &sz, (void *)&decay_time,
544 sizeof(ssize_t)), 0, "Unexpected mallctl() failure");
545 assert_zd_eq(old_decay_time, prev_decay_time,
546 "Unexpected old arenas.decay_time");
547 }
548 }
549 TEST_END
550
TEST_BEGIN(test_arenas_constants)551 TEST_BEGIN(test_arenas_constants)
552 {
553 #define TEST_ARENAS_CONSTANT(t, name, expected) do { \
554 t name; \
555 size_t sz = sizeof(t); \
556 assert_d_eq(mallctl("arenas."#name, (void *)&name, &sz, NULL, \
557 0), 0, "Unexpected mallctl() failure"); \
558 assert_zu_eq(name, expected, "Incorrect "#name" size"); \
559 } while (0)
560
561 TEST_ARENAS_CONSTANT(size_t, quantum, QUANTUM);
562 TEST_ARENAS_CONSTANT(size_t, page, PAGE);
563 TEST_ARENAS_CONSTANT(unsigned, nbins, NBINS);
564 TEST_ARENAS_CONSTANT(unsigned, nlextents, NSIZES - NBINS);
565
566 #undef TEST_ARENAS_CONSTANT
567 }
568 TEST_END
569
TEST_BEGIN(test_arenas_bin_constants)570 TEST_BEGIN(test_arenas_bin_constants)
571 {
572 #define TEST_ARENAS_BIN_CONSTANT(t, name, expected) do { \
573 t name; \
574 size_t sz = sizeof(t); \
575 assert_d_eq(mallctl("arenas.bin.0."#name, (void *)&name, &sz, \
576 NULL, 0), 0, "Unexpected mallctl() failure"); \
577 assert_zu_eq(name, expected, "Incorrect "#name" size"); \
578 } while (0)
579
580 TEST_ARENAS_BIN_CONSTANT(size_t, size, arena_bin_info[0].reg_size);
581 TEST_ARENAS_BIN_CONSTANT(uint32_t, nregs, arena_bin_info[0].nregs);
582 TEST_ARENAS_BIN_CONSTANT(size_t, slab_size,
583 arena_bin_info[0].slab_size);
584
585 #undef TEST_ARENAS_BIN_CONSTANT
586 }
587 TEST_END
588
TEST_BEGIN(test_arenas_lextent_constants)589 TEST_BEGIN(test_arenas_lextent_constants)
590 {
591 #define TEST_ARENAS_LEXTENT_CONSTANT(t, name, expected) do { \
592 t name; \
593 size_t sz = sizeof(t); \
594 assert_d_eq(mallctl("arenas.lextent.0."#name, (void *)&name, \
595 &sz, NULL, 0), 0, "Unexpected mallctl() failure"); \
596 assert_zu_eq(name, expected, "Incorrect "#name" size"); \
597 } while (0)
598
599 TEST_ARENAS_LEXTENT_CONSTANT(size_t, size, LARGE_MINCLASS);
600
601 #undef TEST_ARENAS_LEXTENT_CONSTANT
602 }
603 TEST_END
604
TEST_BEGIN(test_arenas_create)605 TEST_BEGIN(test_arenas_create)
606 {
607 unsigned narenas_before, arena, narenas_after;
608 size_t sz = sizeof(unsigned);
609
610 assert_d_eq(mallctl("arenas.narenas", (void *)&narenas_before, &sz,
611 NULL, 0), 0, "Unexpected mallctl() failure");
612 assert_d_eq(mallctl("arenas.create", (void *)&arena, &sz, NULL, 0), 0,
613 "Unexpected mallctl() failure");
614 assert_d_eq(mallctl("arenas.narenas", (void *)&narenas_after, &sz, NULL,
615 0), 0, "Unexpected mallctl() failure");
616
617 assert_u_eq(narenas_before+1, narenas_after,
618 "Unexpected number of arenas before versus after extension");
619 assert_u_eq(arena, narenas_after-1, "Unexpected arena index");
620 }
621 TEST_END
622
TEST_BEGIN(test_stats_arenas)623 TEST_BEGIN(test_stats_arenas)
624 {
625 #define TEST_STATS_ARENAS(t, name) do { \
626 t name; \
627 size_t sz = sizeof(t); \
628 assert_d_eq(mallctl("stats.arenas.0."#name, (void *)&name, &sz, \
629 NULL, 0), 0, "Unexpected mallctl() failure"); \
630 } while (0)
631
632 TEST_STATS_ARENAS(unsigned, nthreads);
633 TEST_STATS_ARENAS(const char *, dss);
634 TEST_STATS_ARENAS(ssize_t, decay_time);
635 TEST_STATS_ARENAS(size_t, pactive);
636 TEST_STATS_ARENAS(size_t, pdirty);
637
638 #undef TEST_STATS_ARENAS
639 }
640 TEST_END
641
642 int
main(void)643 main(void)
644 {
645 return (test(
646 test_mallctl_errors,
647 test_mallctlnametomib_errors,
648 test_mallctlbymib_errors,
649 test_mallctl_read_write,
650 test_mallctlnametomib_short_mib,
651 test_mallctl_config,
652 test_mallctl_opt,
653 test_manpage_example,
654 test_tcache_none,
655 test_tcache,
656 test_thread_arena,
657 test_arena_i_initialized,
658 test_arena_i_decay_time,
659 test_arena_i_purge,
660 test_arena_i_decay,
661 test_arena_i_dss,
662 test_arenas_decay_time,
663 test_arenas_constants,
664 test_arenas_bin_constants,
665 test_arenas_lextent_constants,
666 test_arenas_create,
667 test_stats_arenas));
668 }
669