1 /* -----------------------------------------------------------------------------
2 * $Id: Storage.h,v 1.16 2000/04/14 15:18:07 sewardj Exp $
4 * (c) The GHC Team, 1998-1999
6 * External Storage Manger Interface
8 * ---------------------------------------------------------------------------*/
14 #include "BlockAlloc.h"
15 #include "StoragePriv.h"
17 /* -----------------------------------------------------------------------------
18 Initialisation / De-initialisation
19 -------------------------------------------------------------------------- */
21 extern void initStorage(void);
22 extern void exitStorage(void);
24 /* -----------------------------------------------------------------------------
27 StgPtr allocate(int n) Allocates a chunk of contiguous store
28 n words long, returning a pointer to
29 the first word. Always succeeds.
31 Don't forget to TICK_ALLOC_XXX(...)
32 after calling allocate, for the
33 benefit of the ticky-ticky profiler.
35 rtsBool doYouWantToGC(void) Returns True if the storage manager is
36 ready to perform a GC, False otherwise.
38 lnat allocated_bytes(void) Returns the number of bytes allocated
39 via allocate() since the last GC.
40 Used in the reoprting of statistics.
42 SMP: allocate and doYouWantToGC can be used from STG code, they are
43 surrounded by a mutex.
44 -------------------------------------------------------------------------- */
46 extern StgPtr allocate(nat n);
47 static inline rtsBool doYouWantToGC(void)
49 return (alloc_blocks >= alloc_blocks_lim);
51 extern lnat allocated_bytes(void);
53 /* -----------------------------------------------------------------------------
54 ExtendNursery(hp,hplim) When hplim is reached, try to grab
55 some more allocation space. Returns
56 False if the allocation space is
57 exhausted, and the application should
58 call GarbageCollect().
59 -------------------------------------------------------------------------- */
61 #define ExtendNursery(hp,hplim) \
62 (CurrentNursery->free = (P_)(hp)+1, \
63 CurrentNursery->link == NULL ? rtsFalse : \
64 (CurrentNursery = CurrentNursery->link, \
65 OpenNursery(hp,hplim), \
68 extern void PleaseStopAllocating(void);
70 /* -----------------------------------------------------------------------------
71 Performing Garbage Collection
73 GarbageCollect(get_roots) Performs a garbage collection.
74 'get_roots' is called to find all the
75 roots that the system knows about.
77 StgClosure Called by get_roots on each root.
78 MarkRoot(StgClosure *p) Returns the new location of the root.
79 -------------------------------------------------------------------------- */
81 extern void GarbageCollect(void (*get_roots)(void),rtsBool force_major_gc);
82 extern StgClosure *MarkRoot(StgClosure *p);
84 /* -----------------------------------------------------------------------------
85 Generational garbage collection support
87 recordMutable(StgPtr p) Informs the garbage collector that a
88 previously immutable object has
89 become (permanently) mutable. Used
90 by thawArray and similar.
92 updateWithIndirection(p1,p2) Updates the object at p1 with an
93 indirection pointing to p2. This is
94 normally called for objects in an old
95 generation (>0) when they are updated.
97 updateWithPermIndirection(p1,p2) As above but uses a permanent indir.
99 -------------------------------------------------------------------------- */
102 recordMutable(StgMutClosure *p)
107 ASSERT(p->header.info == &WHITEHOLE_info || closure_MUTABLE(p));
109 ASSERT(closure_MUTABLE(p));
113 if (bd->gen->no > 0) {
114 p->mut_link = bd->gen->mut_list;
115 bd->gen->mut_list = p;
120 recordOldToNewPtrs(StgMutClosure *p)
125 if (bd->gen->no > 0) {
126 p->mut_link = bd->gen->mut_once_list;
127 bd->gen->mut_once_list = p;
131 #define updateWithIndirection(info, p1, p2) \
135 bd = Bdescr((P_)p1); \
136 if (bd->gen->no == 0) { \
137 ((StgInd *)p1)->indirectee = p2; \
138 SET_INFO(p1,&IND_info); \
139 TICK_UPD_NEW_IND(); \
141 ((StgIndOldGen *)p1)->indirectee = p2; \
142 if (info != &BLACKHOLE_BQ_info) { \
143 ((StgIndOldGen *)p1)->mut_link = bd->gen->mut_once_list; \
144 bd->gen->mut_once_list = (StgMutClosure *)p1; \
146 SET_INFO(p1,&IND_OLDGEN_info); \
147 TICK_UPD_OLD_IND(); \
151 #if defined(TICKY_TICKY) || defined(PROFILING)
153 updateWithPermIndirection(const StgInfoTable *info, StgClosure *p1, StgClosure *p2)
158 if (bd->gen->no == 0) {
159 ((StgInd *)p1)->indirectee = p2;
160 SET_INFO(p1,&IND_PERM_info);
161 TICK_UPD_NEW_PERM_IND(p1);
163 ((StgIndOldGen *)p1)->indirectee = p2;
164 if (info != &BLACKHOLE_BQ_info) {
165 ((StgIndOldGen *)p1)->mut_link = bd->gen->mut_once_list;
166 bd->gen->mut_once_list = (StgMutClosure *)p1;
168 SET_INFO(p1,&IND_OLDGEN_PERM_info);
169 TICK_UPD_OLD_PERM_IND();
174 /* -----------------------------------------------------------------------------
175 The CAF table - used to let us revert CAFs
177 -------------------------------------------------------------------------- */
179 #if defined(INTERPRETER)
180 typedef struct StgCAFTabEntry_ {
182 StgInfoTable* origItbl;
185 extern void addToECafTable ( StgClosure* closure, StgInfoTable* origItbl );
186 extern void clearECafTable ( void );
188 extern StgCAF* ecafList;
189 extern StgCAFTabEntry* ecafTable;
190 extern StgInt usedECafTable;
191 extern StgInt sizeECafTable;
195 void printMutOnceList(generation *gen);
196 void printMutableList(generation *gen);