Skip to content
Snippets Groups Projects
Commit fe68ad50 authored by parcs's avatar parcs
Browse files

Update and deduplicate the comments on CAF management (#8590)

parent 55c703b8
No related branches found
No related tags found
No related merge requests found
...@@ -695,44 +695,17 @@ emitUpdateFrame dflags frame lbl updatee = do ...@@ -695,44 +695,17 @@ emitUpdateFrame dflags frame lbl updatee = do
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Entering a CAF -- Entering a CAF
-- --
-- When a CAF is first entered, it creates a black hole in the heap, -- See Note [CAF management] in rts/sm/Storage.c
-- and updates itself with an indirection to this new black hole.
--
-- We update the CAF with an indirection to a newly-allocated black
-- hole in the heap. We also set the blocking queue on the newly
-- allocated black hole to be empty.
--
-- Why do we make a black hole in the heap when we enter a CAF?
--
-- - for a generational garbage collector, which needs a fast
-- test for whether an updatee is in an old generation or not
--
-- - for the parallel system, which can implement updates more
-- easily if the updatee is always in the heap. (allegedly).
--
-- When debugging, we maintain a separate CAF list so we can tell when
-- a CAF has been garbage collected.
-- newCAF must be called before the itbl ptr is overwritten, since
-- newCAF records the old itbl ptr in order to do CAF reverting
-- (which Hugs needs to do in order that combined mode works right.)
--
link_caf :: LocalReg -- pointer to the closure link_caf :: LocalReg -- pointer to the closure
-> Bool -- True <=> updatable, False <=> single-entry -> Bool -- True <=> updatable, False <=> single-entry
-> FCode CmmExpr -- Returns amode for closure to be updated -> FCode CmmExpr -- Returns amode for closure to be updated
-- To update a CAF we must allocate a black hole, link the CAF onto the
-- CAF list, then update the CAF to point to the fresh black hole.
-- This function returns the address of the black hole, so it can be -- This function returns the address of the black hole, so it can be
-- updated with the new value when available. The reason for all of this -- updated with the new value when available.
-- is that we only want to update dynamic heap objects, not static ones,
-- so that generational GC is easier.
link_caf node _is_upd = do link_caf node _is_upd = do
{ dflags <- getDynFlags { dflags <- getDynFlags
-- Call the RTS function newCAF to add the CAF to the CafList -- Call the RTS function newCAF, returning the newly-allocated
-- so that the garbage collector can find them -- blackhole indirection closure
-- This must be done *before* the info table pointer is overwritten,
-- because the old info table ptr is needed for reversion
; let newCAF_lbl = mkForeignLabel (fsLit "newCAF") Nothing ; let newCAF_lbl = mkForeignLabel (fsLit "newCAF") Nothing
ForeignLabelInExternalPackage IsFunction ForeignLabelInExternalPackage IsFunction
; bh <- newTemp (bWord dflags) ; bh <- newTemp (bWord dflags)
......
...@@ -268,14 +268,12 @@ freeStorage (rtsBool free_heap) ...@@ -268,14 +268,12 @@ freeStorage (rtsBool free_heap)
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
CAF management. Note [CAF management].
The entry code for every CAF does the following: The entry code for every CAF does the following:
- builds a CAF_BLACKHOLE in the heap
- calls newCaf, which atomically updates the CAF with - calls newCaf, which builds a CAF_BLACKHOLE on the heap and atomically
IND_STATIC pointing to the CAF_BLACKHOLE updates the CAF with IND_STATIC pointing to the CAF_BLACKHOLE
- if newCaf returns zero, it re-enters the CAF (see Note [atomic - if newCaf returns zero, it re-enters the CAF (see Note [atomic
CAF entry]) CAF entry])
...@@ -289,7 +287,11 @@ freeStorage (rtsBool free_heap) ...@@ -289,7 +287,11 @@ freeStorage (rtsBool free_heap)
frames would also need special cases for static update frames. frames would also need special cases for static update frames.
newCaf() does the following: newCaf() does the following:
- atomically locks the CAF (see [atomic CAF entry])
- it builds a CAF_BLACKHOLE on the heap
- it updates the CAF with an IND_STATIC pointing to the - it updates the CAF with an IND_STATIC pointing to the
CAF_BLACKHOLE, atomically. CAF_BLACKHOLE, atomically.
...@@ -297,6 +299,8 @@ freeStorage (rtsBool free_heap) ...@@ -297,6 +299,8 @@ freeStorage (rtsBool free_heap)
This is so that we treat the CAF as a root when collecting This is so that we treat the CAF as a root when collecting
younger generations. younger generations.
- links the CAF onto the CAF list (see below)
------------------ ------------------
Note [atomic CAF entry] Note [atomic CAF entry]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment