[project @ 2005-05-12 10:32:40 by simonmar]
[ghc-hetmet.git] / ghc / includes / Storage.h
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-2004
4  *
5  * External Storage Manger Interface
6  *
7  * ---------------------------------------------------------------------------*/
8
9 #ifndef STORAGE_H
10 #define STORAGE_H
11
12 #include <stddef.h>
13 #include "OSThreads.h"
14
15 /* -----------------------------------------------------------------------------
16  * Generational GC
17  *
18  * We support an arbitrary number of generations, with an arbitrary number
19  * of steps per generation.  Notes (in no particular order):
20  *
21  *       - all generations except the oldest should have two steps.  This gives
22  *         objects a decent chance to age before being promoted, and in
23  *         particular will ensure that we don't end up with too many
24  *         thunks being updated in older generations.
25  *
26  *       - the oldest generation has one step.  There's no point in aging
27  *         objects in the oldest generation.
28  *
29  *       - generation 0, step 0 (G0S0) is the allocation area.  It is given
30  *         a fixed set of blocks during initialisation, and these blocks
31  *         are never freed.
32  *
33  *       - during garbage collection, each step which is an evacuation
34  *         destination (i.e. all steps except G0S0) is allocated a to-space.
35  *         evacuated objects are allocated into the step's to-space until
36  *         GC is finished, when the original step's contents may be freed
37  *         and replaced by the to-space.
38  *
39  *       - the mutable-list is per-generation (not per-step).  G0 doesn't 
40  *         have one (since every garbage collection collects at least G0).
41  * 
42  *       - block descriptors contain pointers to both the step and the
43  *         generation that the block belongs to, for convenience.
44  *
45  *       - static objects are stored in per-generation lists.  See GC.c for
46  *         details of how we collect CAFs in the generational scheme.
47  *
48  *       - large objects are per-step, and are promoted in the same way
49  *         as small objects, except that we may allocate large objects into
50  *         generation 1 initially.
51  *
52  * ------------------------------------------------------------------------- */
53
54 typedef struct step_ {
55   unsigned int         no;              /* step number */
56   bdescr *             blocks;          /* blocks in this step */
57   unsigned int         n_blocks;        /* number of blocks */
58   struct step_ *       to;              /* destination step for live objects */
59   struct generation_ * gen;             /* generation this step belongs to */
60   unsigned int         gen_no;          /* generation number (cached) */
61   bdescr *             large_objects;   /* large objects (doubly linked) */
62   unsigned int         n_large_blocks;  /* no. of blocks used by large objs */
63   int                  is_compacted;    /* compact this step? (old gen only) */
64
65   /* temporary use during GC: */
66   StgPtr       hp;                      /* next free locn in to-space */
67   StgPtr       hpLim;                   /* end of current to-space block */
68   bdescr *     hp_bd;                   /* bdescr of current to-space block */
69   bdescr *     to_blocks;               /* bdescr of first to-space block */
70   unsigned int n_to_blocks;             /* number of blocks in to-space */
71   bdescr *     scan_bd;                 /* block currently being scanned */
72   StgPtr       scan;                    /* scan pointer in current block */
73   bdescr *     new_large_objects;       /* large objects collected so far */
74   bdescr *     scavenged_large_objects; /* live large objs after GC (d-link) */
75   unsigned int n_scavenged_large_blocks;/* size of above */
76   bdescr *     bitmap;                  /* bitmap for compacting collection */
77 } step;
78
79 typedef struct generation_ {
80   unsigned int   no;                    /* generation number */
81   step *         steps;                 /* steps */
82   unsigned int   n_steps;               /* number of steps */
83   unsigned int   max_blocks;            /* max blocks in step 0 */
84   bdescr        *mut_list;              /* mut objects in this gen (not G0)*/
85
86   /* temporary use during GC: */
87   bdescr        *saved_mut_list;
88
89   /* stats information */
90   unsigned int collections;
91   unsigned int failed_promotions;
92 } generation;
93
94 extern generation * RTS_VAR(generations);
95
96 extern generation * RTS_VAR(g0);
97 extern step * RTS_VAR(g0s0);
98 extern generation * RTS_VAR(oldest_gen);
99
100 /* -----------------------------------------------------------------------------
101    Initialisation / De-initialisation
102    -------------------------------------------------------------------------- */
103
104 extern void initStorage(void);
105 extern void exitStorage(void);
106
107 /* -----------------------------------------------------------------------------
108    Generic allocation
109
110    StgPtr allocate(nat n)       Allocates a chunk of contiguous store
111                                 n words long, returning a pointer to
112                                 the first word.  Always succeeds.
113                                 
114    StgPtr allocatePinned(nat n) Allocates a chunk of contiguous store
115                                 n words long, which is at a fixed
116                                 address (won't be moved by GC).  
117                                 Returns a pointer to the first word.
118                                 Always succeeds.
119                                 
120                                 NOTE: the GC can't in general handle
121                                 pinned objects, so allocatePinned()
122                                 can only be used for ByteArrays at the
123                                 moment.
124
125                                 Don't forget to TICK_ALLOC_XXX(...)
126                                 after calling allocate or
127                                 allocatePinned, for the
128                                 benefit of the ticky-ticky profiler.
129
130    rtsBool doYouWantToGC(void)  Returns True if the storage manager is
131                                 ready to perform a GC, False otherwise.
132
133    lnat  allocated_bytes(void)  Returns the number of bytes allocated
134                                 via allocate() since the last GC.
135                                 Used in the reporting of statistics.
136
137    SMP: allocate and doYouWantToGC can be used from STG code, they are
138    surrounded by a mutex.
139    -------------------------------------------------------------------------- */
140
141 extern StgPtr  allocate        ( nat n );
142 extern StgPtr  allocateLocal   ( StgRegTable *reg, nat n );
143 extern StgPtr  allocatePinned  ( nat n );
144 extern lnat    allocated_bytes ( void );
145
146 extern bdescr * RTS_VAR(small_alloc_list);
147 extern bdescr * RTS_VAR(large_alloc_list);
148 extern bdescr * RTS_VAR(pinned_object_block);
149
150 extern StgPtr RTS_VAR(alloc_Hp);
151 extern StgPtr RTS_VAR(alloc_HpLim);
152
153 extern nat RTS_VAR(alloc_blocks);
154 extern nat RTS_VAR(alloc_blocks_lim);
155
156 INLINE_HEADER rtsBool
157 doYouWantToGC( void )
158 {
159   return (alloc_blocks >= alloc_blocks_lim);
160 }
161
162 /* -----------------------------------------------------------------------------
163    Performing Garbage Collection
164
165    GarbageCollect(get_roots)    Performs a garbage collection.  
166                                 'get_roots' is called to find all the 
167                                 roots that the system knows about.
168
169    StgClosure                   Called by get_roots on each root.       
170    MarkRoot(StgClosure *p)      Returns the new location of the root.
171    -------------------------------------------------------------------------- */
172
173 extern void GarbageCollect(void (*get_roots)(evac_fn),rtsBool force_major_gc);
174
175 /* -----------------------------------------------------------------------------
176    Generational garbage collection support
177
178    recordMutable(StgPtr p)       Informs the garbage collector that a
179                                  previously immutable object has
180                                  become (permanently) mutable.  Used
181                                  by thawArray and similar.
182
183    updateWithIndirection(p1,p2)  Updates the object at p1 with an
184                                  indirection pointing to p2.  This is
185                                  normally called for objects in an old
186                                  generation (>0) when they are updated.
187
188    updateWithPermIndirection(p1,p2)  As above but uses a permanent indir.
189
190    -------------------------------------------------------------------------- */
191
192 /*
193  * Storage manager mutex
194  */
195 #if defined(SMP)
196 extern Mutex sm_mutex;
197 #endif
198
199 #if defined(SMP)
200 #define ACQUIRE_SM_LOCK   ACQUIRE_LOCK(&sm_mutex);
201 #define RELEASE_SM_LOCK   RELEASE_LOCK(&sm_mutex);
202 #else
203 #define ACQUIRE_SM_LOCK
204 #define RELEASE_SM_LOCK
205 #endif
206
207 INLINE_HEADER void
208 recordMutableGen(StgClosure *p, generation *gen)
209 {
210     bdescr *bd;
211
212     bd = gen->mut_list;
213     if (bd->free >= bd->start + BLOCK_SIZE_W) {
214         bdescr *new_bd;
215         new_bd = allocBlock();
216         new_bd->link = bd;
217         bd = new_bd;
218         gen->mut_list = bd;
219     }
220     *bd->free++ = (StgWord)p;
221
222 }
223
224 INLINE_HEADER void
225 recordMutableGenLock(StgClosure *p, generation *gen)
226 {
227     ACQUIRE_SM_LOCK;
228     recordMutableGen(p,gen);
229     RELEASE_SM_LOCK;
230 }
231
232 INLINE_HEADER void
233 recordMutable(StgClosure *p)
234 {
235     bdescr *bd;
236     ASSERT(closure_MUTABLE(p));
237     bd = Bdescr((P_)p);
238     if (bd->gen_no > 0) recordMutableGen(p, &RTS_DEREF(generations)[bd->gen_no]);
239 }
240
241 INLINE_HEADER void
242 recordMutableLock(StgClosure *p)
243 {
244     ACQUIRE_SM_LOCK;
245     recordMutable(p);
246     RELEASE_SM_LOCK;
247 }
248
249 /* -----------------------------------------------------------------------------
250    The CAF table - used to let us revert CAFs in GHCi
251    -------------------------------------------------------------------------- */
252
253 /* set to disable CAF garbage collection in GHCi. */
254 /* (needed when dynamic libraries are used). */
255 extern rtsBool keepCAFs;
256
257 /* -----------------------------------------------------------------------------
258    DEBUGGING predicates for pointers
259
260    LOOKS_LIKE_INFO_PTR(p)    returns False if p is definitely not an info ptr
261    LOOKS_LIKE_CLOSURE_PTR(p) returns False if p is definitely not a closure ptr
262
263    These macros are complete but not sound.  That is, they might
264    return false positives.  Do not rely on them to distinguish info
265    pointers from closure pointers, for example.
266
267    We don't use address-space predicates these days, for portability
268    reasons, and the fact that code/data can be scattered about the
269    address space in a dynamically-linked environment.  Our best option
270    is to look at the alleged info table and see whether it seems to
271    make sense...
272    -------------------------------------------------------------------------- */
273
274 #define LOOKS_LIKE_INFO_PTR(p) \
275    (p && ((StgInfoTable *)(INFO_PTR_TO_STRUCT(p)))->type != INVALID_OBJECT && \
276     ((StgInfoTable *)(INFO_PTR_TO_STRUCT(p)))->type < N_CLOSURE_TYPES)
277
278 #define LOOKS_LIKE_CLOSURE_PTR(p) \
279    (LOOKS_LIKE_INFO_PTR(((StgClosure *)(p))->header.info))
280
281 /* -----------------------------------------------------------------------------
282    Macros for calculating how big a closure will be (used during allocation)
283    -------------------------------------------------------------------------- */
284
285 INLINE_HEADER StgOffset PAP_sizeW   ( nat n_args )
286 { return sizeofW(StgPAP) + n_args; }
287
288 INLINE_HEADER StgOffset AP_sizeW   ( nat n_args )
289 { return sizeofW(StgAP) + n_args; }
290
291 INLINE_HEADER StgOffset AP_STACK_sizeW ( nat size )
292 { return sizeofW(StgAP_STACK) + size; }
293
294 INLINE_HEADER StgOffset CONSTR_sizeW( nat p, nat np )
295 { return sizeofW(StgHeader) + p + np; }
296
297 INLINE_HEADER StgOffset THUNK_SELECTOR_sizeW ( void )
298 { return stg_max(sizeofW(StgHeader)+MIN_UPD_SIZE, sizeofW(StgSelector)); }
299
300 INLINE_HEADER StgOffset BLACKHOLE_sizeW ( void )
301 { return sizeofW(StgHeader)+MIN_UPD_SIZE; }
302
303 /* --------------------------------------------------------------------------
304    Sizes of closures
305    ------------------------------------------------------------------------*/
306
307 INLINE_HEADER StgOffset sizeW_fromITBL( const StgInfoTable* itbl ) 
308 { return sizeofW(StgClosure) 
309        + sizeofW(StgPtr)  * itbl->layout.payload.ptrs 
310        + sizeofW(StgWord) * itbl->layout.payload.nptrs; }
311
312 INLINE_HEADER StgOffset thunk_sizeW_fromITBL( const StgInfoTable* itbl ) 
313 { return sizeofW(StgThunk) 
314        + sizeofW(StgPtr)  * itbl->layout.payload.ptrs 
315        + sizeofW(StgWord) * itbl->layout.payload.nptrs; }
316
317 INLINE_HEADER StgOffset ap_stack_sizeW( StgAP_STACK* x )
318 { return AP_STACK_sizeW(x->size); }
319
320 INLINE_HEADER StgOffset ap_sizeW( StgAP* x )
321 { return AP_sizeW(x->n_args); }
322
323 INLINE_HEADER StgOffset pap_sizeW( StgPAP* x )
324 { return PAP_sizeW(x->n_args); }
325
326 INLINE_HEADER StgOffset arr_words_sizeW( StgArrWords* x )
327 { return sizeofW(StgArrWords) + x->words; }
328
329 INLINE_HEADER StgOffset mut_arr_ptrs_sizeW( StgMutArrPtrs* x )
330 { return sizeofW(StgMutArrPtrs) + x->ptrs; }
331
332 INLINE_HEADER StgWord tso_sizeW ( StgTSO *tso )
333 { return TSO_STRUCT_SIZEW + tso->stack_size; }
334
335 INLINE_HEADER StgWord bco_sizeW ( StgBCO *bco )
336 { return bco->size; }
337
338 /* -----------------------------------------------------------------------------
339    Sizes of stack frames
340    -------------------------------------------------------------------------- */
341
342 INLINE_HEADER StgWord stack_frame_sizeW( StgClosure *frame )
343 {
344     StgRetInfoTable *info;
345
346     info = get_ret_itbl(frame);
347     switch (info->i.type) {
348
349     case RET_DYN:
350     {
351         StgRetDyn *dyn = (StgRetDyn *)frame;
352         return  sizeofW(StgRetDyn) + RET_DYN_BITMAP_SIZE + 
353             RET_DYN_NONPTR_REGS_SIZE +
354             RET_DYN_PTRS(dyn->liveness) + RET_DYN_NONPTRS(dyn->liveness);
355     }
356             
357     case RET_FUN:
358         return sizeofW(StgRetFun) + ((StgRetFun *)frame)->size;
359
360     case RET_BIG:
361     case RET_VEC_BIG:
362         return 1 + GET_LARGE_BITMAP(&info->i)->size;
363
364     case RET_BCO:
365         return 2 + BCO_BITMAP_SIZE((StgBCO *)((P_)frame)[1]);
366
367     default:
368         return 1 + BITMAP_SIZE(info->i.layout.bitmap);
369     }
370 }
371
372 /* -----------------------------------------------------------------------------
373    Nursery manipulation
374    -------------------------------------------------------------------------- */
375
376 extern void     allocNurseries       ( void );
377 extern void     resetNurseries       ( void );
378 extern void     resizeNurseries      ( nat blocks );
379 extern void     resizeNurseriesFixed ( nat blocks );
380 extern void     tidyAllocateLists    ( void );
381 extern lnat     countNurseryBlocks   ( void );
382
383 /* -----------------------------------------------------------------------------
384    Functions from GC.c 
385    -------------------------------------------------------------------------- */
386
387 extern void         threadPaused ( StgTSO * );
388 extern StgClosure * isAlive      ( StgClosure *p );
389 extern void         markCAFs     ( evac_fn evac );
390
391 /* -----------------------------------------------------------------------------
392    Stats 'n' DEBUG stuff
393    -------------------------------------------------------------------------- */
394
395 extern ullong RTS_VAR(total_allocated);
396
397 extern lnat calcAllocated  ( void );
398 extern lnat calcLive       ( void );
399 extern lnat calcNeeded     ( void );
400
401 #if defined(DEBUG)
402 extern void memInventory(void);
403 extern void checkSanity(void);
404 extern nat  countBlocks(bdescr *);
405 extern void checkNurserySanity( step *stp );
406 #endif
407
408 #if defined(DEBUG)
409 void printMutOnceList(generation *gen);
410 void printMutableList(generation *gen);
411 #endif
412
413 /* ----------------------------------------------------------------------------
414    Storage manager internal APIs and globals
415    ------------------------------------------------------------------------- */
416
417 #define END_OF_STATIC_LIST stgCast(StgClosure*,1)
418
419 extern void newDynCAF(StgClosure *);
420
421 extern void move_TSO(StgTSO *src, StgTSO *dest);
422 extern StgTSO *relocate_stack(StgTSO *dest, ptrdiff_t diff);
423
424 extern StgClosure * RTS_VAR(static_objects);
425 extern StgClosure * RTS_VAR(scavenged_static_objects);
426 extern StgWeak    * RTS_VAR(old_weak_ptr_list);
427 extern StgWeak    * RTS_VAR(weak_ptr_list);
428 extern StgClosure * RTS_VAR(caf_list);
429 extern StgClosure * RTS_VAR(revertible_caf_list);
430 extern StgTSO     * RTS_VAR(resurrected_threads);
431
432 #endif /* STORAGE_H */