summaryrefslogtreecommitdiff
path: root/includes/rts/storage/GC.h
blob: df4ba9d15334b2402fa9b33f62b90087cd6ced36 (plain)
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/* -----------------------------------------------------------------------------
 *
 * (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.
 *
 * ------------------------------------------------------------------------- */

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);

/* -----------------------------------------------------------------------------
   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);

/* set to disable CAF garbage collection in GHCi. */
/* (needed when dynamic libraries are used). */
extern rtsBool keepCAFs;

#endif /* RTS_STORAGE_GC_H */