#include "Queue.h"
#include "SimpleHash.h"
+#define GC_DEBUG 1
// data structures for shared memory allocation
#ifdef TILERA_BME
#ifdef MGC
1, //TERMINATE, // 0xDf
3, //MEMREQUEST, // 0xE0
3, //MEMRESPONSE, // 0xE1
-#ifdef MULTICORE_GC
+#if defined(MULTICORE_GC)||defined(PMC_GC)
1, //GCINVOKE
1, //GCSTARTPRE, // 0xE2
+#endif
+#ifdef MULTICORE_GC
1, //GCSTARTINIT, // 0xE3
1, //GCSTART, // 0xE4
2, //GCSTARTCOMPACT, // 0xE5
#endif //ifndef PMCGC
-#ifdef MULTICORE_GC
+#if defined(MULTICORE_GC)||defined(PMC_GC)
void processmsg_gcinvoke_I() {
BAMBOO_ASSERT(BAMBOO_NUM_OF_CORE==STARTUPCORE);
+#ifdef MULTICORE_GC
if(!gc_status_info.gcprocessing && !gcflag) {
gcflag = true;
gcprecheck = true;
gcnumsendobjs[0][i] = 0;
gcnumreceiveobjs[0][i] = 0;
}
+#endif
+#ifdef PMC_GC
+ if(!gcflag) {
+ gcflag = true;
+#endif
for(int i = 0; i < NUMCORES4GC; i++) {
if(i != STARTUPCORE) {
if(BAMBOO_CHECK_SEND_MODE()) {
// the first time to be informed to start gc
gcflag = true;
}
-
+#endif
+#ifdef MULTICORE_GC
void processmsg_gcstartinit_I() {
gc_status_info.gcphase = INITPHASE;
}
break;
}
#endif
-#ifdef MULTICORE_GC
+#if defined(MULTICORE_GC)||defined(PMC_GC)
// GC msgs
case GCINVOKE: {
processmsg_gcinvoke_I();
processmsg_gcstartpre_I();
break;
}
-
+#endif
+#ifdef MULTICORE_GC
case GCSTARTINIT: {
processmsg_gcstartinit_I();
break;
TERMINATE, // 0xDf
MEMREQUEST, // 0xE0
MEMRESPONSE, // 0xE1
-#ifdef MULTICORE_GC
+#if defined(MULTICORE_GC)||defined(PMC_GC)
GCINVOKE, // 0xE2
GCSTARTPRE, // 0xE3
+#endif
+#ifdef MULTICORE_GC
GCSTARTINIT, // 0xE4
GCSTART, // 0xE5
GCSTARTCOMPACT, // 0xE6
// initialize runtime data structures
initruntimedata();
initCommunication();
+#ifdef PMC_GC
+ pmc_onceInit();
+#endif
if (BAMBOO_NUM_OF_CORE==STARTUPCORE) {
numconfirm=NUMCORES-1;
for(int i=0;i<NUMCORES;i++) {
//Comment: should build dummy byte arrays to allow skipping data...
void pmc_countbytes(struct pmc_unit * unit, void *bottomptr, void *topptr) {
+ tprintf("%x--%x\n",bottomptr, topptr);
void *tmpptr=bottomptr;
unsigned int totalbytes=0;
while(tmpptr<topptr) {
if (startregion==-1)
return;
if (endregion==-1)
- endregion=NUMPMCUNITS;
+ endregion=NUMPMCUNITS-1;
region->lowunit=startregion;
region->highunit=endregion;
region->startptr=(startregion==0)?gcbaseva:pmc_heapptr->units[startregion-1].endptr;
}
}
- while(tmpptr>topptr) {
+ while(tmpptr<topptr) {
unsigned int type;
unsigned int size;
gettype_size(tmpptr, &type, &size);
}
void * pmc_unitend(unsigned int index) {
- return gcbaseva+(index+1)*NUMPMCUNITS;
+ return gcbaseva+(index+1)*UNITSIZE;
}
void pmc_onceInit() {
pmc_localqueue=&pmc_heapptr->regions[BAMBOO_NUM_OF_CORE].markqueue;
pmc_queueinit(pmc_localqueue);
- tmc_spin_barrier_init(&pmc_heapptr->barrier, NUMCORES4GC);
- for(int i=0;i<NUMPMCUNITS;i++) {
- pmc_heapptr->units[i].endptr=pmc_unitend(i);
+ if (BAMBOO_NUM_OF_CORE==STARTUPCORE) {
+ tmc_spin_barrier_init(&pmc_heapptr->barrier, NUMCORES4GC);
+ for(int i=0;i<NUMPMCUNITS;i++) {
+ pmc_heapptr->units[i].endptr=pmc_unitend(i);
+ tprintf("%u endptr=%x\n", i, pmc_heapptr->units[i].endptr);
+ }
+
+ for(int i=0;i<NUMCORES4GC;i+=2) {
+ if (i==0) {
+ pmc_heapptr->regions[i].lastptr=gcbaseva;
+ } else
+ pmc_heapptr->regions[i].lastptr=pmc_heapptr->units[i*4-1].endptr;
+ pmc_heapptr->regions[i].lowunit=4*i;
+ pmc_heapptr->regions[i].highunit=4*i+3;
+ pmc_heapptr->regions[i+1].lastptr=pmc_heapptr->units[(i+1)*4+3].endptr;
+ pmc_heapptr->regions[i+1].lowunit=4*(i+1);
+ pmc_heapptr->regions[i+1].highunit=4*(i+1)+3;
+ }
+ for(int i=0;i<NUMCORES4GC;i++) {
+ tprintf("%u lastptr=%x\n", i, pmc_heapptr->regions[i].lastptr);
+ }
}
}
void pmc_init() {
if (BAMBOO_NUM_OF_CORE==STARTUPCORE) {
pmc_heapptr->numthreads=NUMCORES4GC;
+ for(int i=0;i<NUMCORES4GC;i+=2) {
+ void *startptr=pmc_heapptr->regions[i].lastptr;
+ void *finishptr=pmc_heapptr->regions[i+1].lastptr;
+ struct pmc_region *region=&pmc_heapptr->regions[i];
+ unsigned int startindex=region->lowunit;
+ unsigned int endindex=pmc_heapptr->regions[i+1].highunit;
+ tprintf("Padding %x-%x\n",startptr, finishptr);
+
+ for(unsigned int index=startindex;index<endindex;index++) {
+ void *ptr=pmc_unitend(index);
+ if ((ptr>startptr)&&(ptr<=finishptr)) {
+ pmc_heapptr->units[index].endptr=ptr;
+ padspace(startptr, (unsigned int)(ptr-startptr));
+ startptr=ptr;
+ }
+ if (ptr>finishptr)
+ break;
+ }
+ }
+ }
+ if (bamboo_smem_size) {
+ tprintf("Padding %u bytes at %x\n", bamboo_smem_size, bamboo_cur_msp);
+ padspace(bamboo_cur_msp, bamboo_smem_size);
}
tmc_spin_barrier_wait(&pmc_heapptr->barrier);
}
void gc(struct garbagelist *gl) {
+ tprintf("%x\n", pmc_heapptr);
tprintf("init\n");
pmc_init();
//mark live objects
tprintf("mark\n");
pmc_mark(gl);
//count live objects per unit
+ tmc_spin_barrier_wait(&pmc_heapptr->barrier);
tprintf("count\n");
pmc_count();
tmc_spin_barrier_wait(&pmc_heapptr->barrier);
//compact data
tprintf("compact\n");
pmc_docompact();
- tmc_spin_barrier_wait(&pmc_heapptr->barrier);
+ //reset memory allocation
+ bamboo_cur_msp=NULL;
+ bamboo_smem_size=0;
+
+ if (BAMBOO_NUM_OF_CORE==STARTUPCORE) {
+ tmc_spin_barrier_wait(&pmc_heapptr->barrier);
+ //people will resend...no need to get gcflag so quickly
+ gcflag=false;
+ } else {
+ //start to listen for gcflags before we exit
+ gcflag=false;
+ tmc_spin_barrier_wait(&pmc_heapptr->barrier);
+ }
+}
+
+void padspace(void *ptr, unsigned int length) {
+ //zero small blocks
+ if (length<sizeof(struct ArrayObject)) {
+ BAMBOO_MEMSET_WH(ptr,0,length);
+ } else {
+ //generate fake arrays for big blocks
+ struct ArrayObject *ao=(struct ArrayObject *)ptr;
+ ao->type=CHARARRAYTYPE;
+ unsigned arraylength=length-sizeof(struct ArrayObject);
+ ao->___length___=arraylength;
+ }
}
void gettype_size(void * ptr, int * ttype, unsigned int * tsize) {
#include "pmc_queue.h"
#include "structdefs.h"
-#define PMC_MINALLOC 131072
+//#define PMC_MINALLOC 131072
+#define PMC_MINALLOC 2048
#define NUMPMCUNITS (4*NUMCORES4GC)
#define UNITSIZE (BAMBOO_SHARED_MEM_SIZE/NUMPMCUNITS)
extern struct pmc_heap * pmc_heapptr;
extern struct pmc_queue * pmc_localqueue;
+void padspace(void *ptr, unsigned int length);
void * pmc_unitend(unsigned int index);
void incrementthreads();
void decrementthreads();
#include <stdlib.h>
+#include "multicoregc.h"
+#include "multicoreruntime.h"
#include "pmc_garbage.h"
#include "pmc_mem.h"
+#include "runtime_arch.h"
+#include "multicoremsg.h"
void * pmc_alloc(unsigned int * numbytesallocated, unsigned int minimumbytes) {
unsigned int memcheck=minimumbytes>PMC_MINALLOC?minimumbytes:PMC_MINALLOC;
tmc_spin_mutex_unlock(®ion->lock);
}
}
+ if (BAMBOO_NUM_OF_CORE==STARTUPCORE) {
+ BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
+ if (!gcflag) {
+ gcflag = true;
+ for(int i=0;i<NUMCORESACTIVE;i++) {
+ if (i!=STARTUPCORE)
+ send_msg_1(i, GCSTARTPRE);
+ }
+ }
+ BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
+ } else {
+ send_msg_1_I(STARTUPCORE,GCINVOKE);
+ }
return NULL;
}
#include <stdlib.h>
#include "pmc_queue.h"
#include "mem.h"
+#include "runtime_arch.h"
void pmc_queueinit(struct pmc_queue *queue) {
- queue->head=queue->tail=RUNMALLOC(sizeof(struct pmc_queue_segment));
queue->headindex=queue->tailindex=0;
}
void * pmc_dequeue(struct pmc_queue *queue) {
void *value=NULL;
tmc_spin_mutex_lock(&queue->lock);
- //do-while loop allows sharing cleanup code
- do {
+
+ if (queue->tailindex!=queue->headindex) {
+ value=queue->objects[queue->tailindex];
+ queue->tailindex++;
//check for possible rollover
if (queue->tailindex==NUM_PMC_QUEUE_OBJECTS) {
- if (queue->tail!=queue->head) {
- struct pmc_queue_segment *oldtail=queue->tail;
- queue->tail=oldtail->next;
- queue->tailindex=0;
- RUNFREE(oldtail);
- } else break;
- }
- //now try to decrement
- if (queue->tailindex!=queue->headindex) {
- value=queue->tail->objects[queue->tailindex];
- queue->tailindex++;
+ queue->tailindex=0;
}
- } while(false);
+ }
+
tmc_spin_mutex_unlock(&queue->lock);
return value;
}
void pmc_enqueue(struct pmc_queue* queue, void *ptr) {
- if (queue->headindex<NUM_PMC_QUEUE_OBJECTS) {
- queue->head->objects[queue->headindex]=ptr;
- //need fence to prevent reordering
- __insn_mf();
- queue->headindex++;
- return;
- } else {
- struct pmc_queue_segment * seg=RUNMALLOC(sizeof(struct pmc_queue_segment));
- seg->objects[0]=ptr;
- //simplify everything by grabbing a lock on segment change
- tmc_spin_mutex_lock(&queue->lock);
- queue->headindex=1;
- queue->head->next=seg;
- queue->head=seg;
- tmc_spin_mutex_unlock(&queue->lock);
+ unsigned int currindex=queue->headindex;
+ queue->objects[currindex]=ptr;
+ //need fence to prevent reordering
+ __insn_mf();
+
+ currindex++;
+ if (currindex==NUM_PMC_QUEUE_OBJECTS)
+ currindex=0;
+
+ if (currindex==queue->tailindex) {
+ tprintf("queue full event...\n");
+ BAMBOO_EXIT();
}
+
+ queue->headindex=currindex;
}
bool pmc_isEmpty(struct pmc_queue *queue) {
tmc_spin_mutex_lock(&queue->lock);
- bool status=(queue->head==queue->tail)&&(queue->headindex==queue->tailindex);
+ bool status=(queue->headindex==queue->tailindex);
tmc_spin_mutex_unlock(&queue->lock);
return status;
}
#include "multicore.h"
#include <tmc/spin.h>
-#define NUM_PMC_QUEUE_OBJECTS 256
-struct pmc_queue_segment {
- volatile void * objects[NUM_PMC_QUEUE_OBJECTS];
- struct pmc_queue_segment * next;
-};
+#define NUM_PMC_QUEUE_OBJECTS 4096
struct pmc_queue {
- volatile struct pmc_queue_segment *head;
- volatile struct pmc_queue_segment *tail;
+ volatile void * objects[NUM_PMC_QUEUE_OBJECTS];
volatile int headindex;
volatile int tailindex;
tmc_spin_mutex_t lock;
#define pmcupdateObj(objptr) ((void *)((struct ___Object___ *)objptr)->marked)
-#define PMCUPDATEOBJ(obj) {void *updatetmpptr=obj; if (updatetmpptr!=NULL) {obj=pmcupdateObj(updatetmpptr);}}
+#define PMCUPDATEOBJ(obj) {void *updatetmpptr=obj; tprintf("UP%x\n", updatetmpptr); if (updatetmpptr!=NULL) {obj=pmcupdateObj(updatetmpptr);}}
#define PMCUPDATEOBJNONNULL(obj) {void *updatetmpptr=obj; obj=pmcupdateObj(updatetmpptr);}
void pmc_referenceupdate(void *bottomptr, void *topptr) {
void *tmpptr=bottomptr;
+ tprintf("%x -- %x\n", bottomptr, topptr);
while(tmpptr<topptr) {
unsigned int type;
unsigned int size;
gettype_size(tmpptr, &type, &size);
+ size=((size-1)&(~(ALIGNMENTSIZE-1)))+ALIGNMENTSIZE;
+ tprintf("%x typ=%u sz=%u\n", tmpptr, type, size);
if (!type) {
tmpptr+=ALIGNMENTSIZE;
continue;
pmc_updatePtrs(tmpptr, type);
}
tmpptr+=size;
+ tprintf("INC\n");
}
}
unsigned int type;
unsigned int size;
gettype_size(tmpptr, &type, &size);
+ size=((size-1)&(~(ALIGNMENTSIZE-1)))+ALIGNMENTSIZE;
if (!type) {
tmpptr+=ALIGNMENTSIZE;
continue;
unsigned int type;
unsigned int size;
gettype_size(lastobj, &type, &size);
+ size=((size-1)&(~(ALIGNMENTSIZE-1)))+ALIGNMENTSIZE;
void *forwardptr=(void *)((struct ___Object___ *) lastobj)->marked;
((struct ___Object___ *) lastobj)->marked=NULL;
if (forwardptr) {
int hasgc = 0;
int loopcount = 0;
- while(loopcount<10000) {
+ while(true) {
p = BAMBOO_SHARE_MEM_CALLOC(isize); // calloc(m, isize);
if(p != NULL)
printf("Did %u collections without getting memory\n", hasgc);
BAMBOO_EXIT();
}
+ loopcount++;
+ if (loopcount>10000000)
+ tprintf("Loopcount in mycalloc_share hit %u\n",loopcount);
}
- tprintf("Loopcount hit 10000\n");
+
BAMBOO_EXIT();
return NULL;
}