clean up dtlb sample code...mostly fixing multisample bug
[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 #ifdef GC_CACHE_ADAPT
121   gccachestage = false;
122 #endif 
123
124   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
125     allocationinfo.blocktable=RUNMALLOC(sizeof(struct blockrecord)*GCNUMBLOCK);
126     for(int i=0; i<GCNUMBLOCK;i++) {
127       if (1==NUMCORES4GC)
128         allocationinfo.blocktable[i].corenum=0;
129       else
130         allocationinfo.blocktable[i].corenum=gc_block2core[(i%(NUMCORES4GC*2))];
131       allocationinfo.blocktable[i].status=BS_FREE;
132       allocationinfo.blocktable[i].usedspace=0;
133       allocationinfo.blocktable[i].freespace=GLOBALBLOCKSIZE(i);
134     }
135     buildCore2Test();
136   }
137
138   //initialize update structures
139   origarraycount=0;
140   for(int i=0;i<NUMCORES4GC;i++) {
141     origblockarray[i]=NULL;
142   }
143
144   INIT_MULTICORE_GCPROFILE_DATA();
145 }
146
147 void dismulticoregcdata() {
148   freeMGCHash(gcforwardobjtbl);
149 }
150
151 void initGC() {
152   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
153     for(int i = 0; i < NUMCORES4GC; i++) {
154       gccorestatus[i] = 1;
155       gcnumsendobjs[0][i] = gcnumsendobjs[1][i] = 0;
156       gcnumreceiveobjs[0][i] = gcnumreceiveobjs[1][i] = 0;
157       gcloads[i] = 0;
158       gcrequiredmems[i] = 0;
159     } 
160     for(int i = NUMCORES4GC; i < NUMCORESACTIVE; i++) {
161       gccorestatus[i] = 1;
162       gcnumsendobjs[0][i] = gcnumsendobjs[1][i] = 0;
163       gcnumreceiveobjs[0][i] = gcnumreceiveobjs[1][i] = 0;
164     }
165     gcnumsrobjs_index = 0;
166   } 
167   gcself_numsendobjs = 0;
168   gcself_numreceiveobjs = 0;
169   gcmovestartaddr = 0;
170   gctomove = false;
171   gcblock2fill = 0;
172   gcmovepending = 0;
173   gccurr_heaptop = 0;
174   update_origblockptr=NULL;
175   gc_queueinit();
176
177   MGCHashreset(gcforwardobjtbl);
178
179   GCPROFILE_INIT();
180   gc_output_cache_policy_time=0;
181
182
183 void checkMarkStatus_p2() {
184   //  tprintf("Check mark status 2\n");
185   // check if the sum of send objs and receive obj are the same
186   // yes->check if the info is the latest; no->go on executing
187   unsigned int sumsendobj = 0;
188   for(int i = 0; i < NUMCORESACTIVE; i++) {
189     sumsendobj += gcnumsendobjs[gcnumsrobjs_index][i];
190   } 
191   for(int i = 0; i < NUMCORESACTIVE; i++) {
192     sumsendobj -= gcnumreceiveobjs[gcnumsrobjs_index][i];
193   } 
194   if(0 == sumsendobj) {
195     // Check if there are changes of the numsendobjs or numreceiveobjs 
196     // on each core
197     int i = 0;
198     for(i = 0; i < NUMCORESACTIVE; i++) {
199       if((gcnumsendobjs[0][i]!=gcnumsendobjs[1][i])||(gcnumreceiveobjs[0][i]!=gcnumreceiveobjs[1][i]) ) {
200         break;
201       }
202     }  
203     if(i == NUMCORESACTIVE) {    
204       //tprintf("Mark terminated\n");
205       // all the core status info are the latest,stop mark phase
206       gc_status_info.gcphase = COMPACTPHASE;
207       // restore the gcstatus for all cores
208       for(int i = 0; i < NUMCORESACTIVE; i++) {
209         gccorestatus[i] = 1;
210       }  
211     } else {
212       // There were changes between phase 1 and phase 2, can not decide 
213       // whether the mark phase has been finished
214       waitconfirm = false;
215       // As it fails in phase 2, flip the entries
216       gcnumsrobjs_index = (gcnumsrobjs_index == 0) ? 1 : 0;
217     } 
218   } else {
219     // There were changes between phase 1 and phase 2, can not decide 
220     // whether the mark phase has been finished
221     waitconfirm = false;
222     // As it fails in phase 2, flip the entries
223     gcnumsrobjs_index = (gcnumsrobjs_index == 0) ? 1 : 0;
224   }
225 }
226
227 void checkMarkStatus() {
228   //  tprintf("Check mark status\n");
229   if((!waitconfirm)||(waitconfirm && (numconfirm == 0))) {
230     unsigned int entry_index = 0;
231     if(waitconfirm) {
232       // phase 2
233       entry_index = (gcnumsrobjs_index == 0) ? 1 : 0;
234     } else {
235       // phase 1
236       entry_index = gcnumsrobjs_index;
237     }
238     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
239     // check the status of all cores
240     if (gc_checkCoreStatus()) {
241       // ask for confirm
242       if(!waitconfirm) {
243         // the first time found all cores stall
244         // send out status confirm msg to all other cores
245         // reset the corestatus array too    
246         waitconfirm = true;
247         numconfirm = NUMCORESACTIVE - 1;
248         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
249         GC_SEND_MSG_1_TO_CLIENT(GCMARKCONFIRM);
250       } else {
251         // Phase 2
252         checkMarkStatus_p2(); 
253         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
254       }
255     } else {
256       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
257     } 
258   } 
259
260
261 // compute load balance for all cores
262 int loadbalance() {
263   // compute load balance
264   // get the total loads
265   void * heaptop;
266   unsigned int tloads = 0;
267   for(int i = 0; i < NUMCORES4GC; i++) {
268     tloads += gcloads[i];
269     //tprintf("load: %d %d \n", gcloads[i], i);
270   }
271   heaptop = gcbaseva + tloads;
272
273   unsigned int topblockindex;
274   
275   BLOCKINDEX(topblockindex, heaptop);
276   // num of blocks per core
277   unsigned int numbpc = (topblockindex+NUMCORES4GC-1)/NUMCORES4GC;
278   
279   return numbpc;
280 }
281
282 void gc_collect(struct garbagelist * stackptr) {
283   gc_status_info.gcprocessing = true;
284   // inform the master that this core is at a gc safe point and is ready to 
285   // do gc
286   send_msg_4(STARTUPCORE,GCFINISHPRE,BAMBOO_NUM_OF_CORE,self_numsendobjs,self_numreceiveobjs);
287
288   // core collector routine
289   //wait for init phase
290   WAITFORGCPHASE(INITPHASE);
291
292   GC_PRINTF("Do initGC\n");
293   initGC();
294   CACHEADAPT_GC(true);
295   //send init finish msg to core coordinator
296   send_msg_2(STARTUPCORE,GCFINISHINIT,BAMBOO_NUM_OF_CORE);
297
298   //wait for mark phase
299   WAITFORGCPHASE(MARKPHASE);
300
301   GC_PRINTF("Start mark phase\n");
302   mark(stackptr);
303   GC_PRINTF("Finish mark phase, start compact phase\n");
304   compact();
305   GC_PRINTF("Finish compact phase\n");
306
307   WAITFORGCPHASE(UPDATEPHASE);
308
309   GC_PRINTF("Start update phase\n");
310   GCPROFILE_INFO_2_MASTER();
311   update(stackptr);
312   GC_PRINTF("Finish update phase\n");
313
314   CACHEADAPT_PHASE_CLIENT();
315
316   // invalidate all shared mem pointers
317   bamboo_cur_msp = NULL;
318   bamboo_smem_size = 0;
319   bamboo_smem_zero_top = NULL;
320   gcflag = false;
321
322   WAITFORGCPHASE(FINISHPHASE);
323
324   GC_PRINTF("Finish gc! \n");
325
326
327 void gc_nocollect(struct garbagelist * stackptr) {
328   gc_status_info.gcprocessing = true;
329   // inform the master that this core is at a gc safe point and is ready to 
330   // do gc
331   send_msg_4(STARTUPCORE,GCFINISHPRE,BAMBOO_NUM_OF_CORE,self_numsendobjs,self_numreceiveobjs);
332   
333   WAITFORGCPHASE(INITPHASE);
334
335   GC_PRINTF("Do initGC\n");
336   initGC();
337   CACHEADAPT_GC(true);
338   //send init finish msg to core coordinator
339   send_msg_2(STARTUPCORE,GCFINISHINIT,BAMBOO_NUM_OF_CORE);
340
341   WAITFORGCPHASE(MARKPHASE);
342
343   GC_PRINTF("Start mark phase\n"); 
344   mark(stackptr);
345   GC_PRINTF("Finish mark phase, wait for update\n");
346
347   // non-gc core collector routine
348   WAITFORGCPHASE(UPDATEPHASE);
349
350   GC_PRINTF("Start update phase\n");
351   GCPROFILE_INFO_2_MASTER();
352   update(stackptr);
353   GC_PRINTF("Finish update phase\n"); 
354
355   CACHEADAPT_PHASE_CLIENT();
356
357   // invalidate all shared mem pointers
358   bamboo_cur_msp = NULL;
359   bamboo_smem_size = 0;
360   bamboo_smem_zero_top = NULL;
361
362   gcflag = false;
363   WAITFORGCPHASE(FINISHPHASE);
364
365   GC_PRINTF("Finish gc! \n");
366 }
367
368 void master_mark(struct garbagelist *stackptr) {
369
370   GC_PRINTF("Start mark phase \n");
371   gc_status_info.gcphase = MARKPHASE;
372   GC_SEND_MSG_1_TO_CLIENT(GCSTART);
373   // mark phase
374
375   mark(stackptr);
376 }
377
378 void master_getlargeobjs() {
379   // send msgs to all cores requiring large objs info
380   // Note: only need to ask gc cores, non-gc cores do not host any objs
381   numconfirm = NUMCORES4GC - 1;
382   for(int i = 1; i < NUMCORES4GC; i++) {
383     send_msg_1(i,GCLOBJREQUEST);
384   }
385   gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
386   //spin until we have all responses
387   while(numconfirm!=0) ;
388
389   GCPROFILE_ITEM();
390   GC_PRINTF("prepare to cache large objs \n");
391
392 }
393
394
395 void master_updaterefs(struct garbagelist * stackptr) {
396   gc_status_info.gcphase = UPDATEPHASE;
397   GC_SEND_MSG_1_TO_CLIENT(GCSTARTUPDATE);
398   GCPROFILE_ITEM();
399   GC_PRINTF("Start update phase \n");
400   // update phase
401   update(stackptr);
402   GC_CHECK_ALL_CORE_STATUS();
403   GC_PRINTF("Finish update phase \n");
404 }
405
406 void master_finish() {
407   gc_status_info.gcphase = FINISHPHASE;
408   
409   // invalidate all shared mem pointers
410   // put it here as it takes time to inform all the other cores to
411   // finish gc and it might cause problem when some core resumes
412   // mutator earlier than the other cores
413   bamboo_cur_msp = NULL;
414   bamboo_smem_size = 0;
415   bamboo_smem_zero_top = NULL;
416   
417   GCPROFILE_END();
418   unsigned long long tmpt = BAMBOO_GET_EXE_TIME();
419   CACHEADAPT_OUTPUT_CACHE_POLICY();
420   gc_output_cache_policy_time += (BAMBOO_GET_EXE_TIME()-tmpt);
421   gcflag = false;
422
423   GC_SEND_MSG_1_TO_CLIENT(GCFINISH);
424   gc_status_info.gcprocessing = false;  
425
426   if(gcflag) {
427     // inform other cores to stop and wait for gc
428     GC_PRINTF("Back to Back gc case\n");
429     gcprecheck = true;
430     for(int i = 0; i < NUMCORESACTIVE; i++) {
431       // reuse the gcnumsendobjs & gcnumreceiveobjs
432       gcnumsendobjs[0][i] = 0;
433       gcnumreceiveobjs[0][i] = 0;
434     }
435     GC_SEND_MSG_1_TO_CLIENT(GCSTARTPRE);
436   }
437 }
438
439 void gc_master(struct garbagelist * stackptr) {
440   tprintf("start GC!\n");
441   gc_status_info.gcprocessing = true;
442   gc_status_info.gcphase = INITPHASE;
443
444   waitconfirm = false;
445   numconfirm = 0;
446   initGC();
447   GC_SEND_MSG_1_TO_CLIENT(GCSTARTINIT);
448   CACHEADAPT_GC(true);
449   //tprintf("Check core status \n");
450   GC_CHECK_ALL_CORE_STATUS();
451   GCPROFILE_ITEM();
452   unsigned long long tmpt = BAMBOO_GET_EXE_TIME();
453   CACHEADAPT_OUTPUT_CACHE_SAMPLING();
454   gc_output_cache_policy_time += (BAMBOO_GET_EXE_TIME()-tmpt);
455   //tprintf("start mark phase\n");
456   // do mark phase
457   master_mark(stackptr);
458   //tprintf("finish mark phase\n");
459   // get large objects from all cores
460   master_getlargeobjs();
461   //tprintf("start compact phase\n");
462   // compact the heap
463   master_compact();
464   //tprintf("start update phase\n");
465   // update the references
466   master_updaterefs(stackptr);
467   //tprintf("gc master finished update   \n");
468   // do cache adaptation
469   CACHEADAPT_PHASE_MASTER();
470   //tprintf("finish cachdapt phase\n");
471   // do finish up stuff
472 #ifdef GC_DEBUG
473   for(int i=0;i<GCNUMBLOCK;i++) {
474     struct blockrecord *record=&allocationinfo.blocktable[i];
475     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));
476   }
477 #endif
478
479   master_finish();
480
481   //tprintf("finish GC ! %d \n",gcflag);
482
483
484 void pregccheck() {
485   while(true) {
486     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
487     gcnumsendobjs[0][BAMBOO_NUM_OF_CORE] = self_numsendobjs;
488     gcnumreceiveobjs[0][BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
489     int sumsendobj = 0;
490     for(int i = 0; i < NUMCORESACTIVE; i++) {
491       sumsendobj += gcnumsendobjs[0][i];
492     }  
493     for(int i = 0; i < NUMCORESACTIVE; i++) {
494       sumsendobj -= gcnumreceiveobjs[0][i];
495     } 
496     if(0 != sumsendobj) {
497       // there were still some msgs on the fly, wait until there 
498       // are some update pregc information coming and check it again
499       gcprecheck = false;
500       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
501
502       while(!gcprecheck) ;
503     } else {
504       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
505       return;
506     }
507   }
508 }
509
510 void pregcprocessing() {
511 #if defined(GC_CACHE_ADAPT)&&defined(GC_CACHE_SAMPLING)
512   // disable the timer interrupt
513   bamboo_mask_timer_intr();
514   // get the sampling data 
515   bamboo_output_dtlb_sampling();
516 #endif
517 }
518
519 void postgcprocessing() {
520 #if defined(GC_CACHE_ADAPT)&&defined(GC_CACHE_SAMPLING)
521   // enable the timer interrupt
522   bamboo_tile_timer_set_next_event(GC_TILE_TIMER_EVENT_SETTING); 
523   bamboo_unmask_timer_intr();
524   //turn on sampling again
525   bamboo_dtlb_sampling_init();
526 #endif
527 }
528
529 bool gc(struct garbagelist * stackptr) {
530   // check if do gc
531   if(!gcflag) {
532     gc_status_info.gcprocessing = false;
533     return false;
534   }
535 #ifdef PERFCOUNT
536   profile_start(GC_REGION);
537 #endif
538
539   // core coordinator routine
540   if(0 == BAMBOO_NUM_OF_CORE) {
541     GC_PRINTF("Check if we can do gc or not\n");
542     gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
543
544     //wait for other cores to catch up
545     while(!gc_checkCoreStatus())
546       ;
547
548     GCPROFILE_START();
549     pregccheck();
550     GC_PRINTF("start gc! \n");
551     pregcprocessing();
552     gc_master(stackptr);
553   } else if(BAMBOO_NUM_OF_CORE < NUMCORES4GC) {
554     GC_PRINTF("Core reporting for gc.\n");
555     pregcprocessing();
556     gc_collect(stackptr);
557   } else {
558     pregcprocessing();
559     gc_nocollect(stackptr);
560   }
561   postgcprocessing();
562 #ifdef PERFCOUNT
563   profile_start(APP_REGION);
564 #endif
565   return true;
566
567
568 #endif