Add gcprofile to PMC garbage collector and compute the size of allocated obj instead...
[IRC.git] / Robust / src / Runtime / bamboo / multicoregarbage.c
1 #ifdef MULTICORE_GC
2 #include "runtime.h"
3 #include "multicoreruntime.h"
4 #include "multicoregarbage.h"
5 #include "multicoregcmark.h"
6 #include "multicoregccompact.h"
7 #include "multicoregcflush.h"
8 #include "multicoregcprofile.h"
9 #include "gcqueue.h"
10 #include "multicoremem_helper.h"
11 #include "bambooalign.h"
12 #ifdef PERFCOUNT
13 #include "bme_perf_counter.h"
14 #endif
15
16 volatile bool gcflag;
17 gc_status_t gc_status_info;
18
19 unsigned long long gc_output_cache_policy_time=0;
20
21 #ifdef GC_DEBUG
22 // dump whole mem in blocks
23 void dumpSMem() {
24   int block = 0;
25   int sblock = 0;
26   unsigned int j = 0;
27   unsigned int i = 0;
28   int coren = 0;
29   int x = 0;
30   int y = 0;
31   printf("(%x,%x) Dump shared mem: \n",udn_tile_coord_x(),udn_tile_coord_y());
32   // reserved blocks for sblocktbl
33   printf("(%x,%x) ++++ reserved sblocks ++++ \n", udn_tile_coord_x(),
34          udn_tile_coord_y());
35   for(i=BAMBOO_BASE_VA; i<gcbaseva; i+= 4*16) {
36     printf("(%x,%x) 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \n",
37         udn_tile_coord_x(), udn_tile_coord_y(),
38         *((int *)(i)), *((int *)(i + 4)),
39         *((int *)(i + 4*2)), *((int *)(i + 4*3)),
40         *((int *)(i + 4*4)), *((int *)(i + 4*5)),
41         *((int *)(i + 4*6)), *((int *)(i + 4*7)),
42         *((int *)(i + 4*8)), *((int *)(i + 4*9)),
43         *((int *)(i + 4*10)), *((int *)(i + 4*11)),
44         *((int *)(i + 4*12)), *((int *)(i + 4*13)),
45         *((int *)(i + 4*14)), *((int *)(i + 4*15)));
46   }
47   sblock = 0;
48   bool advanceblock = false;
49   // remaining memory
50   for(i=gcbaseva; (unsigned int)i<(unsigned int)(gcbaseva+BAMBOO_SHARED_MEM_SIZE); i+=4*16) {
51     advanceblock = false;
52     // computing sblock # and block #, core coordinate (x,y) also
53     if(j%((BAMBOO_SMEM_SIZE)/(4*16)) == 0) {
54       // finished a sblock
55       if(j < ((BAMBOO_LARGE_SMEM_BOUND)/(4*16))) {
56         if((j > 0) && (j%((BAMBOO_SMEM_SIZE_L)/(4*16)) == 0)) {
57           // finished a block
58           block++;
59           advanceblock = true;  
60         }
61       } else {
62         // finished a block
63         block++;
64         advanceblock = true;
65       }
66       // compute core #
67       if(advanceblock) {
68         coren = gc_block2core[block%(NUMCORES4GC*2)];
69       }
70       // compute core coordinate
71       x = BAMBOO_COORDS_X(coren);
72       y = BAMBOO_COORDS_Y(coren);
73       printf("(%x,%x) ==== %d, %d : core (%d,%d), saddr %x====\n",
74           udn_tile_coord_x(), udn_tile_coord_y(),block, sblock++, x, y,
75           (sblock-1)*(BAMBOO_SMEM_SIZE)+gcbaseva);
76     }
77     j++;
78     printf("(%x,%x) 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \n",
79         udn_tile_coord_x(), udn_tile_coord_y(),
80         *((int *)(i)), *((int *)(i + 4)),
81         *((int *)(i + 4*2)), *((int *)(i + 4*3)),
82         *((int *)(i + 4*4)), *((int *)(i + 4*5)),
83         *((int *)(i + 4*6)), *((int *)(i + 4*7)),
84         *((int *)(i + 4*8)), *((int *)(i + 4*9)),
85         *((int *)(i + 4*10)), *((int *)(i + 4*11)),
86         *((int *)(i + 4*12)), *((int *)(i + 4*13)),
87         *((int *)(i + 4*14)), *((int *)(i + 4*15)));
88   }
89   printf("(%x,%x) \n", udn_tile_coord_x(), udn_tile_coord_y());
90 }
91 #endif
92
93 bool gc_checkCoreStatus() {
94   for(int i = 0; i < NUMCORES4GC; i++) {
95     if(gccorestatus[i]) {
96       return false;
97     }
98   }
99   return true;
100 }
101
102 void gc_resetCoreStatus() {
103   for(int i = 0; i < NUMCORES4GC; i++) {
104     gccorestatus[i] = 1;
105   }
106 }
107
108
109 void initmulticoregcdata() {
110   bamboo_smem_zero_top = NULL;
111   gcflag = false;
112   gc_status_info.gcprocessing = false;
113   gc_status_info.gcphase = FINISHPHASE;
114
115   gcprecheck = true;
116   gcforwardobjtbl = allocateMGCHash_I(128);
117 #ifdef MGC_SPEC
118   gc_profile_flag = false;
119 #endif
120
121   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
122     allocationinfo.blocktable=RUNMALLOC(sizeof(struct blockrecord)*GCNUMBLOCK);
123     for(int i=0; i<GCNUMBLOCK;i++) {
124       if (1==NUMCORES4GC)
125         allocationinfo.blocktable[i].corenum=0;
126       else
127         allocationinfo.blocktable[i].corenum=gc_block2core[(i%(NUMCORES4GC*2))];
128       allocationinfo.blocktable[i].status=BS_FREE;
129       allocationinfo.blocktable[i].usedspace=0;
130       allocationinfo.blocktable[i].freespace=GLOBALBLOCKSIZE(i);
131     }
132     buildCore2Test();
133   }
134
135   //initialize update structures
136   origarraycount=0;
137   for(int i=0;i<NUMCORES4GC;i++) {
138     origblockarray[i]=NULL;
139   }
140
141   INIT_MULTICORE_GCPROFILE_DATA();
142 }
143
144 void dismulticoregcdata() {
145   freeMGCHash(gcforwardobjtbl);
146 }
147
148 void initGC() {
149   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
150     for(int i = 0; i < NUMCORES4GC; i++) {
151       gccorestatus[i] = 1;
152       gcnumsendobjs[0][i] = gcnumsendobjs[1][i] = 0;
153       gcnumreceiveobjs[0][i] = gcnumreceiveobjs[1][i] = 0;
154       gcloads[i] = 0;
155       gcrequiredmems[i] = 0;
156     } 
157     for(int i = NUMCORES4GC; i < NUMCORESACTIVE; i++) {
158       gccorestatus[i] = 1;
159       gcnumsendobjs[0][i] = gcnumsendobjs[1][i] = 0;
160       gcnumreceiveobjs[0][i] = gcnumreceiveobjs[1][i] = 0;
161     }
162     gcnumsrobjs_index = 0;
163   } 
164   gcself_numsendobjs = 0;
165   gcself_numreceiveobjs = 0;
166   gcmovestartaddr = 0;
167   gctomove = false;
168   gcblock2fill = 0;
169   gcmovepending = 0;
170   gccurr_heaptop = 0;
171   update_origblockptr=NULL;
172   gc_queueinit();
173
174   MGCHashreset(gcforwardobjtbl);
175
176   GCPROFILE_INIT();
177   gc_output_cache_policy_time=0;
178
179
180 void checkMarkStatus_p2() {
181   //  tprintf("Check mark status 2\n");
182   // check if the sum of send objs and receive obj are the same
183   // yes->check if the info is the latest; no->go on executing
184   unsigned int sumsendobj = 0;
185   for(int i = 0; i < NUMCORESACTIVE; i++) {
186     sumsendobj += gcnumsendobjs[gcnumsrobjs_index][i];
187   } 
188   for(int i = 0; i < NUMCORESACTIVE; i++) {
189     sumsendobj -= gcnumreceiveobjs[gcnumsrobjs_index][i];
190   } 
191   if(0 == sumsendobj) {
192     // Check if there are changes of the numsendobjs or numreceiveobjs 
193     // on each core
194     int i = 0;
195     for(i = 0; i < NUMCORESACTIVE; i++) {
196       if((gcnumsendobjs[0][i]!=gcnumsendobjs[1][i])||(gcnumreceiveobjs[0][i]!=gcnumreceiveobjs[1][i]) ) {
197         break;
198       }
199     }  
200     if(i == NUMCORESACTIVE) {    
201       //tprintf("Mark terminated\n");
202       // all the core status info are the latest,stop mark phase
203       gc_status_info.gcphase = COMPACTPHASE;
204       // restore the gcstatus for all cores
205       for(int i = 0; i < NUMCORESACTIVE; i++) {
206         gccorestatus[i] = 1;
207       }  
208     } else {
209       // There were changes between phase 1 and phase 2, can not decide 
210       // whether the mark phase has been finished
211       waitconfirm = false;
212       // As it fails in phase 2, flip the entries
213       gcnumsrobjs_index = (gcnumsrobjs_index == 0) ? 1 : 0;
214     } 
215   } else {
216     // There were changes between phase 1 and phase 2, can not decide 
217     // whether the mark phase has been finished
218     waitconfirm = false;
219     // As it fails in phase 2, flip the entries
220     gcnumsrobjs_index = (gcnumsrobjs_index == 0) ? 1 : 0;
221   }
222 }
223
224 void checkMarkStatus() {
225   //  tprintf("Check mark status\n");
226   if((!waitconfirm)||(waitconfirm && (numconfirm == 0))) {
227     unsigned int entry_index = 0;
228     if(waitconfirm) {
229       // phase 2
230       entry_index = (gcnumsrobjs_index == 0) ? 1 : 0;
231     } else {
232       // phase 1
233       entry_index = gcnumsrobjs_index;
234     }
235     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
236     // check the status of all cores
237     if (gc_checkCoreStatus()) {
238       // ask for confirm
239       if(!waitconfirm) {
240         // the first time found all cores stall
241         // send out status confirm msg to all other cores
242         // reset the corestatus array too    
243         waitconfirm = true;
244         numconfirm = NUMCORESACTIVE - 1;
245         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
246         GC_SEND_MSG_1_TO_CLIENT(GCMARKCONFIRM);
247       } else {
248         // Phase 2
249         checkMarkStatus_p2(); 
250         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
251       }
252     } else {
253       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
254     } 
255   } 
256
257
258 // compute load balance for all cores
259 int loadbalance() {
260   // compute load balance
261   // get the total loads
262   void * heaptop;
263   unsigned int tloads = 0;
264   for(int i = 0; i < NUMCORES4GC; i++) {
265     tloads += gcloads[i];
266     //tprintf("load: %d %d \n", gcloads[i], i);
267   }
268   heaptop = gcbaseva + tloads;
269
270   unsigned int topblockindex;
271   
272   BLOCKINDEX(topblockindex, heaptop);
273   // num of blocks per core
274   unsigned int numbpc = (topblockindex+NUMCORES4GC-1)/NUMCORES4GC;
275   
276   return numbpc;
277 }
278
279 void gc_collect(struct garbagelist * stackptr) {
280   gc_status_info.gcprocessing = true;
281   // inform the master that this core is at a gc safe point and is ready to 
282   // do gc
283   send_msg_4(STARTUPCORE,GCFINISHPRE,BAMBOO_NUM_OF_CORE,self_numsendobjs,self_numreceiveobjs);
284
285   // core collector routine
286   //wait for init phase
287   WAITFORGCPHASE(INITPHASE);
288
289   GC_PRINTF("Do initGC\n");
290   initGC();
291   CACHEADAPT_GC(true);
292   //send init finish msg to core coordinator
293   send_msg_2(STARTUPCORE,GCFINISHINIT,BAMBOO_NUM_OF_CORE);
294
295   //wait for mark phase
296   WAITFORGCPHASE(MARKPHASE);
297
298   GC_PRINTF("Start mark phase\n");
299   mark(stackptr);
300   GC_PRINTF("Finish mark phase, start compact phase\n");
301   compact();
302   GC_PRINTF("Finish compact phase\n");
303
304   WAITFORGCPHASE(UPDATEPHASE);
305
306   GC_PRINTF("Start update phase\n");
307   GCPROFILE_INFO_2_MASTER();
308   update(stackptr);
309   GC_PRINTF("Finish update phase\n");
310
311   CACHEADAPT_PHASE_CLIENT();
312
313   // invalidate all shared mem pointers
314   bamboo_cur_msp = NULL;
315   bamboo_smem_size = 0;
316   bamboo_smem_zero_top = NULL;
317   gcflag = false;
318
319   WAITFORGCPHASE(FINISHPHASE);
320
321   GC_PRINTF("Finish gc! \n");
322
323
324 void gc_nocollect(struct garbagelist * stackptr) {
325   gc_status_info.gcprocessing = true;
326   // inform the master that this core is at a gc safe point and is ready to 
327   // do gc
328   send_msg_4(STARTUPCORE,GCFINISHPRE,BAMBOO_NUM_OF_CORE,self_numsendobjs,self_numreceiveobjs);
329   
330   WAITFORGCPHASE(INITPHASE);
331
332   GC_PRINTF("Do initGC\n");
333   initGC();
334   CACHEADAPT_GC(true);
335
336   //send init finish msg to core coordinator
337   send_msg_2(STARTUPCORE,GCFINISHINIT,BAMBOO_NUM_OF_CORE);
338
339
340   WAITFORGCPHASE(MARKPHASE);
341
342   GC_PRINTF("Start mark phase\n"); 
343   mark(stackptr);
344   GC_PRINTF("Finish mark phase, wait for update\n");
345
346   // non-gc core collector routine
347   WAITFORGCPHASE(UPDATEPHASE);
348
349   GC_PRINTF("Start update phase\n");
350   GCPROFILE_INFO_2_MASTER();
351   update(stackptr);
352   GC_PRINTF("Finish update phase\n"); 
353
354   CACHEADAPT_PHASE_CLIENT();
355
356   // invalidate all shared mem pointers
357   bamboo_cur_msp = NULL;
358   bamboo_smem_size = 0;
359   bamboo_smem_zero_top = NULL;
360
361   gcflag = false;
362   WAITFORGCPHASE(FINISHPHASE);
363
364   GC_PRINTF("Finish gc! \n");
365 }
366
367 void master_mark(struct garbagelist *stackptr) {
368
369   GC_PRINTF("Start mark phase \n");
370   gc_status_info.gcphase = MARKPHASE;
371   GC_SEND_MSG_1_TO_CLIENT(GCSTART);
372   // mark phase
373
374   mark(stackptr);
375 }
376
377 void master_getlargeobjs() {
378   // send msgs to all cores requiring large objs info
379   // Note: only need to ask gc cores, non-gc cores do not host any objs
380   numconfirm = NUMCORES4GC - 1;
381   for(int i = 1; i < NUMCORES4GC; i++) {
382     send_msg_1(i,GCLOBJREQUEST);
383   }
384   gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
385   //spin until we have all responses
386   while(numconfirm!=0) ;
387
388   GCPROFILE_ITEM_MASTER();
389   GC_PRINTF("prepare to cache large objs \n");
390
391 }
392
393
394 void master_updaterefs(struct garbagelist * stackptr) {
395   gc_status_info.gcphase = UPDATEPHASE;
396   GC_SEND_MSG_1_TO_CLIENT(GCSTARTUPDATE);
397   GC_PRINTF("Start update phase \n");
398   // update phase
399   update(stackptr);
400   GC_CHECK_ALL_CORE_STATUS();
401   GC_PRINTF("Finish update phase \n");
402 }
403
404 void master_finish() {
405   gc_status_info.gcphase = FINISHPHASE;
406   
407   // invalidate all shared mem pointers
408   // put it here as it takes time to inform all the other cores to
409   // finish gc and it might cause problem when some core resumes
410   // mutator earlier than the other cores
411   bamboo_cur_msp = NULL;
412   bamboo_smem_size = 0;
413   bamboo_smem_zero_top = NULL;
414   
415   GCPROFILE_END_MASTER();
416   unsigned long long tmpt = BAMBOO_GET_EXE_TIME();
417   CACHEADAPT_OUTPUT_CACHE_POLICY();
418   gc_output_cache_policy_time += (BAMBOO_GET_EXE_TIME()-tmpt);
419   gcflag = false;
420
421   GC_SEND_MSG_1_TO_CLIENT(GCFINISH);
422   gc_status_info.gcprocessing = false;  
423
424   if(gcflag) {
425     // inform other cores to stop and wait for gc
426     GC_PRINTF("Back to Back gc case\n");
427     gcprecheck = true;
428     for(int i = 0; i < NUMCORESACTIVE; i++) {
429       // reuse the gcnumsendobjs & gcnumreceiveobjs
430       gcnumsendobjs[0][i] = 0;
431       gcnumreceiveobjs[0][i] = 0;
432     }
433     GC_SEND_MSG_1_TO_CLIENT(GCSTARTPRE);
434   }
435 }
436
437 void gc_master(struct garbagelist * stackptr) {
438   tprintf("start GC!\n");
439   gc_status_info.gcprocessing = true;
440   gc_status_info.gcphase = INITPHASE;
441
442   waitconfirm = false;
443   numconfirm = 0;
444   initGC();
445   GC_SEND_MSG_1_TO_CLIENT(GCSTARTINIT);
446   CACHEADAPT_GC(true);
447   //tprintf("Check core status \n");
448   GC_CHECK_ALL_CORE_STATUS();
449   GCPROFILE_ITEM_MASTER();
450   unsigned long long tmpt = BAMBOO_GET_EXE_TIME();
451   CACHEADAPT_OUTPUT_CACHE_SAMPLING();
452   gc_output_cache_policy_time += (BAMBOO_GET_EXE_TIME()-tmpt);
453   //tprintf("start mark phase\n");
454   // do mark phase
455   master_mark(stackptr);
456   GCPROFILE_ITEM_MASTER();
457   //tprintf("finish mark phase\n");
458   // get large objects from all cores
459   master_getlargeobjs();
460   //tprintf("start compact phase\n");
461   // compact the heap
462   master_compact();
463   //tprintf("start update phase\n");
464   // update the references
465   master_updaterefs(stackptr);
466   //tprintf("gc master finished update   \n");
467   // do cache adaptation
468   CACHEADAPT_PHASE_MASTER();
469   //tprintf("finish cachdapt phase\n");
470   // do finish up stuff
471 #ifdef GC_DEBUG
472   for(int i=0;i<GCNUMBLOCK;i++) {
473     struct blockrecord *record=&allocationinfo.blocktable[i];
474     tprintf("%u. used=%u free=%u corenum=%u status=%u, base=%x, ptr=%x\n", i, record->usedspace, record->freespace, record->corenum, record->status, gcbaseva+OFFSET2BASEVA(i), (gcbaseva+OFFSET2BASEVA(i)+record->usedspace));
475   }
476 #endif
477
478   master_finish();
479
480   //tprintf("finish GC ! %d \n",gcflag);
481
482
483 void pregccheck() {
484   while(true) {
485     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
486     gcnumsendobjs[0][BAMBOO_NUM_OF_CORE] = self_numsendobjs;
487     gcnumreceiveobjs[0][BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
488     int sumsendobj = 0;
489     for(int i = 0; i < NUMCORESACTIVE; i++) {
490       sumsendobj += gcnumsendobjs[0][i];
491     }  
492     for(int i = 0; i < NUMCORESACTIVE; i++) {
493       sumsendobj -= gcnumreceiveobjs[0][i];
494     } 
495     if(0 != sumsendobj) {
496       // there were still some msgs on the fly, wait until there 
497       // are some update pregc information coming and check it again
498       gcprecheck = false;
499       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
500
501       while(!gcprecheck) ;
502     } else {
503       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
504       return;
505     }
506   }
507 }
508
509 void pregcprocessing() {
510 #if defined(GC_CACHE_ADAPT)&&defined(GC_CACHE_SAMPLING)
511   // disable the timer interrupt
512   bamboo_mask_timer_intr();
513   // get the sampling data 
514   bamboo_output_dtlb_sampling();
515 #endif
516 }
517
518 void postgcprocessing() {
519 #if defined(GC_CACHE_ADAPT)&&defined(GC_CACHE_SAMPLING)
520   // enable the timer interrupt
521   bamboo_tile_timer_set_next_event(GC_TILE_TIMER_EVENT_SETTING); 
522   bamboo_unmask_timer_intr();
523   //turn on sampling again
524   bamboo_dtlb_sampling_init();
525 #endif
526 }
527
528 bool gc(struct garbagelist * stackptr) {
529   // check if do gc
530   if(!gcflag) {
531     gc_status_info.gcprocessing = false;
532     return false;
533   }
534 #ifdef PERFCOUNT
535   profile_start(GC_REGION);
536 #endif
537
538   // core coordinator routine
539   if(0 == BAMBOO_NUM_OF_CORE) {
540     GC_PRINTF("Check if we can do gc or not\n");
541     gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
542
543     //wait for other cores to catch up
544     while(!gc_checkCoreStatus())
545       ;
546
547     pregccheck();
548     GCPROFILE_START_MASTER();
549     GC_PRINTF("start gc! \n");
550     pregcprocessing();
551     gc_master(stackptr);
552   } else if(BAMBOO_NUM_OF_CORE < NUMCORES4GC) {
553     GC_PRINTF("Core reporting for gc.\n");
554     pregcprocessing();
555     gc_collect(stackptr);
556   } else {
557     pregcprocessing();
558     gc_nocollect(stackptr);
559   }
560   postgcprocessing();
561 #ifdef PERFCOUNT
562   profile_start(APP_REGION);
563 #endif
564   return true;
565
566
567 #endif