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