From a60db2f706aaea845cb343bf46e2fcaa634129d8 Mon Sep 17 00:00:00 2001 From: "LAPTOP-QPMELQ26\\Stanislav" Date: Fri, 26 Sep 2025 19:52:32 +0300 Subject: [PATCH 1/6] Add a portable count_trailing_zeroes implementation, use it for faster depth_for_size --- .gitignore | 6 ++++++ bench.c | 2 +- buddy_alloc.h | 49 +++++++++++++++++++++++++++++++++---------------- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 0ef5423..079f130 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,9 @@ out/* # visual studio cmake settings CMakeSettings.json + +# Pelles C project files +# Pelles C is awesome by the way, check it out +*.ppj +*.ppx +*.tag diff --git a/bench.c b/bench.c index 4cc88ad..87d9c11 100644 --- a/bench.c +++ b/bench.c @@ -69,4 +69,4 @@ void *freeing_callback(void *ctx, void *addr, size_t slot_size, size_t allocated struct buddy *buddy = (struct buddy*) ctx; buddy_free(buddy, addr); return NULL; -} \ No newline at end of file +} diff --git a/buddy_alloc.h b/buddy_alloc.h index ac65577..893c0f9 100644 --- a/buddy_alloc.h +++ b/buddy_alloc.h @@ -462,6 +462,9 @@ void bitset_debug(unsigned char *bitset, size_t length); /* Returns the number of set bits in the given byte */ static unsigned int popcount_byte(unsigned char b); +/* Count the number of trailing zeroes in the given value */ +static unsigned char count_trailing_zeroes(size_t val); + /* Returns the index of the highest bit set (1-based) */ static size_t highest_bit_position(size_t value); @@ -1106,16 +1109,16 @@ void buddy_enable_change_tracking(struct buddy* buddy, void* context, void (*tra static size_t depth_for_size(struct buddy *buddy, size_t requested_size) { - size_t depth, effective_memory_size; + size_t depth, effective_memory_size, p2_of_requested_size; if (requested_size < buddy->alignment) { requested_size = buddy->alignment; } depth = 1; effective_memory_size = buddy_effective_memory_size(buddy); - while ((effective_memory_size / requested_size) >> 1u) { - depth++; - effective_memory_size >>= 1u; - } + + p2_of_requested_size = ceiling_power_of_two(requested_size); + depth = count_trailing_zeroes(effective_memory_size) + 1 + - count_trailing_zeroes(p2_of_requested_size); return depth; } @@ -2133,21 +2136,35 @@ void bitset_debug(unsigned char *bitset, size_t length) { Bits */ -static const unsigned char popcount_lookup[256] = { - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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 -}; - static inline unsigned int popcount_byte(unsigned char b) { + static const unsigned char popcount_lookup[256] = { + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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 + }; return popcount_lookup[b]; } +static unsigned char count_trailing_zeroes(size_t val) { + /* Implementation from https://www.chessprogramming.org/BitScan */ + static const unsigned char lookup67[67+1] = { + 64, 0, 1, 39, 2, 15, 40, 23, + 3, 12, 16, 59, 41, 19, 24, 54, + 4, -1, 13, 10, 17, 62, 60, 28, + 42, 30, 20, 51, 25, 44, 55, 47, + 5, 32, -1, 38, 14, 22, 11, 58, + 18, 53, 63, 9, 61, 27, 29, 50, + 43, 46, 31, 37, 21, 57, 52, 8, + 26, 49, 45, 36, 56, 7, 48, 35, + 6, 34, 33, -1 }; + return lookup67[(val & -val) % 67]; +} + /* Returns the highest set bit position for the given value. Returns zero for zero. */ static size_t highest_bit_position(size_t value) { size_t result = 0; From 6fbab11ad305e25da8bca62a5b2cdc0e55d6b5d0 Mon Sep 17 00:00:00 2001 From: "LAPTOP-QPMELQ26\\Stanislav" Date: Fri, 26 Sep 2025 20:04:35 +0300 Subject: [PATCH 2/6] Fix cppcheck and compiler warnings --- buddy_alloc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buddy_alloc.h b/buddy_alloc.h index 893c0f9..06fc921 100644 --- a/buddy_alloc.h +++ b/buddy_alloc.h @@ -759,7 +759,7 @@ size_t buddy_arena_free_size(struct buddy *buddy) { } static unsigned int is_valid_alignment(size_t alignment) { - return ceiling_power_of_two(alignment) == alignment; + return (alignment > 0) && (ceiling_power_of_two(alignment) == alignment); } static size_t buddy_tree_order_for_memory(size_t memory_size, size_t alignment) { @@ -2152,7 +2152,7 @@ static inline unsigned int popcount_byte(unsigned char b) { static unsigned char count_trailing_zeroes(size_t val) { /* Implementation from https://www.chessprogramming.org/BitScan */ - static const unsigned char lookup67[67+1] = { + static const signed char lookup67[67+1] = { 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, 4, -1, 13, 10, 17, 62, 60, 28, From 59624f404007f967e7b08543c7a1c8a5bf2166fd Mon Sep 17 00:00:00 2001 From: "LAPTOP-QPMELQ26\\Stanislav" Date: Fri, 26 Sep 2025 20:13:07 +0300 Subject: [PATCH 3/6] Fighting cppcheck without having it locally is brilliant --- buddy_alloc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/buddy_alloc.h b/buddy_alloc.h index 06fc921..542f0e0 100644 --- a/buddy_alloc.h +++ b/buddy_alloc.h @@ -759,10 +759,11 @@ size_t buddy_arena_free_size(struct buddy *buddy) { } static unsigned int is_valid_alignment(size_t alignment) { - return (alignment > 0) && (ceiling_power_of_two(alignment) == alignment); + return ceiling_power_of_two(alignment) == alignment; } static size_t buddy_tree_order_for_memory(size_t memory_size, size_t alignment) { + // cppcheck-suppress divisionByZero size_t blocks = memory_size / alignment; return highest_bit_position(ceiling_power_of_two(blocks)); } From c593c44c33db5540177fa00b6d7a624a45634bde Mon Sep 17 00:00:00 2001 From: "LAPTOP-QPMELQ26\\Stanislav" Date: Fri, 26 Sep 2025 20:15:49 +0300 Subject: [PATCH 4/6] Use the correct cppcheck check name for division by zero --- buddy_alloc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buddy_alloc.h b/buddy_alloc.h index 542f0e0..c9e83d1 100644 --- a/buddy_alloc.h +++ b/buddy_alloc.h @@ -763,7 +763,7 @@ static unsigned int is_valid_alignment(size_t alignment) { } static size_t buddy_tree_order_for_memory(size_t memory_size, size_t alignment) { - // cppcheck-suppress divisionByZero + // cppcheck-suppress zerodiv size_t blocks = memory_size / alignment; return highest_bit_position(ceiling_power_of_two(blocks)); } From 3409ca2d6025ae3449b27685544f5bed41012ba7 Mon Sep 17 00:00:00 2001 From: "LAPTOP-QPMELQ26\\Stanislav" Date: Fri, 26 Sep 2025 20:19:20 +0300 Subject: [PATCH 5/6] Enable inline suppresion --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 983e013..21fae3b 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ tests.out: $(TESTS_SRC) $(LIB_SRC) test-cppcheck check-recursion $(CC) $(CFLAGS) $(TESTS_SRC) -o $@ test-cppcheck: $(TESTS_SRC) - $(CPPCHECK) --error-exitcode=1 --quiet $^ + $(CPPCHECK) --error-exitcode=1 --inline-suppr --quiet $^ test-cpp-translation-unit: $(TESTCXX_SRC) $(CXX) $(CXXFLAGS) $(TESTCXX_SRC) -o $@ From 2b802e4c40b14031b725b33882e270f0dc775145 Mon Sep 17 00:00:00 2001 From: "LAPTOP-QPMELQ26\\Stanislav" Date: Fri, 26 Sep 2025 20:23:53 +0300 Subject: [PATCH 6/6] Avoid implicit sign conversion --- buddy_alloc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buddy_alloc.h b/buddy_alloc.h index c9e83d1..8bc52a2 100644 --- a/buddy_alloc.h +++ b/buddy_alloc.h @@ -2163,7 +2163,7 @@ static unsigned char count_trailing_zeroes(size_t val) { 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, 7, 48, 35, 6, 34, 33, -1 }; - return lookup67[(val & -val) % 67]; + return ((unsigned char) lookup67[(val & -val) % 67]); } /* Returns the highest set bit position for the given value. Returns zero for zero. */