Home | History | Annotate | Line # | Download | only in unit
      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