Skip to content

Commit b19cb73

Browse files
authored
Add a portable count_trailing_zeroes implementation, use it for faster depth_for_size
1 parent 59e0620 commit b19cb73

File tree

4 files changed

+42
-18
lines changed

4 files changed

+42
-18
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,9 @@ out/*
7171

7272
# visual studio cmake settings
7373
CMakeSettings.json
74+
75+
# Pelles C project files
76+
# Pelles C is awesome by the way, check it out
77+
*.ppj
78+
*.ppx
79+
*.tag

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ tests.out: $(TESTS_SRC) $(LIB_SRC) test-cppcheck check-recursion
3131
$(CC) $(CFLAGS) $(TESTS_SRC) -o $@
3232

3333
test-cppcheck: $(TESTS_SRC)
34-
$(CPPCHECK) --error-exitcode=1 --quiet $^
34+
$(CPPCHECK) --error-exitcode=1 --inline-suppr --quiet $^
3535

3636
test-cpp-translation-unit: $(TESTCXX_SRC)
3737
$(CXX) $(CXXFLAGS) $(TESTCXX_SRC) -o $@

bench.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,4 @@ void *freeing_callback(void *ctx, void *addr, size_t slot_size, size_t allocated
6969
struct buddy *buddy = (struct buddy*) ctx;
7070
buddy_free(buddy, addr);
7171
return NULL;
72-
}
72+
}

buddy_alloc.h

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,9 @@ void bitset_debug(unsigned char *bitset, size_t length);
462462
/* Returns the number of set bits in the given byte */
463463
static unsigned int popcount_byte(unsigned char b);
464464

465+
/* Count the number of trailing zeroes in the given value */
466+
static unsigned char count_trailing_zeroes(size_t val);
467+
465468
/* Returns the index of the highest bit set (1-based) */
466469
static size_t highest_bit_position(size_t value);
467470

@@ -760,6 +763,7 @@ static unsigned int is_valid_alignment(size_t alignment) {
760763
}
761764

762765
static size_t buddy_tree_order_for_memory(size_t memory_size, size_t alignment) {
766+
// cppcheck-suppress zerodiv
763767
size_t blocks = memory_size / alignment;
764768
return highest_bit_position(ceiling_power_of_two(blocks));
765769
}
@@ -1106,16 +1110,16 @@ void buddy_enable_change_tracking(struct buddy* buddy, void* context, void (*tra
11061110

11071111

11081112
static size_t depth_for_size(struct buddy *buddy, size_t requested_size) {
1109-
size_t depth, effective_memory_size;
1113+
size_t depth, effective_memory_size, p2_of_requested_size;
11101114
if (requested_size < buddy->alignment) {
11111115
requested_size = buddy->alignment;
11121116
}
11131117
depth = 1;
11141118
effective_memory_size = buddy_effective_memory_size(buddy);
1115-
while ((effective_memory_size / requested_size) >> 1u) {
1116-
depth++;
1117-
effective_memory_size >>= 1u;
1118-
}
1119+
1120+
p2_of_requested_size = ceiling_power_of_two(requested_size);
1121+
depth = count_trailing_zeroes(effective_memory_size) + 1
1122+
- count_trailing_zeroes(p2_of_requested_size);
11191123
return depth;
11201124
}
11211125

@@ -2133,21 +2137,35 @@ void bitset_debug(unsigned char *bitset, size_t length) {
21332137
Bits
21342138
*/
21352139

2136-
static const unsigned char popcount_lookup[256] = {
2137-
0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
2138-
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
2139-
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
2140-
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
2141-
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
2142-
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
2143-
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
2144-
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
2145-
};
2146-
21472140
static inline unsigned int popcount_byte(unsigned char b) {
2141+
static const unsigned char popcount_lookup[256] = {
2142+
0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
2143+
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
2144+
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
2145+
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
2146+
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
2147+
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
2148+
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
2149+
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
2150+
};
21482151
return popcount_lookup[b];
21492152
}
21502153

2154+
static unsigned char count_trailing_zeroes(size_t val) {
2155+
/* Implementation from https://www.chessprogramming.org/BitScan */
2156+
static const signed char lookup67[67+1] = {
2157+
64, 0, 1, 39, 2, 15, 40, 23,
2158+
3, 12, 16, 59, 41, 19, 24, 54,
2159+
4, -1, 13, 10, 17, 62, 60, 28,
2160+
42, 30, 20, 51, 25, 44, 55, 47,
2161+
5, 32, -1, 38, 14, 22, 11, 58,
2162+
18, 53, 63, 9, 61, 27, 29, 50,
2163+
43, 46, 31, 37, 21, 57, 52, 8,
2164+
26, 49, 45, 36, 56, 7, 48, 35,
2165+
6, 34, 33, -1 };
2166+
return ((unsigned char) lookup67[(val & -val) % 67]);
2167+
}
2168+
21512169
/* Returns the highest set bit position for the given value. Returns zero for zero. */
21522170
static size_t highest_bit_position(size_t value) {
21532171
size_t result = 0;

0 commit comments

Comments
 (0)