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