/* ----------------------------------------------------------------------------- * * (c) The GHC Team, 1998-2004 * * External Storage Manger Interface * * ---------------------------------------------------------------------------*/ #ifndef RTS_STORAGE_GC_H #define RTS_STORAGE_GC_H #include #include "rts/OSThreads.h" /* ----------------------------------------------------------------------------- * Generational GC * * We support an arbitrary number of generations, with an arbitrary number * of steps per generation. Notes (in no particular order): * * - all generations except the oldest should have the same * number of steps. Multiple steps gives objects a decent * chance to age before being promoted, and helps ensure that * we don't end up with too many thunks being updated in older * generations. * * - the oldest generation has one step. There's no point in aging * objects in the oldest generation. * * - generation 0, step 0 (G0S0) is the allocation area. It is given * a fixed set of blocks during initialisation, and these blocks * normally stay in G0S0. In parallel execution, each * Capability has its own nursery. * * - during garbage collection, each step which is an evacuation * destination (i.e. all steps except G0S0) is allocated a to-space. * evacuated objects are allocated into the step's to-space until * GC is finished, when the original step's contents may be freed * and replaced by the to-space. * * - the mutable-list is per-generation (not per-step). G0 doesn't * have one (since every garbage collection collects at least G0). * * - block descriptors contain pointers to both the step and the * generation that the block belongs to, for convenience. * * - static objects are stored in per-generation lists. See GC.c for * details of how we collect CAFs in the generational scheme. * * - large objects are per-step, and are promoted in the same way * as small objects, except that we may allocate large objects into * generation 1 initially. * * ------------------------------------------------------------------------- */ typedef struct step_ { unsigned int no; // step number in this generation unsigned int abs_no; // absolute step number struct generation_ * gen; // generation this step belongs to unsigned int gen_no; // generation number (cached) bdescr * blocks; // blocks in this step unsigned int n_blocks; // number of blocks unsigned int n_words; // number of words struct step_ * to; // destination step for live objects bdescr * large_objects; // large objects (doubly linked) unsigned int n_large_blocks; // no. of blocks used by large objs StgTSO * threads; // threads in this step // linked via global_link // ------------------------------------ // Fields below are used during GC only // During GC, if we are collecting this step, blocks and n_blocks // are copied into the following two fields. After GC, these blocks // are freed. #if defined(THREADED_RTS) char pad[128]; // make sure the following is // on a separate cache line. SpinLock sync_large_objects; // lock for large_objects // and scavenged_large_objects #endif int mark; // mark (not copy)? (old gen only) int compact; // compact (not sweep)? (old gen only) bdescr * old_blocks; // bdescr of first from-space block unsigned int n_old_blocks; // number of blocks in from-space unsigned int live_estimate; // for sweeping: estimate of live data bdescr * part_blocks; // partially-full scanned blocks unsigned int n_part_blocks; // count of above bdescr * scavenged_large_objects; // live large objs after GC (d-link) unsigned int n_scavenged_large_blocks; // size (not count) of above bdescr * bitmap; // bitmap for compacting collection StgTSO * old_threads; } step; typedef struct generation_ { unsigned int no; // generation number step * steps; // steps unsigned int n_steps; // number of steps unsigned int max_blocks; // max blocks in step 0 bdescr *mut_list; // mut objects in this gen (not G0) // stats information unsigned int collections; unsigned int par_collections; unsigned int failed_promotions; // temporary use during GC: bdescr *saved_mut_list; } generation; extern generation * generations; extern generation * g0; extern step * g0s0; extern generation * oldest_gen; extern step * all_steps; extern nat total_steps; /* ----------------------------------------------------------------------------- Generic allocation StgPtr allocateInGen(generation *g, nat n) Allocates a chunk of contiguous store n words long in generation g, returning a pointer to the first word. Always succeeds. StgPtr allocate(nat n) Equaivalent to allocateInGen(g0) StgPtr allocateLocal(Capability *cap, nat n) Allocates memory from the nursery in the current Capability. This can be done without taking a global lock, unlike allocate(). StgPtr allocatePinned(nat n) Allocates a chunk of contiguous store n words long, which is at a fixed address (won't be moved by GC). Returns a pointer to the first word. Always succeeds. NOTE: the GC can't in general handle pinned objects, so allocatePinned() can only be used for ByteArrays at the moment. Don't forget to TICK_ALLOC_XXX(...) after calling allocate or allocatePinned, for the benefit of the ticky-ticky profiler. rtsBool doYouWantToGC(void) Returns True if the storage manager is ready to perform a GC, False otherwise. lnat allocatedBytes(void) Returns the number of bytes allocated via allocate() since the last GC. Used in the reporting of statistics. -------------------------------------------------------------------------- */ StgPtr allocate ( lnat n ); StgPtr allocateInGen ( generation *g, lnat n ); StgPtr allocateLocal ( Capability *cap, lnat n ); StgPtr allocatePinned ( lnat n ); lnat allocatedBytes ( void ); /* memory allocator for executable memory */ void * allocateExec(unsigned int len, void **exec_addr); void freeExec (void *p); // Used by GC checks in external .cmm code: extern nat alloc_blocks; extern nat alloc_blocks_lim; /* ----------------------------------------------------------------------------- Performing Garbage Collection -------------------------------------------------------------------------- */ void performGC(void); void performMajorGC(void); /* ----------------------------------------------------------------------------- The CAF table - used to let us revert CAFs in GHCi -------------------------------------------------------------------------- */ void newCAF (StgClosure*); void newDynCAF (StgClosure *); void revertCAFs (void); // Request that all CAFs are retained indefinitely. void setKeepCAFs (void); /* ----------------------------------------------------------------------------- This is the write barrier for MUT_VARs, a.k.a. IORefs. A MUT_VAR_CLEAN object is not on the mutable list; a MUT_VAR_DIRTY is. When written to, a MUT_VAR_CLEAN turns into a MUT_VAR_DIRTY and is put on the mutable list. -------------------------------------------------------------------------- */ void dirty_MUT_VAR(StgRegTable *reg, StgClosure *p); /* set to disable CAF garbage collection in GHCi. */ /* (needed when dynamic libraries are used). */ extern rtsBool keepCAFs; #endif /* RTS_STORAGE_GC_H */