X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=Robust%2Fsrc%2FRuntime%2Fgarbage.c;h=e43dd3cb3e067e0f3cf025cc56530f096b4c3f8c;hb=81520bb20d5e1ceb2bb7037da6a4cb6a9c9eb033;hp=61e56d92d1840025f105ebb50674c3455d4d1c94;hpb=56b370883d5ff0ca5e7e6a7550a0633f9c02ab8e;p=IRC.git diff --git a/Robust/src/Runtime/garbage.c b/Robust/src/Runtime/garbage.c index 61e56d92..e43dd3cb 100644 --- a/Robust/src/Runtime/garbage.c +++ b/Robust/src/Runtime/garbage.c @@ -19,13 +19,17 @@ #ifdef STM #include "tm.h" #endif +#ifdef DELAYCOMP +#include "delaycomp.h" +#endif + #define NUMPTRS 100 -#define INITIALHEAPSIZE 32*1024*1024 -#define GCPOINT(x) ((int)((x)*0.9)) +#define INITIALHEAPSIZE 256*1024*1024L +#define GCPOINT(x) ((INTPTR)((x)*0.99)) /* This define takes in how full the heap is initially and returns a new heap size to use */ -#define HEAPSIZE(x,y) (((int)((x)/0.6))+y) +#define HEAPSIZE(x,y) ((INTPTR)(x+y))*2 #ifdef TASK extern struct genhashtable * activetasks; @@ -39,10 +43,18 @@ extern struct ctable *reverse; extern struct RuntimeHash *fdtoobject; #endif +#ifdef GARBAGESTATS +#define MAXSTATS 500 +long garbagearray[MAXSTATS]; +#endif + #if defined(THREADS) || defined(DSTM) || defined(STM) int needtocollect=0; struct listitem * list=NULL; int listcount=0; +#ifndef MAC +__thread struct listitem litem; +#endif #endif //Need to check if pointers are transaction pointers @@ -53,32 +65,37 @@ int listcount=0; if (orig>=curr_heapbase&&orig=curr_heapbase&&orig=curr_heapbase&&origptrs[tailindex++]; } +#ifdef STM +void fixobjlist(struct objlist * ptr) { + while(ptr!=NULL) { + int i; + for(i=0;ioffset;i++) { + SENQUEUE(ptr->objs[i], ptr->objs[i]); + } + ptr=ptr->next; + } +} + +void fixtable(chashlistnode_t ** tc_table, chashlistnode_t **tc_list, cliststruct_t **cstr, unsigned int tc_size) { + unsigned int mask=(tc_size<<4)-1; + chashlistnode_t *node=calloc(tc_size, sizeof(chashlistnode_t)); + chashlistnode_t *ptr=*tc_table; + chashlistnode_t *curr; + unsigned int i; + unsigned int index; + int isfirst; + chashlistnode_t *newlist=NULL; + for(i=0;ikey) == 0) { //Exit inner loop if there the first element is 0 + break; //key = val =0 for element if not present within the hash table + } + SENQUEUE(key, key); + if (curr->val>=curr_heapbase&&curr->valval, curr->val); + } else { + //rewrite transaction cache entry + void *vptr=curr->val; + int type=((int *)vptr)[0]; + unsigned INTPTR *pointer=pointerarray[type]; + if (pointer==0) { + //array of primitives - do nothing + struct ArrayObject *ao=(struct ArrayObject *) vptr; + SENQUEUE((void *)ao->___objlocation___, *((void **)&ao->___objlocation___)); + } else if (((INTPTR)pointer)==1) { + //array of pointers + struct ArrayObject *ao=(struct ArrayObject *) vptr; + int length=ao->___length___; + int i; + SENQUEUE((void *)ao->___objlocation___, *((void **)&ao->___objlocation___)); + for(i=0; i___length___)+sizeof(int)))[i]; + SENQUEUE(objptr, ((void **)(((char *)&ao->___length___)+sizeof(int)))[i]); + } + } else { + INTPTR size=pointer[0]; + int i; + for(i=1; i<=size; i++) { + unsigned int offset=pointer[i]; + void * objptr=*((void **)(((char *)vptr)+offset)); + SENQUEUE(objptr, *((void **)(((char *)vptr)+offset))); + } + } + } + + next = curr->next; + index = (((unsigned INTPTR)key) & mask) >>4; + + curr->key=key; + tmp=&node[index]; + // Insert into the new table + if(tmp->key == 0) { + tmp->key = curr->key; + tmp->val = curr->val; + tmp->lnext=newlist; + newlist=tmp; + } else if (isfirst) { + chashlistnode_t *newnode; + if ((*cstr)->numarray[(*cstr)->num]; + (*cstr)->num++; + } else { + //get new list + cliststruct_t *tcl=calloc(1,sizeof(cliststruct_t)); + tcl->next=*cstr; + *cstr=tcl; + newnode=&tcl->array[0]; + tcl->num=1; + } + newnode->key = curr->key; + newnode->val = curr->val; + newnode->next = tmp->next; + newnode->lnext=newlist; + newlist=newnode; + tmp->next=newnode; + } else { + curr->lnext=newlist; + newlist=curr; + curr->next=tmp->next; + tmp->next=curr; + } + isfirst = 0; + curr = next; + } while(curr!=NULL); + } + free(ptr); + (*tc_table)=node; + (*tc_list)=newlist; +} +#endif + int moreItems() { if ((head==tail)&&(tailindex==headindex)) return 0; @@ -152,6 +278,11 @@ void enqueuetag(struct ___TagDescriptor___ *ptr) { } #endif +#if defined(STM)||defined(THREADS) +__thread char * memorybase=NULL; +__thread char * memorytop=NULL; +#endif + void collect(struct garbagelist * stackptr) { #if defined(THREADS)||defined(DSTM)||defined(STM) @@ -164,6 +295,18 @@ void collect(struct garbagelist * stackptr) { pthread_cond_wait(&gccond, &gclistlock); } #endif +#ifdef DELAYCOMP + ptrstack.prev=stackptr; + stackptr=(struct garbagelist *) &ptrstack; +#endif + +#ifdef GARBAGESTATS + { + int i; + for(i=0;inext; + } +#else + { + struct listitem *litem=pthread_getspecific(litemkey); + if (listptr==litem) { + listptr=listptr->next; + } + } +#endif + if (listptr!=NULL) { #ifdef THREADS void * orig=listptr->locklist; ENQUEUE(orig, listptr->locklist); +#endif +#ifdef STM + if ((*listptr->tc_table)!=NULL) { + fixtable(listptr->tc_table, listptr->tc_list, listptr->tc_structs, listptr->tc_size); + fixobjlist(listptr->objlist); +#ifdef STMSTATS + fixobjlist(listptr->lockedlist); +#endif + } + *(listptr->base)=NULL; #endif stackptr=listptr->stackptr; listptr=listptr->next; @@ -308,9 +486,9 @@ void collect(struct garbagelist * stackptr) { while(moreItems()) { void * ptr=dequeue(); - void *cpy=((void **)ptr)[1]; + void *cpy=ptr; int type=((int *)cpy)[0]; - unsigned int * pointer; + unsigned INTPTR * pointer; #ifdef TASK if(type==TAGTYPE) { /* Enqueue Tag */ @@ -329,13 +507,21 @@ void collect(struct garbagelist * stackptr) { ENQUEUE((void *)ao->___nextobject___, *((void **)&ao_cpy->___nextobject___)); ENQUEUE((void *)ao->___localcopy___, *((void **)&ao_cpy->___localcopy___)); #endif - } else if (((int)pointer)==1) { +#if defined(STM) + struct ArrayObject *ao=(struct ArrayObject *) ptr; + struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy; + SENQUEUE((void *)ao->___objlocation___, *((void **)&ao_cpy->___objlocation___)); +#endif + } else if (((INTPTR)pointer)==1) { /* Array of pointers */ struct ArrayObject *ao=(struct ArrayObject *) ptr; struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy; #if (defined(DSTM)||defined(FASTCHECK)) ENQUEUE((void *)ao->___nextobject___, *((void **)&ao_cpy->___nextobject___)); ENQUEUE((void *)ao->___localcopy___, *((void **)&ao_cpy->___localcopy___)); +#endif +#if defined(STM) + SENQUEUE((void *)ao->___objlocation___, *((void **)&ao_cpy->___objlocation___)); #endif int length=ao->___length___; int i; @@ -344,12 +530,12 @@ void collect(struct garbagelist * stackptr) { ENQUEUE(objptr, ((void **)(((char *)&ao_cpy->___length___)+sizeof(int)))[i]); } } else { - int size=pointer[0]; + INTPTR size=pointer[0]; int i; for(i=1; i<=size; i++) { unsigned int offset=pointer[i]; - void * objptr=*((void **)(((int)ptr)+offset)); - ENQUEUE(objptr, *((void **)(((int)cpy)+offset))); + void * objptr=*((void **)(((char *)ptr)+offset)); + ENQUEUE(objptr, *((void **)(((char *)cpy)+offset))); } } } @@ -357,7 +543,7 @@ void collect(struct garbagelist * stackptr) { fixtags(); #endif -#if defined(THREADS)||defined(DSTM) +#if defined(THREADS)||defined(DSTM)||defined(STM) needtocollect=0; pthread_mutex_unlock(&gclistlock); #endif @@ -433,89 +619,118 @@ void * tomalloc(int size) { #if defined(THREADS)||defined(DSTM)||defined(STM) void checkcollect(void * ptr) { - struct listitem * tmp=stopforgc((struct garbagelist *)ptr); - pthread_mutex_lock(&gclock); // Wait for GC - restartaftergc(tmp); - pthread_mutex_unlock(&gclock); + stopforgc((struct garbagelist *)ptr); + restartaftergc(); } #ifdef DSTM void checkcollect2(void * ptr) { int ptrarray[]={1, (int)ptr, (int) revertlist}; - struct listitem * tmp=stopforgc((struct garbagelist *)ptrarray); - pthread_mutex_lock(&gclock); // Wait for GC - restartaftergc(tmp); - pthread_mutex_unlock(&gclock); + stopforgc((struct garbagelist *)ptrarray); + restartaftergc(); revertlist=(struct ___Object___*)ptrarray[2]; } #endif - -struct listitem * stopforgc(struct garbagelist * ptr) { - struct listitem * litem=malloc(sizeof(struct listitem)); +void stopforgc(struct garbagelist * ptr) { +#ifdef DELAYCOMP + //just append us to the list + ptrstack.prev=ptr; + ptr=(struct garbagelist *) &ptrstack; +#endif +#ifndef MAC + litem.stackptr=ptr; +#ifdef THREADS + litem.locklist=pthread_getspecific(threadlocks); +#endif +#ifdef STM + litem.tc_size=c_size; + litem.tc_table=&c_table; + litem.tc_list=&c_list; + litem.tc_structs=&c_structs; + litem.objlist=newobjs; +#ifdef STMSTATS + litem.lockedlist=lockedobjs; +#endif + litem.base=&memorybase; +#endif +#else + //handle MAC + struct listitem *litem=pthread_getspecific(litemkey); litem->stackptr=ptr; #ifdef THREADS litem->locklist=pthread_getspecific(threadlocks); #endif -#ifdef STM - litem->tc_size=c_size; - litem->tc_mask=c_mask; - litem->tc_table=&c_table; #endif - litem->prev=NULL; pthread_mutex_lock(&gclistlock); - litem->next=list; - if(list!=NULL) - list->prev=litem; - list=litem; listcount++; - pthread_cond_signal(&gccond); + if ((listcount+1)==threadcount) { + //only do wakeup if we are ready to GC + pthread_cond_signal(&gccond); + } pthread_mutex_unlock(&gclistlock); - return litem; } -void restartaftergc(struct listitem * litem) { - pthread_mutex_lock(&gclistlock); -#ifdef THREADS - pthread_setspecific(threadlocks, litem->locklist); -#endif - if (litem->prev==NULL) { - list=litem->next; - } else { - litem->prev->next=litem->next; - } - if (litem->next!=NULL) { - litem->next->prev=litem->prev; +void restartaftergc() { + if (needtocollect) { + pthread_mutex_lock(&gclock); // Wait for GC + pthread_mutex_unlock(&gclock); } + pthread_mutex_lock(&gclistlock); listcount--; pthread_mutex_unlock(&gclistlock); - free(litem); } #endif +#if defined(STM)||defined(THREADS) +#define MEMORYBLOCK 65536 +void * helper(struct garbagelist *, int); +void * mygcmalloc(struct garbagelist * stackptr, int size) { + if ((size&7)!=0) + size=(size&~7)+8; + if (memorybase==NULL||size>(memorytop-memorybase)) { + int toallocate=(size>MEMORYBLOCK)?size:MEMORYBLOCK; + memorybase=helper(stackptr, toallocate); + memorytop=memorybase+toallocate; + } + char *retvalue=memorybase; + memorybase+=size; + return retvalue; +} + +void * helper(struct garbagelist * stackptr, int size) { +#else void * mygcmalloc(struct garbagelist * stackptr, int size) { +#endif void *ptr; #if defined(THREADS)||defined(DSTM)||defined(STM) - if (pthread_mutex_trylock(&gclock)!=0) { - struct listitem *tmp=stopforgc(stackptr); - pthread_mutex_lock(&gclock); - restartaftergc(tmp); + while (pthread_mutex_trylock(&gclock)!=0) { + stopforgc(stackptr); + restartaftergc(); } #endif ptr=curr_heapptr; if ((size&7)!=0) - size+=(8-(size%8)); + size=(size&~7)+8; curr_heapptr+=size; - if (curr_heapptr>curr_heapgcpoint) { + if (curr_heapptr>curr_heapgcpoint||curr_heapptr0) { last_heapsize=HEAPSIZE(lastgcsize, size); if ((last_heapsize&7)!=0) @@ -555,6 +770,18 @@ void * mygcmalloc(struct garbagelist * stackptr, int size) { /* Update stat on previous gc size */ lastgcsize=(to_heapptr-to_heapbase)+size; +#ifdef GARBAGESTATS + printf("Garbage collected: Old bytes: %u\n", curr_heapptr-curr_heapbase); + printf("New space: %u\n", to_heapptr-to_heapbase); + printf("Total space: %u\n", to_heaptop-to_heapbase); + { + int i; + for(i=0;i___length___; +#ifdef STM + int size=sizeof(struct ArrayObject)+length*elementsize+sizeof(objheader_t); + void *newobj=tomalloc(size); + memcpy(newobj, ((char*)orig)-sizeof(objheader_t), size); + newobj=((char *)newobj)+sizeof(objheader_t); +#else int size=sizeof(struct ArrayObject)+length*elementsize; void *newobj=tomalloc(size); memcpy(newobj, orig, size); +#endif +#ifdef GARBAGESTATS + garbagearray[type]+=size; +#endif ((int *)orig)[0]=-1; ((void **)orig)[1]=newobj; *copy_ptr=newobj;