summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2022-07-09 22:02:30 -0400
committerBen Gamari <ben@smart-cactus.org>2022-07-14 14:02:08 -0400
commit72364127e1282879b227cb03e0641652f0151bbd (patch)
tree1844db67da957a2b12539158438c2930aa0d3b83
parent41374d5552287d3586f0d2a0150dc0a159b236d3 (diff)
downloadhaskell-72364127e1282879b227cb03e0641652f0151bbd.tar.gz
rts: Fix AdjustorPool bitmap manipulation
Previously the implementation of bitmap_first_unset assumed that `__builtin_clz` would accept `uint8_t` however it apparently rather extends its argument to `unsigned int`. To fix this we simply revert to a naive implementation since handling the various corner cases with `clz` is quite tricky. This should be fine given that AdjustorPool isn't particularly hot. Ideally we would have a single, optimised bitmap implementation in the RTS but I'll leave this for future work. Fixes #21838. (cherry picked from commit dfa95eccf7b45a8961e034710d5e3ca45a36bf5e)
-rw-r--r--rts/adjustor/AdjustorPool.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/rts/adjustor/AdjustorPool.c b/rts/adjustor/AdjustorPool.c
index 9458c67246..146afc5b40 100644
--- a/rts/adjustor/AdjustorPool.c
+++ b/rts/adjustor/AdjustorPool.c
@@ -167,20 +167,6 @@ new_adjustor_pool(
return pool;
}
-/* Return the index of the first unset bit of the given bitmap or
- * length_in_bits. */
-static size_t
-bitmap_first_unset(uint8_t *bitmap, size_t length_in_bits, size_t start_idx)
-{
- for (size_t i = start_idx; i < length_in_bits; i += 8) {
- uint8_t x = bitmap[i / 8];
- if (x != 0xff) {
- return i + __builtin_clz(~x);
- }
- }
- return length_in_bits;
-}
-
static void
bitmap_set(uint8_t *bitmap, size_t idx, bool value)
{
@@ -202,6 +188,19 @@ bitmap_get(uint8_t *bitmap, size_t idx)
return bitmap[word_n] & bit;
}
+/* Return the index of the first unset bit of the given bitmap or
+ * length_in_bits if all bits are set. */
+static size_t
+bitmap_first_unset(uint8_t *bitmap, size_t length_in_bits, size_t start_idx)
+{
+ for (size_t i = start_idx; i < length_in_bits; i ++) {
+ if (bitmap_get(bitmap, i) == 0) {
+ return i;
+ }
+ }
+ return length_in_bits;
+}
+
static void *
get_context(struct AdjustorChunk *chunk, size_t slot_idx)
{
@@ -224,6 +223,7 @@ alloc_adjustor(struct AdjustorPool *pool, void *context)
chunk = pool->free_list;
slot_idx = chunk->first_free;
ASSERT(slot_idx < pool->chunk_slots);
+ ASSERT(bitmap_get(chunk->slot_bitmap, slot_idx) == 0);
bitmap_set(chunk->slot_bitmap, slot_idx, 1);
// advance first_free