... |
... |
@@ -603,7 +603,6 @@ void nonmovingPushFreeSegment(struct NonmovingSegment *seg) |
603
|
603
|
if (cas((StgVolatilePtr) &nonmovingHeap.free, (StgWord) old, (StgWord) seg) == (StgWord) old)
|
604
|
604
|
break;
|
605
|
605
|
}
|
606
|
|
- __sync_add_and_fetch(&nonmovingHeap.n_free, 1);
|
607
|
606
|
}
|
608
|
607
|
|
609
|
608
|
static int
|
... |
... |
@@ -621,20 +620,26 @@ cmp_segment_ptr (const void *x, const void *y) |
621
|
620
|
void nonmovingPruneFreeSegmentList(void)
|
622
|
621
|
{
|
623
|
622
|
trace(TRACE_nonmoving_gc, "Pruning free segment list.");
|
|
623
|
+
|
624
|
624
|
// Atomically grab the entire free list.
|
625
|
625
|
struct NonmovingSegment *free;
|
626
|
|
- size_t length;
|
627
|
626
|
while (true) {
|
628
|
627
|
free = ACQUIRE_LOAD(&nonmovingHeap.free);
|
629
|
|
- length = ACQUIRE_LOAD(&nonmovingHeap.n_free);
|
630
|
628
|
if (cas((StgVolatilePtr) &nonmovingHeap.free,
|
631
|
629
|
(StgWord) free,
|
632
|
630
|
(StgWord) NULL) == (StgWord) free) {
|
633
|
|
- atomic_dec((StgVolatilePtr) &nonmovingHeap.n_free, length);
|
634
|
631
|
break;
|
635
|
632
|
}
|
636
|
|
- // Save the current free list so the sanity checker can see these segments.
|
637
|
|
- nonmovingHeap.saved_free = free;
|
|
633
|
+ }
|
|
634
|
+ // Save the current free list so the sanity checker can see these segments.
|
|
635
|
+ nonmovingHeap.saved_free = free;
|
|
636
|
+
|
|
637
|
+ // Calculate the length of the list we've taken
|
|
638
|
+ size_t length = 0;
|
|
639
|
+ struct NonmovingSegment *free1 = free;
|
|
640
|
+ while (free1) {
|
|
641
|
+ length++;
|
|
642
|
+ free1 = free1->link;
|
638
|
643
|
}
|
639
|
644
|
|
640
|
645
|
// Sort the free list by address.
|
... |
... |
@@ -692,7 +697,6 @@ void nonmovingPruneFreeSegmentList(void) |
692
|
697
|
if (cas((StgVolatilePtr) &nonmovingHeap.free,
|
693
|
698
|
(StgWord) rest,
|
694
|
699
|
(StgWord) free) == (StgWord) rest) {
|
695
|
|
- __sync_add_and_fetch(&nonmovingHeap.n_free, new_length);
|
696
|
700
|
break;
|
697
|
701
|
}
|
698
|
702
|
}
|