1 1.1 christos #include "test/jemalloc_test.h" 2 1.1 christos 3 1.1.1.2 christos #include "test/nbits.h" 4 1.1 christos 5 1.1 christos static void 6 1.1 christos test_bitmap_initializer_body(const bitmap_info_t *binfo, size_t nbits) { 7 1.1 christos bitmap_info_t binfo_dyn; 8 1.1 christos bitmap_info_init(&binfo_dyn, nbits); 9 1.1 christos 10 1.1.1.2 christos expect_zu_eq(bitmap_size(binfo), bitmap_size(&binfo_dyn), 11 1.1 christos "Unexpected difference between static and dynamic initialization, " 12 1.1.1.3 christos "nbits=%zu", 13 1.1.1.3 christos nbits); 14 1.1.1.2 christos expect_zu_eq(binfo->nbits, binfo_dyn.nbits, 15 1.1 christos "Unexpected difference between static and dynamic initialization, " 16 1.1.1.3 christos "nbits=%zu", 17 1.1.1.3 christos nbits); 18 1.1 christos #ifdef BITMAP_USE_TREE 19 1.1.1.2 christos expect_u_eq(binfo->nlevels, binfo_dyn.nlevels, 20 1.1 christos "Unexpected difference between static and dynamic initialization, " 21 1.1.1.3 christos "nbits=%zu", 22 1.1.1.3 christos nbits); 23 1.1 christos { 24 1.1 christos unsigned i; 25 1.1 christos 26 1.1 christos for (i = 0; i < binfo->nlevels; i++) { 27 1.1.1.2 christos expect_zu_eq(binfo->levels[i].group_offset, 28 1.1 christos binfo_dyn.levels[i].group_offset, 29 1.1 christos "Unexpected difference between static and dynamic " 30 1.1.1.3 christos "initialization, nbits=%zu, level=%u", 31 1.1.1.3 christos nbits, i); 32 1.1 christos } 33 1.1 christos } 34 1.1 christos #else 35 1.1.1.2 christos expect_zu_eq(binfo->ngroups, binfo_dyn.ngroups, 36 1.1 christos "Unexpected difference between static and dynamic initialization"); 37 1.1 christos #endif 38 1.1 christos } 39 1.1 christos 40 1.1 christos TEST_BEGIN(test_bitmap_initializer) { 41 1.1.1.3 christos #define NB(nbits) \ 42 1.1.1.3 christos { \ 43 1.1.1.3 christos if (nbits <= BITMAP_MAXBITS) { \ 44 1.1.1.3 christos bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \ 45 1.1.1.3 christos test_bitmap_initializer_body(&binfo, nbits); \ 46 1.1.1.3 christos } \ 47 1.1 christos } 48 1.1 christos NBITS_TAB 49 1.1 christos #undef NB 50 1.1 christos } 51 1.1 christos TEST_END 52 1.1 christos 53 1.1 christos static size_t 54 1.1.1.3 christos test_bitmap_size_body( 55 1.1.1.3 christos const bitmap_info_t *binfo, size_t nbits, size_t prev_size) { 56 1.1 christos size_t size = bitmap_size(binfo); 57 1.1.1.3 christos expect_zu_ge( 58 1.1.1.3 christos size, (nbits >> 3), "Bitmap size is smaller than expected"); 59 1.1.1.2 christos expect_zu_ge(size, prev_size, "Bitmap size is smaller than expected"); 60 1.1 christos return size; 61 1.1 christos } 62 1.1 christos 63 1.1 christos TEST_BEGIN(test_bitmap_size) { 64 1.1 christos size_t nbits, prev_size; 65 1.1 christos 66 1.1 christos prev_size = 0; 67 1.1 christos for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) { 68 1.1 christos bitmap_info_t binfo; 69 1.1 christos bitmap_info_init(&binfo, nbits); 70 1.1 christos prev_size = test_bitmap_size_body(&binfo, nbits, prev_size); 71 1.1 christos } 72 1.1.1.3 christos #define NB(nbits) \ 73 1.1.1.3 christos { \ 74 1.1.1.3 christos bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \ 75 1.1.1.3 christos prev_size = test_bitmap_size_body(&binfo, nbits, prev_size); \ 76 1.1 christos } 77 1.1 christos prev_size = 0; 78 1.1 christos NBITS_TAB 79 1.1 christos #undef NB 80 1.1 christos } 81 1.1 christos TEST_END 82 1.1 christos 83 1.1 christos static void 84 1.1 christos test_bitmap_init_body(const bitmap_info_t *binfo, size_t nbits) { 85 1.1.1.3 christos size_t i; 86 1.1 christos bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo)); 87 1.1.1.2 christos expect_ptr_not_null(bitmap, "Unexpected malloc() failure"); 88 1.1 christos 89 1.1 christos bitmap_init(bitmap, binfo, false); 90 1.1 christos for (i = 0; i < nbits; i++) { 91 1.1.1.3 christos expect_false( 92 1.1.1.3 christos bitmap_get(bitmap, binfo, i), "Bit should be unset"); 93 1.1 christos } 94 1.1 christos 95 1.1 christos bitmap_init(bitmap, binfo, true); 96 1.1 christos for (i = 0; i < nbits; i++) { 97 1.1.1.2 christos expect_true(bitmap_get(bitmap, binfo, i), "Bit should be set"); 98 1.1 christos } 99 1.1 christos 100 1.1 christos free(bitmap); 101 1.1 christos } 102 1.1 christos 103 1.1 christos TEST_BEGIN(test_bitmap_init) { 104 1.1 christos size_t nbits; 105 1.1 christos 106 1.1 christos for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) { 107 1.1 christos bitmap_info_t binfo; 108 1.1 christos bitmap_info_init(&binfo, nbits); 109 1.1 christos test_bitmap_init_body(&binfo, nbits); 110 1.1 christos } 111 1.1.1.3 christos #define NB(nbits) \ 112 1.1.1.3 christos { \ 113 1.1.1.3 christos bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \ 114 1.1.1.3 christos test_bitmap_init_body(&binfo, nbits); \ 115 1.1 christos } 116 1.1 christos NBITS_TAB 117 1.1 christos #undef NB 118 1.1 christos } 119 1.1 christos TEST_END 120 1.1 christos 121 1.1 christos static void 122 1.1 christos test_bitmap_set_body(const bitmap_info_t *binfo, size_t nbits) { 123 1.1.1.3 christos size_t i; 124 1.1 christos bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo)); 125 1.1.1.2 christos expect_ptr_not_null(bitmap, "Unexpected malloc() failure"); 126 1.1 christos bitmap_init(bitmap, binfo, false); 127 1.1 christos 128 1.1 christos for (i = 0; i < nbits; i++) { 129 1.1 christos bitmap_set(bitmap, binfo, i); 130 1.1 christos } 131 1.1.1.2 christos expect_true(bitmap_full(bitmap, binfo), "All bits should be set"); 132 1.1 christos free(bitmap); 133 1.1 christos } 134 1.1 christos 135 1.1 christos TEST_BEGIN(test_bitmap_set) { 136 1.1 christos size_t nbits; 137 1.1 christos 138 1.1 christos for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) { 139 1.1 christos bitmap_info_t binfo; 140 1.1 christos bitmap_info_init(&binfo, nbits); 141 1.1 christos test_bitmap_set_body(&binfo, nbits); 142 1.1 christos } 143 1.1.1.3 christos #define NB(nbits) \ 144 1.1.1.3 christos { \ 145 1.1.1.3 christos bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \ 146 1.1.1.3 christos test_bitmap_set_body(&binfo, nbits); \ 147 1.1 christos } 148 1.1 christos NBITS_TAB 149 1.1 christos #undef NB 150 1.1 christos } 151 1.1 christos TEST_END 152 1.1 christos 153 1.1 christos static void 154 1.1 christos test_bitmap_unset_body(const bitmap_info_t *binfo, size_t nbits) { 155 1.1.1.3 christos size_t i; 156 1.1 christos bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo)); 157 1.1.1.2 christos expect_ptr_not_null(bitmap, "Unexpected malloc() failure"); 158 1.1 christos bitmap_init(bitmap, binfo, false); 159 1.1 christos 160 1.1 christos for (i = 0; i < nbits; i++) { 161 1.1 christos bitmap_set(bitmap, binfo, i); 162 1.1 christos } 163 1.1.1.2 christos expect_true(bitmap_full(bitmap, binfo), "All bits should be set"); 164 1.1 christos for (i = 0; i < nbits; i++) { 165 1.1 christos bitmap_unset(bitmap, binfo, i); 166 1.1 christos } 167 1.1 christos for (i = 0; i < nbits; i++) { 168 1.1 christos bitmap_set(bitmap, binfo, i); 169 1.1 christos } 170 1.1.1.2 christos expect_true(bitmap_full(bitmap, binfo), "All bits should be set"); 171 1.1 christos free(bitmap); 172 1.1 christos } 173 1.1 christos 174 1.1 christos TEST_BEGIN(test_bitmap_unset) { 175 1.1 christos size_t nbits; 176 1.1 christos 177 1.1 christos for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) { 178 1.1 christos bitmap_info_t binfo; 179 1.1 christos bitmap_info_init(&binfo, nbits); 180 1.1 christos test_bitmap_unset_body(&binfo, nbits); 181 1.1 christos } 182 1.1.1.3 christos #define NB(nbits) \ 183 1.1.1.3 christos { \ 184 1.1.1.3 christos bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \ 185 1.1.1.3 christos test_bitmap_unset_body(&binfo, nbits); \ 186 1.1 christos } 187 1.1 christos NBITS_TAB 188 1.1 christos #undef NB 189 1.1 christos } 190 1.1 christos TEST_END 191 1.1 christos 192 1.1 christos static void 193 1.1 christos test_bitmap_xfu_body(const bitmap_info_t *binfo, size_t nbits) { 194 1.1 christos bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo)); 195 1.1.1.2 christos expect_ptr_not_null(bitmap, "Unexpected malloc() failure"); 196 1.1 christos bitmap_init(bitmap, binfo, false); 197 1.1 christos 198 1.1 christos /* Iteratively set bits starting at the beginning. */ 199 1.1 christos for (size_t i = 0; i < nbits; i++) { 200 1.1.1.2 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, 0), i, 201 1.1 christos "First unset bit should be just after previous first unset " 202 1.1 christos "bit"); 203 1.1.1.3 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, (i > 0) ? i - 1 : i), i, 204 1.1 christos "First unset bit should be just after previous first unset " 205 1.1 christos "bit"); 206 1.1.1.2 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, i), i, 207 1.1 christos "First unset bit should be just after previous first unset " 208 1.1 christos "bit"); 209 1.1.1.2 christos expect_zu_eq(bitmap_sfu(bitmap, binfo), i, 210 1.1 christos "First unset bit should be just after previous first unset " 211 1.1 christos "bit"); 212 1.1 christos } 213 1.1.1.2 christos expect_true(bitmap_full(bitmap, binfo), "All bits should be set"); 214 1.1 christos 215 1.1 christos /* 216 1.1 christos * Iteratively unset bits starting at the end, and verify that 217 1.1 christos * bitmap_sfu() reaches the unset bits. 218 1.1 christos */ 219 1.1 christos for (size_t i = nbits - 1; i < nbits; i--) { /* (nbits..0] */ 220 1.1 christos bitmap_unset(bitmap, binfo, i); 221 1.1.1.2 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, 0), i, 222 1.1 christos "First unset bit should the bit previously unset"); 223 1.1.1.3 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, (i > 0) ? i - 1 : i), i, 224 1.1 christos "First unset bit should the bit previously unset"); 225 1.1.1.2 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, i), i, 226 1.1 christos "First unset bit should the bit previously unset"); 227 1.1.1.2 christos expect_zu_eq(bitmap_sfu(bitmap, binfo), i, 228 1.1 christos "First unset bit should the bit previously unset"); 229 1.1 christos bitmap_unset(bitmap, binfo, i); 230 1.1 christos } 231 1.1.1.2 christos expect_false(bitmap_get(bitmap, binfo, 0), "Bit should be unset"); 232 1.1 christos 233 1.1 christos /* 234 1.1 christos * Iteratively set bits starting at the beginning, and verify that 235 1.1 christos * bitmap_sfu() looks past them. 236 1.1 christos */ 237 1.1 christos for (size_t i = 1; i < nbits; i++) { 238 1.1 christos bitmap_set(bitmap, binfo, i - 1); 239 1.1.1.2 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, 0), i, 240 1.1 christos "First unset bit should be just after the bit previously " 241 1.1 christos "set"); 242 1.1.1.3 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, (i > 0) ? i - 1 : i), i, 243 1.1 christos "First unset bit should be just after the bit previously " 244 1.1 christos "set"); 245 1.1.1.2 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, i), i, 246 1.1 christos "First unset bit should be just after the bit previously " 247 1.1 christos "set"); 248 1.1.1.2 christos expect_zu_eq(bitmap_sfu(bitmap, binfo), i, 249 1.1 christos "First unset bit should be just after the bit previously " 250 1.1 christos "set"); 251 1.1 christos bitmap_unset(bitmap, binfo, i); 252 1.1 christos } 253 1.1.1.2 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, 0), nbits - 1, 254 1.1 christos "First unset bit should be the last bit"); 255 1.1.1.3 christos expect_zu_eq( 256 1.1.1.3 christos bitmap_ffu(bitmap, binfo, (nbits > 1) ? nbits - 2 : nbits - 1), 257 1.1 christos nbits - 1, "First unset bit should be the last bit"); 258 1.1.1.2 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, nbits - 1), nbits - 1, 259 1.1 christos "First unset bit should be the last bit"); 260 1.1.1.2 christos expect_zu_eq(bitmap_sfu(bitmap, binfo), nbits - 1, 261 1.1 christos "First unset bit should be the last bit"); 262 1.1.1.2 christos expect_true(bitmap_full(bitmap, binfo), "All bits should be set"); 263 1.1 christos 264 1.1 christos /* 265 1.1 christos * Bubble a "usu" pattern through the bitmap and verify that 266 1.1 christos * bitmap_ffu() finds the correct bit for all five min_bit cases. 267 1.1 christos */ 268 1.1 christos if (nbits >= 3) { 269 1.1.1.3 christos for (size_t i = 0; i < nbits - 2; i++) { 270 1.1 christos bitmap_unset(bitmap, binfo, i); 271 1.1.1.3 christos bitmap_unset(bitmap, binfo, i + 2); 272 1.1 christos if (i > 0) { 273 1.1.1.3 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, i - 1), 274 1.1.1.3 christos i, "Unexpected first unset bit"); 275 1.1 christos } 276 1.1.1.2 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, i), i, 277 1.1 christos "Unexpected first unset bit"); 278 1.1.1.3 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, i + 1), i + 2, 279 1.1 christos "Unexpected first unset bit"); 280 1.1.1.3 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, i + 2), i + 2, 281 1.1 christos "Unexpected first unset bit"); 282 1.1 christos if (i + 3 < nbits) { 283 1.1.1.3 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, i + 3), 284 1.1 christos nbits, "Unexpected first unset bit"); 285 1.1 christos } 286 1.1.1.2 christos expect_zu_eq(bitmap_sfu(bitmap, binfo), i, 287 1.1 christos "Unexpected first unset bit"); 288 1.1.1.3 christos expect_zu_eq(bitmap_sfu(bitmap, binfo), i + 2, 289 1.1 christos "Unexpected first unset bit"); 290 1.1 christos } 291 1.1 christos } 292 1.1 christos 293 1.1 christos /* 294 1.1 christos * Unset the last bit, bubble another unset bit through the bitmap, and 295 1.1 christos * verify that bitmap_ffu() finds the correct bit for all four min_bit 296 1.1 christos * cases. 297 1.1 christos */ 298 1.1 christos if (nbits >= 3) { 299 1.1.1.3 christos bitmap_unset(bitmap, binfo, nbits - 1); 300 1.1.1.3 christos for (size_t i = 0; i < nbits - 1; i++) { 301 1.1 christos bitmap_unset(bitmap, binfo, i); 302 1.1 christos if (i > 0) { 303 1.1.1.3 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, i - 1), 304 1.1.1.3 christos i, "Unexpected first unset bit"); 305 1.1 christos } 306 1.1.1.2 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, i), i, 307 1.1 christos "Unexpected first unset bit"); 308 1.1.1.3 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, i + 1), 309 1.1.1.3 christos nbits - 1, "Unexpected first unset bit"); 310 1.1.1.3 christos expect_zu_eq(bitmap_ffu(bitmap, binfo, nbits - 1), 311 1.1.1.3 christos nbits - 1, "Unexpected first unset bit"); 312 1.1 christos 313 1.1.1.2 christos expect_zu_eq(bitmap_sfu(bitmap, binfo), i, 314 1.1 christos "Unexpected first unset bit"); 315 1.1 christos } 316 1.1.1.3 christos expect_zu_eq(bitmap_sfu(bitmap, binfo), nbits - 1, 317 1.1 christos "Unexpected first unset bit"); 318 1.1 christos } 319 1.1 christos 320 1.1 christos free(bitmap); 321 1.1 christos } 322 1.1 christos 323 1.1 christos TEST_BEGIN(test_bitmap_xfu) { 324 1.1.1.2 christos size_t nbits, nbits_max; 325 1.1 christos 326 1.1.1.2 christos /* The test is O(n^2); large page sizes may slow down too much. */ 327 1.1.1.2 christos nbits_max = BITMAP_MAXBITS > 512 ? 512 : BITMAP_MAXBITS; 328 1.1.1.2 christos for (nbits = 1; nbits <= nbits_max; nbits++) { 329 1.1 christos bitmap_info_t binfo; 330 1.1 christos bitmap_info_init(&binfo, nbits); 331 1.1 christos test_bitmap_xfu_body(&binfo, nbits); 332 1.1 christos } 333 1.1.1.3 christos #define NB(nbits) \ 334 1.1.1.3 christos { \ 335 1.1.1.3 christos bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \ 336 1.1.1.3 christos test_bitmap_xfu_body(&binfo, nbits); \ 337 1.1 christos } 338 1.1 christos NBITS_TAB 339 1.1 christos #undef NB 340 1.1 christos } 341 1.1 christos TEST_END 342 1.1 christos 343 1.1 christos int 344 1.1 christos main(void) { 345 1.1.1.3 christos return test(test_bitmap_initializer, test_bitmap_size, test_bitmap_init, 346 1.1.1.3 christos test_bitmap_set, test_bitmap_unset, test_bitmap_xfu); 347 1.1 christos } 348