summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2022-07-22 18:57:34 +0000
committerMarge Bot <ben+marge-bot@smart-cactus.org>2022-07-25 23:32:06 -0400
commit4b08797380a0a0a789844c17c6ed1570b62dc119 (patch)
treecce93561638adc91582a327329198bc26ca6e4b0
parent82a0991a73130f2cb70bd8ccaaff30cffd1dd2b0 (diff)
downloadhaskell-4b08797380a0a0a789844c17c6ed1570b62dc119.tar.gz
rts/nonmoving: Track segment state
It can often be useful during debugging to be able to determine the state of a nonmoving segment. Introduce some state, enabled by DEBUG, to track this. (cherry picked from commit 40e797ef591ae3122ccc98ab0cc3cfcf9d17bd7f)
-rw-r--r--rts/sm/NonMoving.c5
-rw-r--r--rts/sm/NonMoving.h24
2 files changed, 28 insertions, 1 deletions
diff --git a/rts/sm/NonMoving.c b/rts/sm/NonMoving.c
index a918f422cf..ad140ff495 100644
--- a/rts/sm/NonMoving.c
+++ b/rts/sm/NonMoving.c
@@ -504,6 +504,7 @@ static void nonmovingInitSegment(struct NonmovingSegment *seg, uint8_t log_block
seg->link = NULL;
seg->todo_link = NULL;
seg->next_free = 0;
+ SET_SEGMENT_STATE(seg, FREE);
bd->nonmoving_segment.log_block_size = log_block_size;
bd->nonmoving_segment.next_free_snap = 0;
bd->u.scan = nonmovingSegmentGetBlock(seg, 0);
@@ -526,6 +527,7 @@ void nonmovingPushFreeSegment(struct NonmovingSegment *seg)
return;
}
+ SET_SEGMENT_STATE(seg, FREE);
while (true) {
struct NonmovingSegment *old = nonmovingHeap.free;
seg->link = old;
@@ -694,6 +696,7 @@ void *nonmovingAllocate(Capability *cap, StgWord sz)
// make it current
new_current->link = NULL;
+ SET_SEGMENT_STATE(new_current, CURRENT);
alloca->current[cap->no] = new_current;
}
@@ -790,6 +793,7 @@ void nonmovingAddCapabilities(uint32_t new_n_caps)
for (unsigned int j = old_n_caps; j < new_n_caps; j++) {
allocs[i]->current[j] = nonmovingAllocSegment(capabilities[j]->node);
nonmovingInitSegment(allocs[i]->current[j], NONMOVING_ALLOCA0 + i);
+ SET_SEGMENT_STATE(allocs[i]->current[j], CURRENT);
allocs[i]->current[j]->link = NULL;
}
}
@@ -1067,6 +1071,7 @@ static void nonmovingMark_(MarkQueue *mark_queue, StgWeak **dead_weaks, StgTSO *
break;
}
// add filled segments to sweep_list
+ SET_SEGMENT_STATE(seg, FILLED_SWEEPING);
seg->link = nonmovingHeap.sweep_list;
nonmovingHeap.sweep_list = filled;
}
diff --git a/rts/sm/NonMoving.h b/rts/sm/NonMoving.h
index 17c0a3bec0..0886215de8 100644
--- a/rts/sm/NonMoving.h
+++ b/rts/sm/NonMoving.h
@@ -33,11 +33,31 @@ _Static_assert(NONMOVING_SEGMENT_SIZE % BLOCK_SIZE == 0,
// The index of a block within a segment
typedef uint16_t nonmoving_block_idx;
+#if defined(DEBUG)
+#define TRACK_SEGMENT_STATE
+#endif
+
+#if defined(TRACK_SEGMENT_STATE)
+// The collector itself doesn't require each segment to know its state (this is
+// implied by what segment list it is on) however it can be very useful while
+// debugging to know this.
+enum NonmovingSegmentState {
+ FREE, CURRENT, ACTIVE, FILLED, FILLED_SWEEPING
+};
+
+#define SET_SEGMENT_STATE(seg, st) (seg)->state = (st)
+#else
+#define SET_SEGMENT_STATE(_seg,_st)
+#endif
+
// A non-moving heap segment
struct NonmovingSegment {
- struct NonmovingSegment *link; // for linking together segments into lists
+ struct NonmovingSegment *link; // for linking together segments into lists
struct NonmovingSegment *todo_link; // NULL when not in todo list
nonmoving_block_idx next_free; // index of the next unallocated block
+#if defined(TRACK_SEGMENT_STATE)
+ enum NonmovingSegmentState state;
+#endif
uint8_t bitmap[]; // liveness bitmap
// After the liveness bitmap comes the data blocks. Note that we need to
// ensure that the size of this struct (including the bitmap) is a multiple
@@ -148,6 +168,7 @@ INLINE_HEADER void nonmovingPushActiveSegment(struct NonmovingSegment *seg)
{
struct NonmovingAllocator *alloc =
nonmovingHeap.allocators[nonmovingSegmentLogBlockSize(seg) - NONMOVING_ALLOCA0];
+ SET_SEGMENT_STATE(seg, ACTIVE);
while (true) {
struct NonmovingSegment *current_active = (struct NonmovingSegment*)VOLATILE_LOAD(&alloc->active);
seg->link = current_active;
@@ -162,6 +183,7 @@ INLINE_HEADER void nonmovingPushFilledSegment(struct NonmovingSegment *seg)
{
struct NonmovingAllocator *alloc =
nonmovingHeap.allocators[nonmovingSegmentLogBlockSize(seg) - NONMOVING_ALLOCA0];
+ SET_SEGMENT_STATE(seg, FILLED);
while (true) {
struct NonmovingSegment *current_filled = (struct NonmovingSegment*)VOLATILE_LOAD(&alloc->filled);
seg->link = current_filled;