diff options
author | Ben Gamari <ben@smart-cactus.org> | 2022-07-09 22:02:30 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2022-07-14 14:02:08 -0400 |
commit | 72364127e1282879b227cb03e0641652f0151bbd (patch) | |
tree | 1844db67da957a2b12539158438c2930aa0d3b83 | |
parent | 41374d5552287d3586f0d2a0150dc0a159b236d3 (diff) | |
download | haskell-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.c | 28 |
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 |