More code clean
[IRC.git] / Robust / src / Runtime / bamboo / multicoregccompact.c
1 #ifdef MULTICORE_GC
2 #include "multicoregccompact.h"
3 #include "runtime_arch.h"
4 #include "multicoreruntime.h"
5
6 extern int corenum;
7
8 INLINE bool gc_checkCoreStatus() {
9   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
10   for(int i = 0; i < NUMCORES4GC; ++i) {
11     if(gccorestatus[i] != 0) {
12       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
13       return false;
14     }
15   }  
16   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
17   return true;
18 }
19
20 INLINE void gc_resetCoreStatus() {
21   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
22   for(int i = 0; i < NUMCORES4GC; ++i) {
23     gccorestatus[i] = 1;
24   }
25   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
26 }
27
28 // should be invoked with interrupt closed
29 int assignSpareMem_I(unsigned int sourcecore,
30                      unsigned int * requiredmem,
31                      unsigned int * tomove,
32                      unsigned int * startaddr) {
33   unsigned int b = 0;
34   BLOCKINDEX(gcloads[sourcecore], &b);
35   unsigned int boundptr = (b<NUMCORES4GC) ? ((b+1)*BAMBOO_SMEM_SIZE_L)
36      : (BAMBOO_LARGE_SMEM_BOUND+(b-NUMCORES4GC+1)*BAMBOO_SMEM_SIZE);
37   unsigned int remain = boundptr - gcloads[sourcecore];
38   unsigned int memneed = requiredmem + BAMBOO_CACHE_LINE_SIZE;
39   *startaddr = gcloads[sourcecore];
40   *tomove = gcfilledblocks[sourcecore] + 1;
41   if(memneed < remain) {
42     gcloads[sourcecore] += memneed;
43     return 0;
44   } else {
45     // next available block
46     gcfilledblocks[sourcecore] += 1;
47     unsigned int newbase = 0;
48     BASEPTR(sourcecore, gcfilledblocks[sourcecore], &newbase);
49     gcloads[sourcecore] = newbase;
50     return requiredmem-remain;
51   }
52 }
53
54 int assignSpareMem(unsigned int sourcecore,
55                    unsigned int * requiredmem,
56                    unsigned int * tomove,
57                    unsigned int * startaddr) {
58   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
59   unsigned int b = 0;
60   BLOCKINDEX(gcloads[sourcecore], &b);
61   unsigned int boundptr = (b<NUMCORES4GC) ? ((b+1)*BAMBOO_SMEM_SIZE_L)
62      : (BAMBOO_LARGE_SMEM_BOUND+(b-NUMCORES4GC+1)*BAMBOO_SMEM_SIZE);
63   unsigned int remain = boundptr - gcloads[sourcecore];
64   unsigned int memneed = requiredmem + BAMBOO_CACHE_LINE_SIZE;
65   *startaddr = gcloads[sourcecore];
66   *tomove = gcfilledblocks[sourcecore] + 1;
67   if(memneed < remain) {
68     gcloads[sourcecore] += memneed;
69     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
70     return 0;
71   } else {
72     // next available block
73     gcfilledblocks[sourcecore] += 1;
74     unsigned int newbase = 0;
75     BASEPTR(sourcecore, gcfilledblocks[sourcecore], &newbase);
76     gcloads[sourcecore] = newbase;
77     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
78     return requiredmem-remain;
79   }
80 }
81
82 INLINE void compact2Heaptophelper_I(unsigned int coren,
83                                     unsigned int* p,
84                                     unsigned int* numblocks,
85                                     unsigned int* remain) {
86   unsigned int b;
87   unsigned int memneed = gcrequiredmems[coren] + BAMBOO_CACHE_LINE_SIZE;
88   if(STARTUPCORE == coren) {
89     gctomove = true;
90     gcmovestartaddr = *p;
91     gcdstcore = gctopcore;
92     gcblock2fill = *numblocks + 1;
93   } else {
94     if(BAMBOO_CHECK_SEND_MODE()) {
95       cache_msg_4_I(coren,GCMOVESTART,gctopcore,*p,(*numblocks)+1);
96     } else {
97       send_msg_4_I(coren,GCMOVESTART,gctopcore,*p,(*numblocks)+1);
98     }
99   }
100   if(memneed < *remain) {
101     *p = *p + memneed;
102     gcrequiredmems[coren] = 0;
103     gcloads[gctopcore] += memneed;
104     *remain = *remain - memneed;
105   } else {
106     // next available block
107     *p = *p + *remain;
108     gcfilledblocks[gctopcore] += 1;
109     unsigned int newbase = 0;
110     BASEPTR(gctopcore, gcfilledblocks[gctopcore], &newbase);
111     gcloads[gctopcore] = newbase;
112     gcrequiredmems[coren] -= *remain - BAMBOO_CACHE_LINE_SIZE;
113     gcstopblock[gctopcore]++;
114     gctopcore = NEXTTOPCORE(gctopblock);
115     gctopblock++;
116     *numblocks = gcstopblock[gctopcore];
117     *p = gcloads[gctopcore];
118     BLOCKINDEX(*p, &b);
119     *remain=GC_BLOCK_REMAIN_SIZE(b, (*p));
120   }  
121   gcmovepending--;
122
123
124 INLINE void compact2Heaptop() {
125   // no cores with spare mem and some cores are blocked with pending move
126   // find the current heap top and make them move to the heap top
127   unsigned int p;
128   unsigned int numblocks = gcfilledblocks[gctopcore];
129   p = gcloads[gctopcore];
130   unsigned int b;
131   BLOCKINDEX(p, &b);
132   unsigned int remain=GC_BLOCK_REMAIN_SIZE(b, p);
133   // check if the top core finishes
134   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
135   if(gccorestatus[gctopcore] != 0) {
136     // let the top core finishes its own work first
137     compact2Heaptophelper_I(gctopcore, &p, &numblocks, &remain);
138     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
139     return;
140   }
141   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
142
143   for(int i = 0; i < NUMCORES4GC; i++) {
144     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
145     if((gccorestatus[i] != 0) && (gcrequiredmems[i] > 0)) {
146       compact2Heaptophelper_I(i, &p, &numblocks, &remain);
147       if(gccorestatus[gctopcore] != 0) {
148         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
149         // the top core is not free now
150         return;
151       }
152     }  
153     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
154   } 
155 }
156
157 INLINE void resolvePendingMoveRequest() {
158   int i;
159   int j;
160   bool nosparemem = true;
161   bool haspending = false;
162   bool hasrunning = false;
163   bool noblock = false;
164   unsigned int dstcore = 0;       // the core who need spare mem
165   unsigned int sourcecore = 0;       // the core who has spare mem
166   for(i = j = 0; (i < NUMCORES4GC) && (j < NUMCORES4GC); ) {
167     if(nosparemem) {
168       // check if there are cores with spare mem
169       if(gccorestatus[i] == 0) {
170         // finished working, check if it still have spare mem
171         if(gcfilledblocks[i] < gcstopblock[i]) {
172           // still have spare mem
173           nosparemem = false;
174           sourcecore = i;
175         }  
176       }
177       i++;
178     }  
179     if(!haspending) {
180       if(gccorestatus[j] != 0) {
181         // not finished, check if it has pending move requests
182         if((gcfilledblocks[j]==gcstopblock[j])&&(gcrequiredmems[j]>0)) {
183           dstcore = j;
184           haspending = true;
185         } else {
186           hasrunning = true;
187         } 
188       } 
189       j++;
190     }  
191     if(!nosparemem && haspending) {
192       // find match
193       unsigned int tomove = 0;
194       unsigned int startaddr = 0;
195       gcrequiredmems[dstcore] = assignSpareMem(sourcecore,
196                                                gcrequiredmems[dstcore],
197                                                &tomove,
198                                                &startaddr);
199       if(STARTUPCORE == dstcore) {
200         gcdstcore = sourcecore;
201         gctomove = true;
202         gcmovestartaddr = startaddr;
203         gcblock2fill = tomove;
204       } else {
205         send_msg_4(dstcore,GCMOVESTART,sourcecore,startaddr,tomove);
206       }
207       gcmovepending--;
208       nosparemem = true;
209       haspending = false;
210       noblock = true;
211     }
212   }  
213   
214   if(!hasrunning && !noblock) {
215     gcphase = SUBTLECOMPACTPHASE;
216     compact2Heaptop();
217   }
218
219
220 // If out of boundary of valid shared memory, return false, else return true
221 INLINE bool nextSBlock(struct moveHelper * orig) {
222   orig->blockbase = orig->blockbound;
223   
224   bool sbchanged = false;
225   unsigned int origptr = orig->ptr;
226   unsigned int blockbase = orig->blockbase;
227   unsigned int blockbound = orig->blockbound;
228   unsigned int bound = orig->bound;
229 outernextSBlock:
230   // check if across a big block
231   // TODO now do not zero out the whole memory, maybe the last two conditions
232   // are useless now
233   if((blockbase>=bound)||(origptr>=bound)
234     ||((origptr!=NULL)&&(*((int*)origptr))==0)||((*((int*)blockbase))==0)) {
235   innernextSBlock:
236     // end of current heap block, jump to next one
237     orig->numblocks++;
238     BASEPTR(BAMBOO_NUM_OF_CORE, orig->numblocks, &(orig->base));
239     if(orig->base >= gcbaseva + BAMBOO_SHARED_MEM_SIZE) {
240       // out of boundary
241       orig->ptr = orig->base; // set current ptr to out of boundary too
242       return false;
243     }
244     orig->blockbase = orig->base;
245     orig->sblockindex = 
246       (unsigned int)(orig->blockbase-gcbaseva)/BAMBOO_SMEM_SIZE;
247     sbchanged = true;
248     unsigned int blocknum = 0;
249     BLOCKINDEX(orig->base, &blocknum);
250     if(bamboo_smemtbl[blocknum] == 0) {
251       // goto next block
252       goto innernextSBlock;
253     }
254     // check the bamboo_smemtbl to decide the real bound
255     orig->bound = orig->base + bamboo_smemtbl[blocknum];
256   } else if(0 == (orig->blockbase%BAMBOO_SMEM_SIZE)) {
257     orig->sblockindex += 1;
258     sbchanged = true;
259   }  
260
261   // check if this sblock should be skipped or have special start point
262   int sbstart = gcsbstarttbl[orig->sblockindex];
263   if(sbstart == -1) {
264     // goto next sblock
265     orig->sblockindex += 1;
266     orig->blockbase += BAMBOO_SMEM_SIZE;
267     goto outernextSBlock;
268   } else if((sbstart != 0) && (sbchanged)) {
269     // the first time to access this SBlock
270     // not start from the very beginning
271     orig->blockbase = sbstart;
272   } 
273
274   // setup information for this sblock
275   orig->blockbound = orig->blockbase+(unsigned int)*((int*)(orig->blockbase));
276   orig->offset = BAMBOO_CACHE_LINE_SIZE;
277   orig->ptr = orig->blockbase + orig->offset;
278   if(orig->ptr >= orig->bound) {
279     // met a lobj, move to next block
280     goto innernextSBlock;
281   }
282
283   return true;
284
285
286 // return false if there are no available data to compact
287 INLINE bool initOrig_Dst(struct moveHelper * orig,
288                          struct moveHelper * to) {
289   // init the dst ptr
290   to->numblocks = 0;
291   to->top = to->offset = BAMBOO_CACHE_LINE_SIZE;
292   to->bound = BAMBOO_SMEM_SIZE_L;
293   BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
294
295   unsigned int tobase = to->base;
296   to->ptr = tobase + to->offset;
297
298   // init the orig ptr
299   orig->numblocks = 0;
300   orig->base = tobase;
301   unsigned int blocknum = 0;
302   BLOCKINDEX(orig->base, &blocknum);
303   unsigned int origbase = orig->base;
304   // check the bamboo_smemtbl to decide the real bound
305   orig->bound = origbase + (unsigned int)bamboo_smemtbl[blocknum];
306   orig->blockbase = origbase;
307   orig->sblockindex = (unsigned int)(origbase - gcbaseva) / BAMBOO_SMEM_SIZE;
308
309   int sbstart = gcsbstarttbl[orig->sblockindex];
310   if(sbstart == -1) {
311     // goto next sblock
312     orig->blockbound=gcbaseva+BAMBOO_SMEM_SIZE*(orig->sblockindex+1);
313     return nextSBlock(orig);
314   } else if(sbstart != 0) {
315     orig->blockbase = sbstart;
316   }
317   orig->blockbound = orig->blockbase + *((int*)(orig->blockbase));
318   orig->offset = BAMBOO_CACHE_LINE_SIZE;
319   orig->ptr = orig->blockbase + orig->offset;
320
321   return true;
322 }
323
324 INLINE void nextBlock(struct moveHelper * to) {
325   to->top = to->bound + BAMBOO_CACHE_LINE_SIZE; // header!
326   to->bound += BAMBOO_SMEM_SIZE;
327   to->numblocks++;
328   BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
329   to->offset = BAMBOO_CACHE_LINE_SIZE;
330   to->ptr = to->base + to->offset;
331 }
332
333 INLINE unsigned int findValidObj(struct moveHelper * orig,
334                                  struct moveHelper * to,
335                                  int * type) {
336   unsigned int size = 0;
337   while(true) {
338     CACHEADAPT_COMPLETE_PAGE_CONVERT(orig, to, to->ptr, false);
339     unsigned int origptr = (unsigned int)(orig->ptr);
340     unsigned int origbound = (unsigned int)orig->bound;
341     unsigned int origblockbound = (unsigned int)orig->blockbound;
342     if((origptr >= origbound) || (origptr == origblockbound)) {
343       if(!nextSBlock(orig)) {
344         // finished, no more data
345         return -1;
346       }
347       continue;
348     }
349     // check the obj's type, size and mark flag
350     *type = ((int *)(origptr))[0];
351     size = 0;
352     if(*type == 0) {
353       // end of this block, go to next one
354       if(!nextSBlock(orig)) {
355         // finished, no more data
356         return -1;
357       }
358       continue;
359     } else if(*type < NUMCLASSES) {
360       // a normal object
361       size = classsize[*type];
362     } else {
363       // an array
364       struct ArrayObject *ao=(struct ArrayObject *)(origptr);
365       unsigned int elementsize=classsize[*type];
366       unsigned int length=ao->___length___;
367       size=(unsigned int)sizeof(struct ArrayObject)
368         +(unsigned int)(length*elementsize);
369     }
370     return size;
371   }
372 }
373
374 // endaddr does not contain spaces for headers
375 INLINE bool moveobj(struct moveHelper * orig, struct moveHelper * to, unsigned int stopblock) {
376   if(stopblock == 0) {
377     return true;
378   }
379
380   int type = 0;
381   unsigned int size = findValidObj(orig, to, &type);
382   unsigned int isize = 0;
383
384   if(size == -1) {
385     // finished, no more data
386     return true;
387   }
388   ALIGNSIZE(size, &isize);       // no matter is the obj marked or not
389                                  // should be able to across
390   unsigned int origptr = (unsigned int)(orig->ptr);
391   if(((struct ___Object___ *)origptr)->marked == MARKED) {
392     unsigned int totop = (unsigned int)to->top;
393     unsigned int tobound = (unsigned int)to->bound;
394     GCPROFILE_RECORD_LIVE_OBJ();
395     // marked obj, copy it to current heap top
396     // check to see if remaining space is enough
397     if((unsigned int)(totop + isize) > tobound) {
398       // fill 0 indicating the end of this block
399       BAMBOO_MEMSET_WH(to->ptr,  '\0', tobound - totop);
400       // fill the header of this block and then go to next block
401       to->offset += tobound - totop;
402       CLOSEBLOCK(to->base, to->offset);
403 #ifdef GC_CACHE_ADAPT
404       unsigned int tmp_ptr = to->ptr;
405 #endif 
406       nextBlock(to);
407 #ifdef GC_CACHE_ADAPT
408       CACHEADAPT_COMPLETE_PAGE_CONVERT(orig, to, tmp_ptr, true);
409 #endif 
410       if(stopblock == to->numblocks) {
411         // already fulfilled the block
412         return true;
413       }  
414     } 
415     // set the mark field to 2, indicating that this obj has been moved
416     // and need to be flushed
417     ((struct ___Object___ *)origptr)->marked = COMPACTED;
418     unsigned int toptr = (unsigned int)to->ptr;
419     if(toptr != origptr) {
420       if((unsigned int)(origptr) < (unsigned int)(toptr+size)) {
421         memmove(toptr, origptr, size);
422       } else {
423         memcpy(toptr, origptr, size);
424       }
425       // fill the remaining space with -2
426       BAMBOO_MEMSET_WH((unsigned int)(toptr+size), -2, isize-size);
427     }
428     // store mapping info
429     gcmappingtbl[OBJMAPPINGINDEX((unsigned int)origptr)]=(unsigned int)toptr;
430     gccurr_heaptop -= isize;
431     to->ptr += isize;
432     to->offset += isize;
433     to->top += isize;
434 #ifdef GC_CACHE_ADAPT
435     unsigned int tmp_ptr = to->ptr;
436 #endif // GC_CACHE_ADAPT
437     if(to->top == to->bound) {
438       CLOSEBLOCK(to->base, to->offset);
439       nextBlock(to);
440     }
441 #ifdef GC_CACHE_ADAPT
442     CACHEADAPT_COMPLETE_PAGE_CONVERT(orig, to, tmp_ptr, true);
443 #endif
444   } 
445   
446   // move to next obj
447   orig->ptr += isize; 
448   
449   return ((((unsigned int)(orig->ptr) > (unsigned int)(orig->bound))
450            || ((unsigned int)(orig->ptr) == (unsigned int)(orig->blockbound)))
451           &&!nextSBlock(orig));
452
453
454 // should be invoked with interrupt closed
455 bool gcfindSpareMem_I(unsigned int * startaddr,
456                       unsigned int * tomove,
457                       unsigned int * dstcore,
458                       unsigned int requiredmem,
459                       unsigned int requiredcore) {
460   for(int k = 0; k < NUMCORES4GC; k++) {
461     if((gccorestatus[k] == 0) && (gcfilledblocks[k] < gcstopblock[k])) {
462       // check if this stopped core has enough mem
463       assignSpareMem_I(k, requiredmem, tomove, startaddr);
464       *dstcore = k;
465       return true;
466     }
467   }
468   // if can not find spare mem right now, hold the request
469   gcrequiredmems[requiredcore] = requiredmem;
470   gcmovepending++;
471   return false;
472
473
474 bool gcfindSpareMem(unsigned int * startaddr,
475                     unsigned int * tomove,
476                     unsigned int * dstcore,
477                     unsigned int requiredmem,
478                     unsigned int requiredcore) {
479   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
480   for(int k = 0; k < NUMCORES4GC; k++) {
481     if((gccorestatus[k] == 0) && (gcfilledblocks[k] < gcstopblock[k])) {
482       // check if this stopped core has enough mem
483       assignSpareMem_I(k, requiredmem, tomove, startaddr);
484       *dstcore = k;
485       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
486       return true;
487     }
488   }
489   // if can not find spare mem right now, hold the request
490   gcrequiredmems[requiredcore] = requiredmem;
491   gcmovepending++;
492   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
493   return false;
494 }
495
496 INLINE bool compacthelper(struct moveHelper * orig,
497                           struct moveHelper * to,
498                           int * filledblocks,
499                           unsigned int * heaptopptr,
500                           bool * localcompact) {
501   // scan over all objs in this block, compact the marked objs
502   // loop stop when finishing either scanning all active objs or
503   // fulfilled the gcstopblock
504 innercompact:
505   while((unsigned int)(orig->ptr) < (unsigned int)gcmarkedptrbound) {
506     if(moveobj(orig, to, gcblock2fill)) {
507       break;
508     }
509   }
510   CACHEADAPT_SAMPLING_DATA_CONVERT(to->ptr);
511   // if no objs have been compact, do nothing,
512   // otherwise, fill the header of this block
513   if(to->offset > (unsigned int)BAMBOO_CACHE_LINE_SIZE) {
514     CLOSEBLOCK(to->base, to->offset);
515   } else {
516     to->offset = 0;
517     to->ptr = to->base;
518     to->top -= BAMBOO_CACHE_LINE_SIZE;
519   }  
520   if(*localcompact) {
521     *heaptopptr = to->ptr;
522     *filledblocks = to->numblocks;
523   }
524   
525   // send msgs to core coordinator indicating that the compact is finishing
526   // send compact finish message to core coordinator
527   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
528     gcfilledblocks[BAMBOO_NUM_OF_CORE] = *filledblocks;
529     gcloads[BAMBOO_NUM_OF_CORE] = *heaptopptr;
530     if((unsigned int)(orig->ptr) < (unsigned int)gcmarkedptrbound) {
531       // ask for more mem
532       gctomove = false;
533       if(gcfindSpareMem(&gcmovestartaddr, &gcblock2fill, &gcdstcore,
534             gccurr_heaptop, BAMBOO_NUM_OF_CORE)) {
535         gctomove = true;
536       } else {
537         return false;
538       }
539     } else {
540       gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
541       gctomove = false;
542       return true;
543     }
544   } else {
545     if((unsigned int)(orig->ptr) < (unsigned int)gcmarkedptrbound) {
546       // ask for more mem
547       gctomove = false;
548       send_msg_5(STARTUPCORE,GCFINISHCOMPACT,BAMBOO_NUM_OF_CORE,*filledblocks,*heaptopptr,gccurr_heaptop);
549     } else {
550       // finish compacting
551       send_msg_5(STARTUPCORE,GCFINISHCOMPACT,BAMBOO_NUM_OF_CORE,*filledblocks,*heaptopptr, 0);
552     }
553   } 
554
555   if(orig->ptr < gcmarkedptrbound) {
556     // still have unpacked obj
557     while(!gctomove) ;
558     
559     gctomove = false;
560
561     to->ptr = gcmovestartaddr;
562     to->numblocks = gcblock2fill - 1;
563     to->bound = ((to->numblocks==0)?BAMBOO_SMEM_SIZE_L:BAMBOO_SMEM_SIZE_L)+BAMBOO_SMEM_SIZE*to->numblocks;
564     BASEPTR(gcdstcore, to->numblocks, &(to->base));
565     to->offset = to->ptr - to->base;
566     to->top = (to->numblocks==0)?(to->offset):(to->bound-BAMBOO_SMEM_SIZE+to->offset);
567     to->base = to->ptr;
568     to->offset = BAMBOO_CACHE_LINE_SIZE;
569     to->ptr += to->offset;   // for header
570     to->top += to->offset;
571     *localcompact = (gcdstcore == BAMBOO_NUM_OF_CORE);
572     CACHEADAPT_SAMPLING_DATA_REVISE_INIT();
573     goto innercompact;
574   }
575   return true;
576 }
577
578 void compact() {
579   BAMBOO_ASSERT(COMPACTPHASE == gcphase);
580   
581   // initialize pointers for comapcting
582   struct moveHelper * orig = (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
583   struct moveHelper * to = (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
584   if(!initOrig_Dst(orig, to)) {
585     // no available data to compact
586     // send compact finish msg to STARTUP core
587     send_msg_5(STARTUPCORE,GCFINISHCOMPACT,BAMBOO_NUM_OF_CORE,0,to->base,0);
588     RUNFREE(orig);
589     RUNFREE(to);
590   } else {
591     CACHEADAPT_SAMPLING_DATA_REVISE_INIT();
592
593     unsigned int filledblocks = 0;
594     unsigned int heaptopptr = 0;
595     bool localcompact = true;
596     compacthelper(orig, to, &filledblocks, &heaptopptr, &localcompact);
597     RUNFREE(orig);
598     RUNFREE(to);
599   }
600
601
602 void compact_master(struct moveHelper * orig, struct moveHelper * to) {
603   // initialize pointers for comapcting
604   initOrig_Dst(orig, to);
605   CACHEADAPT_SAMPLING_DATA_REVISE_INIT();
606   int filledblocks = 0;
607   unsigned int heaptopptr = 0;
608   bool finishcompact = false;
609   bool iscontinue = true;
610   bool localcompact = true;
611   while((COMPACTPHASE == gcphase) || (SUBTLECOMPACTPHASE == gcphase)) {
612     if((!finishcompact) && iscontinue) {
613       finishcompact = compacthelper(orig,to,&filledblocks,&heaptopptr,&localcompact);
614     }
615     
616     if(gc_checkCoreStatus()) {
617       // all cores have finished compacting restore the gcstatus of all cores
618       gc_resetCoreStatus();
619       break;
620     } else {
621       // check if there are spare mem for pending move requires
622       if(COMPACTPHASE == gcphase) {
623         resolvePendingMoveRequest();
624       } else {
625         compact2Heaptop();
626       }
627     } 
628
629     if(gctomove) {
630       to->ptr = gcmovestartaddr;
631       to->numblocks = gcblock2fill - 1;
632       to->bound = (to->numblocks==0) ? BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE_L+BAMBOO_SMEM_SIZE*to->numblocks;
633       BASEPTR(gcdstcore, to->numblocks, &(to->base));
634       to->offset = to->ptr - to->base;
635       to->top = (to->numblocks==0)?(to->offset):(to->bound-BAMBOO_SMEM_SIZE+to->offset);
636       to->base = to->ptr;
637       to->offset = BAMBOO_CACHE_LINE_SIZE;
638       to->ptr += to->offset;  // for header
639       to->top += to->offset;
640       localcompact = (gcdstcore == BAMBOO_NUM_OF_CORE);
641       gctomove = false;
642       iscontinue = true;
643     } else if(!finishcompact) {
644       // still pending
645       iscontinue = false;
646     }
647   }
648 }
649
650 #endif // MULTICORE_GC