1 /* ----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team 1998-2008
4  *
5  * Generational garbage collector: utilities
6  *
7  * Documentation on the architecture of the Garbage Collector can be
8  * found in the online commentary:
9  *
10  *   https://gitlab.haskell.org/ghc/ghc/wikis/commentary/rts/storage/gc
11  *
12  * --------------------------------------------------------------------------*/
13 
14 #pragma once
15 
16 #include "BeginPrivate.h"
17 
18 #include "GCTDecl.h"
19 
20 bdescr* allocGroup_sync(uint32_t n);
21 bdescr* allocGroupOnNode_sync(uint32_t node, uint32_t n);
22 
allocBlock_sync(void)23 INLINE_HEADER bdescr *allocBlock_sync(void)
24 {
25     return allocGroup_sync(1);
26 }
27 
allocBlockOnNode_sync(uint32_t node)28 INLINE_HEADER bdescr *allocBlockOnNode_sync(uint32_t node)
29 {
30     return allocGroupOnNode_sync(node,1);
31 }
32 
33 void    freeChain_sync(bdescr *bd);
34 void    freeGroup_sync(bdescr *bd);
35 
36 void    push_scanned_block   (bdescr *bd, gen_workspace *ws);
37 StgPtr  todo_block_full      (uint32_t size, gen_workspace *ws);
38 StgPtr  alloc_todo_block     (gen_workspace *ws, uint32_t size);
39 
40 bdescr *grab_local_todo_block  (gen_workspace *ws);
41 #if defined(THREADED_RTS)
42 bdescr *steal_todo_block       (uint32_t s);
43 #endif
44 
45 // Returns true if a block is partially full.  This predicate is used to try
46 // to re-use partial blocks wherever possible, and to reduce wastage.
47 // We might need to tweak the actual value.
48 INLINE_HEADER bool
isPartiallyFull(bdescr * bd)49 isPartiallyFull(bdescr *bd)
50 {
51     return (bd->free + WORK_UNIT_WORDS < bd->start + BLOCK_SIZE_W);
52 }
53 
54 // Version of recordMutableGen for use during GC.  This uses the
55 // mutable lists attached to the current gc_thread structure, which
56 // are the same as the mutable lists on the Capability.
57 INLINE_HEADER void
recordMutableGen_GC(StgClosure * p,uint32_t gen_no)58 recordMutableGen_GC (StgClosure *p, uint32_t gen_no)
59 {
60     bdescr *bd;
61 
62     bd = gct->mut_lists[gen_no];
63     if (bd->free >= bd->start + BLOCK_SIZE_W) {
64         bdescr *new_bd;
65         new_bd = allocBlock_sync();
66         new_bd->link = bd;
67         bd = new_bd;
68         gct->mut_lists[gen_no] = bd;
69     }
70     *bd->free++ = (StgWord) p;
71     // N.B. we are allocating into our Capability-local mut_list, therefore
72     // we don't need an atomic increment.
73 }
74 
75 #include "EndPrivate.h"
76