1*8e33eff8Schristos #include "test/jemalloc_test.h" 2*8e33eff8Schristos 3*8e33eff8Schristos /* 4*8e33eff8Schristos * Size class that is a divisor of the page size, ideally 4+ regions per run. 5*8e33eff8Schristos */ 6*8e33eff8Schristos #if LG_PAGE <= 14 7*8e33eff8Schristos #define SZ (ZU(1) << (LG_PAGE - 2)) 8*8e33eff8Schristos #else 9*8e33eff8Schristos #define SZ ZU(4096) 10*8e33eff8Schristos #endif 11*8e33eff8Schristos 12*8e33eff8Schristos /* 13*8e33eff8Schristos * Number of slabs to consume at high water mark. Should be at least 2 so that 14*8e33eff8Schristos * if mmap()ed memory grows downward, downward growth of mmap()ed memory is 15*8e33eff8Schristos * tested. 16*8e33eff8Schristos */ 17*8e33eff8Schristos #define NSLABS 8 18*8e33eff8Schristos 19*8e33eff8Schristos static unsigned 20*8e33eff8Schristos binind_compute(void) { 21*8e33eff8Schristos size_t sz; 22*8e33eff8Schristos unsigned nbins, i; 23*8e33eff8Schristos 24*8e33eff8Schristos sz = sizeof(nbins); 25*8e33eff8Schristos assert_d_eq(mallctl("arenas.nbins", (void *)&nbins, &sz, NULL, 0), 0, 26*8e33eff8Schristos "Unexpected mallctl failure"); 27*8e33eff8Schristos 28*8e33eff8Schristos for (i = 0; i < nbins; i++) { 29*8e33eff8Schristos size_t mib[4]; 30*8e33eff8Schristos size_t miblen = sizeof(mib)/sizeof(size_t); 31*8e33eff8Schristos size_t size; 32*8e33eff8Schristos 33*8e33eff8Schristos assert_d_eq(mallctlnametomib("arenas.bin.0.size", mib, 34*8e33eff8Schristos &miblen), 0, "Unexpected mallctlnametomb failure"); 35*8e33eff8Schristos mib[2] = (size_t)i; 36*8e33eff8Schristos 37*8e33eff8Schristos sz = sizeof(size); 38*8e33eff8Schristos assert_d_eq(mallctlbymib(mib, miblen, (void *)&size, &sz, NULL, 39*8e33eff8Schristos 0), 0, "Unexpected mallctlbymib failure"); 40*8e33eff8Schristos if (size == SZ) { 41*8e33eff8Schristos return i; 42*8e33eff8Schristos } 43*8e33eff8Schristos } 44*8e33eff8Schristos 45*8e33eff8Schristos test_fail("Unable to compute nregs_per_run"); 46*8e33eff8Schristos return 0; 47*8e33eff8Schristos } 48*8e33eff8Schristos 49*8e33eff8Schristos static size_t 50*8e33eff8Schristos nregs_per_run_compute(void) { 51*8e33eff8Schristos uint32_t nregs; 52*8e33eff8Schristos size_t sz; 53*8e33eff8Schristos unsigned binind = binind_compute(); 54*8e33eff8Schristos size_t mib[4]; 55*8e33eff8Schristos size_t miblen = sizeof(mib)/sizeof(size_t); 56*8e33eff8Schristos 57*8e33eff8Schristos assert_d_eq(mallctlnametomib("arenas.bin.0.nregs", mib, &miblen), 0, 58*8e33eff8Schristos "Unexpected mallctlnametomb failure"); 59*8e33eff8Schristos mib[2] = (size_t)binind; 60*8e33eff8Schristos sz = sizeof(nregs); 61*8e33eff8Schristos assert_d_eq(mallctlbymib(mib, miblen, (void *)&nregs, &sz, NULL, 62*8e33eff8Schristos 0), 0, "Unexpected mallctlbymib failure"); 63*8e33eff8Schristos return nregs; 64*8e33eff8Schristos } 65*8e33eff8Schristos 66*8e33eff8Schristos static unsigned 67*8e33eff8Schristos arenas_create_mallctl(void) { 68*8e33eff8Schristos unsigned arena_ind; 69*8e33eff8Schristos size_t sz; 70*8e33eff8Schristos 71*8e33eff8Schristos sz = sizeof(arena_ind); 72*8e33eff8Schristos assert_d_eq(mallctl("arenas.create", (void *)&arena_ind, &sz, NULL, 0), 73*8e33eff8Schristos 0, "Error in arenas.create"); 74*8e33eff8Schristos 75*8e33eff8Schristos return arena_ind; 76*8e33eff8Schristos } 77*8e33eff8Schristos 78*8e33eff8Schristos static void 79*8e33eff8Schristos arena_reset_mallctl(unsigned arena_ind) { 80*8e33eff8Schristos size_t mib[3]; 81*8e33eff8Schristos size_t miblen = sizeof(mib)/sizeof(size_t); 82*8e33eff8Schristos 83*8e33eff8Schristos assert_d_eq(mallctlnametomib("arena.0.reset", mib, &miblen), 0, 84*8e33eff8Schristos "Unexpected mallctlnametomib() failure"); 85*8e33eff8Schristos mib[1] = (size_t)arena_ind; 86*8e33eff8Schristos assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0, 87*8e33eff8Schristos "Unexpected mallctlbymib() failure"); 88*8e33eff8Schristos } 89*8e33eff8Schristos 90*8e33eff8Schristos TEST_BEGIN(test_pack) { 91*8e33eff8Schristos bool prof_enabled; 92*8e33eff8Schristos size_t sz = sizeof(prof_enabled); 93*8e33eff8Schristos if (mallctl("opt.prof", (void *)&prof_enabled, &sz, NULL, 0) == 0) { 94*8e33eff8Schristos test_skip_if(prof_enabled); 95*8e33eff8Schristos } 96*8e33eff8Schristos 97*8e33eff8Schristos unsigned arena_ind = arenas_create_mallctl(); 98*8e33eff8Schristos size_t nregs_per_run = nregs_per_run_compute(); 99*8e33eff8Schristos size_t nregs = nregs_per_run * NSLABS; 100*8e33eff8Schristos VARIABLE_ARRAY(void *, ptrs, nregs); 101*8e33eff8Schristos size_t i, j, offset; 102*8e33eff8Schristos 103*8e33eff8Schristos /* Fill matrix. */ 104*8e33eff8Schristos for (i = offset = 0; i < NSLABS; i++) { 105*8e33eff8Schristos for (j = 0; j < nregs_per_run; j++) { 106*8e33eff8Schristos void *p = mallocx(SZ, MALLOCX_ARENA(arena_ind) | 107*8e33eff8Schristos MALLOCX_TCACHE_NONE); 108*8e33eff8Schristos assert_ptr_not_null(p, 109*8e33eff8Schristos "Unexpected mallocx(%zu, MALLOCX_ARENA(%u) |" 110*8e33eff8Schristos " MALLOCX_TCACHE_NONE) failure, run=%zu, reg=%zu", 111*8e33eff8Schristos SZ, arena_ind, i, j); 112*8e33eff8Schristos ptrs[(i * nregs_per_run) + j] = p; 113*8e33eff8Schristos } 114*8e33eff8Schristos } 115*8e33eff8Schristos 116*8e33eff8Schristos /* 117*8e33eff8Schristos * Free all but one region of each run, but rotate which region is 118*8e33eff8Schristos * preserved, so that subsequent allocations exercise the within-run 119*8e33eff8Schristos * layout policy. 120*8e33eff8Schristos */ 121*8e33eff8Schristos offset = 0; 122*8e33eff8Schristos for (i = offset = 0; 123*8e33eff8Schristos i < NSLABS; 124*8e33eff8Schristos i++, offset = (offset + 1) % nregs_per_run) { 125*8e33eff8Schristos for (j = 0; j < nregs_per_run; j++) { 126*8e33eff8Schristos void *p = ptrs[(i * nregs_per_run) + j]; 127*8e33eff8Schristos if (offset == j) { 128*8e33eff8Schristos continue; 129*8e33eff8Schristos } 130*8e33eff8Schristos dallocx(p, MALLOCX_ARENA(arena_ind) | 131*8e33eff8Schristos MALLOCX_TCACHE_NONE); 132*8e33eff8Schristos } 133*8e33eff8Schristos } 134*8e33eff8Schristos 135*8e33eff8Schristos /* 136*8e33eff8Schristos * Logically refill matrix, skipping preserved regions and verifying 137*8e33eff8Schristos * that the matrix is unmodified. 138*8e33eff8Schristos */ 139*8e33eff8Schristos offset = 0; 140*8e33eff8Schristos for (i = offset = 0; 141*8e33eff8Schristos i < NSLABS; 142*8e33eff8Schristos i++, offset = (offset + 1) % nregs_per_run) { 143*8e33eff8Schristos for (j = 0; j < nregs_per_run; j++) { 144*8e33eff8Schristos void *p; 145*8e33eff8Schristos 146*8e33eff8Schristos if (offset == j) { 147*8e33eff8Schristos continue; 148*8e33eff8Schristos } 149*8e33eff8Schristos p = mallocx(SZ, MALLOCX_ARENA(arena_ind) | 150*8e33eff8Schristos MALLOCX_TCACHE_NONE); 151*8e33eff8Schristos assert_ptr_eq(p, ptrs[(i * nregs_per_run) + j], 152*8e33eff8Schristos "Unexpected refill discrepancy, run=%zu, reg=%zu\n", 153*8e33eff8Schristos i, j); 154*8e33eff8Schristos } 155*8e33eff8Schristos } 156*8e33eff8Schristos 157*8e33eff8Schristos /* Clean up. */ 158*8e33eff8Schristos arena_reset_mallctl(arena_ind); 159*8e33eff8Schristos } 160*8e33eff8Schristos TEST_END 161*8e33eff8Schristos 162*8e33eff8Schristos int 163*8e33eff8Schristos main(void) { 164*8e33eff8Schristos return test( 165*8e33eff8Schristos test_pack); 166*8e33eff8Schristos } 167