1*7bdf38e5Schristos #include "test/jemalloc_test.h" 2*7bdf38e5Schristos 3*7bdf38e5Schristos static void 4*7bdf38e5Schristos do_fill_test(cache_bin_t *bin, cache_bin_info_t *info, void **ptrs, 5*7bdf38e5Schristos cache_bin_sz_t ncached_max, cache_bin_sz_t nfill_attempt, 6*7bdf38e5Schristos cache_bin_sz_t nfill_succeed) { 7*7bdf38e5Schristos bool success; 8*7bdf38e5Schristos void *ptr; 9*7bdf38e5Schristos assert_true(cache_bin_ncached_get_local(bin, info) == 0, ""); 10*7bdf38e5Schristos CACHE_BIN_PTR_ARRAY_DECLARE(arr, nfill_attempt); 11*7bdf38e5Schristos cache_bin_init_ptr_array_for_fill(bin, info, &arr, nfill_attempt); 12*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < nfill_succeed; i++) { 13*7bdf38e5Schristos arr.ptr[i] = &ptrs[i]; 14*7bdf38e5Schristos } 15*7bdf38e5Schristos cache_bin_finish_fill(bin, info, &arr, nfill_succeed); 16*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(bin, info) == nfill_succeed, 17*7bdf38e5Schristos ""); 18*7bdf38e5Schristos cache_bin_low_water_set(bin); 19*7bdf38e5Schristos 20*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < nfill_succeed; i++) { 21*7bdf38e5Schristos ptr = cache_bin_alloc(bin, &success); 22*7bdf38e5Schristos expect_true(success, ""); 23*7bdf38e5Schristos expect_ptr_eq(ptr, (void *)&ptrs[i], 24*7bdf38e5Schristos "Should pop in order filled"); 25*7bdf38e5Schristos expect_true(cache_bin_low_water_get(bin, info) 26*7bdf38e5Schristos == nfill_succeed - i - 1, ""); 27*7bdf38e5Schristos } 28*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(bin, info) == 0, ""); 29*7bdf38e5Schristos expect_true(cache_bin_low_water_get(bin, info) == 0, ""); 30*7bdf38e5Schristos } 31*7bdf38e5Schristos 32*7bdf38e5Schristos static void 33*7bdf38e5Schristos do_flush_test(cache_bin_t *bin, cache_bin_info_t *info, void **ptrs, 34*7bdf38e5Schristos cache_bin_sz_t nfill, cache_bin_sz_t nflush) { 35*7bdf38e5Schristos bool success; 36*7bdf38e5Schristos assert_true(cache_bin_ncached_get_local(bin, info) == 0, ""); 37*7bdf38e5Schristos 38*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < nfill; i++) { 39*7bdf38e5Schristos success = cache_bin_dalloc_easy(bin, &ptrs[i]); 40*7bdf38e5Schristos expect_true(success, ""); 41*7bdf38e5Schristos } 42*7bdf38e5Schristos 43*7bdf38e5Schristos CACHE_BIN_PTR_ARRAY_DECLARE(arr, nflush); 44*7bdf38e5Schristos cache_bin_init_ptr_array_for_flush(bin, info, &arr, nflush); 45*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < nflush; i++) { 46*7bdf38e5Schristos expect_ptr_eq(arr.ptr[i], &ptrs[nflush - i - 1], ""); 47*7bdf38e5Schristos } 48*7bdf38e5Schristos cache_bin_finish_flush(bin, info, &arr, nflush); 49*7bdf38e5Schristos 50*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(bin, info) == nfill - nflush, 51*7bdf38e5Schristos ""); 52*7bdf38e5Schristos while (cache_bin_ncached_get_local(bin, info) > 0) { 53*7bdf38e5Schristos cache_bin_alloc(bin, &success); 54*7bdf38e5Schristos } 55*7bdf38e5Schristos } 56*7bdf38e5Schristos 57*7bdf38e5Schristos static void 58*7bdf38e5Schristos do_batch_alloc_test(cache_bin_t *bin, cache_bin_info_t *info, void **ptrs, 59*7bdf38e5Schristos cache_bin_sz_t nfill, size_t batch) { 60*7bdf38e5Schristos assert_true(cache_bin_ncached_get_local(bin, info) == 0, ""); 61*7bdf38e5Schristos CACHE_BIN_PTR_ARRAY_DECLARE(arr, nfill); 62*7bdf38e5Schristos cache_bin_init_ptr_array_for_fill(bin, info, &arr, nfill); 63*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < nfill; i++) { 64*7bdf38e5Schristos arr.ptr[i] = &ptrs[i]; 65*7bdf38e5Schristos } 66*7bdf38e5Schristos cache_bin_finish_fill(bin, info, &arr, nfill); 67*7bdf38e5Schristos assert_true(cache_bin_ncached_get_local(bin, info) == nfill, ""); 68*7bdf38e5Schristos cache_bin_low_water_set(bin); 69*7bdf38e5Schristos 70*7bdf38e5Schristos void **out = malloc((batch + 1) * sizeof(void *)); 71*7bdf38e5Schristos size_t n = cache_bin_alloc_batch(bin, batch, out); 72*7bdf38e5Schristos assert_true(n == ((size_t)nfill < batch ? (size_t)nfill : batch), ""); 73*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < (cache_bin_sz_t)n; i++) { 74*7bdf38e5Schristos expect_ptr_eq(out[i], &ptrs[i], ""); 75*7bdf38e5Schristos } 76*7bdf38e5Schristos expect_true(cache_bin_low_water_get(bin, info) == nfill - 77*7bdf38e5Schristos (cache_bin_sz_t)n, ""); 78*7bdf38e5Schristos while (cache_bin_ncached_get_local(bin, info) > 0) { 79*7bdf38e5Schristos bool success; 80*7bdf38e5Schristos cache_bin_alloc(bin, &success); 81*7bdf38e5Schristos } 82*7bdf38e5Schristos free(out); 83*7bdf38e5Schristos } 84*7bdf38e5Schristos 85*7bdf38e5Schristos static void 86*7bdf38e5Schristos test_bin_init(cache_bin_t *bin, cache_bin_info_t *info) { 87*7bdf38e5Schristos size_t size; 88*7bdf38e5Schristos size_t alignment; 89*7bdf38e5Schristos cache_bin_info_compute_alloc(info, 1, &size, &alignment); 90*7bdf38e5Schristos void *mem = mallocx(size, MALLOCX_ALIGN(alignment)); 91*7bdf38e5Schristos assert_ptr_not_null(mem, "Unexpected mallocx failure"); 92*7bdf38e5Schristos 93*7bdf38e5Schristos size_t cur_offset = 0; 94*7bdf38e5Schristos cache_bin_preincrement(info, 1, mem, &cur_offset); 95*7bdf38e5Schristos cache_bin_init(bin, info, mem, &cur_offset); 96*7bdf38e5Schristos cache_bin_postincrement(info, 1, mem, &cur_offset); 97*7bdf38e5Schristos assert_zu_eq(cur_offset, size, "Should use all requested memory"); 98*7bdf38e5Schristos } 99*7bdf38e5Schristos 100*7bdf38e5Schristos TEST_BEGIN(test_cache_bin) { 101*7bdf38e5Schristos const int ncached_max = 100; 102*7bdf38e5Schristos bool success; 103*7bdf38e5Schristos void *ptr; 104*7bdf38e5Schristos 105*7bdf38e5Schristos cache_bin_info_t info; 106*7bdf38e5Schristos cache_bin_info_init(&info, ncached_max); 107*7bdf38e5Schristos cache_bin_t bin; 108*7bdf38e5Schristos test_bin_init(&bin, &info); 109*7bdf38e5Schristos 110*7bdf38e5Schristos /* Initialize to empty; should then have 0 elements. */ 111*7bdf38e5Schristos expect_d_eq(ncached_max, cache_bin_info_ncached_max(&info), ""); 112*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(&bin, &info) == 0, ""); 113*7bdf38e5Schristos expect_true(cache_bin_low_water_get(&bin, &info) == 0, ""); 114*7bdf38e5Schristos 115*7bdf38e5Schristos ptr = cache_bin_alloc_easy(&bin, &success); 116*7bdf38e5Schristos expect_false(success, "Shouldn't successfully allocate when empty"); 117*7bdf38e5Schristos expect_ptr_null(ptr, "Shouldn't get a non-null pointer on failure"); 118*7bdf38e5Schristos 119*7bdf38e5Schristos ptr = cache_bin_alloc(&bin, &success); 120*7bdf38e5Schristos expect_false(success, "Shouldn't successfully allocate when empty"); 121*7bdf38e5Schristos expect_ptr_null(ptr, "Shouldn't get a non-null pointer on failure"); 122*7bdf38e5Schristos 123*7bdf38e5Schristos /* 124*7bdf38e5Schristos * We allocate one more item than ncached_max, so we can test cache bin 125*7bdf38e5Schristos * exhaustion. 126*7bdf38e5Schristos */ 127*7bdf38e5Schristos void **ptrs = mallocx(sizeof(void *) * (ncached_max + 1), 0); 128*7bdf38e5Schristos assert_ptr_not_null(ptrs, "Unexpected mallocx failure"); 129*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < ncached_max; i++) { 130*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(&bin, &info) == i, ""); 131*7bdf38e5Schristos success = cache_bin_dalloc_easy(&bin, &ptrs[i]); 132*7bdf38e5Schristos expect_true(success, 133*7bdf38e5Schristos "Should be able to dalloc into a non-full cache bin."); 134*7bdf38e5Schristos expect_true(cache_bin_low_water_get(&bin, &info) == 0, 135*7bdf38e5Schristos "Pushes and pops shouldn't change low water of zero."); 136*7bdf38e5Schristos } 137*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(&bin, &info) == ncached_max, 138*7bdf38e5Schristos ""); 139*7bdf38e5Schristos success = cache_bin_dalloc_easy(&bin, &ptrs[ncached_max]); 140*7bdf38e5Schristos expect_false(success, "Shouldn't be able to dalloc into a full bin."); 141*7bdf38e5Schristos 142*7bdf38e5Schristos cache_bin_low_water_set(&bin); 143*7bdf38e5Schristos 144*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < ncached_max; i++) { 145*7bdf38e5Schristos expect_true(cache_bin_low_water_get(&bin, &info) 146*7bdf38e5Schristos == ncached_max - i, ""); 147*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(&bin, &info) 148*7bdf38e5Schristos == ncached_max - i, ""); 149*7bdf38e5Schristos /* 150*7bdf38e5Schristos * This should fail -- the easy variant can't change the low 151*7bdf38e5Schristos * water mark. 152*7bdf38e5Schristos */ 153*7bdf38e5Schristos ptr = cache_bin_alloc_easy(&bin, &success); 154*7bdf38e5Schristos expect_ptr_null(ptr, ""); 155*7bdf38e5Schristos expect_false(success, ""); 156*7bdf38e5Schristos expect_true(cache_bin_low_water_get(&bin, &info) 157*7bdf38e5Schristos == ncached_max - i, ""); 158*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(&bin, &info) 159*7bdf38e5Schristos == ncached_max - i, ""); 160*7bdf38e5Schristos 161*7bdf38e5Schristos /* This should succeed, though. */ 162*7bdf38e5Schristos ptr = cache_bin_alloc(&bin, &success); 163*7bdf38e5Schristos expect_true(success, ""); 164*7bdf38e5Schristos expect_ptr_eq(ptr, &ptrs[ncached_max - i - 1], 165*7bdf38e5Schristos "Alloc should pop in stack order"); 166*7bdf38e5Schristos expect_true(cache_bin_low_water_get(&bin, &info) 167*7bdf38e5Schristos == ncached_max - i - 1, ""); 168*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(&bin, &info) 169*7bdf38e5Schristos == ncached_max - i - 1, ""); 170*7bdf38e5Schristos } 171*7bdf38e5Schristos /* Now we're empty -- all alloc attempts should fail. */ 172*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(&bin, &info) == 0, ""); 173*7bdf38e5Schristos ptr = cache_bin_alloc_easy(&bin, &success); 174*7bdf38e5Schristos expect_ptr_null(ptr, ""); 175*7bdf38e5Schristos expect_false(success, ""); 176*7bdf38e5Schristos ptr = cache_bin_alloc(&bin, &success); 177*7bdf38e5Schristos expect_ptr_null(ptr, ""); 178*7bdf38e5Schristos expect_false(success, ""); 179*7bdf38e5Schristos 180*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < ncached_max / 2; i++) { 181*7bdf38e5Schristos cache_bin_dalloc_easy(&bin, &ptrs[i]); 182*7bdf38e5Schristos } 183*7bdf38e5Schristos cache_bin_low_water_set(&bin); 184*7bdf38e5Schristos 185*7bdf38e5Schristos for (cache_bin_sz_t i = ncached_max / 2; i < ncached_max; i++) { 186*7bdf38e5Schristos cache_bin_dalloc_easy(&bin, &ptrs[i]); 187*7bdf38e5Schristos } 188*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(&bin, &info) == ncached_max, 189*7bdf38e5Schristos ""); 190*7bdf38e5Schristos for (cache_bin_sz_t i = ncached_max - 1; i >= ncached_max / 2; i--) { 191*7bdf38e5Schristos /* 192*7bdf38e5Schristos * Size is bigger than low water -- the reduced version should 193*7bdf38e5Schristos * succeed. 194*7bdf38e5Schristos */ 195*7bdf38e5Schristos ptr = cache_bin_alloc_easy(&bin, &success); 196*7bdf38e5Schristos expect_true(success, ""); 197*7bdf38e5Schristos expect_ptr_eq(ptr, &ptrs[i], ""); 198*7bdf38e5Schristos } 199*7bdf38e5Schristos /* But now, we've hit low-water. */ 200*7bdf38e5Schristos ptr = cache_bin_alloc_easy(&bin, &success); 201*7bdf38e5Schristos expect_false(success, ""); 202*7bdf38e5Schristos expect_ptr_null(ptr, ""); 203*7bdf38e5Schristos 204*7bdf38e5Schristos /* We're going to test filling -- we must be empty to start. */ 205*7bdf38e5Schristos while (cache_bin_ncached_get_local(&bin, &info)) { 206*7bdf38e5Schristos cache_bin_alloc(&bin, &success); 207*7bdf38e5Schristos expect_true(success, ""); 208*7bdf38e5Schristos } 209*7bdf38e5Schristos 210*7bdf38e5Schristos /* Test fill. */ 211*7bdf38e5Schristos /* Try to fill all, succeed fully. */ 212*7bdf38e5Schristos do_fill_test(&bin, &info, ptrs, ncached_max, ncached_max, ncached_max); 213*7bdf38e5Schristos /* Try to fill all, succeed partially. */ 214*7bdf38e5Schristos do_fill_test(&bin, &info, ptrs, ncached_max, ncached_max, 215*7bdf38e5Schristos ncached_max / 2); 216*7bdf38e5Schristos /* Try to fill all, fail completely. */ 217*7bdf38e5Schristos do_fill_test(&bin, &info, ptrs, ncached_max, ncached_max, 0); 218*7bdf38e5Schristos 219*7bdf38e5Schristos /* Try to fill some, succeed fully. */ 220*7bdf38e5Schristos do_fill_test(&bin, &info, ptrs, ncached_max, ncached_max / 2, 221*7bdf38e5Schristos ncached_max / 2); 222*7bdf38e5Schristos /* Try to fill some, succeed partially. */ 223*7bdf38e5Schristos do_fill_test(&bin, &info, ptrs, ncached_max, ncached_max / 2, 224*7bdf38e5Schristos ncached_max / 4); 225*7bdf38e5Schristos /* Try to fill some, fail completely. */ 226*7bdf38e5Schristos do_fill_test(&bin, &info, ptrs, ncached_max, ncached_max / 2, 0); 227*7bdf38e5Schristos 228*7bdf38e5Schristos do_flush_test(&bin, &info, ptrs, ncached_max, ncached_max); 229*7bdf38e5Schristos do_flush_test(&bin, &info, ptrs, ncached_max, ncached_max / 2); 230*7bdf38e5Schristos do_flush_test(&bin, &info, ptrs, ncached_max, 0); 231*7bdf38e5Schristos do_flush_test(&bin, &info, ptrs, ncached_max / 2, ncached_max / 2); 232*7bdf38e5Schristos do_flush_test(&bin, &info, ptrs, ncached_max / 2, ncached_max / 4); 233*7bdf38e5Schristos do_flush_test(&bin, &info, ptrs, ncached_max / 2, 0); 234*7bdf38e5Schristos 235*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, ncached_max, ncached_max); 236*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, ncached_max, ncached_max * 2); 237*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, ncached_max, ncached_max / 2); 238*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, ncached_max, 2); 239*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, ncached_max, 1); 240*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, ncached_max, 0); 241*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, ncached_max / 2, 242*7bdf38e5Schristos ncached_max / 2); 243*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, ncached_max / 2, ncached_max); 244*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, ncached_max / 2, 245*7bdf38e5Schristos ncached_max / 4); 246*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, ncached_max / 2, 2); 247*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, ncached_max / 2, 1); 248*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, ncached_max / 2, 0); 249*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, 2, ncached_max); 250*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, 2, 2); 251*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, 2, 1); 252*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, 2, 0); 253*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, 1, 2); 254*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, 1, 1); 255*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, 1, 0); 256*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, 0, 2); 257*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, 0, 1); 258*7bdf38e5Schristos do_batch_alloc_test(&bin, &info, ptrs, 0, 0); 259*7bdf38e5Schristos 260*7bdf38e5Schristos free(ptrs); 261*7bdf38e5Schristos } 262*7bdf38e5Schristos TEST_END 263*7bdf38e5Schristos 264*7bdf38e5Schristos static void 265*7bdf38e5Schristos do_flush_stashed_test(cache_bin_t *bin, cache_bin_info_t *info, void **ptrs, 266*7bdf38e5Schristos cache_bin_sz_t nfill, cache_bin_sz_t nstash) { 267*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(bin, info) == 0, 268*7bdf38e5Schristos "Bin not empty"); 269*7bdf38e5Schristos expect_true(cache_bin_nstashed_get_local(bin, info) == 0, 270*7bdf38e5Schristos "Bin not empty"); 271*7bdf38e5Schristos expect_true(nfill + nstash <= info->ncached_max, "Exceeded max"); 272*7bdf38e5Schristos 273*7bdf38e5Schristos bool ret; 274*7bdf38e5Schristos /* Fill */ 275*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < nfill; i++) { 276*7bdf38e5Schristos ret = cache_bin_dalloc_easy(bin, &ptrs[i]); 277*7bdf38e5Schristos expect_true(ret, "Unexpected fill failure"); 278*7bdf38e5Schristos } 279*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(bin, info) == nfill, 280*7bdf38e5Schristos "Wrong cached count"); 281*7bdf38e5Schristos 282*7bdf38e5Schristos /* Stash */ 283*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < nstash; i++) { 284*7bdf38e5Schristos ret = cache_bin_stash(bin, &ptrs[i + nfill]); 285*7bdf38e5Schristos expect_true(ret, "Unexpected stash failure"); 286*7bdf38e5Schristos } 287*7bdf38e5Schristos expect_true(cache_bin_nstashed_get_local(bin, info) == nstash, 288*7bdf38e5Schristos "Wrong stashed count"); 289*7bdf38e5Schristos 290*7bdf38e5Schristos if (nfill + nstash == info->ncached_max) { 291*7bdf38e5Schristos ret = cache_bin_dalloc_easy(bin, &ptrs[0]); 292*7bdf38e5Schristos expect_false(ret, "Should not dalloc into a full bin"); 293*7bdf38e5Schristos ret = cache_bin_stash(bin, &ptrs[0]); 294*7bdf38e5Schristos expect_false(ret, "Should not stash into a full bin"); 295*7bdf38e5Schristos } 296*7bdf38e5Schristos 297*7bdf38e5Schristos /* Alloc filled ones */ 298*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < nfill; i++) { 299*7bdf38e5Schristos void *ptr = cache_bin_alloc(bin, &ret); 300*7bdf38e5Schristos expect_true(ret, "Unexpected alloc failure"); 301*7bdf38e5Schristos /* Verify it's not from the stashed range. */ 302*7bdf38e5Schristos expect_true((uintptr_t)ptr < (uintptr_t)&ptrs[nfill], 303*7bdf38e5Schristos "Should not alloc stashed ptrs"); 304*7bdf38e5Schristos } 305*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(bin, info) == 0, 306*7bdf38e5Schristos "Wrong cached count"); 307*7bdf38e5Schristos expect_true(cache_bin_nstashed_get_local(bin, info) == nstash, 308*7bdf38e5Schristos "Wrong stashed count"); 309*7bdf38e5Schristos 310*7bdf38e5Schristos cache_bin_alloc(bin, &ret); 311*7bdf38e5Schristos expect_false(ret, "Should not alloc stashed"); 312*7bdf38e5Schristos 313*7bdf38e5Schristos /* Clear stashed ones */ 314*7bdf38e5Schristos cache_bin_finish_flush_stashed(bin, info); 315*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(bin, info) == 0, 316*7bdf38e5Schristos "Wrong cached count"); 317*7bdf38e5Schristos expect_true(cache_bin_nstashed_get_local(bin, info) == 0, 318*7bdf38e5Schristos "Wrong stashed count"); 319*7bdf38e5Schristos 320*7bdf38e5Schristos cache_bin_alloc(bin, &ret); 321*7bdf38e5Schristos expect_false(ret, "Should not alloc from empty bin"); 322*7bdf38e5Schristos } 323*7bdf38e5Schristos 324*7bdf38e5Schristos TEST_BEGIN(test_cache_bin_stash) { 325*7bdf38e5Schristos const int ncached_max = 100; 326*7bdf38e5Schristos 327*7bdf38e5Schristos cache_bin_t bin; 328*7bdf38e5Schristos cache_bin_info_t info; 329*7bdf38e5Schristos cache_bin_info_init(&info, ncached_max); 330*7bdf38e5Schristos test_bin_init(&bin, &info); 331*7bdf38e5Schristos 332*7bdf38e5Schristos /* 333*7bdf38e5Schristos * The content of this array is not accessed; instead the interior 334*7bdf38e5Schristos * addresses are used to insert / stash into the bins as test pointers. 335*7bdf38e5Schristos */ 336*7bdf38e5Schristos void **ptrs = mallocx(sizeof(void *) * (ncached_max + 1), 0); 337*7bdf38e5Schristos assert_ptr_not_null(ptrs, "Unexpected mallocx failure"); 338*7bdf38e5Schristos bool ret; 339*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < ncached_max; i++) { 340*7bdf38e5Schristos expect_true(cache_bin_ncached_get_local(&bin, &info) == 341*7bdf38e5Schristos (i / 2 + i % 2), "Wrong ncached value"); 342*7bdf38e5Schristos expect_true(cache_bin_nstashed_get_local(&bin, &info) == i / 2, 343*7bdf38e5Schristos "Wrong nstashed value"); 344*7bdf38e5Schristos if (i % 2 == 0) { 345*7bdf38e5Schristos cache_bin_dalloc_easy(&bin, &ptrs[i]); 346*7bdf38e5Schristos } else { 347*7bdf38e5Schristos ret = cache_bin_stash(&bin, &ptrs[i]); 348*7bdf38e5Schristos expect_true(ret, "Should be able to stash into a " 349*7bdf38e5Schristos "non-full cache bin"); 350*7bdf38e5Schristos } 351*7bdf38e5Schristos } 352*7bdf38e5Schristos ret = cache_bin_dalloc_easy(&bin, &ptrs[0]); 353*7bdf38e5Schristos expect_false(ret, "Should not dalloc into a full cache bin"); 354*7bdf38e5Schristos ret = cache_bin_stash(&bin, &ptrs[0]); 355*7bdf38e5Schristos expect_false(ret, "Should not stash into a full cache bin"); 356*7bdf38e5Schristos for (cache_bin_sz_t i = 0; i < ncached_max; i++) { 357*7bdf38e5Schristos void *ptr = cache_bin_alloc(&bin, &ret); 358*7bdf38e5Schristos if (i < ncached_max / 2) { 359*7bdf38e5Schristos expect_true(ret, "Should be able to alloc"); 360*7bdf38e5Schristos uintptr_t diff = ((uintptr_t)ptr - (uintptr_t)&ptrs[0]) 361*7bdf38e5Schristos / sizeof(void *); 362*7bdf38e5Schristos expect_true(diff % 2 == 0, "Should be able to alloc"); 363*7bdf38e5Schristos } else { 364*7bdf38e5Schristos expect_false(ret, "Should not alloc stashed"); 365*7bdf38e5Schristos expect_true(cache_bin_nstashed_get_local(&bin, &info) == 366*7bdf38e5Schristos ncached_max / 2, "Wrong nstashed value"); 367*7bdf38e5Schristos } 368*7bdf38e5Schristos } 369*7bdf38e5Schristos 370*7bdf38e5Schristos test_bin_init(&bin, &info); 371*7bdf38e5Schristos do_flush_stashed_test(&bin, &info, ptrs, ncached_max, 0); 372*7bdf38e5Schristos do_flush_stashed_test(&bin, &info, ptrs, 0, ncached_max); 373*7bdf38e5Schristos do_flush_stashed_test(&bin, &info, ptrs, ncached_max / 2, ncached_max / 2); 374*7bdf38e5Schristos do_flush_stashed_test(&bin, &info, ptrs, ncached_max / 4, ncached_max / 2); 375*7bdf38e5Schristos do_flush_stashed_test(&bin, &info, ptrs, ncached_max / 2, ncached_max / 4); 376*7bdf38e5Schristos do_flush_stashed_test(&bin, &info, ptrs, ncached_max / 4, ncached_max / 4); 377*7bdf38e5Schristos } 378*7bdf38e5Schristos TEST_END 379*7bdf38e5Schristos 380*7bdf38e5Schristos int 381*7bdf38e5Schristos main(void) { 382*7bdf38e5Schristos return test(test_cache_bin, 383*7bdf38e5Schristos test_cache_bin_stash); 384*7bdf38e5Schristos } 385