Home | History | Annotate | Line # | Download | only in unit
mallctl.c revision 1.1.1.1.14.1
      1           1.1  christos #include "test/jemalloc_test.h"
      2           1.1  christos 
      3  1.1.1.1.14.1  perseant #include "jemalloc/internal/ctl.h"
      4  1.1.1.1.14.1  perseant #include "jemalloc/internal/hook.h"
      5           1.1  christos #include "jemalloc/internal/util.h"
      6           1.1  christos 
      7           1.1  christos TEST_BEGIN(test_mallctl_errors) {
      8           1.1  christos 	uint64_t epoch;
      9           1.1  christos 	size_t sz;
     10           1.1  christos 
     11  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("no_such_name", NULL, NULL, NULL, 0), ENOENT,
     12           1.1  christos 	    "mallctl() should return ENOENT for non-existent names");
     13           1.1  christos 
     14  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("version", NULL, NULL, "0.0.0", strlen("0.0.0")),
     15           1.1  christos 	    EPERM, "mallctl() should return EPERM on attempt to write "
     16           1.1  christos 	    "read-only value");
     17           1.1  christos 
     18  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch,
     19           1.1  christos 	    sizeof(epoch)-1), EINVAL,
     20           1.1  christos 	    "mallctl() should return EINVAL for input size mismatch");
     21  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch,
     22           1.1  christos 	    sizeof(epoch)+1), EINVAL,
     23           1.1  christos 	    "mallctl() should return EINVAL for input size mismatch");
     24           1.1  christos 
     25           1.1  christos 	sz = sizeof(epoch)-1;
     26  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("epoch", (void *)&epoch, &sz, NULL, 0), EINVAL,
     27           1.1  christos 	    "mallctl() should return EINVAL for output size mismatch");
     28           1.1  christos 	sz = sizeof(epoch)+1;
     29  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("epoch", (void *)&epoch, &sz, NULL, 0), EINVAL,
     30           1.1  christos 	    "mallctl() should return EINVAL for output size mismatch");
     31           1.1  christos }
     32           1.1  christos TEST_END
     33           1.1  christos 
     34           1.1  christos TEST_BEGIN(test_mallctlnametomib_errors) {
     35           1.1  christos 	size_t mib[1];
     36           1.1  christos 	size_t miblen;
     37           1.1  christos 
     38           1.1  christos 	miblen = sizeof(mib)/sizeof(size_t);
     39  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlnametomib("no_such_name", mib, &miblen), ENOENT,
     40           1.1  christos 	    "mallctlnametomib() should return ENOENT for non-existent names");
     41           1.1  christos }
     42           1.1  christos TEST_END
     43           1.1  christos 
     44           1.1  christos TEST_BEGIN(test_mallctlbymib_errors) {
     45           1.1  christos 	uint64_t epoch;
     46           1.1  christos 	size_t sz;
     47           1.1  christos 	size_t mib[1];
     48           1.1  christos 	size_t miblen;
     49           1.1  christos 
     50           1.1  christos 	miblen = sizeof(mib)/sizeof(size_t);
     51  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlnametomib("version", mib, &miblen), 0,
     52           1.1  christos 	    "Unexpected mallctlnametomib() failure");
     53           1.1  christos 
     54  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, NULL, NULL, "0.0.0",
     55           1.1  christos 	    strlen("0.0.0")), EPERM, "mallctl() should return EPERM on "
     56           1.1  christos 	    "attempt to write read-only value");
     57           1.1  christos 
     58           1.1  christos 	miblen = sizeof(mib)/sizeof(size_t);
     59  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlnametomib("epoch", mib, &miblen), 0,
     60           1.1  christos 	    "Unexpected mallctlnametomib() failure");
     61           1.1  christos 
     62  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, NULL, NULL, (void *)&epoch,
     63           1.1  christos 	    sizeof(epoch)-1), EINVAL,
     64           1.1  christos 	    "mallctlbymib() should return EINVAL for input size mismatch");
     65  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, NULL, NULL, (void *)&epoch,
     66           1.1  christos 	    sizeof(epoch)+1), EINVAL,
     67           1.1  christos 	    "mallctlbymib() should return EINVAL for input size mismatch");
     68           1.1  christos 
     69           1.1  christos 	sz = sizeof(epoch)-1;
     70  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, (void *)&epoch, &sz, NULL, 0),
     71           1.1  christos 	    EINVAL,
     72           1.1  christos 	    "mallctlbymib() should return EINVAL for output size mismatch");
     73           1.1  christos 	sz = sizeof(epoch)+1;
     74  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, (void *)&epoch, &sz, NULL, 0),
     75           1.1  christos 	    EINVAL,
     76           1.1  christos 	    "mallctlbymib() should return EINVAL for output size mismatch");
     77           1.1  christos }
     78           1.1  christos TEST_END
     79           1.1  christos 
     80           1.1  christos TEST_BEGIN(test_mallctl_read_write) {
     81           1.1  christos 	uint64_t old_epoch, new_epoch;
     82           1.1  christos 	size_t sz = sizeof(old_epoch);
     83           1.1  christos 
     84           1.1  christos 	/* Blind. */
     85  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("epoch", NULL, NULL, NULL, 0), 0,
     86           1.1  christos 	    "Unexpected mallctl() failure");
     87  1.1.1.1.14.1  perseant 	expect_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
     88           1.1  christos 
     89           1.1  christos 	/* Read. */
     90  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("epoch", (void *)&old_epoch, &sz, NULL, 0), 0,
     91           1.1  christos 	    "Unexpected mallctl() failure");
     92  1.1.1.1.14.1  perseant 	expect_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
     93           1.1  christos 
     94           1.1  christos 	/* Write. */
     95  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("epoch", NULL, NULL, (void *)&new_epoch,
     96           1.1  christos 	    sizeof(new_epoch)), 0, "Unexpected mallctl() failure");
     97  1.1.1.1.14.1  perseant 	expect_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
     98           1.1  christos 
     99           1.1  christos 	/* Read+write. */
    100  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("epoch", (void *)&old_epoch, &sz,
    101           1.1  christos 	    (void *)&new_epoch, sizeof(new_epoch)), 0,
    102           1.1  christos 	    "Unexpected mallctl() failure");
    103  1.1.1.1.14.1  perseant 	expect_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
    104           1.1  christos }
    105           1.1  christos TEST_END
    106           1.1  christos 
    107           1.1  christos TEST_BEGIN(test_mallctlnametomib_short_mib) {
    108           1.1  christos 	size_t mib[4];
    109           1.1  christos 	size_t miblen;
    110           1.1  christos 
    111           1.1  christos 	miblen = 3;
    112           1.1  christos 	mib[3] = 42;
    113  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlnametomib("arenas.bin.0.nregs", mib, &miblen), 0,
    114           1.1  christos 	    "Unexpected mallctlnametomib() failure");
    115  1.1.1.1.14.1  perseant 	expect_zu_eq(miblen, 3, "Unexpected mib output length");
    116  1.1.1.1.14.1  perseant 	expect_zu_eq(mib[3], 42,
    117           1.1  christos 	    "mallctlnametomib() wrote past the end of the input mib");
    118           1.1  christos }
    119           1.1  christos TEST_END
    120           1.1  christos 
    121  1.1.1.1.14.1  perseant TEST_BEGIN(test_mallctlnametomib_short_name) {
    122  1.1.1.1.14.1  perseant 	size_t mib[4];
    123  1.1.1.1.14.1  perseant 	size_t miblen;
    124  1.1.1.1.14.1  perseant 
    125  1.1.1.1.14.1  perseant 	miblen = 4;
    126  1.1.1.1.14.1  perseant 	mib[3] = 42;
    127  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlnametomib("arenas.bin.0", mib, &miblen), 0,
    128  1.1.1.1.14.1  perseant 	    "Unexpected mallctlnametomib() failure");
    129  1.1.1.1.14.1  perseant 	expect_zu_eq(miblen, 3, "Unexpected mib output length");
    130  1.1.1.1.14.1  perseant 	expect_zu_eq(mib[3], 42,
    131  1.1.1.1.14.1  perseant 	    "mallctlnametomib() wrote past the end of the input mib");
    132  1.1.1.1.14.1  perseant }
    133  1.1.1.1.14.1  perseant TEST_END
    134  1.1.1.1.14.1  perseant 
    135  1.1.1.1.14.1  perseant TEST_BEGIN(test_mallctlmibnametomib) {
    136  1.1.1.1.14.1  perseant 	size_t mib[4];
    137  1.1.1.1.14.1  perseant 	size_t miblen = 4;
    138  1.1.1.1.14.1  perseant 	uint32_t result, result_ref;
    139  1.1.1.1.14.1  perseant 	size_t len_result = sizeof(uint32_t);
    140  1.1.1.1.14.1  perseant 
    141  1.1.1.1.14.1  perseant 	tsd_t *tsd = tsd_fetch();
    142  1.1.1.1.14.1  perseant 
    143  1.1.1.1.14.1  perseant 	/* Error cases */
    144  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_mibnametomib(tsd, mib, 0, "bob", &miblen), ENOENT, "");
    145  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 4, "");
    146  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_mibnametomib(tsd, mib, 0, "9999", &miblen), ENOENT, "");
    147  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 4, "");
    148  1.1.1.1.14.1  perseant 
    149  1.1.1.1.14.1  perseant 	/* Valid case. */
    150  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_mibnametomib(tsd, mib, 0, "arenas", &miblen), 0, "");
    151  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 1, "");
    152  1.1.1.1.14.1  perseant 	miblen = 4;
    153  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_mibnametomib(tsd, mib, 1, "bin", &miblen), 0, "");
    154  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 2, "");
    155  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, &result, &len_result, NULL, 0),
    156  1.1.1.1.14.1  perseant 	    ENOENT, "mallctlbymib() should fail on partial path");
    157  1.1.1.1.14.1  perseant 
    158  1.1.1.1.14.1  perseant 	/* Error cases. */
    159  1.1.1.1.14.1  perseant 	miblen = 4;
    160  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_mibnametomib(tsd, mib, 2, "bob", &miblen), ENOENT, "");
    161  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 4, "");
    162  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_mibnametomib(tsd, mib, 2, "9999", &miblen), ENOENT, "");
    163  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 4, "");
    164  1.1.1.1.14.1  perseant 
    165  1.1.1.1.14.1  perseant 	/* Valid case. */
    166  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_mibnametomib(tsd, mib, 2, "0", &miblen), 0, "");
    167  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 3, "");
    168  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, &result, &len_result, NULL, 0),
    169  1.1.1.1.14.1  perseant 	    ENOENT, "mallctlbymib() should fail on partial path");
    170  1.1.1.1.14.1  perseant 
    171  1.1.1.1.14.1  perseant 	/* Error cases. */
    172  1.1.1.1.14.1  perseant 	miblen = 4;
    173  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_mibnametomib(tsd, mib, 3, "bob", &miblen), ENOENT, "");
    174  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 4, "");
    175  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_mibnametomib(tsd, mib, 3, "9999", &miblen), ENOENT, "");
    176  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 4, "");
    177  1.1.1.1.14.1  perseant 
    178  1.1.1.1.14.1  perseant 	/* Valid case. */
    179  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_mibnametomib(tsd, mib, 3, "nregs", &miblen), 0, "");
    180  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 4, "");
    181  1.1.1.1.14.1  perseant 	assert_d_eq(mallctlbymib(mib, miblen, &result, &len_result, NULL, 0),
    182  1.1.1.1.14.1  perseant 	    0, "Unexpected mallctlbymib() failure");
    183  1.1.1.1.14.1  perseant 	assert_d_eq(mallctl("arenas.bin.0.nregs", &result_ref, &len_result,
    184  1.1.1.1.14.1  perseant 	    NULL, 0), 0, "Unexpected mallctl() failure");
    185  1.1.1.1.14.1  perseant 	expect_zu_eq(result, result_ref,
    186  1.1.1.1.14.1  perseant 	    "mallctlbymib() and mallctl() returned different result");
    187  1.1.1.1.14.1  perseant }
    188  1.1.1.1.14.1  perseant TEST_END
    189  1.1.1.1.14.1  perseant 
    190  1.1.1.1.14.1  perseant TEST_BEGIN(test_mallctlbymibname) {
    191  1.1.1.1.14.1  perseant 	size_t mib[4];
    192  1.1.1.1.14.1  perseant 	size_t miblen = 4;
    193  1.1.1.1.14.1  perseant 	uint32_t result, result_ref;
    194  1.1.1.1.14.1  perseant 	size_t len_result = sizeof(uint32_t);
    195  1.1.1.1.14.1  perseant 
    196  1.1.1.1.14.1  perseant 	tsd_t *tsd = tsd_fetch();
    197  1.1.1.1.14.1  perseant 
    198  1.1.1.1.14.1  perseant 	/* Error cases. */
    199  1.1.1.1.14.1  perseant 
    200  1.1.1.1.14.1  perseant 	assert_d_eq(mallctlnametomib("arenas", mib, &miblen), 0,
    201  1.1.1.1.14.1  perseant 	    "Unexpected mallctlnametomib() failure");
    202  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 1, "");
    203  1.1.1.1.14.1  perseant 
    204  1.1.1.1.14.1  perseant 	miblen = 4;
    205  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_bymibname(tsd, mib, 1, "bin.0", &miblen,
    206  1.1.1.1.14.1  perseant 	    &result, &len_result, NULL, 0), ENOENT, "");
    207  1.1.1.1.14.1  perseant 	miblen = 4;
    208  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_bymibname(tsd, mib, 1, "bin.0.bob", &miblen,
    209  1.1.1.1.14.1  perseant 	    &result, &len_result, NULL, 0), ENOENT, "");
    210  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 4, "");
    211  1.1.1.1.14.1  perseant 
    212  1.1.1.1.14.1  perseant 	/* Valid cases. */
    213  1.1.1.1.14.1  perseant 
    214  1.1.1.1.14.1  perseant 	assert_d_eq(mallctl("arenas.bin.0.nregs", &result_ref, &len_result,
    215  1.1.1.1.14.1  perseant 	    NULL, 0), 0, "Unexpected mallctl() failure");
    216  1.1.1.1.14.1  perseant 	miblen = 4;
    217  1.1.1.1.14.1  perseant 
    218  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_bymibname(tsd, mib, 0, "arenas.bin.0.nregs", &miblen,
    219  1.1.1.1.14.1  perseant 	    &result, &len_result, NULL, 0), 0, "");
    220  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 4, "");
    221  1.1.1.1.14.1  perseant 	expect_zu_eq(result, result_ref, "Unexpected result");
    222  1.1.1.1.14.1  perseant 
    223  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_bymibname(tsd, mib, 1, "bin.0.nregs", &miblen, &result,
    224  1.1.1.1.14.1  perseant 	    &len_result, NULL, 0), 0, "");
    225  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 4, "");
    226  1.1.1.1.14.1  perseant 	expect_zu_eq(result, result_ref, "Unexpected result");
    227  1.1.1.1.14.1  perseant 
    228  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_bymibname(tsd, mib, 2, "0.nregs", &miblen, &result,
    229  1.1.1.1.14.1  perseant 	    &len_result, NULL, 0), 0, "");
    230  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 4, "");
    231  1.1.1.1.14.1  perseant 	expect_zu_eq(result, result_ref, "Unexpected result");
    232  1.1.1.1.14.1  perseant 
    233  1.1.1.1.14.1  perseant 	assert_d_eq(ctl_bymibname(tsd, mib, 3, "nregs", &miblen, &result,
    234  1.1.1.1.14.1  perseant 	    &len_result, NULL, 0), 0, "");
    235  1.1.1.1.14.1  perseant 	assert_zu_eq(miblen, 4, "");
    236  1.1.1.1.14.1  perseant 	expect_zu_eq(result, result_ref, "Unexpected result");
    237  1.1.1.1.14.1  perseant }
    238  1.1.1.1.14.1  perseant TEST_END
    239  1.1.1.1.14.1  perseant 
    240           1.1  christos TEST_BEGIN(test_mallctl_config) {
    241           1.1  christos #define TEST_MALLCTL_CONFIG(config, t) do {				\
    242           1.1  christos 	t oldval;							\
    243           1.1  christos 	size_t sz = sizeof(oldval);					\
    244  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("config."#config, (void *)&oldval, &sz,	\
    245           1.1  christos 	    NULL, 0), 0, "Unexpected mallctl() failure");		\
    246  1.1.1.1.14.1  perseant 	expect_b_eq(oldval, config_##config, "Incorrect config value");	\
    247  1.1.1.1.14.1  perseant 	expect_zu_eq(sz, sizeof(oldval), "Unexpected output size");	\
    248           1.1  christos } while (0)
    249           1.1  christos 
    250           1.1  christos 	TEST_MALLCTL_CONFIG(cache_oblivious, bool);
    251           1.1  christos 	TEST_MALLCTL_CONFIG(debug, bool);
    252           1.1  christos 	TEST_MALLCTL_CONFIG(fill, bool);
    253           1.1  christos 	TEST_MALLCTL_CONFIG(lazy_lock, bool);
    254           1.1  christos 	TEST_MALLCTL_CONFIG(malloc_conf, const char *);
    255           1.1  christos 	TEST_MALLCTL_CONFIG(prof, bool);
    256           1.1  christos 	TEST_MALLCTL_CONFIG(prof_libgcc, bool);
    257           1.1  christos 	TEST_MALLCTL_CONFIG(prof_libunwind, bool);
    258           1.1  christos 	TEST_MALLCTL_CONFIG(stats, bool);
    259           1.1  christos 	TEST_MALLCTL_CONFIG(utrace, bool);
    260           1.1  christos 	TEST_MALLCTL_CONFIG(xmalloc, bool);
    261           1.1  christos 
    262           1.1  christos #undef TEST_MALLCTL_CONFIG
    263           1.1  christos }
    264           1.1  christos TEST_END
    265           1.1  christos 
    266           1.1  christos TEST_BEGIN(test_mallctl_opt) {
    267           1.1  christos 	bool config_always = true;
    268           1.1  christos 
    269           1.1  christos #define TEST_MALLCTL_OPT(t, opt, config) do {				\
    270           1.1  christos 	t oldval;							\
    271           1.1  christos 	size_t sz = sizeof(oldval);					\
    272           1.1  christos 	int expected = config_##config ? 0 : ENOENT;			\
    273           1.1  christos 	int result = mallctl("opt."#opt, (void *)&oldval, &sz, NULL,	\
    274           1.1  christos 	    0);								\
    275  1.1.1.1.14.1  perseant 	expect_d_eq(result, expected,					\
    276           1.1  christos 	    "Unexpected mallctl() result for opt."#opt);		\
    277  1.1.1.1.14.1  perseant 	expect_zu_eq(sz, sizeof(oldval), "Unexpected output size");	\
    278           1.1  christos } while (0)
    279           1.1  christos 
    280           1.1  christos 	TEST_MALLCTL_OPT(bool, abort, always);
    281           1.1  christos 	TEST_MALLCTL_OPT(bool, abort_conf, always);
    282  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(bool, cache_oblivious, always);
    283  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(bool, trust_madvise, always);
    284  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(bool, confirm_conf, always);
    285           1.1  christos 	TEST_MALLCTL_OPT(const char *, metadata_thp, always);
    286           1.1  christos 	TEST_MALLCTL_OPT(bool, retain, always);
    287           1.1  christos 	TEST_MALLCTL_OPT(const char *, dss, always);
    288  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(bool, hpa, always);
    289  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(size_t, hpa_slab_max_alloc, always);
    290  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(size_t, hpa_sec_nshards, always);
    291  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(size_t, hpa_sec_max_alloc, always);
    292  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(size_t, hpa_sec_max_bytes, always);
    293  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(size_t, hpa_sec_bytes_after_flush, always);
    294  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(size_t, hpa_sec_batch_fill_extra, always);
    295           1.1  christos 	TEST_MALLCTL_OPT(unsigned, narenas, always);
    296           1.1  christos 	TEST_MALLCTL_OPT(const char *, percpu_arena, always);
    297  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(size_t, oversize_threshold, always);
    298           1.1  christos 	TEST_MALLCTL_OPT(bool, background_thread, always);
    299           1.1  christos 	TEST_MALLCTL_OPT(ssize_t, dirty_decay_ms, always);
    300           1.1  christos 	TEST_MALLCTL_OPT(ssize_t, muzzy_decay_ms, always);
    301           1.1  christos 	TEST_MALLCTL_OPT(bool, stats_print, always);
    302  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(const char *, stats_print_opts, always);
    303  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(int64_t, stats_interval, always);
    304  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(const char *, stats_interval_opts, always);
    305           1.1  christos 	TEST_MALLCTL_OPT(const char *, junk, fill);
    306           1.1  christos 	TEST_MALLCTL_OPT(bool, zero, fill);
    307           1.1  christos 	TEST_MALLCTL_OPT(bool, utrace, utrace);
    308           1.1  christos 	TEST_MALLCTL_OPT(bool, xmalloc, xmalloc);
    309           1.1  christos 	TEST_MALLCTL_OPT(bool, tcache, always);
    310           1.1  christos 	TEST_MALLCTL_OPT(size_t, lg_extent_max_active_fit, always);
    311  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(size_t, tcache_max, always);
    312           1.1  christos 	TEST_MALLCTL_OPT(const char *, thp, always);
    313  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(const char *, zero_realloc, always);
    314           1.1  christos 	TEST_MALLCTL_OPT(bool, prof, prof);
    315           1.1  christos 	TEST_MALLCTL_OPT(const char *, prof_prefix, prof);
    316           1.1  christos 	TEST_MALLCTL_OPT(bool, prof_active, prof);
    317           1.1  christos 	TEST_MALLCTL_OPT(ssize_t, lg_prof_sample, prof);
    318           1.1  christos 	TEST_MALLCTL_OPT(bool, prof_accum, prof);
    319           1.1  christos 	TEST_MALLCTL_OPT(ssize_t, lg_prof_interval, prof);
    320           1.1  christos 	TEST_MALLCTL_OPT(bool, prof_gdump, prof);
    321           1.1  christos 	TEST_MALLCTL_OPT(bool, prof_final, prof);
    322           1.1  christos 	TEST_MALLCTL_OPT(bool, prof_leak, prof);
    323  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(bool, prof_leak_error, prof);
    324  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(ssize_t, prof_recent_alloc_max, prof);
    325  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(bool, prof_stats, prof);
    326  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(bool, prof_sys_thread_name, prof);
    327  1.1.1.1.14.1  perseant 	TEST_MALLCTL_OPT(ssize_t, lg_san_uaf_align, uaf_detection);
    328           1.1  christos 
    329           1.1  christos #undef TEST_MALLCTL_OPT
    330           1.1  christos }
    331           1.1  christos TEST_END
    332           1.1  christos 
    333           1.1  christos TEST_BEGIN(test_manpage_example) {
    334           1.1  christos 	unsigned nbins, i;
    335           1.1  christos 	size_t mib[4];
    336           1.1  christos 	size_t len, miblen;
    337           1.1  christos 
    338           1.1  christos 	len = sizeof(nbins);
    339  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.nbins", (void *)&nbins, &len, NULL, 0), 0,
    340           1.1  christos 	    "Unexpected mallctl() failure");
    341           1.1  christos 
    342           1.1  christos 	miblen = 4;
    343  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlnametomib("arenas.bin.0.size", mib, &miblen), 0,
    344           1.1  christos 	    "Unexpected mallctlnametomib() failure");
    345           1.1  christos 	for (i = 0; i < nbins; i++) {
    346           1.1  christos 		size_t bin_size;
    347           1.1  christos 
    348           1.1  christos 		mib[2] = i;
    349           1.1  christos 		len = sizeof(bin_size);
    350  1.1.1.1.14.1  perseant 		expect_d_eq(mallctlbymib(mib, miblen, (void *)&bin_size, &len,
    351           1.1  christos 		    NULL, 0), 0, "Unexpected mallctlbymib() failure");
    352           1.1  christos 		/* Do something with bin_size... */
    353           1.1  christos 	}
    354           1.1  christos }
    355           1.1  christos TEST_END
    356           1.1  christos 
    357           1.1  christos TEST_BEGIN(test_tcache_none) {
    358           1.1  christos 	test_skip_if(!opt_tcache);
    359           1.1  christos 
    360           1.1  christos 	/* Allocate p and q. */
    361           1.1  christos 	void *p0 = mallocx(42, 0);
    362  1.1.1.1.14.1  perseant 	expect_ptr_not_null(p0, "Unexpected mallocx() failure");
    363           1.1  christos 	void *q = mallocx(42, 0);
    364  1.1.1.1.14.1  perseant 	expect_ptr_not_null(q, "Unexpected mallocx() failure");
    365           1.1  christos 
    366           1.1  christos 	/* Deallocate p and q, but bypass the tcache for q. */
    367           1.1  christos 	dallocx(p0, 0);
    368           1.1  christos 	dallocx(q, MALLOCX_TCACHE_NONE);
    369           1.1  christos 
    370           1.1  christos 	/* Make sure that tcache-based allocation returns p, not q. */
    371           1.1  christos 	void *p1 = mallocx(42, 0);
    372  1.1.1.1.14.1  perseant 	expect_ptr_not_null(p1, "Unexpected mallocx() failure");
    373  1.1.1.1.14.1  perseant 	if (!opt_prof && !san_uaf_detection_enabled()) {
    374  1.1.1.1.14.1  perseant 		expect_ptr_eq(p0, p1,
    375  1.1.1.1.14.1  perseant 		    "Expected tcache to allocate cached region");
    376  1.1.1.1.14.1  perseant 	}
    377           1.1  christos 
    378           1.1  christos 	/* Clean up. */
    379           1.1  christos 	dallocx(p1, MALLOCX_TCACHE_NONE);
    380           1.1  christos }
    381           1.1  christos TEST_END
    382           1.1  christos 
    383           1.1  christos TEST_BEGIN(test_tcache) {
    384           1.1  christos #define NTCACHES	10
    385           1.1  christos 	unsigned tis[NTCACHES];
    386           1.1  christos 	void *ps[NTCACHES];
    387           1.1  christos 	void *qs[NTCACHES];
    388           1.1  christos 	unsigned i;
    389           1.1  christos 	size_t sz, psz, qsz;
    390           1.1  christos 
    391           1.1  christos 	psz = 42;
    392           1.1  christos 	qsz = nallocx(psz, 0) + 1;
    393           1.1  christos 
    394           1.1  christos 	/* Create tcaches. */
    395           1.1  christos 	for (i = 0; i < NTCACHES; i++) {
    396           1.1  christos 		sz = sizeof(unsigned);
    397  1.1.1.1.14.1  perseant 		expect_d_eq(mallctl("tcache.create", (void *)&tis[i], &sz, NULL,
    398           1.1  christos 		    0), 0, "Unexpected mallctl() failure, i=%u", i);
    399           1.1  christos 	}
    400           1.1  christos 
    401           1.1  christos 	/* Exercise tcache ID recycling. */
    402           1.1  christos 	for (i = 0; i < NTCACHES; i++) {
    403  1.1.1.1.14.1  perseant 		expect_d_eq(mallctl("tcache.destroy", NULL, NULL,
    404           1.1  christos 		    (void *)&tis[i], sizeof(unsigned)), 0,
    405           1.1  christos 		    "Unexpected mallctl() failure, i=%u", i);
    406           1.1  christos 	}
    407           1.1  christos 	for (i = 0; i < NTCACHES; i++) {
    408           1.1  christos 		sz = sizeof(unsigned);
    409  1.1.1.1.14.1  perseant 		expect_d_eq(mallctl("tcache.create", (void *)&tis[i], &sz, NULL,
    410           1.1  christos 		    0), 0, "Unexpected mallctl() failure, i=%u", i);
    411           1.1  christos 	}
    412           1.1  christos 
    413           1.1  christos 	/* Flush empty tcaches. */
    414           1.1  christos 	for (i = 0; i < NTCACHES; i++) {
    415  1.1.1.1.14.1  perseant 		expect_d_eq(mallctl("tcache.flush", NULL, NULL, (void *)&tis[i],
    416           1.1  christos 		    sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
    417           1.1  christos 		    i);
    418           1.1  christos 	}
    419           1.1  christos 
    420           1.1  christos 	/* Cache some allocations. */
    421           1.1  christos 	for (i = 0; i < NTCACHES; i++) {
    422           1.1  christos 		ps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i]));
    423  1.1.1.1.14.1  perseant 		expect_ptr_not_null(ps[i], "Unexpected mallocx() failure, i=%u",
    424           1.1  christos 		    i);
    425           1.1  christos 		dallocx(ps[i], MALLOCX_TCACHE(tis[i]));
    426           1.1  christos 
    427           1.1  christos 		qs[i] = mallocx(qsz, MALLOCX_TCACHE(tis[i]));
    428  1.1.1.1.14.1  perseant 		expect_ptr_not_null(qs[i], "Unexpected mallocx() failure, i=%u",
    429           1.1  christos 		    i);
    430           1.1  christos 		dallocx(qs[i], MALLOCX_TCACHE(tis[i]));
    431           1.1  christos 	}
    432           1.1  christos 
    433           1.1  christos 	/* Verify that tcaches allocate cached regions. */
    434           1.1  christos 	for (i = 0; i < NTCACHES; i++) {
    435           1.1  christos 		void *p0 = ps[i];
    436           1.1  christos 		ps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i]));
    437  1.1.1.1.14.1  perseant 		expect_ptr_not_null(ps[i], "Unexpected mallocx() failure, i=%u",
    438           1.1  christos 		    i);
    439  1.1.1.1.14.1  perseant 		if (!san_uaf_detection_enabled()) {
    440  1.1.1.1.14.1  perseant 			expect_ptr_eq(ps[i], p0, "Expected mallocx() to "
    441  1.1.1.1.14.1  perseant 			    "allocate cached region, i=%u", i);
    442  1.1.1.1.14.1  perseant 		}
    443           1.1  christos 	}
    444           1.1  christos 
    445           1.1  christos 	/* Verify that reallocation uses cached regions. */
    446           1.1  christos 	for (i = 0; i < NTCACHES; i++) {
    447           1.1  christos 		void *q0 = qs[i];
    448           1.1  christos 		qs[i] = rallocx(ps[i], qsz, MALLOCX_TCACHE(tis[i]));
    449  1.1.1.1.14.1  perseant 		expect_ptr_not_null(qs[i], "Unexpected rallocx() failure, i=%u",
    450           1.1  christos 		    i);
    451  1.1.1.1.14.1  perseant 		if (!san_uaf_detection_enabled()) {
    452  1.1.1.1.14.1  perseant 			expect_ptr_eq(qs[i], q0, "Expected rallocx() to "
    453  1.1.1.1.14.1  perseant 			    "allocate cached region, i=%u", i);
    454  1.1.1.1.14.1  perseant 		}
    455           1.1  christos 		/* Avoid undefined behavior in case of test failure. */
    456           1.1  christos 		if (qs[i] == NULL) {
    457           1.1  christos 			qs[i] = ps[i];
    458           1.1  christos 		}
    459           1.1  christos 	}
    460           1.1  christos 	for (i = 0; i < NTCACHES; i++) {
    461           1.1  christos 		dallocx(qs[i], MALLOCX_TCACHE(tis[i]));
    462           1.1  christos 	}
    463           1.1  christos 
    464           1.1  christos 	/* Flush some non-empty tcaches. */
    465           1.1  christos 	for (i = 0; i < NTCACHES/2; i++) {
    466  1.1.1.1.14.1  perseant 		expect_d_eq(mallctl("tcache.flush", NULL, NULL, (void *)&tis[i],
    467           1.1  christos 		    sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
    468           1.1  christos 		    i);
    469           1.1  christos 	}
    470           1.1  christos 
    471           1.1  christos 	/* Destroy tcaches. */
    472           1.1  christos 	for (i = 0; i < NTCACHES; i++) {
    473  1.1.1.1.14.1  perseant 		expect_d_eq(mallctl("tcache.destroy", NULL, NULL,
    474           1.1  christos 		    (void *)&tis[i], sizeof(unsigned)), 0,
    475           1.1  christos 		    "Unexpected mallctl() failure, i=%u", i);
    476           1.1  christos 	}
    477           1.1  christos }
    478           1.1  christos TEST_END
    479           1.1  christos 
    480           1.1  christos TEST_BEGIN(test_thread_arena) {
    481           1.1  christos 	unsigned old_arena_ind, new_arena_ind, narenas;
    482           1.1  christos 
    483           1.1  christos 	const char *opa;
    484           1.1  christos 	size_t sz = sizeof(opa);
    485  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("opt.percpu_arena", (void *)&opa, &sz, NULL, 0), 0,
    486           1.1  christos 	    "Unexpected mallctl() failure");
    487           1.1  christos 
    488           1.1  christos 	sz = sizeof(unsigned);
    489  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.narenas", (void *)&narenas, &sz, NULL, 0),
    490           1.1  christos 	    0, "Unexpected mallctl() failure");
    491  1.1.1.1.14.1  perseant 	if (opt_oversize_threshold != 0) {
    492  1.1.1.1.14.1  perseant 		narenas--;
    493  1.1.1.1.14.1  perseant 	}
    494  1.1.1.1.14.1  perseant 	expect_u_eq(narenas, opt_narenas, "Number of arenas incorrect");
    495           1.1  christos 
    496           1.1  christos 	if (strcmp(opa, "disabled") == 0) {
    497           1.1  christos 		new_arena_ind = narenas - 1;
    498  1.1.1.1.14.1  perseant 		expect_d_eq(mallctl("thread.arena", (void *)&old_arena_ind, &sz,
    499           1.1  christos 		    (void *)&new_arena_ind, sizeof(unsigned)), 0,
    500           1.1  christos 		    "Unexpected mallctl() failure");
    501           1.1  christos 		new_arena_ind = 0;
    502  1.1.1.1.14.1  perseant 		expect_d_eq(mallctl("thread.arena", (void *)&old_arena_ind, &sz,
    503           1.1  christos 		    (void *)&new_arena_ind, sizeof(unsigned)), 0,
    504           1.1  christos 		    "Unexpected mallctl() failure");
    505           1.1  christos 	} else {
    506  1.1.1.1.14.1  perseant 		expect_d_eq(mallctl("thread.arena", (void *)&old_arena_ind, &sz,
    507           1.1  christos 		    NULL, 0), 0, "Unexpected mallctl() failure");
    508           1.1  christos 		new_arena_ind = percpu_arena_ind_limit(opt_percpu_arena) - 1;
    509           1.1  christos 		if (old_arena_ind != new_arena_ind) {
    510  1.1.1.1.14.1  perseant 			expect_d_eq(mallctl("thread.arena",
    511           1.1  christos 			    (void *)&old_arena_ind, &sz, (void *)&new_arena_ind,
    512           1.1  christos 			    sizeof(unsigned)), EPERM, "thread.arena ctl "
    513           1.1  christos 			    "should not be allowed with percpu arena");
    514           1.1  christos 		}
    515           1.1  christos 	}
    516           1.1  christos }
    517           1.1  christos TEST_END
    518           1.1  christos 
    519           1.1  christos TEST_BEGIN(test_arena_i_initialized) {
    520           1.1  christos 	unsigned narenas, i;
    521           1.1  christos 	size_t sz;
    522           1.1  christos 	size_t mib[3];
    523           1.1  christos 	size_t miblen = sizeof(mib) / sizeof(size_t);
    524           1.1  christos 	bool initialized;
    525           1.1  christos 
    526           1.1  christos 	sz = sizeof(narenas);
    527  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.narenas", (void *)&narenas, &sz, NULL, 0),
    528           1.1  christos 	    0, "Unexpected mallctl() failure");
    529           1.1  christos 
    530  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlnametomib("arena.0.initialized", mib, &miblen), 0,
    531           1.1  christos 	    "Unexpected mallctlnametomib() failure");
    532           1.1  christos 	for (i = 0; i < narenas; i++) {
    533           1.1  christos 		mib[1] = i;
    534           1.1  christos 		sz = sizeof(initialized);
    535  1.1.1.1.14.1  perseant 		expect_d_eq(mallctlbymib(mib, miblen, &initialized, &sz, NULL,
    536           1.1  christos 		    0), 0, "Unexpected mallctl() failure");
    537           1.1  christos 	}
    538           1.1  christos 
    539           1.1  christos 	mib[1] = MALLCTL_ARENAS_ALL;
    540           1.1  christos 	sz = sizeof(initialized);
    541  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, &initialized, &sz, NULL, 0), 0,
    542           1.1  christos 	    "Unexpected mallctl() failure");
    543  1.1.1.1.14.1  perseant 	expect_true(initialized,
    544           1.1  christos 	    "Merged arena statistics should always be initialized");
    545           1.1  christos 
    546           1.1  christos 	/* Equivalent to the above but using mallctl() directly. */
    547           1.1  christos 	sz = sizeof(initialized);
    548  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl(
    549           1.1  christos 	    "arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".initialized",
    550           1.1  christos 	    (void *)&initialized, &sz, NULL, 0), 0,
    551           1.1  christos 	    "Unexpected mallctl() failure");
    552  1.1.1.1.14.1  perseant 	expect_true(initialized,
    553           1.1  christos 	    "Merged arena statistics should always be initialized");
    554           1.1  christos }
    555           1.1  christos TEST_END
    556           1.1  christos 
    557           1.1  christos TEST_BEGIN(test_arena_i_dirty_decay_ms) {
    558           1.1  christos 	ssize_t dirty_decay_ms, orig_dirty_decay_ms, prev_dirty_decay_ms;
    559           1.1  christos 	size_t sz = sizeof(ssize_t);
    560           1.1  christos 
    561  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arena.0.dirty_decay_ms",
    562           1.1  christos 	    (void *)&orig_dirty_decay_ms, &sz, NULL, 0), 0,
    563           1.1  christos 	    "Unexpected mallctl() failure");
    564           1.1  christos 
    565           1.1  christos 	dirty_decay_ms = -2;
    566  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arena.0.dirty_decay_ms", NULL, NULL,
    567           1.1  christos 	    (void *)&dirty_decay_ms, sizeof(ssize_t)), EFAULT,
    568           1.1  christos 	    "Unexpected mallctl() success");
    569           1.1  christos 
    570           1.1  christos 	dirty_decay_ms = 0x7fffffff;
    571  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arena.0.dirty_decay_ms", NULL, NULL,
    572           1.1  christos 	    (void *)&dirty_decay_ms, sizeof(ssize_t)), 0,
    573           1.1  christos 	    "Unexpected mallctl() failure");
    574           1.1  christos 
    575           1.1  christos 	for (prev_dirty_decay_ms = dirty_decay_ms, dirty_decay_ms = -1;
    576           1.1  christos 	    dirty_decay_ms < 20; prev_dirty_decay_ms = dirty_decay_ms,
    577           1.1  christos 	    dirty_decay_ms++) {
    578           1.1  christos 		ssize_t old_dirty_decay_ms;
    579           1.1  christos 
    580  1.1.1.1.14.1  perseant 		expect_d_eq(mallctl("arena.0.dirty_decay_ms",
    581           1.1  christos 		    (void *)&old_dirty_decay_ms, &sz, (void *)&dirty_decay_ms,
    582           1.1  christos 		    sizeof(ssize_t)), 0, "Unexpected mallctl() failure");
    583  1.1.1.1.14.1  perseant 		expect_zd_eq(old_dirty_decay_ms, prev_dirty_decay_ms,
    584           1.1  christos 		    "Unexpected old arena.0.dirty_decay_ms");
    585           1.1  christos 	}
    586           1.1  christos }
    587           1.1  christos TEST_END
    588           1.1  christos 
    589           1.1  christos TEST_BEGIN(test_arena_i_muzzy_decay_ms) {
    590           1.1  christos 	ssize_t muzzy_decay_ms, orig_muzzy_decay_ms, prev_muzzy_decay_ms;
    591           1.1  christos 	size_t sz = sizeof(ssize_t);
    592           1.1  christos 
    593  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arena.0.muzzy_decay_ms",
    594           1.1  christos 	    (void *)&orig_muzzy_decay_ms, &sz, NULL, 0), 0,
    595           1.1  christos 	    "Unexpected mallctl() failure");
    596           1.1  christos 
    597           1.1  christos 	muzzy_decay_ms = -2;
    598  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arena.0.muzzy_decay_ms", NULL, NULL,
    599           1.1  christos 	    (void *)&muzzy_decay_ms, sizeof(ssize_t)), EFAULT,
    600           1.1  christos 	    "Unexpected mallctl() success");
    601           1.1  christos 
    602           1.1  christos 	muzzy_decay_ms = 0x7fffffff;
    603  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arena.0.muzzy_decay_ms", NULL, NULL,
    604           1.1  christos 	    (void *)&muzzy_decay_ms, sizeof(ssize_t)), 0,
    605           1.1  christos 	    "Unexpected mallctl() failure");
    606           1.1  christos 
    607           1.1  christos 	for (prev_muzzy_decay_ms = muzzy_decay_ms, muzzy_decay_ms = -1;
    608           1.1  christos 	    muzzy_decay_ms < 20; prev_muzzy_decay_ms = muzzy_decay_ms,
    609           1.1  christos 	    muzzy_decay_ms++) {
    610           1.1  christos 		ssize_t old_muzzy_decay_ms;
    611           1.1  christos 
    612  1.1.1.1.14.1  perseant 		expect_d_eq(mallctl("arena.0.muzzy_decay_ms",
    613           1.1  christos 		    (void *)&old_muzzy_decay_ms, &sz, (void *)&muzzy_decay_ms,
    614           1.1  christos 		    sizeof(ssize_t)), 0, "Unexpected mallctl() failure");
    615  1.1.1.1.14.1  perseant 		expect_zd_eq(old_muzzy_decay_ms, prev_muzzy_decay_ms,
    616           1.1  christos 		    "Unexpected old arena.0.muzzy_decay_ms");
    617           1.1  christos 	}
    618           1.1  christos }
    619           1.1  christos TEST_END
    620           1.1  christos 
    621           1.1  christos TEST_BEGIN(test_arena_i_purge) {
    622           1.1  christos 	unsigned narenas;
    623           1.1  christos 	size_t sz = sizeof(unsigned);
    624           1.1  christos 	size_t mib[3];
    625           1.1  christos 	size_t miblen = 3;
    626           1.1  christos 
    627  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
    628           1.1  christos 	    "Unexpected mallctl() failure");
    629           1.1  christos 
    630  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.narenas", (void *)&narenas, &sz, NULL, 0),
    631           1.1  christos 	    0, "Unexpected mallctl() failure");
    632  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlnametomib("arena.0.purge", mib, &miblen), 0,
    633           1.1  christos 	    "Unexpected mallctlnametomib() failure");
    634           1.1  christos 	mib[1] = narenas;
    635  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,
    636           1.1  christos 	    "Unexpected mallctlbymib() failure");
    637           1.1  christos 
    638           1.1  christos 	mib[1] = MALLCTL_ARENAS_ALL;
    639  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,
    640           1.1  christos 	    "Unexpected mallctlbymib() failure");
    641           1.1  christos }
    642           1.1  christos TEST_END
    643           1.1  christos 
    644           1.1  christos TEST_BEGIN(test_arena_i_decay) {
    645           1.1  christos 	unsigned narenas;
    646           1.1  christos 	size_t sz = sizeof(unsigned);
    647           1.1  christos 	size_t mib[3];
    648           1.1  christos 	size_t miblen = 3;
    649           1.1  christos 
    650  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arena.0.decay", NULL, NULL, NULL, 0), 0,
    651           1.1  christos 	    "Unexpected mallctl() failure");
    652           1.1  christos 
    653  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.narenas", (void *)&narenas, &sz, NULL, 0),
    654           1.1  christos 	    0, "Unexpected mallctl() failure");
    655  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlnametomib("arena.0.decay", mib, &miblen), 0,
    656           1.1  christos 	    "Unexpected mallctlnametomib() failure");
    657           1.1  christos 	mib[1] = narenas;
    658  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,
    659           1.1  christos 	    "Unexpected mallctlbymib() failure");
    660           1.1  christos 
    661           1.1  christos 	mib[1] = MALLCTL_ARENAS_ALL;
    662  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,
    663           1.1  christos 	    "Unexpected mallctlbymib() failure");
    664           1.1  christos }
    665           1.1  christos TEST_END
    666           1.1  christos 
    667           1.1  christos TEST_BEGIN(test_arena_i_dss) {
    668           1.1  christos 	const char *dss_prec_old, *dss_prec_new;
    669           1.1  christos 	size_t sz = sizeof(dss_prec_old);
    670           1.1  christos 	size_t mib[3];
    671           1.1  christos 	size_t miblen;
    672           1.1  christos 
    673           1.1  christos 	miblen = sizeof(mib)/sizeof(size_t);
    674  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlnametomib("arena.0.dss", mib, &miblen), 0,
    675           1.1  christos 	    "Unexpected mallctlnametomib() error");
    676           1.1  christos 
    677           1.1  christos 	dss_prec_new = "disabled";
    678  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_old, &sz,
    679           1.1  christos 	    (void *)&dss_prec_new, sizeof(dss_prec_new)), 0,
    680           1.1  christos 	    "Unexpected mallctl() failure");
    681  1.1.1.1.14.1  perseant 	expect_str_ne(dss_prec_old, "primary",
    682           1.1  christos 	    "Unexpected default for dss precedence");
    683           1.1  christos 
    684  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_new, &sz,
    685           1.1  christos 	    (void *)&dss_prec_old, sizeof(dss_prec_old)), 0,
    686           1.1  christos 	    "Unexpected mallctl() failure");
    687           1.1  christos 
    688  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_old, &sz, NULL,
    689           1.1  christos 	    0), 0, "Unexpected mallctl() failure");
    690  1.1.1.1.14.1  perseant 	expect_str_ne(dss_prec_old, "primary",
    691           1.1  christos 	    "Unexpected value for dss precedence");
    692           1.1  christos 
    693           1.1  christos 	mib[1] = narenas_total_get();
    694           1.1  christos 	dss_prec_new = "disabled";
    695  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_old, &sz,
    696           1.1  christos 	    (void *)&dss_prec_new, sizeof(dss_prec_new)), 0,
    697           1.1  christos 	    "Unexpected mallctl() failure");
    698  1.1.1.1.14.1  perseant 	expect_str_ne(dss_prec_old, "primary",
    699           1.1  christos 	    "Unexpected default for dss precedence");
    700           1.1  christos 
    701  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_new, &sz,
    702           1.1  christos 	    (void *)&dss_prec_old, sizeof(dss_prec_new)), 0,
    703           1.1  christos 	    "Unexpected mallctl() failure");
    704           1.1  christos 
    705  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, (void *)&dss_prec_old, &sz, NULL,
    706           1.1  christos 	    0), 0, "Unexpected mallctl() failure");
    707  1.1.1.1.14.1  perseant 	expect_str_ne(dss_prec_old, "primary",
    708           1.1  christos 	    "Unexpected value for dss precedence");
    709           1.1  christos }
    710           1.1  christos TEST_END
    711           1.1  christos 
    712           1.1  christos TEST_BEGIN(test_arena_i_retain_grow_limit) {
    713           1.1  christos 	size_t old_limit, new_limit, default_limit;
    714           1.1  christos 	size_t mib[3];
    715           1.1  christos 	size_t miblen;
    716           1.1  christos 
    717           1.1  christos 	bool retain_enabled;
    718           1.1  christos 	size_t sz = sizeof(retain_enabled);
    719  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("opt.retain", &retain_enabled, &sz, NULL, 0),
    720           1.1  christos 	    0, "Unexpected mallctl() failure");
    721           1.1  christos 	test_skip_if(!retain_enabled);
    722           1.1  christos 
    723           1.1  christos 	sz = sizeof(default_limit);
    724           1.1  christos 	miblen = sizeof(mib)/sizeof(size_t);
    725  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlnametomib("arena.0.retain_grow_limit", mib, &miblen),
    726           1.1  christos 	    0, "Unexpected mallctlnametomib() error");
    727           1.1  christos 
    728  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, &default_limit, &sz, NULL, 0), 0,
    729           1.1  christos 	    "Unexpected mallctl() failure");
    730  1.1.1.1.14.1  perseant 	expect_zu_eq(default_limit, SC_LARGE_MAXCLASS,
    731           1.1  christos 	    "Unexpected default for retain_grow_limit");
    732           1.1  christos 
    733           1.1  christos 	new_limit = PAGE - 1;
    734  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &new_limit,
    735           1.1  christos 	    sizeof(new_limit)), EFAULT, "Unexpected mallctl() success");
    736           1.1  christos 
    737           1.1  christos 	new_limit = PAGE + 1;
    738  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &new_limit,
    739           1.1  christos 	    sizeof(new_limit)), 0, "Unexpected mallctl() failure");
    740  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, &old_limit, &sz, NULL, 0), 0,
    741           1.1  christos 	    "Unexpected mallctl() failure");
    742  1.1.1.1.14.1  perseant 	expect_zu_eq(old_limit, PAGE,
    743           1.1  christos 	    "Unexpected value for retain_grow_limit");
    744           1.1  christos 
    745           1.1  christos 	/* Expect grow less than psize class 10. */
    746           1.1  christos 	new_limit = sz_pind2sz(10) - 1;
    747  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &new_limit,
    748           1.1  christos 	    sizeof(new_limit)), 0, "Unexpected mallctl() failure");
    749  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, &old_limit, &sz, NULL, 0), 0,
    750           1.1  christos 	    "Unexpected mallctl() failure");
    751  1.1.1.1.14.1  perseant 	expect_zu_eq(old_limit, sz_pind2sz(9),
    752           1.1  christos 	    "Unexpected value for retain_grow_limit");
    753           1.1  christos 
    754           1.1  christos 	/* Restore to default. */
    755  1.1.1.1.14.1  perseant 	expect_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &default_limit,
    756           1.1  christos 	    sizeof(default_limit)), 0, "Unexpected mallctl() failure");
    757           1.1  christos }
    758           1.1  christos TEST_END
    759           1.1  christos 
    760           1.1  christos TEST_BEGIN(test_arenas_dirty_decay_ms) {
    761           1.1  christos 	ssize_t dirty_decay_ms, orig_dirty_decay_ms, prev_dirty_decay_ms;
    762           1.1  christos 	size_t sz = sizeof(ssize_t);
    763           1.1  christos 
    764  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.dirty_decay_ms",
    765           1.1  christos 	    (void *)&orig_dirty_decay_ms, &sz, NULL, 0), 0,
    766           1.1  christos 	    "Unexpected mallctl() failure");
    767           1.1  christos 
    768           1.1  christos 	dirty_decay_ms = -2;
    769  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.dirty_decay_ms", NULL, NULL,
    770           1.1  christos 	    (void *)&dirty_decay_ms, sizeof(ssize_t)), EFAULT,
    771           1.1  christos 	    "Unexpected mallctl() success");
    772           1.1  christos 
    773           1.1  christos 	dirty_decay_ms = 0x7fffffff;
    774  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.dirty_decay_ms", NULL, NULL,
    775           1.1  christos 	    (void *)&dirty_decay_ms, sizeof(ssize_t)), 0,
    776           1.1  christos 	    "Expected mallctl() failure");
    777           1.1  christos 
    778           1.1  christos 	for (prev_dirty_decay_ms = dirty_decay_ms, dirty_decay_ms = -1;
    779           1.1  christos 	    dirty_decay_ms < 20; prev_dirty_decay_ms = dirty_decay_ms,
    780           1.1  christos 	    dirty_decay_ms++) {
    781           1.1  christos 		ssize_t old_dirty_decay_ms;
    782           1.1  christos 
    783  1.1.1.1.14.1  perseant 		expect_d_eq(mallctl("arenas.dirty_decay_ms",
    784           1.1  christos 		    (void *)&old_dirty_decay_ms, &sz, (void *)&dirty_decay_ms,
    785           1.1  christos 		    sizeof(ssize_t)), 0, "Unexpected mallctl() failure");
    786  1.1.1.1.14.1  perseant 		expect_zd_eq(old_dirty_decay_ms, prev_dirty_decay_ms,
    787           1.1  christos 		    "Unexpected old arenas.dirty_decay_ms");
    788           1.1  christos 	}
    789           1.1  christos }
    790           1.1  christos TEST_END
    791           1.1  christos 
    792           1.1  christos TEST_BEGIN(test_arenas_muzzy_decay_ms) {
    793           1.1  christos 	ssize_t muzzy_decay_ms, orig_muzzy_decay_ms, prev_muzzy_decay_ms;
    794           1.1  christos 	size_t sz = sizeof(ssize_t);
    795           1.1  christos 
    796  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.muzzy_decay_ms",
    797           1.1  christos 	    (void *)&orig_muzzy_decay_ms, &sz, NULL, 0), 0,
    798           1.1  christos 	    "Unexpected mallctl() failure");
    799           1.1  christos 
    800           1.1  christos 	muzzy_decay_ms = -2;
    801  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.muzzy_decay_ms", NULL, NULL,
    802           1.1  christos 	    (void *)&muzzy_decay_ms, sizeof(ssize_t)), EFAULT,
    803           1.1  christos 	    "Unexpected mallctl() success");
    804           1.1  christos 
    805           1.1  christos 	muzzy_decay_ms = 0x7fffffff;
    806  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.muzzy_decay_ms", NULL, NULL,
    807           1.1  christos 	    (void *)&muzzy_decay_ms, sizeof(ssize_t)), 0,
    808           1.1  christos 	    "Expected mallctl() failure");
    809           1.1  christos 
    810           1.1  christos 	for (prev_muzzy_decay_ms = muzzy_decay_ms, muzzy_decay_ms = -1;
    811           1.1  christos 	    muzzy_decay_ms < 20; prev_muzzy_decay_ms = muzzy_decay_ms,
    812           1.1  christos 	    muzzy_decay_ms++) {
    813           1.1  christos 		ssize_t old_muzzy_decay_ms;
    814           1.1  christos 
    815  1.1.1.1.14.1  perseant 		expect_d_eq(mallctl("arenas.muzzy_decay_ms",
    816           1.1  christos 		    (void *)&old_muzzy_decay_ms, &sz, (void *)&muzzy_decay_ms,
    817           1.1  christos 		    sizeof(ssize_t)), 0, "Unexpected mallctl() failure");
    818  1.1.1.1.14.1  perseant 		expect_zd_eq(old_muzzy_decay_ms, prev_muzzy_decay_ms,
    819           1.1  christos 		    "Unexpected old arenas.muzzy_decay_ms");
    820           1.1  christos 	}
    821           1.1  christos }
    822           1.1  christos TEST_END
    823           1.1  christos 
    824           1.1  christos TEST_BEGIN(test_arenas_constants) {
    825           1.1  christos #define TEST_ARENAS_CONSTANT(t, name, expected) do {			\
    826           1.1  christos 	t name;								\
    827           1.1  christos 	size_t sz = sizeof(t);						\
    828  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas."#name, (void *)&name, &sz, NULL,	\
    829           1.1  christos 	    0), 0, "Unexpected mallctl() failure");			\
    830  1.1.1.1.14.1  perseant 	expect_zu_eq(name, expected, "Incorrect "#name" size");		\
    831           1.1  christos } while (0)
    832           1.1  christos 
    833           1.1  christos 	TEST_ARENAS_CONSTANT(size_t, quantum, QUANTUM);
    834           1.1  christos 	TEST_ARENAS_CONSTANT(size_t, page, PAGE);
    835  1.1.1.1.14.1  perseant 	TEST_ARENAS_CONSTANT(unsigned, nbins, SC_NBINS);
    836  1.1.1.1.14.1  perseant 	TEST_ARENAS_CONSTANT(unsigned, nlextents, SC_NSIZES - SC_NBINS);
    837           1.1  christos 
    838           1.1  christos #undef TEST_ARENAS_CONSTANT
    839           1.1  christos }
    840           1.1  christos TEST_END
    841           1.1  christos 
    842           1.1  christos TEST_BEGIN(test_arenas_bin_constants) {
    843           1.1  christos #define TEST_ARENAS_BIN_CONSTANT(t, name, expected) do {		\
    844           1.1  christos 	t name;								\
    845           1.1  christos 	size_t sz = sizeof(t);						\
    846  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.bin.0."#name, (void *)&name, &sz,	\
    847           1.1  christos 	    NULL, 0), 0, "Unexpected mallctl() failure");		\
    848  1.1.1.1.14.1  perseant 	expect_zu_eq(name, expected, "Incorrect "#name" size");		\
    849           1.1  christos } while (0)
    850           1.1  christos 
    851           1.1  christos 	TEST_ARENAS_BIN_CONSTANT(size_t, size, bin_infos[0].reg_size);
    852           1.1  christos 	TEST_ARENAS_BIN_CONSTANT(uint32_t, nregs, bin_infos[0].nregs);
    853           1.1  christos 	TEST_ARENAS_BIN_CONSTANT(size_t, slab_size,
    854           1.1  christos 	    bin_infos[0].slab_size);
    855  1.1.1.1.14.1  perseant 	TEST_ARENAS_BIN_CONSTANT(uint32_t, nshards, bin_infos[0].n_shards);
    856           1.1  christos 
    857           1.1  christos #undef TEST_ARENAS_BIN_CONSTANT
    858           1.1  christos }
    859           1.1  christos TEST_END
    860           1.1  christos 
    861           1.1  christos TEST_BEGIN(test_arenas_lextent_constants) {
    862           1.1  christos #define TEST_ARENAS_LEXTENT_CONSTANT(t, name, expected) do {		\
    863           1.1  christos 	t name;								\
    864           1.1  christos 	size_t sz = sizeof(t);						\
    865  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.lextent.0."#name, (void *)&name,	\
    866           1.1  christos 	    &sz, NULL, 0), 0, "Unexpected mallctl() failure");		\
    867  1.1.1.1.14.1  perseant 	expect_zu_eq(name, expected, "Incorrect "#name" size");		\
    868           1.1  christos } while (0)
    869           1.1  christos 
    870  1.1.1.1.14.1  perseant 	TEST_ARENAS_LEXTENT_CONSTANT(size_t, size,
    871  1.1.1.1.14.1  perseant 	    SC_LARGE_MINCLASS);
    872           1.1  christos 
    873           1.1  christos #undef TEST_ARENAS_LEXTENT_CONSTANT
    874           1.1  christos }
    875           1.1  christos TEST_END
    876           1.1  christos 
    877           1.1  christos TEST_BEGIN(test_arenas_create) {
    878           1.1  christos 	unsigned narenas_before, arena, narenas_after;
    879           1.1  christos 	size_t sz = sizeof(unsigned);
    880           1.1  christos 
    881  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.narenas", (void *)&narenas_before, &sz,
    882           1.1  christos 	    NULL, 0), 0, "Unexpected mallctl() failure");
    883  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.create", (void *)&arena, &sz, NULL, 0), 0,
    884           1.1  christos 	    "Unexpected mallctl() failure");
    885  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.narenas", (void *)&narenas_after, &sz, NULL,
    886           1.1  christos 	    0), 0, "Unexpected mallctl() failure");
    887           1.1  christos 
    888  1.1.1.1.14.1  perseant 	expect_u_eq(narenas_before+1, narenas_after,
    889           1.1  christos 	    "Unexpected number of arenas before versus after extension");
    890  1.1.1.1.14.1  perseant 	expect_u_eq(arena, narenas_after-1, "Unexpected arena index");
    891           1.1  christos }
    892           1.1  christos TEST_END
    893           1.1  christos 
    894           1.1  christos TEST_BEGIN(test_arenas_lookup) {
    895           1.1  christos 	unsigned arena, arena1;
    896           1.1  christos 	void *ptr;
    897           1.1  christos 	size_t sz = sizeof(unsigned);
    898           1.1  christos 
    899  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.create", (void *)&arena, &sz, NULL, 0), 0,
    900           1.1  christos 	    "Unexpected mallctl() failure");
    901           1.1  christos 	ptr = mallocx(42, MALLOCX_ARENA(arena) | MALLOCX_TCACHE_NONE);
    902  1.1.1.1.14.1  perseant 	expect_ptr_not_null(ptr, "Unexpected mallocx() failure");
    903  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("arenas.lookup", &arena1, &sz, &ptr, sizeof(ptr)),
    904           1.1  christos 	    0, "Unexpected mallctl() failure");
    905  1.1.1.1.14.1  perseant 	expect_u_eq(arena, arena1, "Unexpected arena index");
    906           1.1  christos 	dallocx(ptr, 0);
    907           1.1  christos }
    908           1.1  christos TEST_END
    909           1.1  christos 
    910  1.1.1.1.14.1  perseant TEST_BEGIN(test_prof_active) {
    911  1.1.1.1.14.1  perseant 	/*
    912  1.1.1.1.14.1  perseant 	 * If config_prof is off, then the test for prof_active in
    913  1.1.1.1.14.1  perseant 	 * test_mallctl_opt was already enough.
    914  1.1.1.1.14.1  perseant 	 */
    915  1.1.1.1.14.1  perseant 	test_skip_if(!config_prof);
    916  1.1.1.1.14.1  perseant 	test_skip_if(opt_prof);
    917  1.1.1.1.14.1  perseant 
    918  1.1.1.1.14.1  perseant 	bool active, old;
    919  1.1.1.1.14.1  perseant 	size_t len = sizeof(bool);
    920  1.1.1.1.14.1  perseant 
    921  1.1.1.1.14.1  perseant 	active = true;
    922  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("prof.active", NULL, NULL, &active, len), ENOENT,
    923  1.1.1.1.14.1  perseant 	    "Setting prof_active to true should fail when opt_prof is off");
    924  1.1.1.1.14.1  perseant 	old = true;
    925  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("prof.active", &old, &len, &active, len), ENOENT,
    926  1.1.1.1.14.1  perseant 	    "Setting prof_active to true should fail when opt_prof is off");
    927  1.1.1.1.14.1  perseant 	expect_true(old, "old value should not be touched when mallctl fails");
    928  1.1.1.1.14.1  perseant 	active = false;
    929  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("prof.active", NULL, NULL, &active, len), 0,
    930  1.1.1.1.14.1  perseant 	    "Setting prof_active to false should succeed when opt_prof is off");
    931  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("prof.active", &old, &len, &active, len), 0,
    932  1.1.1.1.14.1  perseant 	    "Setting prof_active to false should succeed when opt_prof is off");
    933  1.1.1.1.14.1  perseant 	expect_false(old, "prof_active should be false when opt_prof is off");
    934  1.1.1.1.14.1  perseant }
    935  1.1.1.1.14.1  perseant TEST_END
    936  1.1.1.1.14.1  perseant 
    937           1.1  christos TEST_BEGIN(test_stats_arenas) {
    938           1.1  christos #define TEST_STATS_ARENAS(t, name) do {					\
    939           1.1  christos 	t name;								\
    940           1.1  christos 	size_t sz = sizeof(t);						\
    941  1.1.1.1.14.1  perseant 	expect_d_eq(mallctl("stats.arenas.0."#name, (void *)&name, &sz,	\
    942           1.1  christos 	    NULL, 0), 0, "Unexpected mallctl() failure");		\
    943           1.1  christos } while (0)
    944           1.1  christos 
    945           1.1  christos 	TEST_STATS_ARENAS(unsigned, nthreads);
    946           1.1  christos 	TEST_STATS_ARENAS(const char *, dss);
    947           1.1  christos 	TEST_STATS_ARENAS(ssize_t, dirty_decay_ms);
    948           1.1  christos 	TEST_STATS_ARENAS(ssize_t, muzzy_decay_ms);
    949           1.1  christos 	TEST_STATS_ARENAS(size_t, pactive);
    950           1.1  christos 	TEST_STATS_ARENAS(size_t, pdirty);
    951           1.1  christos 
    952           1.1  christos #undef TEST_STATS_ARENAS
    953           1.1  christos }
    954           1.1  christos TEST_END
    955           1.1  christos 
    956  1.1.1.1.14.1  perseant static void
    957  1.1.1.1.14.1  perseant alloc_hook(void *extra, UNUSED hook_alloc_t type, UNUSED void *result,
    958  1.1.1.1.14.1  perseant     UNUSED uintptr_t result_raw, UNUSED uintptr_t args_raw[3]) {
    959  1.1.1.1.14.1  perseant 	*(bool *)extra = true;
    960  1.1.1.1.14.1  perseant }
    961  1.1.1.1.14.1  perseant 
    962  1.1.1.1.14.1  perseant static void
    963  1.1.1.1.14.1  perseant dalloc_hook(void *extra, UNUSED hook_dalloc_t type,
    964  1.1.1.1.14.1  perseant     UNUSED void *address, UNUSED uintptr_t args_raw[3]) {
    965  1.1.1.1.14.1  perseant 	*(bool *)extra = true;
    966  1.1.1.1.14.1  perseant }
    967  1.1.1.1.14.1  perseant 
    968  1.1.1.1.14.1  perseant TEST_BEGIN(test_hooks) {
    969  1.1.1.1.14.1  perseant 	bool hook_called = false;
    970  1.1.1.1.14.1  perseant 	hooks_t hooks = {&alloc_hook, &dalloc_hook, NULL, &hook_called};
    971  1.1.1.1.14.1  perseant 	void *handle = NULL;
    972  1.1.1.1.14.1  perseant 	size_t sz = sizeof(handle);
    973  1.1.1.1.14.1  perseant 	int err = mallctl("experimental.hooks.install", &handle, &sz, &hooks,
    974  1.1.1.1.14.1  perseant 	    sizeof(hooks));
    975  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "Hook installation failed");
    976  1.1.1.1.14.1  perseant 	expect_ptr_ne(handle, NULL, "Hook installation gave null handle");
    977  1.1.1.1.14.1  perseant 	void *ptr = mallocx(1, 0);
    978  1.1.1.1.14.1  perseant 	expect_true(hook_called, "Alloc hook not called");
    979  1.1.1.1.14.1  perseant 	hook_called = false;
    980  1.1.1.1.14.1  perseant 	free(ptr);
    981  1.1.1.1.14.1  perseant 	expect_true(hook_called, "Free hook not called");
    982  1.1.1.1.14.1  perseant 
    983  1.1.1.1.14.1  perseant 	err = mallctl("experimental.hooks.remove", NULL, NULL, &handle,
    984  1.1.1.1.14.1  perseant 	    sizeof(handle));
    985  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "Hook removal failed");
    986  1.1.1.1.14.1  perseant 	hook_called = false;
    987  1.1.1.1.14.1  perseant 	ptr = mallocx(1, 0);
    988  1.1.1.1.14.1  perseant 	free(ptr);
    989  1.1.1.1.14.1  perseant 	expect_false(hook_called, "Hook called after removal");
    990  1.1.1.1.14.1  perseant }
    991  1.1.1.1.14.1  perseant TEST_END
    992  1.1.1.1.14.1  perseant 
    993  1.1.1.1.14.1  perseant TEST_BEGIN(test_hooks_exhaustion) {
    994  1.1.1.1.14.1  perseant 	bool hook_called = false;
    995  1.1.1.1.14.1  perseant 	hooks_t hooks = {&alloc_hook, &dalloc_hook, NULL, &hook_called};
    996  1.1.1.1.14.1  perseant 
    997  1.1.1.1.14.1  perseant 	void *handle;
    998  1.1.1.1.14.1  perseant 	void *handles[HOOK_MAX];
    999  1.1.1.1.14.1  perseant 	size_t sz = sizeof(handle);
   1000  1.1.1.1.14.1  perseant 	int err;
   1001  1.1.1.1.14.1  perseant 	for (int i = 0; i < HOOK_MAX; i++) {
   1002  1.1.1.1.14.1  perseant 		handle = NULL;
   1003  1.1.1.1.14.1  perseant 		err = mallctl("experimental.hooks.install", &handle, &sz,
   1004  1.1.1.1.14.1  perseant 		    &hooks, sizeof(hooks));
   1005  1.1.1.1.14.1  perseant 		expect_d_eq(err, 0, "Error installation hooks");
   1006  1.1.1.1.14.1  perseant 		expect_ptr_ne(handle, NULL, "Got NULL handle");
   1007  1.1.1.1.14.1  perseant 		handles[i] = handle;
   1008  1.1.1.1.14.1  perseant 	}
   1009  1.1.1.1.14.1  perseant 	err = mallctl("experimental.hooks.install", &handle, &sz, &hooks,
   1010  1.1.1.1.14.1  perseant 	    sizeof(hooks));
   1011  1.1.1.1.14.1  perseant 	expect_d_eq(err, EAGAIN, "Should have failed hook installation");
   1012  1.1.1.1.14.1  perseant 	for (int i = 0; i < HOOK_MAX; i++) {
   1013  1.1.1.1.14.1  perseant 		err = mallctl("experimental.hooks.remove", NULL, NULL,
   1014  1.1.1.1.14.1  perseant 		    &handles[i], sizeof(handles[i]));
   1015  1.1.1.1.14.1  perseant 		expect_d_eq(err, 0, "Hook removal failed");
   1016  1.1.1.1.14.1  perseant 	}
   1017  1.1.1.1.14.1  perseant 	/* Insertion failed, but then we removed some; it should work now. */
   1018  1.1.1.1.14.1  perseant 	handle = NULL;
   1019  1.1.1.1.14.1  perseant 	err = mallctl("experimental.hooks.install", &handle, &sz, &hooks,
   1020  1.1.1.1.14.1  perseant 	    sizeof(hooks));
   1021  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "Hook insertion failed");
   1022  1.1.1.1.14.1  perseant 	expect_ptr_ne(handle, NULL, "Got NULL handle");
   1023  1.1.1.1.14.1  perseant 	err = mallctl("experimental.hooks.remove", NULL, NULL, &handle,
   1024  1.1.1.1.14.1  perseant 	    sizeof(handle));
   1025  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "Hook removal failed");
   1026  1.1.1.1.14.1  perseant }
   1027  1.1.1.1.14.1  perseant TEST_END
   1028  1.1.1.1.14.1  perseant 
   1029  1.1.1.1.14.1  perseant TEST_BEGIN(test_thread_idle) {
   1030  1.1.1.1.14.1  perseant 	/*
   1031  1.1.1.1.14.1  perseant 	 * We're cheating a little bit in this test, and inferring things about
   1032  1.1.1.1.14.1  perseant 	 * implementation internals (like tcache details).  We have to;
   1033  1.1.1.1.14.1  perseant 	 * thread.idle has no guaranteed effects.  We need stats to make these
   1034  1.1.1.1.14.1  perseant 	 * inferences.
   1035  1.1.1.1.14.1  perseant 	 */
   1036  1.1.1.1.14.1  perseant 	test_skip_if(!config_stats);
   1037  1.1.1.1.14.1  perseant 
   1038  1.1.1.1.14.1  perseant 	int err;
   1039  1.1.1.1.14.1  perseant 	size_t sz;
   1040  1.1.1.1.14.1  perseant 	size_t miblen;
   1041  1.1.1.1.14.1  perseant 
   1042  1.1.1.1.14.1  perseant 	bool tcache_enabled = false;
   1043  1.1.1.1.14.1  perseant 	sz = sizeof(tcache_enabled);
   1044  1.1.1.1.14.1  perseant 	err = mallctl("thread.tcache.enabled", &tcache_enabled, &sz, NULL, 0);
   1045  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1046  1.1.1.1.14.1  perseant 	test_skip_if(!tcache_enabled);
   1047  1.1.1.1.14.1  perseant 
   1048  1.1.1.1.14.1  perseant 	size_t tcache_max;
   1049  1.1.1.1.14.1  perseant 	sz = sizeof(tcache_max);
   1050  1.1.1.1.14.1  perseant 	err = mallctl("arenas.tcache_max", &tcache_max, &sz, NULL, 0);
   1051  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1052  1.1.1.1.14.1  perseant 	test_skip_if(tcache_max == 0);
   1053  1.1.1.1.14.1  perseant 
   1054  1.1.1.1.14.1  perseant 	unsigned arena_ind;
   1055  1.1.1.1.14.1  perseant 	sz = sizeof(arena_ind);
   1056  1.1.1.1.14.1  perseant 	err = mallctl("thread.arena", &arena_ind, &sz, NULL, 0);
   1057  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1058  1.1.1.1.14.1  perseant 
   1059  1.1.1.1.14.1  perseant 	/* We're going to do an allocation of size 1, which we know is small. */
   1060  1.1.1.1.14.1  perseant 	size_t mib[5];
   1061  1.1.1.1.14.1  perseant 	miblen = sizeof(mib)/sizeof(mib[0]);
   1062  1.1.1.1.14.1  perseant 	err = mallctlnametomib("stats.arenas.0.small.ndalloc", mib, &miblen);
   1063  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1064  1.1.1.1.14.1  perseant 	mib[2] = arena_ind;
   1065  1.1.1.1.14.1  perseant 
   1066  1.1.1.1.14.1  perseant 	/*
   1067  1.1.1.1.14.1  perseant 	 * This alloc and dalloc should leave something in the tcache, in a
   1068  1.1.1.1.14.1  perseant 	 * small size's cache bin.
   1069  1.1.1.1.14.1  perseant 	 */
   1070  1.1.1.1.14.1  perseant 	void *ptr = mallocx(1, 0);
   1071  1.1.1.1.14.1  perseant 	dallocx(ptr, 0);
   1072  1.1.1.1.14.1  perseant 
   1073  1.1.1.1.14.1  perseant 	uint64_t epoch;
   1074  1.1.1.1.14.1  perseant 	err = mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch));
   1075  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1076  1.1.1.1.14.1  perseant 
   1077  1.1.1.1.14.1  perseant 	uint64_t small_dalloc_pre_idle;
   1078  1.1.1.1.14.1  perseant 	sz = sizeof(small_dalloc_pre_idle);
   1079  1.1.1.1.14.1  perseant 	err = mallctlbymib(mib, miblen, &small_dalloc_pre_idle, &sz, NULL, 0);
   1080  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1081  1.1.1.1.14.1  perseant 
   1082  1.1.1.1.14.1  perseant 	err = mallctl("thread.idle", NULL, NULL, NULL, 0);
   1083  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1084  1.1.1.1.14.1  perseant 
   1085  1.1.1.1.14.1  perseant 	err = mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch));
   1086  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1087  1.1.1.1.14.1  perseant 
   1088  1.1.1.1.14.1  perseant 	uint64_t small_dalloc_post_idle;
   1089  1.1.1.1.14.1  perseant 	sz = sizeof(small_dalloc_post_idle);
   1090  1.1.1.1.14.1  perseant 	err = mallctlbymib(mib, miblen, &small_dalloc_post_idle, &sz, NULL, 0);
   1091  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1092  1.1.1.1.14.1  perseant 
   1093  1.1.1.1.14.1  perseant 	expect_u64_lt(small_dalloc_pre_idle, small_dalloc_post_idle,
   1094  1.1.1.1.14.1  perseant 	    "Purge didn't flush the tcache");
   1095  1.1.1.1.14.1  perseant }
   1096  1.1.1.1.14.1  perseant TEST_END
   1097  1.1.1.1.14.1  perseant 
   1098  1.1.1.1.14.1  perseant TEST_BEGIN(test_thread_peak) {
   1099  1.1.1.1.14.1  perseant 	test_skip_if(!config_stats);
   1100  1.1.1.1.14.1  perseant 
   1101  1.1.1.1.14.1  perseant 	/*
   1102  1.1.1.1.14.1  perseant 	 * We don't commit to any stable amount of accuracy for peak tracking
   1103  1.1.1.1.14.1  perseant 	 * (in practice, when this test was written, we made sure to be within
   1104  1.1.1.1.14.1  perseant 	 * 100k).  But 10MB is big for more or less any definition of big.
   1105  1.1.1.1.14.1  perseant 	 */
   1106  1.1.1.1.14.1  perseant 	size_t big_size = 10 * 1024 * 1024;
   1107  1.1.1.1.14.1  perseant 	size_t small_size = 256;
   1108  1.1.1.1.14.1  perseant 
   1109  1.1.1.1.14.1  perseant 	void *ptr;
   1110  1.1.1.1.14.1  perseant 	int err;
   1111  1.1.1.1.14.1  perseant 	size_t sz;
   1112  1.1.1.1.14.1  perseant 	uint64_t peak;
   1113  1.1.1.1.14.1  perseant 	sz = sizeof(uint64_t);
   1114  1.1.1.1.14.1  perseant 
   1115  1.1.1.1.14.1  perseant 	err = mallctl("thread.peak.reset", NULL, NULL, NULL, 0);
   1116  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1117  1.1.1.1.14.1  perseant 	ptr = mallocx(SC_SMALL_MAXCLASS, 0);
   1118  1.1.1.1.14.1  perseant 	err = mallctl("thread.peak.read", &peak, &sz, NULL, 0);
   1119  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1120  1.1.1.1.14.1  perseant 	expect_u64_eq(peak, SC_SMALL_MAXCLASS, "Missed an update");
   1121  1.1.1.1.14.1  perseant 	free(ptr);
   1122  1.1.1.1.14.1  perseant 	err = mallctl("thread.peak.read", &peak, &sz, NULL, 0);
   1123  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1124  1.1.1.1.14.1  perseant 	expect_u64_eq(peak, SC_SMALL_MAXCLASS, "Freeing changed peak");
   1125  1.1.1.1.14.1  perseant 	ptr = mallocx(big_size, 0);
   1126  1.1.1.1.14.1  perseant 	free(ptr);
   1127  1.1.1.1.14.1  perseant 	/*
   1128  1.1.1.1.14.1  perseant 	 * The peak should have hit big_size in the last two lines, even though
   1129  1.1.1.1.14.1  perseant 	 * the net allocated bytes has since dropped back down to zero.  We
   1130  1.1.1.1.14.1  perseant 	 * should have noticed the peak change without having down any mallctl
   1131  1.1.1.1.14.1  perseant 	 * calls while net allocated bytes was high.
   1132  1.1.1.1.14.1  perseant 	 */
   1133  1.1.1.1.14.1  perseant 	err = mallctl("thread.peak.read", &peak, &sz, NULL, 0);
   1134  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1135  1.1.1.1.14.1  perseant 	expect_u64_ge(peak, big_size, "Missed a peak change.");
   1136  1.1.1.1.14.1  perseant 
   1137  1.1.1.1.14.1  perseant 	/* Allocate big_size, but using small allocations. */
   1138  1.1.1.1.14.1  perseant 	size_t nallocs = big_size / small_size;
   1139  1.1.1.1.14.1  perseant 	void **ptrs = calloc(nallocs, sizeof(void *));
   1140  1.1.1.1.14.1  perseant 	err = mallctl("thread.peak.reset", NULL, NULL, NULL, 0);
   1141  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1142  1.1.1.1.14.1  perseant 	err = mallctl("thread.peak.read", &peak, &sz, NULL, 0);
   1143  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1144  1.1.1.1.14.1  perseant 	expect_u64_eq(0, peak, "Missed a reset.");
   1145  1.1.1.1.14.1  perseant 	for (size_t i = 0; i < nallocs; i++) {
   1146  1.1.1.1.14.1  perseant 		ptrs[i] = mallocx(small_size, 0);
   1147  1.1.1.1.14.1  perseant 	}
   1148  1.1.1.1.14.1  perseant 	for (size_t i = 0; i < nallocs; i++) {
   1149  1.1.1.1.14.1  perseant 		free(ptrs[i]);
   1150  1.1.1.1.14.1  perseant 	}
   1151  1.1.1.1.14.1  perseant 	err = mallctl("thread.peak.read", &peak, &sz, NULL, 0);
   1152  1.1.1.1.14.1  perseant 	expect_d_eq(err, 0, "");
   1153  1.1.1.1.14.1  perseant 	/*
   1154  1.1.1.1.14.1  perseant 	 * We don't guarantee exactness; make sure we're within 10% of the peak,
   1155  1.1.1.1.14.1  perseant 	 * though.
   1156  1.1.1.1.14.1  perseant 	 */
   1157  1.1.1.1.14.1  perseant 	expect_u64_ge(peak, nallocx(small_size, 0) * nallocs * 9 / 10,
   1158  1.1.1.1.14.1  perseant 	    "Missed some peak changes.");
   1159  1.1.1.1.14.1  perseant 	expect_u64_le(peak, nallocx(small_size, 0) * nallocs * 11 / 10,
   1160  1.1.1.1.14.1  perseant 	    "Overcounted peak changes.");
   1161  1.1.1.1.14.1  perseant 	free(ptrs);
   1162  1.1.1.1.14.1  perseant }
   1163  1.1.1.1.14.1  perseant TEST_END
   1164  1.1.1.1.14.1  perseant 
   1165  1.1.1.1.14.1  perseant typedef struct activity_test_data_s activity_test_data_t;
   1166  1.1.1.1.14.1  perseant struct activity_test_data_s {
   1167  1.1.1.1.14.1  perseant 	uint64_t obtained_alloc;
   1168  1.1.1.1.14.1  perseant 	uint64_t obtained_dalloc;
   1169  1.1.1.1.14.1  perseant };
   1170  1.1.1.1.14.1  perseant 
   1171  1.1.1.1.14.1  perseant static void
   1172  1.1.1.1.14.1  perseant activity_test_callback(void *uctx, uint64_t alloc, uint64_t dalloc) {
   1173  1.1.1.1.14.1  perseant 	activity_test_data_t *test_data = (activity_test_data_t *)uctx;
   1174  1.1.1.1.14.1  perseant 	test_data->obtained_alloc = alloc;
   1175  1.1.1.1.14.1  perseant 	test_data->obtained_dalloc = dalloc;
   1176  1.1.1.1.14.1  perseant }
   1177  1.1.1.1.14.1  perseant 
   1178  1.1.1.1.14.1  perseant TEST_BEGIN(test_thread_activity_callback) {
   1179  1.1.1.1.14.1  perseant 	test_skip_if(!config_stats);
   1180  1.1.1.1.14.1  perseant 
   1181  1.1.1.1.14.1  perseant 	const size_t big_size = 10 * 1024 * 1024;
   1182  1.1.1.1.14.1  perseant 	void *ptr;
   1183  1.1.1.1.14.1  perseant 	int err;
   1184  1.1.1.1.14.1  perseant 	size_t sz;
   1185  1.1.1.1.14.1  perseant 
   1186  1.1.1.1.14.1  perseant 	uint64_t *allocatedp;
   1187  1.1.1.1.14.1  perseant 	uint64_t *deallocatedp;
   1188  1.1.1.1.14.1  perseant 	sz = sizeof(allocatedp);
   1189  1.1.1.1.14.1  perseant 	err = mallctl("thread.allocatedp", &allocatedp, &sz, NULL, 0);
   1190  1.1.1.1.14.1  perseant 	assert_d_eq(0, err, "");
   1191  1.1.1.1.14.1  perseant 	err = mallctl("thread.deallocatedp", &deallocatedp, &sz, NULL, 0);
   1192  1.1.1.1.14.1  perseant 	assert_d_eq(0, err, "");
   1193  1.1.1.1.14.1  perseant 
   1194  1.1.1.1.14.1  perseant 	activity_callback_thunk_t old_thunk = {(activity_callback_t)111,
   1195  1.1.1.1.14.1  perseant 		(void *)222};
   1196  1.1.1.1.14.1  perseant 
   1197  1.1.1.1.14.1  perseant 	activity_test_data_t test_data = {333, 444};
   1198  1.1.1.1.14.1  perseant 	activity_callback_thunk_t new_thunk =
   1199  1.1.1.1.14.1  perseant 	    {&activity_test_callback, &test_data};
   1200  1.1.1.1.14.1  perseant 
   1201  1.1.1.1.14.1  perseant 	sz = sizeof(old_thunk);
   1202  1.1.1.1.14.1  perseant 	err = mallctl("experimental.thread.activity_callback", &old_thunk, &sz,
   1203  1.1.1.1.14.1  perseant 	    &new_thunk, sizeof(new_thunk));
   1204  1.1.1.1.14.1  perseant 	assert_d_eq(0, err, "");
   1205  1.1.1.1.14.1  perseant 
   1206  1.1.1.1.14.1  perseant 	expect_true(old_thunk.callback == NULL, "Callback already installed");
   1207  1.1.1.1.14.1  perseant 	expect_true(old_thunk.uctx == NULL, "Callback data already installed");
   1208  1.1.1.1.14.1  perseant 
   1209  1.1.1.1.14.1  perseant 	ptr = mallocx(big_size, 0);
   1210  1.1.1.1.14.1  perseant 	expect_u64_eq(test_data.obtained_alloc, *allocatedp, "");
   1211  1.1.1.1.14.1  perseant 	expect_u64_eq(test_data.obtained_dalloc, *deallocatedp, "");
   1212  1.1.1.1.14.1  perseant 
   1213  1.1.1.1.14.1  perseant 	free(ptr);
   1214  1.1.1.1.14.1  perseant 	expect_u64_eq(test_data.obtained_alloc, *allocatedp, "");
   1215  1.1.1.1.14.1  perseant 	expect_u64_eq(test_data.obtained_dalloc, *deallocatedp, "");
   1216  1.1.1.1.14.1  perseant 
   1217  1.1.1.1.14.1  perseant 	sz = sizeof(old_thunk);
   1218  1.1.1.1.14.1  perseant 	new_thunk = (activity_callback_thunk_t){ NULL, NULL };
   1219  1.1.1.1.14.1  perseant 	err = mallctl("experimental.thread.activity_callback", &old_thunk, &sz,
   1220  1.1.1.1.14.1  perseant 	    &new_thunk, sizeof(new_thunk));
   1221  1.1.1.1.14.1  perseant 	assert_d_eq(0, err, "");
   1222  1.1.1.1.14.1  perseant 
   1223  1.1.1.1.14.1  perseant 	expect_true(old_thunk.callback == &activity_test_callback, "");
   1224  1.1.1.1.14.1  perseant 	expect_true(old_thunk.uctx == &test_data, "");
   1225  1.1.1.1.14.1  perseant 
   1226  1.1.1.1.14.1  perseant 	/* Inserting NULL should have turned off tracking. */
   1227  1.1.1.1.14.1  perseant 	test_data.obtained_alloc = 333;
   1228  1.1.1.1.14.1  perseant 	test_data.obtained_dalloc = 444;
   1229  1.1.1.1.14.1  perseant 	ptr = mallocx(big_size, 0);
   1230  1.1.1.1.14.1  perseant 	free(ptr);
   1231  1.1.1.1.14.1  perseant 	expect_u64_eq(333, test_data.obtained_alloc, "");
   1232  1.1.1.1.14.1  perseant 	expect_u64_eq(444, test_data.obtained_dalloc, "");
   1233  1.1.1.1.14.1  perseant }
   1234  1.1.1.1.14.1  perseant TEST_END
   1235  1.1.1.1.14.1  perseant 
   1236           1.1  christos int
   1237           1.1  christos main(void) {
   1238           1.1  christos 	return test(
   1239           1.1  christos 	    test_mallctl_errors,
   1240           1.1  christos 	    test_mallctlnametomib_errors,
   1241           1.1  christos 	    test_mallctlbymib_errors,
   1242           1.1  christos 	    test_mallctl_read_write,
   1243           1.1  christos 	    test_mallctlnametomib_short_mib,
   1244  1.1.1.1.14.1  perseant 	    test_mallctlnametomib_short_name,
   1245  1.1.1.1.14.1  perseant 	    test_mallctlmibnametomib,
   1246  1.1.1.1.14.1  perseant 	    test_mallctlbymibname,
   1247           1.1  christos 	    test_mallctl_config,
   1248           1.1  christos 	    test_mallctl_opt,
   1249           1.1  christos 	    test_manpage_example,
   1250           1.1  christos 	    test_tcache_none,
   1251           1.1  christos 	    test_tcache,
   1252           1.1  christos 	    test_thread_arena,
   1253           1.1  christos 	    test_arena_i_initialized,
   1254           1.1  christos 	    test_arena_i_dirty_decay_ms,
   1255           1.1  christos 	    test_arena_i_muzzy_decay_ms,
   1256           1.1  christos 	    test_arena_i_purge,
   1257           1.1  christos 	    test_arena_i_decay,
   1258           1.1  christos 	    test_arena_i_dss,
   1259           1.1  christos 	    test_arena_i_retain_grow_limit,
   1260           1.1  christos 	    test_arenas_dirty_decay_ms,
   1261           1.1  christos 	    test_arenas_muzzy_decay_ms,
   1262           1.1  christos 	    test_arenas_constants,
   1263           1.1  christos 	    test_arenas_bin_constants,
   1264           1.1  christos 	    test_arenas_lextent_constants,
   1265           1.1  christos 	    test_arenas_create,
   1266           1.1  christos 	    test_arenas_lookup,
   1267  1.1.1.1.14.1  perseant 	    test_prof_active,
   1268  1.1.1.1.14.1  perseant 	    test_stats_arenas,
   1269  1.1.1.1.14.1  perseant 	    test_hooks,
   1270  1.1.1.1.14.1  perseant 	    test_hooks_exhaustion,
   1271  1.1.1.1.14.1  perseant 	    test_thread_idle,
   1272  1.1.1.1.14.1  perseant 	    test_thread_peak,
   1273  1.1.1.1.14.1  perseant 	    test_thread_activity_callback);
   1274           1.1  christos }
   1275