Note [Deadlock detection under the nonmoving collector]
In GHC the garbage collector is responsible for identifying deadlocked
programs. Providing for this responsibility is slightly tricky in the
non-moving collector due to the existence of aging. In particular, the
non-moving collector cannot traverse objects living in a young generation
but reachable from the non-moving generation, as described in Note [Aging
under the non-moving collector].
However, this can pose trouble for deadlock detection since it means that we
may conservatively mark dead closures as live. Consider this case:
moving heap ┆ non-moving heap
───────────────┆──────────────────
┆
MVAR_QUEUE ←───── TSO ←───────────── gen1 mut_list
↑ │ ╰────────↗ │
│ │ ┆ │
│ │ ┆ ↓
│ ╰──────────→ MVAR
╰─────────────────╯
┆
In this case we have a TSO blocked on a dead MVar. Because the MVAR_TSO_QUEUE on
which it is blocked lives in the moving heap, the TSO is necessarily on the
oldest generation's mut_list. As in Note [Aging under the non-moving
collector], the MVAR_TSO_QUEUE will be evacuated. If MVAR_TSO_QUEUE is aged
(e.g. evacuated to the young generation) then the MVAR will be added to the
mark queue. Consequently, we will falsely conclude that the MVAR is still
alive and fail to spot the deadlock.
To avoid this sort of situation we disable aging when we are starting a
major GC specifically for deadlock detection (as done by
scheduleDetectDeadlock). This condition is recorded by the
deadlock_detect_gc global variable declared in GC.h. Setting this has a few
effects on the preparatory GC:
- Evac.c:alloc_for_copy forces evacuation to the non-moving generation.
- The evacuation logic usually responsible for pushing objects living in
the non-moving heap to the mark queue is disabled. This is safe because
we know that all live objects will be in the non-moving heap by the end
of the preparatory moving collection. References 0
This Note does not link to any other.
Referenced by 7
- rts/sm/Evac.c call site ×2
- rts/Schedule.c call site
- rts/sm/GC.c call site
- rts/sm/GC.h call site
- rts/sm/NonMovingMark.c call site
- rts/sm/Scav.c call site