From: jzhou Date: Thu, 5 Aug 2010 18:36:08 +0000 (+0000) Subject: Fix bug in multicore gc: the master core should send msgs to all the other cores... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=06f9007e8c8870a7d858a83b7776a981b6ac1df4;p=IRC.git Fix bug in multicore gc: the master core should send msgs to all the other cores and tell them to stop for gc as soon as it finds that there is no more shared memory --- diff --git a/Robust/src/Runtime/mem.c b/Robust/src/Runtime/mem.c index 2263113c..227c4ee2 100644 --- a/Robust/src/Runtime/mem.c +++ b/Robust/src/Runtime/mem.c @@ -24,7 +24,7 @@ void * mycalloc_share(struct garbagelist * stackptr, void * p = NULL; //int isize = 2*BAMBOO_CACHE_LINE_SIZE-4+(size-1)&(~BAMBOO_CACHE_LINE_MASK); int isize = (size & (~(BAMBOO_CACHE_LINE_MASK))) + (BAMBOO_CACHE_LINE_SIZE); - bool hasgc = false; + int hasgc = 0; memalloc: BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT(); #ifdef DEBUG @@ -37,12 +37,14 @@ memalloc: if(p == NULL) { // no more global shared memory BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME(); - if(!hasgc) { - // start gc - gc(stackptr); - hasgc = true; + if(hasgc < 5) { + // start gc + if(gc(stackptr)) { + hasgc++; + } } else { // no more global shared memory + //BAMBOO_DEBUGPRINT_REG(isize); BAMBOO_EXIT(0xc002); } diff --git a/Robust/src/Runtime/multicoregarbage.c b/Robust/src/Runtime/multicoregarbage.c index aeadde7e..32df0914 100644 --- a/Robust/src/Runtime/multicoregarbage.c +++ b/Robust/src/Runtime/multicoregarbage.c @@ -530,7 +530,7 @@ inline void checkMarkStatue() { BAMBOO_DEBUGPRINT(0xee0a); #endif } // void checkMarkStatue() - +/* inline bool preGC() { // preparation for gc // make sure to clear all incoming msgs espacially transfer obj msgs @@ -548,7 +548,7 @@ inline bool preGC() { corestatus[i] = 1; // send status confirm msg to core i send_msg_1(i, STATUSCONFIRM, false); - } // for(i = 1; i < NUMCORESACTIVE; ++i) + } // for(i = 1; i < NUMCORESACTIVE; ++i) #ifdef DEBUG BAMBOO_DEBUGPRINT(0xec02); @@ -557,7 +557,7 @@ inline bool preGC() { if(numconfirm == 0) { break; } - } // wait for confirmations + } // wait for confirmations waitconfirm = false; numconfirm = 0; #ifdef DEBUG @@ -594,7 +594,7 @@ inline bool preGC() { } else { // still have some transfer obj msgs on-the-fly, can not start gc return false; - } // if(0 == sumsendobj) + } // if(0 == sumsendobj) } else { #ifdef DEBUG BAMBOO_DEBUGPRINT(0xec07); @@ -603,7 +603,7 @@ inline bool preGC() { // confirmations yet, can not start gc return false; } // if((!waitconfirm) || -} // bool preGC() +} // bool preGC()*/ inline void initGC() { int i; @@ -1194,6 +1194,14 @@ inline void moveLObjs() { } } while(true); + // TODO + /*unsigned long long gc_num_livespace = 0; + for(int tmpi = 0; tmpi < gcnumblock; tmpi++) { + gc_num_livespace += bamboo_smemtbl[tmpi]; + } + BAMBOO_DEBUGPRINT_REG(gc_num_livespace); + BAMBOO_DEBUGPRINT_REG(bamboo_free_block);*/ + #ifdef GC_PROFILE // check how many live space there are gc_num_livespace = 0; @@ -2783,6 +2791,12 @@ inline void flush(struct garbagelist * stackptr) { } // flush() inline void gc_collect(struct garbagelist * stackptr) { + //BAMBOO_DEBUGPRINT(0xcccc); // TODO + // inform the master that this core is at a gc safe point and is ready to + // do gc + send_msg_4(STARTUPCORE, GCFINISHPRE, BAMBOO_NUM_OF_CORE, self_numsendobjs, + self_numreceiveobjs, false); + // core collector routine while(true) { if(INITPHASE == gcphase) { @@ -2867,6 +2881,12 @@ inline void gc_collect(struct garbagelist * stackptr) { } // void gc_collect(struct garbagelist * stackptr) inline void gc_nocollect(struct garbagelist * stackptr) { + //BAMBOO_DEBUGPRINT(0xcccc); // TODO + // inform the master that this core is at a gc safe point and is ready to + // do gc + send_msg_4(STARTUPCORE, GCFINISHPRE, BAMBOO_NUM_OF_CORE, self_numsendobjs, + self_numreceiveobjs, false); + while(true) { if(INITPHASE == gcphase) { break; @@ -2930,11 +2950,11 @@ inline void gc_nocollect(struct garbagelist * stackptr) { #endif } // void gc_collect(struct garbagelist * stackptr) -inline void gc(struct garbagelist * stackptr) { +inline bool gc(struct garbagelist * stackptr) { // check if do gc if(!gcflag) { gcprocessing = false; - return; + return false; } // core coordinator routine @@ -2943,16 +2963,81 @@ inline void gc(struct garbagelist * stackptr) { printf("(%x,%X) Check if can do gc or not\n", udn_tile_coord_x(), udn_tile_coord_y()); #endif - if(!preGC()) { - // not ready to do gc - gcflag = true; - return; - } - + //if(gcnumpre != 0) { + bool isallstall = true; + gccorestatus[BAMBOO_NUM_OF_CORE] = 0; + BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT(); + int ti = 0; + for(ti = 0; ti < NUMCORESACTIVE; ++ti) { + if(gccorestatus[ti] != 0) { + isallstall = false; + break; + } + } + if(!isallstall) { + BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME(); + // some of the cores are still executing the mutator and did not reach + // some gc safe point, therefore it is not ready to do gc + // in case that there are some pregc information msg lost, send a confirm + // msg to the 'busy' core + send_msg_1(ti, GCSTARTPRE, false); + gcflag = true; + return false; + } else { + // TODO #ifdef GC_PROFILE gc_profileStart(); #endif - + //BAMBOO_DEBUGPRINT(0x1111); // TODO +pregccheck: + //BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT(); + gcnumsendobjs[0][BAMBOO_NUM_OF_CORE] = self_numsendobjs; + gcnumreceiveobjs[0][BAMBOO_NUM_OF_CORE] = self_numreceiveobjs; + int sumsendobj = 0; +#ifdef DEBUG + BAMBOO_DEBUGPRINT(0xec04); +#endif + for(int i = 0; i < NUMCORESACTIVE; ++i) { + sumsendobj += gcnumsendobjs[0][i]; +#ifdef DEBUG + BAMBOO_DEBUGPRINT(0xf000 + gcnumsendobjs[0][i]); +#endif + } // for(i = 1; i < NUMCORESACTIVE; ++i) +#ifdef DEBUG + BAMBOO_DEBUGPRINT(0xec05); + BAMBOO_DEBUGPRINT_REG(sumsendobj); +#endif + for(int i = 0; i < NUMCORESACTIVE; ++i) { + sumsendobj -= gcnumreceiveobjs[0][i]; +#ifdef DEBUG + BAMBOO_DEBUGPRINT(0xf000 + gcnumreceiveobjs[i]); +#endif + } // for(i = 1; i < NUMCORESACTIVE; ++i) +#ifdef DEBUG + BAMBOO_DEBUGPRINT(0xec06); + BAMBOO_DEBUGPRINT_REG(sumsendobj); +#endif + if(0 != sumsendobj) { + // there were still some msgs on the fly, wait until there + // are some update pregc information coming and check it again + gcprecheck = false; + BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME(); + //BAMBOO_DEBUGPRINT(0x2222); // TODO + while(true) { + if(gcprecheck) { + break; + } + } + goto pregccheck; + } else { + BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME(); + } + } +/* +#ifdef GC_PROFILE + gc_profileStart(); +#endif +*/ #ifdef RAWPATH // TODO GC_DEBUG printf("(%x,%x) start gc! \n", udn_tile_coord_x(), udn_tile_coord_y()); //dumpSMem(); @@ -3342,6 +3427,8 @@ inline void gc(struct garbagelist * stackptr) { gcflag = false; gcprocessing = false; } + //if(STARTUPCORE == BAMBOO_NUM_OF_CORE) BAMBOO_DEBUGPRINT(0xeeee); // TODO + return true; } // void gc(struct garbagelist * stackptr) #ifdef GC_PROFILE diff --git a/Robust/src/Runtime/multicoregarbage.h b/Robust/src/Runtime/multicoregarbage.h index b7f73b9a..a6722e87 100644 --- a/Robust/src/Runtime/multicoregarbage.h +++ b/Robust/src/Runtime/multicoregarbage.h @@ -76,6 +76,9 @@ volatile bool gcflag; volatile bool gcprocessing; volatile GCPHASETYPE gcphase; // indicating GC phase +volatile bool gcpreinform; // counter for stopped cores +volatile bool gcprecheck; // indicates if there are updated pregc information + int gccurr_heaptop; struct MGCHash * gcforwardobjtbl; // cache forwarded objs in mark phase // for mark phase termination @@ -230,7 +233,7 @@ int gcbaseva; // base va for shared memory without reserved sblocks // the next core in the top of the heap #define NEXTTOPCORE(b) (gc_block2core[((b)+1)%(NUMCORES4GC*2)]) -inline void gc(struct garbagelist * stackptr); // core coordinator routine +inline bool gc(struct garbagelist * stackptr); // core coordinator routine inline void gc_collect(struct garbagelist* stackptr); //core collector routine inline void gc_nocollect(struct garbagelist* stackptr); //non-gc core collector routine inline void transferMarkResults_I(); diff --git a/Robust/src/Runtime/multicoreruntime.h b/Robust/src/Runtime/multicoreruntime.h index df49ed10..1482c67c 100644 --- a/Robust/src/Runtime/multicoreruntime.h +++ b/Robust/src/Runtime/multicoreruntime.h @@ -192,29 +192,31 @@ typedef enum { MEMREQUEST, // 0xE0 MEMRESPONSE, // 0xE1 #ifdef MULTICORE_GC - GCSTARTINIT, // 0xE2 - GCSTART, // 0xE3 - GCSTARTCOMPACT, // 0xE4 - GCSTARTMAPINFO, // 0xE5 - GCSTARTFLUSH, // 0xE6 - GCFINISHINIT, // 0xE7 - GCFINISHMARK, // 0xE8 - GCFINISHCOMPACT, // 0xE9 - GCFINISHMAPINFO, // 0xEa - GCFINISHFLUSH, // 0xEb - GCFINISH, // 0xEc - GCMARKCONFIRM, // 0xEd - GCMARKREPORT, // 0xEe - GCMARKEDOBJ, // 0xEf - GCMOVESTART, // 0xF0 - GCMAPREQUEST, // 0xF1 - GCMAPINFO, // 0xF2 - GCMAPTBL, // 0xF3 - GCLOBJREQUEST, // 0xF4 - GCLOBJINFO, // 0xF5 - GCLOBJMAPPING, // 0xF6 -#ifdef GC_PROFILE//_S - GCPROFILES, // 0xF7 + GCSTARTPRE, // 0xE2 + GCSTARTINIT, // 0xE3 + GCSTART, // 0xE4 + GCSTARTCOMPACT, // 0xE5 + GCSTARTMAPINFO, // 0xE6 + GCSTARTFLUSH, // 0xE7 + GCFINISHPRE, // 0xE8 + GCFINISHINIT, // 0xE9 + GCFINISHMARK, // 0xEa + GCFINISHCOMPACT, // 0xEb + GCFINISHMAPINFO, // 0xEc + GCFINISHFLUSH, // 0xEd + GCFINISH, // 0xEe + GCMARKCONFIRM, // 0xEf + GCMARKREPORT, // 0xF0 + GCMARKEDOBJ, // 0xF1 + GCMOVESTART, // 0xF2 + GCMAPREQUEST, // 0xF3 + GCMAPINFO, // 0xF4 + GCMAPTBL, // 0xF5 + GCLOBJREQUEST, // 0xF6 + GCLOBJINFO, // 0xF7 + GCLOBJMAPPING, // 0xF8 +#ifdef GC_PROFILE + GCPROFILES, // 0xF9 #endif #endif MSGEND diff --git a/Robust/src/Runtime/multicoretask.c b/Robust/src/Runtime/multicoretask.c index f7a830b5..0f5e8020 100644 --- a/Robust/src/Runtime/multicoretask.c +++ b/Robust/src/Runtime/multicoretask.c @@ -257,6 +257,8 @@ void initruntimedata() { gcflag = false; gcprocessing = false; gcphase = FINISHPHASE; + //gcnumpre = 0; + gcprecheck = true; gccurr_heaptop = 0; gcself_numsendobjs = 0; gcself_numreceiveobjs = 0; @@ -750,7 +752,9 @@ inline void run(void * arg) { while(true) { #ifdef MULTICORE_GC // check if need to do GC - gc(NULL); + if(gcflag) { + gc(NULL); + } #endif // check if there are new active tasks can be executed @@ -1875,7 +1879,27 @@ void * smemalloc_I(int coren, // no enough shared global memory *allocsize = 0; #ifdef MULTICORE_GC - gcflag = true; + //gcflag = true; + if(!gcflag) { + gcflag = true; + // inform other cores to stop and wait for gc + gcprecheck = true; + for(int i = 0; i < NUMCORESACTIVE; i++) { + // reuse the gcnumsendobjs & gcnumreceiveobjs + gccorestatus[i] = 1; + gcnumsendobjs[0][i] = 0; + gcnumreceiveobjs[0][i] = 0; + } + for(int i = 0; i < NUMCORESACTIVE; i++) { + if(i != BAMBOO_NUM_OF_CORE) { + if(BAMBOO_CHECK_SEND_MODE()) { + cache_msg_1(i, GCSTARTPRE); + } else { + send_msg_1(i, GCSTARTPRE, true); + } + } + } + } return NULL; #else BAMBOO_DEBUGPRINT(0xa001); @@ -1896,6 +1920,7 @@ INLINE int checkMsgLength_I(int size) { case STATUSCONFIRM: case TERMINATE: #ifdef MULTICORE_GC + case GCSTARTPRE: case GCSTARTINIT: case GCSTART: case GCSTARTMAPINFO: @@ -1944,6 +1969,7 @@ INLINE int checkMsgLength_I(int size) { case REDIRECTDENY: case REDIRECTRELEASE: #ifdef MULTICORE_GC + case GCFINISHPRE: case GCFINISHMARK: case GCMOVESTART: #ifdef GC_PROFILE//_S @@ -2074,6 +2100,23 @@ INLINE void processmsg_transobj_I() { addNewItem_I(&objqueue, (void *)transObj); } ++(self_numreceiveobjs); +#ifdef MULTICORE_GC + if(gcprocessing) { + if(STARTUPCORE == BAMBOO_NUM_OF_CORE) { + // set the gcprecheck to enable checking again + gcprecheck = true; + } else { + // send a update pregc information msg to the master core + if(BAMBOO_CHECK_SEND_MODE()) { + cache_msg_4(STARTUPCORE, GCFINISHPRE, BAMBOO_NUM_OF_CORE, + self_numsendobjs, self_numreceiveobjs); + } else { + send_msg_4(STARTUPCORE, GCFINISHPRE, BAMBOO_NUM_OF_CORE, + self_numsendobjs, self_numreceiveobjs, true); + } + } + } +#endif } INLINE void processmsg_transtall_I() { @@ -2359,6 +2402,7 @@ INLINE void processmsg_statusconfirm_I() { BAMBOO_DEBUGPRINT(0xe887); #endif #endif + //BAMBOO_DEBUGPRINT(0xffff); // TODO // cache the msg first if(BAMBOO_CHECK_SEND_MODE()) { cache_msg_5(STARTUPCORE, STATUSREPORT, @@ -2463,10 +2507,28 @@ INLINE void processmsg_memrequest_I() { } else { send_msg_3(data2, MEMRESPONSE, mem, allocsize, true); } - } // if mem == NULL, the gcflag of the startup core has been set - // and the gc should be started later, then a GCSTARTINIT msg - // will be sent to the requesting core to notice it to start gc - // and try malloc again + } else { + // if mem == NULL, the gcflag of the startup core has been set + // and all the other cores have been informed to start gc + // TODO + // inform other cores to stop and wait for gc + /*gcprecheck = true; + for(int i = 0; i < NUMCORESACTIVE; i++) { + // reuse the gcnumsendobjs & gcnumreceiveobjs + gccorestatus[i] = 1; + gcnumsendobjs[0][i] = 0; + gcnumreceiveobjs[0][i] = 0; + } + for(int i = 0; i < NUMCORESACTIVE; i++) { + if(i != BAMBOO_NUM_OF_CORE) { + if(BAMBOO_CHECK_SEND_MODE()) { + cache_msg_1(i, GCSTARTPRE); + } else { + send_msg_1(i, GCSTARTPRE, true); + } + } + }*/ + } #ifdef MULTICORE_GC } #endif @@ -2524,17 +2586,43 @@ INLINE void processmsg_memresponse_I() { } #ifdef MULTICORE_GC +INLINE void processmsg_gcstartpre_I() { + //BAMBOO_DEBUGPRINT(0xc000); // TODO + if(gcprocessing) { + // already stall for gc + // send a update pregc information msg to the master core + if(BAMBOO_CHECK_SEND_MODE()) { + cache_msg_4(STARTUPCORE, GCFINISHPRE, BAMBOO_NUM_OF_CORE, + self_numsendobjs, self_numreceiveobjs); + } else { + send_msg_4(STARTUPCORE, GCFINISHPRE, BAMBOO_NUM_OF_CORE, + self_numsendobjs, self_numreceiveobjs, true); + } + } else { + // the first time to be informed to start gc + gcflag = true; + if(!smemflag) { + // is waiting for response of mem request + // let it return NULL and start gc + bamboo_smem_size = 0; + bamboo_cur_msp = NULL; + smemflag = true; + bamboo_smem_zero_top = NULL; + } + } +} + INLINE void processmsg_gcstartinit_I() { - gcflag = true; + //gcflag = true; gcphase = INITPHASE; - if(!smemflag) { + /*if(!smemflag) { // is waiting for response of mem request // let it return NULL and start gc bamboo_smem_size = 0; bamboo_cur_msp = NULL; smemflag = true; bamboo_smem_zero_top = NULL; - } + }*/ } INLINE void processmsg_gcstart_I() { @@ -2561,6 +2649,33 @@ INLINE void processmsg_gcstartflush_I() { gcphase = FLUSHPHASE; } +INLINE void processmsg_gcfinishpre_I() { + int data1 = msgdata[msgdataindex]; + MSG_INDEXINC_I(); + int data2 = msgdata[msgdataindex]; + MSG_INDEXINC_I(); + int data3 = msgdata[msgdataindex]; + MSG_INDEXINC_I(); + // received a init phase finish msg + if(BAMBOO_NUM_OF_CORE != STARTUPCORE) { + // non startup core can not receive this msg +#ifndef CLOSE_PRINT + BAMBOO_DEBUGPRINT_REG(data1); +#endif + BAMBOO_EXIT(0xb000); + } + // All cores should do init GC + /*if(gcprecheck && (gcnumpre > 0)) { + gcnumpre--; + } else {*/ + if(!gcprecheck) { + gcprecheck = true; + } + gccorestatus[data1] = 0; + gcnumsendobjs[0][data1] = data2; + gcnumreceiveobjs[0][data1] = data3; +} + INLINE void processmsg_gcfinishinit_I() { int data1 = msgdata[msgdataindex]; MSG_INDEXINC_I(); @@ -3067,7 +3182,12 @@ processmsg: #ifdef MULTICORE_GC // GC msgs - case GCSTARTINIT: { + case GCSTARTPRE: { + processmsg_gcstartpre_I(); + break; + } // case GCSTARTPRE + + case GCSTARTINIT: { processmsg_gcstartinit_I(); break; } // case GCSTARTINIT @@ -3096,7 +3216,12 @@ processmsg: break; } // case GCSTARTFLUSH - case GCFINISHINIT: { + case GCFINISHPRE: { + processmsg_gcfinishpre_I(); + break; + } // case GCFINISHPRE + + case GCFINISHINIT: { processmsg_gcfinishinit_I(); break; } // case GCFINISHINIT @@ -3494,7 +3619,7 @@ void executetasks() { newtask: while(hashsize(activetasks)>0) { #ifdef MULTICORE_GC - gc(NULL); + if(gcflag) gc(NULL); #endif #ifdef DEBUG BAMBOO_DEBUGPRINT(0xe990);