gc_output_cache_policy_time=0;
}
-bool gc_checkAllCoreStatus() {
- for(int i = 0; i < NUMCORESACTIVE; i++) {
- if(gccorestatus[i] != 0) {
- return false;
- }
- }
- return true;
-}
-
-// NOTE: should be invoked with interrupts turned off
-bool gc_checkAllCoreStatus_I() {
- for(int i = 0; i < NUMCORESACTIVE; i++) {
- if(gccorestatus[i] != 0) {
- return false;
- }
- }
- return true;
-}
-
void checkMarkStatus_p2() {
// check if the sum of send objs and receive obj are the same
// yes->check if the info is the latest; no->go on executing
gcnumsendobjs[entry_index][BAMBOO_NUM_OF_CORE] = gcself_numsendobjs;
gcnumreceiveobjs[entry_index][BAMBOO_NUM_OF_CORE] = gcself_numreceiveobjs;
// check the status of all cores
- if (gc_checkAllCoreStatus_I()) {
+ if (gc_checkCoreStatus()) {
// ask for confirm
if(!waitconfirm) {
// the first time found all cores stall
if(0 == BAMBOO_NUM_OF_CORE) {
GC_PRINTF("Check if we can do gc or not\n");
gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
- if(!gc_checkAllCoreStatus()) {
+ if(!gc_checkCoreStatus()) {
// 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
gcflag = true;
volatile unsigned int gccorestatus[NUMCORESACTIVE];//records status of each core
// 1: running gc
// 0: stall
+
+volatile unsigned int returnedmem[NUMCORESACTIVE];//records status of each core
+ // 1: running gc
+ // 0: stall
volatile unsigned int gcnumsendobjs[2][NUMCORESACTIVE];//# of objects sent out
volatile unsigned int gcnumreceiveobjs[2][NUMCORESACTIVE];//# of objects received
volatile unsigned int gcnumsrobjs_index;//indicates which entry to record the
volatile bool gctomove;
//keeps track of memory request master was not able to serve
-unsigned int gcrequiredmems[NUMCORES4GC]; //record pending mem requests
+volatile unsigned int maxusefulmems[NUMCORES4GC]; //record pending mem requests
+volatile unsigned int gcrequiredmems[NUMCORES4GC]; //record pending mem requests
volatile unsigned int gcmovepending;
// shared memory pointer for pointer mapping tbls
void * gcbaseva; // base va for shared memory without reserved sblocks
+static bool gc_checkCoreStatus() {
+ for(int i = 0; i < NUMCORES4GC; i++) {
+ if(gccorestatus[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void gc_resetCoreStatus() {
+ for(int i = 0; i < NUMCORES4GC; i++) {
+ gccorestatus[i] = 1;
+ }
+}
+
+
/* Structure to keep track of free space in block */
enum blockstatus {
/* BS_USED indicates that we don't have information for this block yet */
#define GCNUMBLOCK (NUMCORES4GC+(BAMBOO_SHARED_MEM_SIZE-BAMBOO_LARGE_SMEM_BOUND)/BAMBOO_SMEM_SIZE)
#define GCNUMLOCALBLOCK (GCNUMBLOCK/NUMCORES4GC)
+/* This macro defines the smallest memoy chunk the master will hand out to another core during compacting */
+
+#define MINMEMORYCHUNKSIZE 32768
+
/* This macro waits for the given gc phase */
#define WAITFORGCPHASE(phase) while(gc_status_info.gcphase != phase) ;
{ \
gccorestatus[BAMBOO_NUM_OF_CORE] = 0; \
while(f) { \
- if(gc_checkAllCoreStatus()) { \
+ if(gc_checkCoreStatus()) { \
break; \
} \
} \
void initmulticoregcdata();
void dismulticoregcdata();
-bool gc_checkAllCoreStatus();
bool gc(struct garbagelist * stackptr); // core coordinator routine
void gc_collect(struct garbagelist* stackptr); //core collector routine
void gc_nocollect(struct garbagelist* stackptr); //non-gc core collector routine
void transferMarkResults_I();
-void * gcfindSpareMem_I(unsigned int requiredmem,unsigned int requiredcore);
+void * gcfindSpareMem_I(unsigned INTPTR requiredmem, unsigned INTPTR maxbytesneeded, unsigned int requiredcore);
#define INITMULTICOREGCDATA() initmulticoregcdata()
#define DISMULTICOREGCDATA() dismulticoregcdata()
int gc_countRunningCores() {
int count=0;
- for(int i = 0; i < NUMCORES4GC; ++i) {
- if(gccorestatus[i] != 0) {
+ for(int i = 0; i < NUMCORES4GC; i++) {
+ if(returnedmem[i]) {
count++;
}
}
return count;
}
-bool gc_checkCoreStatus() {
- for(int i = 0; i < NUMCORES4GC; ++i) {
- if(gccorestatus[i] != 0) {
- return false;
- }
- }
- return true;
-}
-
-void gc_resetCoreStatus() {
- for(int i = 0; i < NUMCORES4GC; ++i) {
- gccorestatus[i] = 1;
- }
-}
-
void initOrig_Dst(struct moveHelper * orig,struct moveHelper * to) {
// init the dst ptr
to->localblocknum = 0;
//set flag to wait for memory
gctomove=false;
//send request for memory
- send_msg_3(STARTUPCORE,GCFINISHCOMPACT,BAMBOO_NUM_OF_CORE, minimumbytes);
+ send_msg_4(STARTUPCORE,GCFINISHCOMPACT,BAMBOO_NUM_OF_CORE, minimumbytes, gccurr_heaptop);
//wait for flag to be set that we received message
while(!gctomove) ;
}
}
- send_msg_3(STARTUPCORE,GCFINISHCOMPACT,BAMBOO_NUM_OF_CORE, 0);
+ send_msg_4(STARTUPCORE,GCFINISHCOMPACT,BAMBOO_NUM_OF_CORE, 0, 0);
}
-void * checkNeighbors(int corenum, unsigned INTPTR requiredmem) {
+void * checkNeighbors_I(int corenum, unsigned INTPTR requiredmem, unsigned INTPTR desiredmem) {
int minblockindex=allocationinfo.lowestfreeblock/NUMCORES4GC;
+ unsigned INTPTR threshold=(desiredmem<MINMEMORYCHUNKSIZE)? desiredmem: MINMEMORYCHUNKSIZE;
+ unsigned INTPTR memcheck=requiredmem>threshold?requiredmem:threshold;
+
for(int i=0;i<NUM_CORES2TEST;i++) {
int neighborcore=core2test[corenum][i];
if (neighborcore!=-1) {
struct blockrecord * block=&allocationinfo.blocktable[globalblockindex];
if (block->status==BS_FREE) {
unsigned INTPTR freespace=block->freespace&~BAMBOO_CACHE_LINE_MASK;
- if (requiredmem<freespace) {
+ if (memcheck<=freespace) {
//we have a block
//mark block as used
block->status=BS_USED;
return NULL;
}
-void * globalSearch(unsigned int topblock, unsigned INTPTR requiredmem) {
+void * globalSearch_I(unsigned int topblock, unsigned INTPTR requiredmem, unsigned INTPTR desiredmem) {
unsigned int firstfree=NOFREEBLOCK;
+ unsigned INTPTR threshold=(desiredmem<MINMEMORYCHUNKSIZE)? desiredmem: MINMEMORYCHUNKSIZE;
+ unsigned INTPTR memcheck=requiredmem>threshold?requiredmem:threshold;
+
for(block_t i=allocationinfo.lowestfreeblock;i<topblock;i++) {
struct blockrecord * block=&allocationinfo.blocktable[i];
if (block->status==BS_FREE) {
if(firstfree==NOFREEBLOCK)
firstfree=i;
unsigned INTPTR freespace=block->freespace&~BAMBOO_CACHE_LINE_MASK;
- if (requiredmem<freespace) {
+ if (memcheck<=freespace) {
//we have a block
//mark block as used
block->status=BS_USED;
return NULL;
}
+void handleOneMemoryRequest(int core, unsigned int lowestblock) {
+ unsigned INTPTR requiredmem=gcrequiredmems[core];
+ unsigned INTPTR desiredmem=maxusefulmems[core];
+ block_t firstfree=NOFREEBLOCK;
+ unsigned INTPTR threshold=(desiredmem<MINMEMORYCHUNKSIZE)? desiredmem: MINMEMORYCHUNKSIZE;
+ unsigned INTPTR memcheck=requiredmem>threshold?requiredmem:threshold;
+
+ for(block_t searchblock=lowestblock;searchblock<GCNUMBLOCK;searchblock++) {
+ struct blockrecord * block=&allocationinfo.blocktable[searchblock];
+ if (block->status==BS_FREE) {
+ if(firstfree==NOFREEBLOCK)
+ firstfree=searchblock;
+ unsigned INTPTR freespace=block->freespace&~BAMBOO_CACHE_LINE_MASK;
+ if (freespace>=memcheck) {
+ //TODO: should check memory block at same level on our own core...if that works, use it to preserve locality
+
+ //we have a block
+ //mark block as used
+ block->status=BS_USED;
+ void *blockptr=OFFSET2BASEVA(searchblock)+gcbaseva;
+ unsigned INTPTR usedspace=((block->usedspace-1)&~BAMBOO_CACHE_LINE_MASK)+BAMBOO_CACHE_LINE_SIZE;
+ allocationinfo.lowestfreeblock=firstfree;
+ //taken care of one block
+ gcmovepending--;
+ void *startaddr=blockptr+usedspace;
+ if(BAMBOO_CHECK_SEND_MODE()) {
+ cache_msg_2_I(core,GCMOVESTART,startaddr);
+ } else {
+ send_msg_2_I(core,GCMOVESTART,startaddr);
+ }
+ return;
+ }
+ }
+ }
+ //this is bad...ran out of memory
+ BAMBOO_EXIT();
+}
+
+void handleMemoryRequests_I() {
+ unsigned int lowestblock=allocationinfo.lowestfreeblock;
+ if (lowestblock==NOFREEBLOCK) {
+ lowestblock=numblockspercore*NUMCORES4GC;
+ }
+
+ for(int i=0;i < NUMCORES4GC; i++) {
+ if (gcrequiredmems[i]) {
+ handleOneMemoryRequest(i, lowestblock);
+ lowestblock=allocationinfo.lowestfreeblock;
+ }
+ }
+}
+
/* should be invoked with interrupt turned off */
-void * gcfindSpareMem_I(unsigned INTPTR requiredmem,unsigned int requiredcore) {
+void * gcfindSpareMem_I(unsigned INTPTR requiredmem, unsigned INTPTR desiredmem,unsigned int requiredcore) {
if (allocationinfo.lowestfreeblock!=NOFREEBLOCK) {
//There are spare blocks
unsigned int topblock=numblockspercore*NUMCORES4GC;
void *memblock;
- if (memblock=checkNeighbors(requiredcore, requiredmem)) {
+ if (memblock=checkNeighbors_I(requiredcore, requiredmem, desiredmem)) {
return memblock;
- } else if (memblock=globalSearch(topblock, requiredmem)) {
+ } else if (memblock=globalSearch_I(topblock, requiredmem, desiredmem)) {
return memblock;
}
}
int count=gc_countRunningCores();
if (gcmovepending==count) {
// All cores have stopped...hand out memory as necessary to handle all requests
-
+ handleMemoryRequests_I();
}
return NULL;
}
-bool gcfindSpareMem(unsigned int requiredmem,unsigned int requiredcore) {
- BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
- bool retval=gcfindSpareMem_I(requiredmem, requiredcore);
- BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
- return retval;
-}
-
/* This function is performance critical... spend more time optimizing it */
unsigned int compactblocks(struct moveHelper * orig, struct moveHelper * to) {
void compact() {
BAMBOO_ASSERT(COMPACTPHASE == gc_status_info.gcphase);
- BAMBOO_CACHE_MF();
// initialize structs for compacting
struct moveHelper orig={0,NULL,NULL,0,NULL,0,0,0,0};
// init some data strutures for compact phase
gcrequiredmems[i] = 0;
gccorestatus[i] = 1;
+ returnedmem[i] = 1;
//send start compact messages to all cores
if(i != STARTUPCORE) {
send_msg_2(i, GCSTARTCOMPACT, numblockspercore);
gcblock2fill = numblockspercore;
}
}
- BAMBOO_CACHE_MF();
GCPROFILE_ITEM();
// compact phase
compact();
GCPROFILE_ITEM();
+ //just in case we didn't get blocks back...
+ if (allocationinfo.lowestfreeblock=NOFREEBLOCK)
+ allocationinfo.lowestfreeblock=numblockspercore*NUMCORES4GC;
+
GC_PRINTF("compact phase finished \n");
}
return mem;
}
-// 06/07/11 add a parameter minremain, it specifies the minimum number of
-// blocks to leave for each core for local allocation.
-INLINE void * searchBlock4Mem(int* tofindb,
- int* totest,
- int gccorenum,
- int isize,
- int * allocsize,
- int minremain) {
-
- return NULL;
-}
-
-INLINE void * searchBlock4Mem_global(int* tofindb,
- int* totest,
- int isize,
- int * allocsize) {
-
- return NULL;
-}
-
// Only allocate local mem chunks to each core.
// If a core has used up its local shared memory, start gc.
void * localmalloc_I(int coren,
int isize,
int * allocsize) {
- void * mem=NULL;
- int gccorenum=(coren<NUMCORES4GC)?(coren):(coren%NUMCORES4GC);
- int tofindb=gc_core2block[2*gccorenum];
- int totest=tofindb;
- mem=searchBlock4Mem(&tofindb,&totest,gccorenum,isize,allocsize,0);
- if(mem==NULL) {
- // no more local mem, do not find suitable block
- *allocsize=0;
- }
+ void * mem=globalmalloc_I(coren,isize,allocsize);
return mem;
}
-#define LOCALMEMRESERVATION 2
-
#ifdef SMEMF
// Allocate the local shared memory to each core with the highest priority,
// if a core has used up its local shared memory, try to allocate the
void * fixedmalloc_I(int coren,
int isize,
int * allocsize) {
- void * mem;
- int k;
- int gccorenum=(coren<NUMCORES4GC)?(coren):(coren%NUMCORES4GC);
- int totest,tofindb;
- int bound=BAMBOO_SMEM_SIZE_L;
- int foundsmem=0;
- int size=0;
- for(k=0;k<NUM_CORES2TEST;k++) {
- if(core2test[gccorenum][k]==-1) {
- // try next neighbour
- continue;
- }
- tofindb=totest=gc_core2block[2*core2test[gccorenum][k]];
- mem=searchBlock4Mem(&tofindb,&totest,core2test[gccorenum][k],isize,allocsize,(k==0)?0:((GCNUMBLOCK/NUMCORES4GC)>>LOCALMEMRESERVATION));
- if(mem!=NULL) {
- return mem;
- }
- }
- // no more memory available on either coren or its neighbour cores
- *allocsize=0;
- return NULL;
+ void * mem=globalmalloc_I(coren,isize,allocsize);
+ return mem;
}
#endif
void * mixedmalloc_I(int coren,
int isize,
int * allocsize) {
- void * mem;
- int k;
- int gccorenum=(coren<NUMCORES4GC)?(coren):(coren%NUMCORES4GC);
- int totest,tofindb;
- int size=0;
- for(k=0;k<NUM_CORES2TEST;k++) {
- if(core2test[gccorenum][k]==-1) {
- // try next neighbour
- continue;
- }
- tofindb=totest=gc_core2block[2*core2test[gccorenum][k]];
- mem=searchBlock4Mem(&tofindb,&totest,core2test[gccorenum][k],isize,allocsize,(k==0)?0:((GCNUMBLOCK/NUMCORES4GC)>>LOCALMEMRESERVATION));
- if(mem!=NULL) {
- return mem;
- }
- }
-
- // try allocate globally
- mem=globalmalloc_I(coren,isize,allocsize);
+ void * mem=globalmalloc_I(coren,isize,allocsize);
return mem;
}
#endif
// Allocate all the memory chunks globally, do not consider the host cores
// When all the shared memory are used up, start gc.
-void * globalmalloc_I(int coren,
- int isize,
- int * allocsize) {
+void * globalmalloc_I(int coren, unsigned INTPTR memcheck, int * allocsize) {
+ block_t firstfree=NOFREEBLOCK;
+ block_t lowestblock=allocationinfo.lowestfreeblock;
+ for(block_t searchblock=lowestblock;searchblock<GCNUMBLOCK;searchblock++) {
+ struct blockrecord * block=&allocationinfo.blocktable[searchblock];
+ if (block->status==BS_FREE) {
+ if(firstfree==NOFREEBLOCK)
+ firstfree=searchblock;
+ unsigned INTPTR freespace=block->freespace&~BAMBOO_CACHE_LINE_MASK;
+ if (freespace>=memcheck) {
+ //we have a block
+ //mark block as used
+ block->status=BS_USED;
+ void *blockptr=OFFSET2BASEVA(searchblock)+gcbaseva;
+ unsigned INTPTR usedspace=((block->usedspace-1)&~BAMBOO_CACHE_LINE_MASK)+BAMBOO_CACHE_LINE_SIZE;
+ allocationinfo.lowestfreeblock=firstfree;
+ void *startaddr=blockptr+usedspace;
+ *allocsize=freespace;
+ return startaddr;
+ }
+ }
+ }
return NULL;
}
if(mem == NULL) {
// no enough shared global memory
// trigger gc
- *allocsize = 0;
if(!gcflag) {
gcflag = true;
if(!gc_status_info.gcprocessing) {
4, //GCFINISHPRE, // 0xE7
2, //GCFINISHINIT, // 0xE8
4, //GCFINISHMARK, // 0xE9
- 3, //GCFINISHCOMPACT, // 0xEa
+ 4, //GCFINISHCOMPACT, // 0xEa
3, //GCRETURNMEM,
2, //GCFINISHUPDATE, // 0xEb
1, //GCFINISH, // 0xEc
MSG_INDEXINC_I();
// receive a shared memory request msg
BAMBOO_ASSERT(BAMBOO_NUM_OF_CORE == STARTUPCORE);
- int allocsize = 0;
- void * mem = NULL;
#ifdef MULTICORE_GC
if(!gc_status_info.gcprocessing || !gcflag) {
// either not doing GC or the master core has decided to stop GC but
// // still sending msgs to other cores to inform them to stop the GC
#endif
- mem = smemalloc_I(data2, data1, &allocsize);
+ int allocsize = 0;
+ void * mem = smemalloc_I(data2, data1, &allocsize);
if(mem != NULL) {
// send the start_va to request core, cache the msg first
if(BAMBOO_CHECK_SEND_MODE()) {
BLOCKINDEX(blockindex, heaptop);
unsigned INTPTR localblocknum=GLOBALBLOCK2LOCAL(blockindex);
+ //this core is done as far as memory usage is concerned
+ returnedmem[cnum]=0;
+
struct blockrecord * blockrecord=&allocationinfo.blocktable[blockindex];
blockrecord->status=BS_FREE;
MSG_INDEXINC_I();
unsigned int bytesneeded = msgdata[msgdataindex];
MSG_INDEXINC_I();
+ unsigned int maxbytesneeded = msgdata[msgdataindex];
+ MSG_INDEXINC_I();
if(bytesneeded > 0) {
// ask for more mem
- void * startaddr = gcfindSpareMem_I(bytesneeded, cnum);
+ void * startaddr = gcfindSpareMem_I(bytesneeded, maxbytesneeded, cnum);
if(startaddr) {
// cache the msg first
if(BAMBOO_CHECK_SEND_MODE()) {
} else {
send_msg_2_I(cnum,GCMOVESTART,startaddr);
}
+ } else {
+ maxusefulmems[cnum]=maxbytesneeded;
+ gcrequiredmems[cnum]=bytesneeded;
}
} else {
//done with compacting