GC.h 9.01 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
typedef struct generation_ {
Gabor Greif's avatar
Gabor Greif committed
70
    nat            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
    struct generation_ *to;		// destination gen for live objects

    // stats information
Gabor Greif's avatar
Gabor Greif committed
88 89 90
    nat collections;
    nat par_collections;
    nat 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

Simon Marlow's avatar
Simon Marlow committed
127
   StgPtr allocate(Capability *cap, W_ 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().

Simon Marlow's avatar
Simon Marlow committed
133
   StgPtr allocatePinned(Capability *cap, W_ n)
134
                                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, W_ n );
StgPtr  allocatePinned  ( Capability *cap, W_ n );
Simon Marlow's avatar
Simon Marlow committed
154 155

/* memory allocator for executable memory */
Simon Marlow's avatar
Simon Marlow committed
156
void * allocateExec(W_ len, void **exec_addr);
Simon Marlow's avatar
Simon Marlow committed
157 158
void   freeExec (void *p);

159
// Used by GC checks in external .cmm code:
Simon Marlow's avatar
Simon Marlow committed
160
extern W_ 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
   -------------------------------------------------------------------------- */

Simon Marlow's avatar
Simon Marlow committed
173 174
StgWord newCAF    (StgRegTable *reg, StgClosure *caf, StgClosure *bh);
StgWord newDynCAF (StgRegTable *reg, StgClosure *caf, StgClosure *bh);
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
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;
195
  StgWord64 par_tot_bytes_copied;
196 197 198 199 200
  StgWord64 par_max_bytes_copied;
  StgDouble mutator_cpu_seconds;
  StgDouble mutator_wall_seconds;
  StgDouble gc_cpu_seconds;
  StgDouble gc_wall_seconds;
201 202
  StgDouble cpu_seconds;
  StgDouble wall_seconds;
203 204
} GCStats;
void getGCStats (GCStats *s);
pcapriotti's avatar
pcapriotti committed
205
rtsBool getGCStatsEnabled (void);
206 207 208 209 210 211

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

typedef struct _ParGCStats {
212
  StgWord64 tot_copied;
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
  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
231 232 233
// Returns the total number of bytes allocated since the start of the program.
HsInt64 getAllocations (void);

234 235 236 237 238 239 240 241 242
/* -----------------------------------------------------------------------------
   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
243 244 245 246
/* set to disable CAF garbage collection in GHCi. */
/* (needed when dynamic libraries are used). */
extern rtsBool keepCAFs;

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

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