Add code for change the cache policy for the mutator. In each round of gc, decide...
[IRC.git] / Robust / src / Runtime / bamboo / multicoregarbage.h
1 #ifndef MULTICORE_GARBAGE_H
2 #define MULTICORE_GARBAGE_H
3 #include "multicoregc.h"
4 #include "multicorehelper.h"  // for mappins between core # and block #
5 #include "structdefs.h"
6 #include "MGCHash.h"
7 #include "GCSharedHash.h"
8 #ifdef GC_CACHE_ADAPT
9 #include "multicorecache.h"
10 #endif // GC_CACHE_ADAPT
11
12 #ifndef bool
13 #define bool int
14 #endif
15
16 // data structures for GC
17 #ifdef GC_DEBUG
18 #define BAMBOO_SMEM_SIZE_L (BAMBOO_SMEM_SIZE * 2)
19 #else
20 #define BAMBOO_SMEM_SIZE_L (BAMBOO_SMEM_SIZE * 2)
21 #endif
22 #define BAMBOO_LARGE_SMEM_BOUND (BAMBOO_SMEM_SIZE_L*NUMCORES4GC)
23 // let each gc core to have one big block, this is very important
24 // for the computation of NUMBLOCKS(s, n), DO NOT change this!
25
26 #ifdef GC_FLUSH_DTLB
27 #define GC_NUM_FLUSH_DTLB 1
28 int gc_num_flush_dtlb;
29 #endif
30
31 #define NUMPTRS 100
32
33 // for GC profile
34 #ifdef GC_PROFILE
35 #define GCINFOLENGTH 100
36
37 #ifdef GC_CACHE_ADAPT
38 #define GC_PROFILE_NUM_FIELD 16
39 #else
40 #define GC_PROFILE_NUM_FIELD 15
41 #endif // GC_CACHE_ADAPT
42
43 typedef struct gc_info {
44   unsigned long long time[GC_PROFILE_NUM_FIELD];
45   int index;
46 } GCInfo;
47
48 GCInfo * gc_infoArray[GCINFOLENGTH];
49 int gc_infoIndex;
50 bool gc_infoOverflow;
51 unsigned long long gc_num_livespace;
52 unsigned long long gc_num_freespace;
53 unsigned long long gc_num_lobjspace;
54 unsigned int gc_num_lobj;
55
56 // TODO
57 /*unsigned long long flushstalltime;
58 unsigned long long flushstalltime_i;
59 int num_mapinforequest_i;*/
60 unsigned int gc_num_liveobj;
61 unsigned int gc_num_obj;
62 unsigned int gc_num_forwardobj;
63 int gc_num_profiles;
64
65 #endif // GC_PROFILE
66
67 typedef enum {
68   INIT = 0,           // 0
69   DISCOVERED = 2,     // 2
70   REMOTEM = 4,        // 4
71   MARKED = 8,         // 8
72   COMPACTED = 16,     // 16
73   FLUSHED = 32,       // 32
74   END = 33            // 33
75 } GCOBJFLAG;
76
77 typedef enum {
78   INITPHASE = 0x0,         // 0x0
79   MARKPHASE,               // 0x1
80   COMPACTPHASE,            // 0x2
81   SUBTLECOMPACTPHASE,      // 0x3
82   MAPPHASE,                // 0x4
83   FLUSHPHASE,              // 0x5
84 #ifdef GC_CACHE_ADAPT
85   PREFINISHPHASE,          // 0x6
86 #endif // GC_CACHE_ADAPT
87   FINISHPHASE              // 0x6/0x7
88 } GCPHASETYPE;
89
90 volatile bool gcflag;
91 volatile bool gcprocessing;
92 volatile GCPHASETYPE gcphase; // indicating GC phase
93
94 volatile bool gcpreinform; // counter for stopped cores
95 volatile bool gcprecheck; // indicates if there are updated pregc information
96
97 int gccurr_heaptop;
98 struct MGCHash * gcforwardobjtbl; // cache forwarded objs in mark phase
99 // for mark phase termination
100 volatile int gccorestatus[NUMCORESACTIVE]; // records status of each core
101                                            // 1: running gc
102                                            // 0: stall
103 volatile int gcnumsendobjs[2][NUMCORESACTIVE]; // the # of objects sent out
104 volatile int gcnumreceiveobjs[2][NUMCORESACTIVE]; // the # of objects received
105 volatile int gcnumsrobjs_index;  // indicates which entry to record the info 
106                                          // received before phase 1 of the mark finish 
107                                                          // checking process
108                                                                  // the info received in phase 2 must be 
109                                                                  // recorded in the other entry
110 volatile bool gcbusystatus;
111 int gcself_numsendobjs;
112 int gcself_numreceiveobjs;
113
114 // for load balancing
115 INTPTR gcheaptop;
116 int gcloads[NUMCORES4GC];
117 int gctopcore; // the core host the top of the heap
118 int gctopblock; // the number of current top block
119
120 int gcnumlobjs;
121
122 // compact instruction
123 INTPTR gcmarkedptrbound;
124 int gcblock2fill;
125 int gcstopblock[NUMCORES4GC]; // indicate when to stop compact phase
126 int gcfilledblocks[NUMCORES4GC]; //indicate how many blocks have been fulfilled
127 // move instruction;
128 INTPTR gcmovestartaddr;
129 int gcdstcore;
130 volatile bool gctomove;
131 int gcrequiredmems[NUMCORES4GC]; //record pending mem requests
132 volatile int gcmovepending;
133
134 // data structures to record remote cores that transferred the marked 
135 // objs in the mark phase
136 /*struct rcoreinfo{
137   int high;
138   int low;
139 };
140 struct RuntimeHash * gcrcoretbl;
141 #define NUM_MAPPING 40
142 void * gcmappingtbl[NUMCORESACTIVE][NUM_MAPPING];*/
143
144 // shared memory pointer for shared pointer mapping tbls
145 // In GC version, this block of memory is located at the bottom of the 
146 // shared memory, right on the top of the smem tbl.
147 // The bottom of the shared memory = sbstart tbl + smemtbl 
148 //                                  + NUMCORES4GC bamboo_rmsp
149 // These three types of table are always reside at the bottom of the shared 
150 // memory and will never be moved or garbage collected
151 #ifdef GC_SMALLPAGESIZE
152 #define BAMBOO_RMSP_SIZE (1024 * 1024)
153 #else
154 #define BAMBOO_RMSP_SIZE (BAMBOO_SMEM_SIZE) // (45 * 16 * 1024)
155 #endif
156 mspace bamboo_rmsp;
157 // shared pointer mapping tbl
158 //volatile struct GCSharedHash * gcsharedptbl;
159 mgcsharedhashtbl_t * gcsharedptbl;
160 // remote shared pointer tbls
161 //struct GCSharedHash * gcrpointertbls[NUMCORES4GC];
162 mgcsharedhashtbl_t * gcrpointertbls[NUMCORES4GC];
163
164 #ifdef LOCALHASHTBL_TEST
165 struct RuntimeHash * gcpointertbl;
166 #else
167 mgchashtable_t * gcpointertbl;
168 #endif
169 //struct MGCHash * gcpointertbl;
170 int gcobj2map;
171 int gcmappedobj;
172 volatile bool gcismapped;
173
174 // table recording the starting address of each small block
175 // (size is BAMBOO_SMEM_SIZE)
176 // Note: 1. this table always resides on the very bottom of the shared memory
177 //       2. it is not counted in the shared heap, would never be garbage 
178 //          collected
179 INTPTR * gcsbstarttbl;
180 int gcreservedsb;  // number of reserved sblock for sbstarttbl
181 int gcnumblock; // number of total blocks in the shared mem
182 int gcbaseva; // base va for shared memory without reserved sblocks
183 #ifdef GC_CACHE_ADAPT
184 int gctopva; // top va for shared memory without reserved sblocks
185 volatile bool gccachestage;
186 // table recording the sampling data collected for cache adaption 
187 int * gccachesamplingtbl;
188 int * gccachesamplingtbl_local;
189 unsigned int size_cachesamplingtbl_local;
190 int * gccachesamplingtbl_r;
191 int * gccachesamplingtbl_local_r;
192 unsigned int size_cachesamplingtbl_local_r;
193 int * gccachepolicytbl;
194 unsigned int size_cachepolicytbl;
195 #endif // GC_CACHE_ADAPT
196
197 #define ISSHAREDOBJ(p) \
198   ((((int)p)>gcbaseva)&&(((int)p)<(gcbaseva+(BAMBOO_SHARED_MEM_SIZE))))
199
200 #define ALIGNSIZE(s, as) \
201   (*((int*)as)) = (((s) & (~(BAMBOO_CACHE_LINE_MASK))) + (BAMBOO_CACHE_LINE_SIZE))
202
203 // mapping of pointer to block # (start from 0), here the block # is
204 // the global index
205 #define BLOCKINDEX(p, b) \
206   { \
207     int t = (p) - gcbaseva; \
208     if(t < (BAMBOO_LARGE_SMEM_BOUND)) { \
209       (*((int*)b)) = t / (BAMBOO_SMEM_SIZE_L); \
210     } else { \
211       (*((int*)b)) = NUMCORES4GC+((t-(BAMBOO_LARGE_SMEM_BOUND))/(BAMBOO_SMEM_SIZE)); \
212     } \
213   }
214
215 // mapping of pointer to core #
216 #define RESIDECORE(p, c) \
217   { \
218     if(1 == (NUMCORES4GC)) { \
219       (*((int*)c)) = 0; \
220     } else { \
221       int b; \
222       BLOCKINDEX((p), &b); \
223       (*((int*)c)) = gc_block2core[(b%(NUMCORES4GC*2))]; \
224     } \
225   }
226
227 // NOTE: n starts from 0
228 // mapping of heaptop (how many bytes there are in the local heap) to
229 // the number of the block
230 // the number of the block indicates that the block is the xth block on
231 // the local heap
232 #define NUMBLOCKS(s, n) \
233   if(s < (BAMBOO_SMEM_SIZE_L)) { \
234     (*((int*)(n))) = 0; \
235   } else { \
236     (*((int*)(n))) = 1 + ((s) - (BAMBOO_SMEM_SIZE_L)) / (BAMBOO_SMEM_SIZE); \
237   }
238
239 #define OFFSET(s, o) \
240   if(s < BAMBOO_SMEM_SIZE_L) { \
241     (*((int*)(o))) = (s); \
242   } else { \
243     (*((int*)(o))) = ((s) - (BAMBOO_SMEM_SIZE_L)) % (BAMBOO_SMEM_SIZE); \
244   }
245
246 // mapping of (core #, index of the block) to the global block index
247 #define BLOCKINDEX2(c, n) (gc_core2block[(2*(c))+((n)%2)]+((NUMCORES4GC*2)*((n)/2)))
248
249 // mapping of (core #, number of the block) to the base pointer of the block
250 #define BASEPTR(c, n, p) \
251   { \
252     int b = BLOCKINDEX2((c), (n)); \
253     if(b < (NUMCORES4GC)) { \
254       (*((int*)p)) = gcbaseva + b * (BAMBOO_SMEM_SIZE_L); \
255     } else { \
256       (*((int*)p)) = gcbaseva+(BAMBOO_LARGE_SMEM_BOUND)+ \
257                      (b-(NUMCORES4GC))*(BAMBOO_SMEM_SIZE); \
258     } \
259   }
260
261 // the next core in the top of the heap
262 #define NEXTTOPCORE(b) (gc_block2core[((b)+1)%(NUMCORES4GC*2)])
263
264 inline bool gc(struct garbagelist * stackptr); // core coordinator routine
265 inline void gc_collect(struct garbagelist* stackptr); //core collector routine
266 inline void gc_nocollect(struct garbagelist* stackptr); //non-gc core collector routine
267 inline void transferMarkResults_I();
268 inline void gc_enqueue_I(void *ptr);
269 inline void gc_lobjenqueue_I(void *ptr, int length, int host);
270 inline bool gcfindSpareMem_I(int * startaddr,
271                              int * tomove,
272                              int * dstcore,
273                              int requiredmem,
274                              int requiredcore);
275
276 inline void * gc_lobjdequeue4(int * length, int * host);
277 inline int gc_lobjmoreItems4();
278 inline void gc_lobjqueueinit4();
279
280 #ifdef GC_PROFILE
281 INLINE void gc_profileStart(void);
282 INLINE void gc_profileItem(void);
283 INLINE void gc_profileEnd(void);
284 void gc_outputProfileData();
285 #endif
286
287 #endif
288