diff options
author | Ben Gamari <ben@smart-cactus.org> | 2022-07-09 22:02:30 -0400 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2022-07-13 20:44:08 -0400 |
commit | dcf8b30a1a5f802b1d8a22ea74499e2896a6ff16 (patch) | |
tree | c04740512aae29f3e30c718f16e1d82e7d5102c3 | |
parent | a2f142f84bbc865f586ecc6ce94126c5427a86c1 (diff) | |
download | haskell-dcf8b30a1a5f802b1d8a22ea74499e2896a6ff16.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.
-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 |