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-11 11:02:38 -0400
commitdfa95eccf7b45a8961e034710d5e3ca45a36bf5e (patch)
tree53325fa926e449ff3267fac9a6155b0b72276610
parent460505345e500eb902da9737c75c077d5fc5ef66 (diff)
downloadhaskell-wip/T21838.tar.gz
rts: Fix AdjustorPool bitmap manipulationwip/T21838
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.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