1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team, 1998-2004
5 * External Storage Manger Interface
7 * ---------------------------------------------------------------------------*/
13 #include "OSThreads.h"
15 /* -----------------------------------------------------------------------------
18 * We support an arbitrary number of generations, with an arbitrary number
19 * of steps per generation. Notes (in no particular order):
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.
26 * - the oldest generation has one step. There's no point in aging
27 * objects in the oldest generation.
29 * - generation 0, step 0 (G0S0) is the allocation area. It is given
30 * a fixed set of blocks during initialisation, and these blocks
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.
39 * - the mutable-list is per-generation (not per-step). G0 doesn't
40 * have one (since every garbage collection collects at least G0).
42 * - block descriptors contain pointers to both the step and the
43 * generation that the block belongs to, for convenience.
45 * - static objects are stored in per-generation lists. See GC.c for
46 * details of how we collect CAFs in the generational scheme.
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.
52 * ------------------------------------------------------------------------- */
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) */
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 */
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)*/
86 /* temporary use during GC: */
87 bdescr *saved_mut_list;
89 /* stats information */
90 unsigned int collections;
91 unsigned int failed_promotions;
94 extern generation * RTS_VAR(generations);
96 extern generation * RTS_VAR(g0);
97 extern step * RTS_VAR(g0s0);
98 extern generation * RTS_VAR(oldest_gen);
100 /* -----------------------------------------------------------------------------
101 Initialisation / De-initialisation
102 -------------------------------------------------------------------------- */
104 extern void initStorage(void);
105 extern void exitStorage(void);
107 /* -----------------------------------------------------------------------------
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.
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.
120 NOTE: the GC can't in general handle
121 pinned objects, so allocatePinned()
122 can only be used for ByteArrays at the
125 Don't forget to TICK_ALLOC_XXX(...)
126 after calling allocate or
127 allocatePinned, for the
128 benefit of the ticky-ticky profiler.
130 rtsBool doYouWantToGC(void) Returns True if the storage manager is
131 ready to perform a GC, False otherwise.
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.
137 SMP: allocate and doYouWantToGC can be used from STG code, they are
138 surrounded by a mutex.
139 -------------------------------------------------------------------------- */
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 );
146 extern bdescr * RTS_VAR(small_alloc_list);
147 extern bdescr * RTS_VAR(large_alloc_list);
148 extern bdescr * RTS_VAR(pinned_object_block);
150 extern StgPtr RTS_VAR(alloc_Hp);
151 extern StgPtr RTS_VAR(alloc_HpLim);
153 extern nat RTS_VAR(alloc_blocks);
154 extern nat RTS_VAR(alloc_blocks_lim);
156 INLINE_HEADER rtsBool
157 doYouWantToGC( void )
159 return (alloc_blocks >= alloc_blocks_lim);
162 /* -----------------------------------------------------------------------------
163 Performing Garbage Collection
165 GarbageCollect(get_roots) Performs a garbage collection.
166 'get_roots' is called to find all the
167 roots that the system knows about.
169 StgClosure Called by get_roots on each root.
170 MarkRoot(StgClosure *p) Returns the new location of the root.
171 -------------------------------------------------------------------------- */
173 extern void GarbageCollect(void (*get_roots)(evac_fn),rtsBool force_major_gc);
175 /* -----------------------------------------------------------------------------
176 Generational garbage collection support
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.
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.
188 updateWithPermIndirection(p1,p2) As above but uses a permanent indir.
190 -------------------------------------------------------------------------- */
193 * Storage manager mutex
196 extern Mutex sm_mutex;
200 #define ACQUIRE_SM_LOCK ACQUIRE_LOCK(&sm_mutex);
201 #define RELEASE_SM_LOCK RELEASE_LOCK(&sm_mutex);
203 #define ACQUIRE_SM_LOCK
204 #define RELEASE_SM_LOCK
208 recordMutableGen(StgClosure *p, generation *gen)
213 if (bd->free >= bd->start + BLOCK_SIZE_W) {
215 new_bd = allocBlock();
220 *bd->free++ = (StgWord)p;
225 recordMutableGenLock(StgClosure *p, generation *gen)
228 recordMutableGen(p,gen);
233 recordMutable(StgClosure *p)
236 ASSERT(closure_MUTABLE(p));
238 if (bd->gen_no > 0) recordMutableGen(p, &RTS_DEREF(generations)[bd->gen_no]);
242 recordMutableLock(StgClosure *p)
249 /* -----------------------------------------------------------------------------
250 The CAF table - used to let us revert CAFs in GHCi
251 -------------------------------------------------------------------------- */
253 /* set to disable CAF garbage collection in GHCi. */
254 /* (needed when dynamic libraries are used). */
255 extern rtsBool keepCAFs;
257 /* -----------------------------------------------------------------------------
258 DEBUGGING predicates for pointers
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
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.
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
272 -------------------------------------------------------------------------- */
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)
278 #define LOOKS_LIKE_CLOSURE_PTR(p) \
279 (LOOKS_LIKE_INFO_PTR(((StgClosure *)(p))->header.info))
281 /* -----------------------------------------------------------------------------
282 Macros for calculating how big a closure will be (used during allocation)
283 -------------------------------------------------------------------------- */
285 INLINE_HEADER StgOffset PAP_sizeW ( nat n_args )
286 { return sizeofW(StgPAP) + n_args; }
288 INLINE_HEADER StgOffset AP_sizeW ( nat n_args )
289 { return sizeofW(StgAP) + n_args; }
291 INLINE_HEADER StgOffset AP_STACK_sizeW ( nat size )
292 { return sizeofW(StgAP_STACK) + size; }
294 INLINE_HEADER StgOffset CONSTR_sizeW( nat p, nat np )
295 { return sizeofW(StgHeader) + p + np; }
297 INLINE_HEADER StgOffset THUNK_SELECTOR_sizeW ( void )
298 { return stg_max(sizeofW(StgHeader)+MIN_UPD_SIZE, sizeofW(StgSelector)); }
300 INLINE_HEADER StgOffset BLACKHOLE_sizeW ( void )
301 { return sizeofW(StgHeader)+MIN_UPD_SIZE; }
303 /* --------------------------------------------------------------------------
305 ------------------------------------------------------------------------*/
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; }
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; }
317 INLINE_HEADER StgOffset ap_stack_sizeW( StgAP_STACK* x )
318 { return AP_STACK_sizeW(x->size); }
320 INLINE_HEADER StgOffset ap_sizeW( StgAP* x )
321 { return AP_sizeW(x->n_args); }
323 INLINE_HEADER StgOffset pap_sizeW( StgPAP* x )
324 { return PAP_sizeW(x->n_args); }
326 INLINE_HEADER StgOffset arr_words_sizeW( StgArrWords* x )
327 { return sizeofW(StgArrWords) + x->words; }
329 INLINE_HEADER StgOffset mut_arr_ptrs_sizeW( StgMutArrPtrs* x )
330 { return sizeofW(StgMutArrPtrs) + x->ptrs; }
332 INLINE_HEADER StgWord tso_sizeW ( StgTSO *tso )
333 { return TSO_STRUCT_SIZEW + tso->stack_size; }
335 INLINE_HEADER StgWord bco_sizeW ( StgBCO *bco )
336 { return bco->size; }
338 /* -----------------------------------------------------------------------------
339 Sizes of stack frames
340 -------------------------------------------------------------------------- */
342 INLINE_HEADER StgWord stack_frame_sizeW( StgClosure *frame )
344 StgRetInfoTable *info;
346 info = get_ret_itbl(frame);
347 switch (info->i.type) {
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);
358 return sizeofW(StgRetFun) + ((StgRetFun *)frame)->size;
362 return 1 + GET_LARGE_BITMAP(&info->i)->size;
365 return 2 + BCO_BITMAP_SIZE((StgBCO *)((P_)frame)[1]);
368 return 1 + BITMAP_SIZE(info->i.layout.bitmap);
372 /* -----------------------------------------------------------------------------
374 -------------------------------------------------------------------------- */
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 );
383 /* -----------------------------------------------------------------------------
385 -------------------------------------------------------------------------- */
387 extern void threadPaused ( StgTSO * );
388 extern StgClosure * isAlive ( StgClosure *p );
389 extern void markCAFs ( evac_fn evac );
391 /* -----------------------------------------------------------------------------
392 Stats 'n' DEBUG stuff
393 -------------------------------------------------------------------------- */
395 extern ullong RTS_VAR(total_allocated);
397 extern lnat calcAllocated ( void );
398 extern lnat calcLive ( void );
399 extern lnat calcNeeded ( void );
402 extern void memInventory(void);
403 extern void checkSanity(void);
404 extern nat countBlocks(bdescr *);
405 extern void checkNurserySanity( step *stp );
409 void printMutOnceList(generation *gen);
410 void printMutableList(generation *gen);
413 /* ----------------------------------------------------------------------------
414 Storage manager internal APIs and globals
415 ------------------------------------------------------------------------- */
417 #define END_OF_STATIC_LIST stgCast(StgClosure*,1)
419 extern void newDynCAF(StgClosure *);
421 extern void move_TSO(StgTSO *src, StgTSO *dest);
422 extern StgTSO *relocate_stack(StgTSO *dest, ptrdiff_t diff);
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);
432 #endif /* STORAGE_H */