GC.h 8.93 KB
Newer Older
Simon Marlow's avatar
Simon Marlow committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
/* -----------------------------------------------------------------------------
 *
 * (c) The GHC Team, 1998-2004
 *
 * External Storage Manger Interface
 *
 * ---------------------------------------------------------------------------*/

#ifndef RTS_STORAGE_GC_H
#define RTS_STORAGE_GC_H

#include <stddef.h>
#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.
 *
 * ------------------------------------------------------------------------- */

56 57 58 59 60 61 62 63
// A count of blocks needs to store anything up to the size of memory
// divided by the block size.  The safest thing is therefore to use a
// type that can store the full range of memory addresses,
// ie. StgWord.  Note that we have had some tricky int overflows in a
// couple of cases caused by using ints rather than longs (e.g. #5086)

typedef StgWord memcount;

Simon Marlow's avatar
Simon Marlow committed
64 65
typedef struct nursery_ {
    bdescr *       blocks;
66
    memcount       n_blocks;
Simon Marlow's avatar
Simon Marlow committed
67
} nursery;
Simon Marlow's avatar
Simon Marlow committed
68

Simon Marlow's avatar
Simon Marlow committed
69 70
typedef struct generation_ {
    unsigned int   no;			// generation number
Simon Marlow's avatar
Simon Marlow committed
71

Simon Marlow's avatar
Simon Marlow committed
72
    bdescr *       blocks;	        // blocks in this gen
73 74
    memcount       n_blocks;            // number of blocks
    memcount       n_words;             // number of used words
Simon Marlow's avatar
Simon Marlow committed
75

Simon Marlow's avatar
Simon Marlow committed
76
    bdescr *       large_objects;	// large objects (doubly linked)
77 78
    memcount       n_large_blocks;      // no. of blocks used by large objs
    memcount       n_new_large_words;   // words of new large objects
79
                                        // (for allocation stats)
Simon Marlow's avatar
Simon Marlow committed
80

81
    memcount       max_blocks;          // max blocks
82

Simon Marlow's avatar
Simon Marlow committed
83
    StgTSO *       threads;             // threads in this gen
Simon Marlow's avatar
Simon Marlow committed
84
                                        // linked via global_link
Simon Marlow's avatar
Simon Marlow committed
85 86 87 88 89 90
    struct generation_ *to;		// destination gen for live objects

    // stats information
    unsigned int collections;
    unsigned int par_collections;
    unsigned int failed_promotions;
Simon Marlow's avatar
Simon Marlow committed
91 92 93 94 95 96 97

    // ------------------------------------
    // Fields below are used during GC only

#if defined(THREADED_RTS)
    char pad[128];                      // make sure the following is
                                        // on a separate cache line.
Simon Marlow's avatar
Simon Marlow committed
98
    SpinLock     sync;                  // lock for large_objects
Simon Marlow's avatar
Simon Marlow committed
99 100 101 102 103 104
                                        //    and scavenged_large_objects
#endif

    int          mark;			// mark (not copy)? (old gen only)
    int          compact;		// compact (not sweep)? (old gen only)

Simon Marlow's avatar
Simon Marlow committed
105
    // During GC, if we are collecting this gen, blocks and n_blocks
106 107
    // are copied into the following two fields.  After GC, these blocks
    // are freed.
Simon Marlow's avatar
Simon Marlow committed
108
    bdescr *     old_blocks;	        // bdescr of first from-space block
109 110
    memcount     n_old_blocks;         // number of blocks in from-space
    memcount     live_estimate;         // for sweeping: estimate of live data
Simon Marlow's avatar
Simon Marlow committed
111 112
    
    bdescr *     scavenged_large_objects;  // live large objs after GC (d-link)
113
    memcount     n_scavenged_large_blocks; // size (not count) of above
Simon Marlow's avatar
Simon Marlow committed
114 115 116 117 118 119 120 121 122 123 124 125 126

    bdescr *     bitmap;  		// bitmap for compacting collection

    StgTSO *     old_threads;
} generation;

extern generation * generations;
extern generation * g0;
extern generation * oldest_gen;

/* -----------------------------------------------------------------------------
   Generic allocation

127
   StgPtr allocate(Capability *cap, nat n)
Simon Marlow's avatar
Simon Marlow committed
128 129 130 131 132
                                Allocates memory from the nursery in
				the current Capability.  This can be
				done without taking a global lock,
                                unlike allocate().

133 134
   StgPtr allocatePinned(Capability *cap, nat n) 
                                Allocates a chunk of contiguous store
Simon Marlow's avatar
Simon Marlow committed
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
   				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.

   -------------------------------------------------------------------------- */

152 153
StgPtr  allocate        ( Capability *cap, lnat n );
StgPtr  allocatePinned  ( Capability *cap, lnat n );
Simon Marlow's avatar
Simon Marlow committed
154 155 156 157 158

/* memory allocator for executable memory */
void * allocateExec(unsigned int len, void **exec_addr);
void   freeExec (void *p);

159
// Used by GC checks in external .cmm code:
160
extern nat large_alloc_lim;
161

Simon Marlow's avatar
Simon Marlow committed
162 163 164 165 166 167 168 169 170 171 172
/* -----------------------------------------------------------------------------
   Performing Garbage Collection
   -------------------------------------------------------------------------- */

void performGC(void);
void performMajorGC(void);

/* -----------------------------------------------------------------------------
   The CAF table - used to let us revert CAFs in GHCi
   -------------------------------------------------------------------------- */

173 174
void newCAF     (StgRegTable *reg, StgClosure *);
void newDynCAF  (StgRegTable *reg, StgClosure *);
Simon Marlow's avatar
Simon Marlow committed
175 176
void revertCAFs (void);

177 178 179
// Request that all CAFs are retained indefinitely.
void setKeepCAFs (void);

Simon Marlow's avatar
Simon Marlow committed
180 181 182 183
/* -----------------------------------------------------------------------------
   Stats
   -------------------------------------------------------------------------- */

184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
typedef struct _GCStats {
  StgWord64 bytes_allocated;
  StgWord64 num_gcs;
  StgWord64 num_byte_usage_samples;
  StgWord64 max_bytes_used;
  StgWord64 cumulative_bytes_used;
  StgWord64 bytes_copied;
  StgWord64 current_bytes_used;
  StgWord64 current_bytes_slop;
  StgWord64 max_bytes_slop;
  StgWord64 peak_megabytes_allocated;
  StgWord64 par_avg_bytes_copied;
  StgWord64 par_max_bytes_copied;
  StgDouble mutator_cpu_seconds;
  StgDouble mutator_wall_seconds;
  StgDouble gc_cpu_seconds;
  StgDouble gc_wall_seconds;
} GCStats;
void getGCStats (GCStats *s);

// These don't change over execution, so do them elsewhere
//  StgDouble init_cpu_seconds;
//  StgDouble init_wall_seconds;

typedef struct _ParGCStats {
  StgWord64 avg_copied;
  StgWord64 max_copied;
} ParGCStats;
void getParGCStats (ParGCStats *s);

/*
typedef struct _TaskStats {
  StgWord64 mut_time;
  StgWord64 mut_etime;
  StgWord64 gc_time;
  StgWord64 gc_etime;
} TaskStats;
// would need to allocate arbitrarily large amount of memory
// because it's a linked list of results
void getTaskStats (TaskStats **s);
// Need to stuff SparkCounters in a public header file...
void getSparkStats (SparkCounters *s);
*/

Simon Marlow's avatar
Simon Marlow committed
228 229 230
// Returns the total number of bytes allocated since the start of the program.
HsInt64 getAllocations (void);

231 232 233 234 235 236 237 238 239
/* -----------------------------------------------------------------------------
   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);

Simon Marlow's avatar
Simon Marlow committed
240 241 242 243
/* set to disable CAF garbage collection in GHCi. */
/* (needed when dynamic libraries are used). */
extern rtsBool keepCAFs;

Simon Marlow's avatar
Simon Marlow committed
244
INLINE_HEADER void initBdescr(bdescr *bd, generation *gen, generation *dest)
245
{
Simon Marlow's avatar
Simon Marlow committed
246 247 248
    bd->gen     = gen;
    bd->gen_no  = gen->no;
    bd->dest_no = dest->no;
249 250
}

Simon Marlow's avatar
Simon Marlow committed
251
#endif /* RTS_STORAGE_GC_H */