remove debug printouts
[IRC.git] / Robust / src / Runtime / bamboo / multicoregarbage.h
1 #ifndef BAMBOO_MULTICORE_GARBAGE_H
2 #define BAMBOO_MULTICORE_GARBAGE_H
3 #ifdef MULTICORE_GC
4 #include "multicore.h"
5 #include "multicoregc.h"
6 #include "multicorehelper.h"  // for mappings between core # and block #
7 #include "structdefs.h"
8 #include "multicoregcprofile.h"
9
10 #ifdef GC_DEBUG
11 #define GC_PRINTF tprintf
12 #else
13 #define GC_PRINTF if(0) tprintf
14 #endif 
15
16 #ifdef GC_DEBUG
17 #define TR() tprintf("%u\n",__LINE__)
18 #else
19 #define TR()
20 #endif
21
22 // data structures for GC
23 #define BAMBOO_SMEM_SIZE_L (BAMBOO_SMEM_SIZE * 2)
24 #define BAMBOO_LARGE_SMEM_BOUND (BAMBOO_SMEM_SIZE_L*NUMCORES4GC)
25 // let each gc core to have one big block, this is very important
26 // for the computation of NUMBLOCKS(s, n), DO NOT change this!
27
28 typedef int block_t;
29
30 typedef enum {
31   INITPHASE = 0x0,         // 0x0
32   MARKPHASE,               // 0x1
33   COMPACTPHASE,            // 0x2
34   SUBTLECOMPACTPHASE,      // 0x3
35   MAPPHASE,                // 0x4
36   UPDATEPHASE,             // 0x5
37   CACHEPOLICYPHASE,        // 0x6
38   PREFINISHPHASE,          // 0x7
39   FINISHPHASE              // 0x8
40 } GCPHASETYPE;
41
42 typedef struct gc_status {
43   volatile bool gcprocessing;
44   volatile GCPHASETYPE gcphase; // indicating GC phase
45   volatile bool gcbusystatus;
46 } gc_status_t;
47
48 extern volatile bool gcflag;
49 extern gc_status_t gc_status_info;
50 volatile bool gcprecheck; // indicates if there are updated pregc information
51
52 unsigned INTPTR gccurr_heaptop;
53 struct MGCHash * gcforwardobjtbl; // cache forwarded objs in mark phase
54 // for mark phase termination
55 volatile unsigned int gccorestatus[NUMCORESACTIVE];//records status of each core
56                                                    // 1: running gc
57                                                    // 0: stall
58
59 volatile unsigned int returnedmem[NUMCORESACTIVE];//records status of each core
60                                                    // 1: running gc
61                                                    // 0: stall
62 volatile unsigned int gcnumsendobjs[2][NUMCORESACTIVE];//# of objects sent out
63 volatile unsigned int gcnumreceiveobjs[2][NUMCORESACTIVE];//# of objects received
64 volatile unsigned int gcnumsrobjs_index;//indicates which entry to record the  
65                  // info received before phase 1 of the mark finish 
66                  // checking process
67                  // the info received in phase 2 must be 
68                  // recorded in the other entry
69
70 unsigned int gcself_numsendobjs;
71 unsigned int gcself_numreceiveobjs;
72
73 // for load balancing
74 unsigned INTPTR gcloads[NUMCORES4GC];
75 block_t numblockspercore;
76
77 //Top of each core's heap
78 void * topptrs[NUMCORES4GC];
79
80 // compact instruction
81 //keep track of what block we can fill to
82 unsigned int gcblock2fill;
83
84 // move instruction;
85 //this points to memory handed to core from master
86 volatile unsigned int gcmovestartaddr;
87 //this flag tells core that it is okay to start compacting
88 volatile bool gctomove;
89
90 //keeps track of memory request master was not able to serve
91 volatile unsigned int maxusefulmems[NUMCORES4GC]; //record pending mem requests
92 volatile unsigned int gcrequiredmems[NUMCORES4GC]; //record pending mem requests
93 volatile unsigned int gcmovepending;
94
95 //keep track of current base block pointer for orig block
96 volatile void * update_origblockptr;
97 volatile void * origblockarray[NUMCORES4GC];
98 volatile int origarraycount;
99 volatile bool blockgranted;
100
101
102 // shared memory pointer for pointer mapping tbls
103 // In GC version, this block of memory is located at the bottom of the 
104 // shared memory, right on the top of the smem tbl.
105 // The bottom of the shared memory = sbstart tbl + smemtbl + bamboo_rmsp
106 // These three types of table are always reside at the bottom of the shared 
107 // memory and will never be moved or garbage collected
108 //gcmappingtable gives new pointer location
109 void ** gcmappingtbl;
110 //number of bytes in mapping table
111 unsigned int bamboo_rmsp_size;
112
113 //mark table....keep track of mark bits
114 volatile unsigned int * gcmarktbl;
115
116 void * gcbaseva; // base va for shared memory without reserved sblocks
117
118 static bool gc_checkCoreStatus() {
119   for(int i = 0; i < NUMCORES4GC; i++) {
120     if(gccorestatus[i]) {
121       return false;
122     }
123   }  
124   return true;
125 }
126
127 static void gc_resetCoreStatus() {
128   for(int i = 0; i < NUMCORES4GC; i++) {
129     gccorestatus[i] = 1;
130   }
131 }
132
133
134 /* Structure to keep track of free space in block */
135 enum blockstatus {
136   /* BS_USED indicates that we don't have information for this block yet */
137   BS_USED,
138   /* BS_LARGEOBJECT indicates that the beginning of this block has a large object*/
139   BS_LARGEOBJECT,
140   /* BS_FREE indicates that the block is at least partially free */
141   BS_FREE
142 };
143
144 struct blockrecord {
145   enum blockstatus status;
146   unsigned INTPTR usedspace;
147   unsigned INTPTR freespace;
148   unsigned int corenum;
149 };
150
151 #define NOFREEBLOCK 0xffffffff
152 struct allocrecord {
153   unsigned int lowestfreeblock;
154   struct blockrecord * blocktable;
155 };
156
157 struct allocrecord allocationinfo;
158
159 #ifdef GC_CACHE_ADAPT
160 void * gctopva; // top va for shared memory without reserved sblocks
161 volatile bool gccachestage;
162 // table recording the sampling data collected for cache adaption 
163 int * gccachesamplingtbl;
164 int * gccachesamplingtbl_local;
165 unsigned int size_cachesamplingtbl_local;
166 int * gccachesamplingtbl_r;
167 int * gccachesamplingtbl_local_r;
168 unsigned int size_cachesamplingtbl_local_r;
169 int * gccachepolicytbl;
170 unsigned int size_cachepolicytbl;
171 #endif
172
173 /* Total number of blocks in heap */
174
175 #define GCNUMBLOCK (NUMCORES4GC+(BAMBOO_SHARED_MEM_SIZE-BAMBOO_LARGE_SMEM_BOUND)/BAMBOO_SMEM_SIZE)
176 #define GCNUMLOCALBLOCK (GCNUMBLOCK/NUMCORES4GC)
177
178 /* This macro defines the smallest memoy chunk the master will hand out to another core during compacting */
179
180 #define MINMEMORYCHUNKSIZE 32768
181
182 /* This macro waits for the given gc phase */
183 #define WAITFORGCPHASE(phase) while(gc_status_info.gcphase != phase) ;
184
185 /* Local block number that can never be reached...*/
186 #define MAXBLOCK 0x4fffffff 
187
188 //Takes in pointer to heap object and converts to offset in alignment units
189 #define OBJMAPPINGINDEX(p) ALIGNOBJSIZE((unsigned INTPTR)(p-gcbaseva))
190
191 //Converts size of object into alignment units (need to round up)
192 #define ALIGNUNITS(s) (((s-1)>>ALIGNMENTSHIFT)+1)
193
194 //Rounds object size up to next alignment unit size
195 #define ALIGNSIZE(s) ((((unsigned int)(s-1))&~(ALIGNMENTBYTES-1))+ALIGNMENTBYTES)
196
197 #define GLOBALBLOCK2LOCAL(s) (s/NUMCORES4GC)
198
199 // mapping of pointer to block # (start from 0), here the block # is
200 // the global index
201 #define BLOCKINDEX(b, p)                        \
202   {                                                             \
203     unsigned INTPTR t = (unsigned INTPTR)(p - gcbaseva);        \
204     if(t < BAMBOO_LARGE_SMEM_BOUND) {                           \
205       b = t / BAMBOO_SMEM_SIZE_L;                               \
206     } else {                                                          \
207       b = NUMCORES4GC+((t-BAMBOO_LARGE_SMEM_BOUND)/BAMBOO_SMEM_SIZE); \
208     }                                                                 \
209   }
210
211 #define RESIDECORE(c, p) {     \
212     if(1 == (NUMCORES4GC)) { \
213       c = 0; \
214     } else { \
215       unsigned INTPTR b; \
216       BLOCKINDEX(b, p);               \
217       c = gc_block2core[(b%(NUMCORES4GC*2))]; \
218     } \
219   }
220
221 #define BLOCK2CORE(c, b) {                      \
222     if(1 == (NUMCORES4GC)) {                    \
223       c = 0;                                    \
224     } else {                                    \
225       c = gc_block2core[(b%(NUMCORES4GC*2))];   \
226     }                                           \
227   }
228
229 INLINE static unsigned int hostcore(void * ptr) {
230   // check the host core of ptr
231   unsigned int host;
232   RESIDECORE(host, ptr);
233   return host;
234 }
235
236 /*This macro takes in a number of bytes (the current offset into the
237   heap) and returns the number of local blocks needed for that many
238   bytes */
239
240 #define NUMBLOCKS(s, n) \
241   if(s < (BAMBOO_SMEM_SIZE_L)) { \
242     (n) = 0; \
243   } else { \
244     (n) = 1 + ((s) - (BAMBOO_SMEM_SIZE_L)) / (BAMBOO_SMEM_SIZE); \
245   }
246
247 //this macro takes in a global block identifier and returns the base
248 //offset into the heap
249 #define OFFSET2BASEVA(i) \
250   (((i)<NUMCORES4GC)?(BAMBOO_SMEM_SIZE_L*(i)):(BAMBOO_SMEM_SIZE*((i)-NUMCORES4GC)+BAMBOO_LARGE_SMEM_BOUND))
251
252
253 //This macro takes in a local block number and returns the size of the block
254 #define BLOCKSIZE(c) \
255   ((c)?BAMBOO_SMEM_SIZE:BAMBOO_SMEM_SIZE_L)
256
257 //This macro takes in a local block number and returns the size of the block
258 #define GLOBALBLOCKSIZE(c) \
259   ((c<NUMCORES4GC)?BAMBOO_SMEM_SIZE_L:BAMBOO_SMEM_SIZE)
260
261 //Takes as input the core number c and the local block index n and
262 //returns the global block index
263
264 #define BLOCKINDEX2(c, n) \
265   (gc_core2block[2*(c)+((n)&1)]+(NUMCORES4GC*2)*((n)>>1))
266
267 //This macro takes in a global block number and returns the base
268 //pointer of the next block
269 #define BOUNDPTR(b) \
270   (((b)<NUMCORES4GC)?(((b)+1)*BAMBOO_SMEM_SIZE_L):(BAMBOO_LARGE_SMEM_BOUND+((b)-NUMCORES4GC+1)*BAMBOO_SMEM_SIZE))
271
272 //This macro takes in the core number c and the local block number and
273 //sets p to the base pointer
274
275 #define BASEPTR(p, c, n) {                                 \
276     unsigned int b = BLOCKINDEX2((c), (n));                \
277     if(b < (NUMCORES4GC)) {                                \
278       p = gcbaseva + b * (BAMBOO_SMEM_SIZE_L);             \
279     } else {                                               \
280       p = gcbaseva+(BAMBOO_LARGE_SMEM_BOUND)+              \
281         (b-(NUMCORES4GC))*(BAMBOO_SMEM_SIZE);              \
282     }                                                      \
283   }
284
285 // the next core in the top of the heap
286 #define NEXTTOPCORE(b) (gc_block2core[((b)+1)%(NUMCORES4GC*2)])
287
288 // check if all cores are stall now
289 #define GC_CHECK_ALL_CORE_STATUS() gccorestatus[BAMBOO_NUM_OF_CORE] = 0; \
290   while(!gc_checkCoreStatus()) ;
291
292 // send a 1-word msg to all clients
293 #define GC_SEND_MSG_1_TO_CLIENT(m) \
294   { \
295     for(int i = 0; i < NUMCORESACTIVE; ++i) { \
296       gccorestatus[i] = 1; \
297       if(BAMBOO_NUM_OF_CORE != i) { \
298         send_msg_1(i, (m)); \
299       } \
300     } \
301   }
302
303 #define ISLOCAL(p) (hostcore(p)==BAMBOO_NUM_OF_CORE)
304
305 void initmulticoregcdata();
306 void dismulticoregcdata();
307 bool gc(struct garbagelist * stackptr); // core coordinator routine
308 void gc_collect(struct garbagelist* stackptr); //core collector routine
309 void gc_nocollect(struct garbagelist* stackptr); //non-gc core collector routine
310 void master_mark(struct garbagelist *stackptr);
311 void master_getlargeobjs();
312 void master_compact();
313 void master_updaterefs();
314 void master_finish();
315 void gc_master(struct garbagelist * stackptr);
316
317
318 void transferMarkResults_I();
319 void * gcfindSpareMem_I(unsigned INTPTR requiredmem, unsigned INTPTR maxbytesneeded, unsigned int requiredcore);
320
321 #define INITMULTICOREGCDATA() initmulticoregcdata()
322 #define DISMULTICOREGCDATA() dismulticoregcdata()
323 #else // MULTICORE_GC
324 #define INITMULTICOREGCDATA()
325 #define DISMULTICOREGCDATA()
326 #endif // MULTICORE_GC
327 #endif // BAMBOO_MULTICORE_GARBAGE_H