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