1 1.1 christos #include "test/jemalloc_test.h" 2 1.1 christos 3 1.1 christos #include "jemalloc/internal/bit_util.h" 4 1.1 christos 5 1.1.1.3 christos #define TEST_POW2_CEIL(t, suf, pri) \ 6 1.1.1.3 christos do { \ 7 1.1.1.3 christos unsigned i, pow2; \ 8 1.1.1.3 christos t x; \ 9 1.1.1.3 christos \ 10 1.1.1.3 christos expect_##suf##_eq(pow2_ceil_##suf(0), 0, "Unexpected result"); \ 11 1.1.1.3 christos \ 12 1.1.1.3 christos for (i = 0; i < sizeof(t) * 8; i++) { \ 13 1.1.1.3 christos expect_##suf##_eq(pow2_ceil_##suf(((t)1) << i), \ 14 1.1.1.3 christos ((t)1) << i, "Unexpected result"); \ 15 1.1.1.3 christos } \ 16 1.1.1.3 christos \ 17 1.1.1.3 christos for (i = 2; i < sizeof(t) * 8; i++) { \ 18 1.1.1.3 christos expect_##suf##_eq(pow2_ceil_##suf((((t)1) << i) - 1), \ 19 1.1.1.3 christos ((t)1) << i, "Unexpected result"); \ 20 1.1.1.3 christos } \ 21 1.1.1.3 christos \ 22 1.1.1.3 christos for (i = 0; i < sizeof(t) * 8 - 1; i++) { \ 23 1.1.1.3 christos expect_##suf##_eq(pow2_ceil_##suf((((t)1) << i) + 1), \ 24 1.1.1.3 christos ((t)1) << (i + 1), "Unexpected result"); \ 25 1.1.1.3 christos } \ 26 1.1.1.3 christos \ 27 1.1.1.3 christos for (pow2 = 1; pow2 < 25; pow2++) { \ 28 1.1.1.3 christos for (x = (((t)1) << (pow2 - 1)) + 1; \ 29 1.1.1.3 christos x <= ((t)1) << pow2; x++) { \ 30 1.1.1.3 christos expect_##suf##_eq(pow2_ceil_##suf(x), \ 31 1.1.1.3 christos ((t)1) << pow2, \ 32 1.1.1.3 christos "Unexpected result, x=%" pri, x); \ 33 1.1.1.3 christos } \ 34 1.1.1.3 christos } \ 35 1.1.1.3 christos } while (0) 36 1.1 christos 37 1.1 christos TEST_BEGIN(test_pow2_ceil_u64) { 38 1.1 christos TEST_POW2_CEIL(uint64_t, u64, FMTu64); 39 1.1 christos } 40 1.1 christos TEST_END 41 1.1 christos 42 1.1 christos TEST_BEGIN(test_pow2_ceil_u32) { 43 1.1 christos TEST_POW2_CEIL(uint32_t, u32, FMTu32); 44 1.1 christos } 45 1.1 christos TEST_END 46 1.1 christos 47 1.1 christos TEST_BEGIN(test_pow2_ceil_zu) { 48 1.1 christos TEST_POW2_CEIL(size_t, zu, "zu"); 49 1.1 christos } 50 1.1 christos TEST_END 51 1.1 christos 52 1.1.1.3 christos static void 53 1.1.1.2 christos expect_lg_ceil_range(size_t input, unsigned answer) { 54 1.1.1.2 christos if (input == 1) { 55 1.1.1.2 christos expect_u_eq(0, answer, "Got %u as lg_ceil of 1", answer); 56 1.1.1.2 christos return; 57 1.1.1.2 christos } 58 1.1.1.3 christos expect_zu_le(input, (ZU(1) << answer), "Got %u as lg_ceil of %zu", 59 1.1.1.3 christos answer, input); 60 1.1.1.3 christos expect_zu_gt(input, (ZU(1) << (answer - 1)), "Got %u as lg_ceil of %zu", 61 1.1.1.3 christos answer, input); 62 1.1.1.2 christos } 63 1.1.1.2 christos 64 1.1.1.3 christos static void 65 1.1.1.2 christos expect_lg_floor_range(size_t input, unsigned answer) { 66 1.1.1.2 christos if (input == 1) { 67 1.1.1.2 christos expect_u_eq(0, answer, "Got %u as lg_floor of 1", answer); 68 1.1.1.2 christos return; 69 1.1.1.2 christos } 70 1.1.1.3 christos expect_zu_ge(input, (ZU(1) << answer), "Got %u as lg_floor of %zu", 71 1.1.1.3 christos answer, input); 72 1.1.1.2 christos expect_zu_lt(input, (ZU(1) << (answer + 1)), 73 1.1.1.2 christos "Got %u as lg_floor of %zu", answer, input); 74 1.1.1.2 christos } 75 1.1.1.2 christos 76 1.1.1.2 christos TEST_BEGIN(test_lg_ceil_floor) { 77 1.1.1.2 christos for (size_t i = 1; i < 10 * 1000 * 1000; i++) { 78 1.1.1.2 christos expect_lg_ceil_range(i, lg_ceil(i)); 79 1.1.1.2 christos expect_lg_ceil_range(i, LG_CEIL(i)); 80 1.1.1.2 christos expect_lg_floor_range(i, lg_floor(i)); 81 1.1.1.2 christos expect_lg_floor_range(i, LG_FLOOR(i)); 82 1.1.1.2 christos } 83 1.1.1.2 christos for (int i = 10; i < 8 * (1 << LG_SIZEOF_PTR) - 5; i++) { 84 1.1.1.2 christos for (size_t j = 0; j < (1 << 4); j++) { 85 1.1.1.2 christos size_t num1 = ((size_t)1 << i) 86 1.1.1.2 christos - j * ((size_t)1 << (i - 4)); 87 1.1.1.2 christos size_t num2 = ((size_t)1 << i) 88 1.1.1.2 christos + j * ((size_t)1 << (i - 4)); 89 1.1.1.2 christos expect_zu_ne(num1, 0, "Invalid lg argument"); 90 1.1.1.2 christos expect_zu_ne(num2, 0, "Invalid lg argument"); 91 1.1.1.2 christos expect_lg_ceil_range(num1, lg_ceil(num1)); 92 1.1.1.2 christos expect_lg_ceil_range(num1, LG_CEIL(num1)); 93 1.1.1.2 christos expect_lg_ceil_range(num2, lg_ceil(num2)); 94 1.1.1.2 christos expect_lg_ceil_range(num2, LG_CEIL(num2)); 95 1.1.1.2 christos 96 1.1.1.2 christos expect_lg_floor_range(num1, lg_floor(num1)); 97 1.1.1.2 christos expect_lg_floor_range(num1, LG_FLOOR(num1)); 98 1.1.1.2 christos expect_lg_floor_range(num2, lg_floor(num2)); 99 1.1.1.2 christos expect_lg_floor_range(num2, LG_FLOOR(num2)); 100 1.1.1.2 christos } 101 1.1.1.2 christos } 102 1.1.1.2 christos } 103 1.1.1.2 christos TEST_END 104 1.1.1.2 christos 105 1.1.1.3 christos #define TEST_FFS(t, suf, test_suf, pri) \ 106 1.1.1.3 christos do { \ 107 1.1.1.3 christos for (unsigned i = 0; i < sizeof(t) * 8; i++) { \ 108 1.1.1.3 christos for (unsigned j = 0; j <= i; j++) { \ 109 1.1.1.3 christos for (unsigned k = 0; k <= j; k++) { \ 110 1.1.1.3 christos t x = (t)1 << i; \ 111 1.1.1.3 christos x |= (t)1 << j; \ 112 1.1.1.3 christos x |= (t)1 << k; \ 113 1.1.1.3 christos expect_##test_suf##_eq(ffs_##suf(x), \ 114 1.1.1.3 christos k, "Unexpected result, x=%" pri, \ 115 1.1.1.3 christos x); \ 116 1.1.1.3 christos } \ 117 1.1.1.3 christos } \ 118 1.1.1.3 christos } \ 119 1.1.1.3 christos } while (0) 120 1.1.1.2 christos 121 1.1.1.2 christos TEST_BEGIN(test_ffs_u) { 122 1.1.1.3 christos TEST_FFS(unsigned, u, u, "u"); 123 1.1.1.2 christos } 124 1.1.1.2 christos TEST_END 125 1.1.1.2 christos 126 1.1.1.2 christos TEST_BEGIN(test_ffs_lu) { 127 1.1.1.2 christos TEST_FFS(unsigned long, lu, lu, "lu"); 128 1.1.1.2 christos } 129 1.1.1.2 christos TEST_END 130 1.1.1.2 christos 131 1.1.1.2 christos TEST_BEGIN(test_ffs_llu) { 132 1.1.1.2 christos TEST_FFS(unsigned long long, llu, qd, "llu"); 133 1.1.1.2 christos } 134 1.1.1.2 christos TEST_END 135 1.1.1.2 christos 136 1.1.1.2 christos TEST_BEGIN(test_ffs_u32) { 137 1.1.1.2 christos TEST_FFS(uint32_t, u32, u32, FMTu32); 138 1.1.1.2 christos } 139 1.1.1.2 christos TEST_END 140 1.1.1.2 christos 141 1.1.1.2 christos TEST_BEGIN(test_ffs_u64) { 142 1.1.1.2 christos TEST_FFS(uint64_t, u64, u64, FMTu64); 143 1.1.1.2 christos } 144 1.1.1.2 christos TEST_END 145 1.1.1.2 christos 146 1.1.1.2 christos TEST_BEGIN(test_ffs_zu) { 147 1.1.1.2 christos TEST_FFS(size_t, zu, zu, "zu"); 148 1.1.1.2 christos } 149 1.1.1.2 christos TEST_END 150 1.1.1.2 christos 151 1.1.1.3 christos #define TEST_FLS(t, suf, test_suf, pri) \ 152 1.1.1.3 christos do { \ 153 1.1.1.3 christos for (unsigned i = 0; i < sizeof(t) * 8; i++) { \ 154 1.1.1.3 christos for (unsigned j = 0; j <= i; j++) { \ 155 1.1.1.3 christos for (unsigned k = 0; k <= j; k++) { \ 156 1.1.1.3 christos t x = (t)1 << i; \ 157 1.1.1.3 christos x |= (t)1 << j; \ 158 1.1.1.3 christos x |= (t)1 << k; \ 159 1.1.1.3 christos expect_##test_suf##_eq(fls_##suf(x), \ 160 1.1.1.3 christos i, "Unexpected result, x=%" pri, \ 161 1.1.1.3 christos x); \ 162 1.1.1.3 christos } \ 163 1.1.1.3 christos } \ 164 1.1.1.3 christos } \ 165 1.1.1.3 christos } while (0) 166 1.1.1.2 christos 167 1.1.1.2 christos TEST_BEGIN(test_fls_u) { 168 1.1.1.3 christos TEST_FLS(unsigned, u, u, "u"); 169 1.1.1.2 christos } 170 1.1.1.2 christos TEST_END 171 1.1.1.2 christos 172 1.1.1.2 christos TEST_BEGIN(test_fls_lu) { 173 1.1.1.2 christos TEST_FLS(unsigned long, lu, lu, "lu"); 174 1.1.1.2 christos } 175 1.1.1.2 christos TEST_END 176 1.1.1.2 christos 177 1.1.1.2 christos TEST_BEGIN(test_fls_llu) { 178 1.1.1.2 christos TEST_FLS(unsigned long long, llu, qd, "llu"); 179 1.1.1.2 christos } 180 1.1.1.2 christos TEST_END 181 1.1.1.2 christos 182 1.1.1.2 christos TEST_BEGIN(test_fls_u32) { 183 1.1.1.2 christos TEST_FLS(uint32_t, u32, u32, FMTu32); 184 1.1.1.2 christos } 185 1.1.1.2 christos TEST_END 186 1.1.1.2 christos 187 1.1.1.2 christos TEST_BEGIN(test_fls_u64) { 188 1.1.1.2 christos TEST_FLS(uint64_t, u64, u64, FMTu64); 189 1.1.1.2 christos } 190 1.1.1.2 christos TEST_END 191 1.1.1.2 christos 192 1.1.1.2 christos TEST_BEGIN(test_fls_zu) { 193 1.1.1.2 christos TEST_FLS(size_t, zu, zu, "zu"); 194 1.1.1.2 christos } 195 1.1.1.2 christos TEST_END 196 1.1.1.2 christos 197 1.1.1.2 christos TEST_BEGIN(test_fls_u_slow) { 198 1.1.1.3 christos TEST_FLS(unsigned, u_slow, u, "u"); 199 1.1.1.2 christos } 200 1.1.1.2 christos TEST_END 201 1.1.1.2 christos 202 1.1.1.2 christos TEST_BEGIN(test_fls_lu_slow) { 203 1.1.1.2 christos TEST_FLS(unsigned long, lu_slow, lu, "lu"); 204 1.1.1.2 christos } 205 1.1.1.2 christos TEST_END 206 1.1.1.2 christos 207 1.1.1.2 christos TEST_BEGIN(test_fls_llu_slow) { 208 1.1.1.2 christos TEST_FLS(unsigned long long, llu_slow, qd, "llu"); 209 1.1.1.2 christos } 210 1.1.1.2 christos TEST_END 211 1.1.1.2 christos 212 1.1.1.2 christos static unsigned 213 1.1.1.2 christos popcount_byte(unsigned byte) { 214 1.1.1.2 christos int count = 0; 215 1.1.1.2 christos for (int i = 0; i < 8; i++) { 216 1.1.1.2 christos if ((byte & (1 << i)) != 0) { 217 1.1.1.2 christos count++; 218 1.1.1.2 christos } 219 1.1.1.2 christos } 220 1.1.1.2 christos return count; 221 1.1.1.2 christos } 222 1.1.1.2 christos 223 1.1.1.2 christos static uint64_t 224 1.1.1.2 christos expand_byte_to_mask(unsigned byte) { 225 1.1.1.2 christos uint64_t result = 0; 226 1.1.1.2 christos for (int i = 0; i < 8; i++) { 227 1.1.1.2 christos if ((byte & (1 << i)) != 0) { 228 1.1.1.2 christos result |= ((uint64_t)0xFF << (i * 8)); 229 1.1.1.2 christos } 230 1.1.1.2 christos } 231 1.1.1.2 christos return result; 232 1.1.1.2 christos } 233 1.1.1.2 christos 234 1.1.1.3 christos /* clang-format off */ 235 1.1.1.2 christos #define TEST_POPCOUNT(t, suf, pri_hex) do { \ 236 1.1.1.2 christos t bmul = (t)0x0101010101010101ULL; \ 237 1.1.1.2 christos for (unsigned i = 0; i < (1 << sizeof(t)); i++) { \ 238 1.1.1.2 christos for (unsigned j = 0; j < 256; j++) { \ 239 1.1.1.2 christos /* \ 240 1.1.1.2 christos * Replicate the byte j into various \ 241 1.1.1.2 christos * bytes of the integer (as indicated by the \ 242 1.1.1.2 christos * mask in i), and ensure that the popcount of \ 243 1.1.1.2 christos * the result is popcount(i) * popcount(j) \ 244 1.1.1.2 christos */ \ 245 1.1.1.2 christos t mask = (t)expand_byte_to_mask(i); \ 246 1.1.1.2 christos t x = (bmul * j) & mask; \ 247 1.1.1.2 christos expect_u_eq( \ 248 1.1.1.2 christos popcount_byte(i) * popcount_byte(j), \ 249 1.1.1.2 christos popcount_##suf(x), \ 250 1.1.1.2 christos "Unexpected result, x=0x%"pri_hex, x); \ 251 1.1.1.2 christos } \ 252 1.1.1.2 christos } \ 253 1.1.1.2 christos } while (0) 254 1.1.1.3 christos /* clang-format on */ 255 1.1.1.2 christos 256 1.1.1.2 christos TEST_BEGIN(test_popcount_u) { 257 1.1.1.2 christos TEST_POPCOUNT(unsigned, u, "x"); 258 1.1.1.2 christos } 259 1.1.1.2 christos TEST_END 260 1.1.1.2 christos 261 1.1.1.2 christos TEST_BEGIN(test_popcount_u_slow) { 262 1.1.1.2 christos TEST_POPCOUNT(unsigned, u_slow, "x"); 263 1.1.1.2 christos } 264 1.1.1.2 christos TEST_END 265 1.1.1.2 christos 266 1.1.1.2 christos TEST_BEGIN(test_popcount_lu) { 267 1.1.1.2 christos TEST_POPCOUNT(unsigned long, lu, "lx"); 268 1.1.1.2 christos } 269 1.1.1.2 christos TEST_END 270 1.1.1.2 christos 271 1.1.1.2 christos TEST_BEGIN(test_popcount_lu_slow) { 272 1.1.1.2 christos TEST_POPCOUNT(unsigned long, lu_slow, "lx"); 273 1.1.1.2 christos } 274 1.1.1.2 christos TEST_END 275 1.1.1.2 christos 276 1.1.1.2 christos TEST_BEGIN(test_popcount_llu) { 277 1.1.1.2 christos TEST_POPCOUNT(unsigned long long, llu, "llx"); 278 1.1.1.2 christos } 279 1.1.1.2 christos TEST_END 280 1.1.1.2 christos 281 1.1.1.2 christos TEST_BEGIN(test_popcount_llu_slow) { 282 1.1.1.2 christos TEST_POPCOUNT(unsigned long long, llu_slow, "llx"); 283 1.1.1.2 christos } 284 1.1.1.2 christos TEST_END 285 1.1.1.2 christos 286 1.1 christos int 287 1.1 christos main(void) { 288 1.1.1.3 christos return test_no_reentrancy(test_pow2_ceil_u64, test_pow2_ceil_u32, 289 1.1.1.3 christos test_pow2_ceil_zu, test_lg_ceil_floor, test_ffs_u, test_ffs_lu, 290 1.1.1.3 christos test_ffs_llu, test_ffs_u32, test_ffs_u64, test_ffs_zu, test_fls_u, 291 1.1.1.3 christos test_fls_lu, test_fls_llu, test_fls_u32, test_fls_u64, test_fls_zu, 292 1.1.1.3 christos test_fls_u_slow, test_fls_lu_slow, test_fls_llu_slow, 293 1.1.1.3 christos test_popcount_u, test_popcount_u_slow, test_popcount_lu, 294 1.1.1.3 christos test_popcount_lu_slow, test_popcount_llu, test_popcount_llu_slow); 295 1.1 christos } 296