[Git][ghc/ghc][wip/T26186] rts/nonmovingGC: remove n_free

Teo Camarasu pushed to branch wip/T26186 at Glasgow Haskell Compiler / GHC Commits: e2cfe7bc by Teo Camarasu at 2025-07-11T16:45:20+01:00 rts/nonmovingGC: remove n_free We remove the nonmovingHeap.n_free variable. We wanted this to track the length of nonmovingHeap.free. But this isn't possible to do atomically. When this isn't accurate we can get a segfault by going past the end of the list. Instead, we just count the length of the list when we grab it in nonmovingPruneFreeSegment. Resolves #26186 - - - - - 3 changed files: - rts/sm/NonMoving.c - rts/sm/NonMoving.h - rts/sm/NonMovingAllocate.c Changes: ===================================== rts/sm/NonMoving.c ===================================== @@ -603,7 +603,6 @@ void nonmovingPushFreeSegment(struct NonmovingSegment *seg) if (cas((StgVolatilePtr) &nonmovingHeap.free, (StgWord) old, (StgWord) seg) == (StgWord) old) break; } - __sync_add_and_fetch(&nonmovingHeap.n_free, 1); } static int @@ -621,20 +620,26 @@ cmp_segment_ptr (const void *x, const void *y) void nonmovingPruneFreeSegmentList(void) { trace(TRACE_nonmoving_gc, "Pruning free segment list."); + // Atomically grab the entire free list. struct NonmovingSegment *free; - size_t length; while (true) { free = ACQUIRE_LOAD(&nonmovingHeap.free); - length = ACQUIRE_LOAD(&nonmovingHeap.n_free); if (cas((StgVolatilePtr) &nonmovingHeap.free, (StgWord) free, (StgWord) NULL) == (StgWord) free) { - atomic_dec((StgVolatilePtr) &nonmovingHeap.n_free, length); break; } - // Save the current free list so the sanity checker can see these segments. - nonmovingHeap.saved_free = free; + } + // Save the current free list so the sanity checker can see these segments. + nonmovingHeap.saved_free = free; + + // Calculate the length of the list we've taken + size_t length = 0; + struct NonmovingSegment *free1 = free; + while (!free1) { + length++; + free1 = free1->link; } // Sort the free list by address. @@ -692,7 +697,6 @@ void nonmovingPruneFreeSegmentList(void) if (cas((StgVolatilePtr) &nonmovingHeap.free, (StgWord) rest, (StgWord) free) == (StgWord) rest) { - __sync_add_and_fetch(&nonmovingHeap.n_free, new_length); break; } } ===================================== rts/sm/NonMoving.h ===================================== @@ -134,8 +134,6 @@ struct NonmovingHeap { // saved free segment list, so the sanity checker can // see the segments while the free list is being pruned. struct NonmovingSegment *saved_free; - // how many segments in free segment list? accessed atomically. - unsigned int n_free; // records the current length of the nonmovingAllocator.current arrays unsigned int n_caps; ===================================== rts/sm/NonMovingAllocate.c ===================================== @@ -183,7 +183,6 @@ static struct NonmovingSegment *nonmovingPopFreeSegment(void) if (cas((StgVolatilePtr) &nonmovingHeap.free, (StgWord) seg, (StgWord) seg->link) == (StgWord) seg) { - __sync_sub_and_fetch(&nonmovingHeap.n_free, 1); return seg; } } View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e2cfe7bc0639e70a4fda5170cb06d89a... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e2cfe7bc0639e70a4fda5170cb06d89a... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Teo Camarasu (@teo)