#include "dmalloc.h"
#endif
#ifdef DSTM
-#include "dstm.h"
+#ifdef RECOVERY
+#include <DSTM/interface_recovery/dstm.h>
+#else
+#include <DSTM/interface/dstm.h>
+#endif
#endif
#ifdef STM
#include "tm.h"
#endif
+#ifdef DELAYCOMP
+#include "delaycomp.h"
+#endif
+
#define NUMPTRS 100
-#define INITIALHEAPSIZE 128*1024*1024
-#define GCPOINT(x) ((int)((x)*0.95))
+#define INITIALHEAPSIZE 128*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+y))*2
+#define HEAPSIZE(x,y) ((INTPTR)(x+y))*2
#ifdef TASK
extern struct genhashtable * activetasks;
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
if (orig>=curr_heapbase&&orig<curr_heaptop) { \
void *copy; \
if (gc_createcopy(orig,©)) \
- enqueue(orig);\
+ enqueue(copy);\
dst=copy; \
} \
}
if (orig>=curr_heapbase&&orig<curr_heaptop) { \
void *copy; \
if (gc_createcopy(orig,©)) \
- enqueue(orig);\
+ enqueue(copy);\
dst=copy; \
}
#define SENQUEUE(orig, dst) \
{ \
void *copy; \
if (gc_createcopy(orig,©)) \
- enqueue(orig);\
+ enqueue(copy);\
dst=copy; \
}
#elif defined(FASTCHECK)
if (((unsigned int)orig)!=1) { \
void *copy; \
if (gc_createcopy(orig,©)) \
- enqueue(orig);\
+ enqueue(copy);\
dst=copy; }
#else
#define ENQUEUE(orig, dst) \
void *copy; \
if (gc_createcopy(orig,©)) \
- enqueue(orig);\
+ enqueue(copy);\
dst=copy
#endif
}
}
-void fixtable(chashlistnode_t ** tc_table, unsigned int tc_size) {
- unsigned int mask=(tc_size<<3)-1;
+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;i<tc_size;i++) {
curr=&ptr[i];
isfirst=1;
//rewrite transaction cache entry
void *vptr=curr->val;
int type=((int *)vptr)[0];
- unsigned int *pointer=pointerarray[type];
+ 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 (((int)pointer)==1) {
+ } 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; i++) {
- void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
- SENQUEUE(objptr, ((void **)(((char *)&ao->___length___)+sizeof(int)))[i]);
+#ifdef STMARRAY
+ int lowindex=ao->lowindex;
+ int highindex=ao->highindex;
+ int j;
+ for(j=lowindex; j<=highindex; j++) {
+ unsigned int lockval;
+ GETLOCKVAL(lockval, ao, j);
+ if (lockval!=STMNONE) {
+ int lowi=(j<<INDEXSHIFT)/sizeof(void *);
+ int highi=lowi+(INDEXLENGTH/sizeof(void *));
+ for(i=lowi; i<highi;i++) {
+#else
+ for(i=0; i<length; i++) {
+#endif
+ void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
+ SENQUEUE(objptr, ((void **)(((char *)&ao->___length___)+sizeof(int)))[i]);
+ }
+#ifdef STMARRAY
+ }
}
+#endif
} 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)vptr)+offset));
- SENQUEUE(objptr, *((void **)(((int)vptr)+offset)));
+ void * objptr=*((void **)(((char *)vptr)+offset));
+ SENQUEUE(objptr, *((void **)(((char *)vptr)+offset)));
}
}
}
next = curr->next;
- index = (((unsigned int)key) & mask) >>3;
+ index = (((unsigned INTPTR)key) & mask) >>4;
- curr->key=(unsigned int)key;
+ curr->key=key;
tmp=&node[index];
// Insert into the new table
if(tmp->key == 0) {
tmp->key = curr->key;
tmp->val = curr->val;
- if (!isfirst) {
- free(curr);
- }
+ tmp->lnext=newlist;
+ newlist=tmp;
} else if (isfirst) {
- chashlistnode_t *newnode= calloc(1, sizeof(chashlistnode_t));
+ chashlistnode_t *newnode;
+ if ((*cstr)->num<NUMCLIST) {
+ newnode=&(*cstr)->array[(*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;
}
}
free(ptr);
(*tc_table)=node;
+ (*tc_list)=newlist;
}
#endif
}
#endif
-#ifdef STM
+#if defined(STM)||defined(THREADS)
__thread char * memorybase=NULL;
__thread char * memorytop=NULL;
#endif
pthread_cond_wait(&gccond, &gclistlock);
}
#endif
+#ifdef DELAYCOMP
+ ptrstack.prev=stackptr;
+ stackptr=(struct garbagelist *) &ptrstack;
+#if defined(STMARRAY)&&!defined(DUALVIEW)
+ arraystack.prev=stackptr;
+ stackptr=(struct garbagelist *) &arraystack;
+#endif
+#endif
+
+#ifdef GARBAGESTATS
+ {
+ int i;
+ for(i=0;i<MAXSTATS;i++)
+ garbagearray[i]=0;
+ }
+#endif
if (head==NULL) {
headindex=0;
#ifdef STM
if (c_table!=NULL) {
- fixtable(&c_table, c_size);
- fixobjlist(newobjs);
- memorybase=NULL;
+ fixtable(&c_table, &c_list, &c_structs, c_size);
+ fixobjlist(newobjs);
+#ifdef STMSTATS
+ fixobjlist(lockedobjs);
+#endif
}
#endif
+#if defined(STM)||defined(THREADS)
+ memorybase=NULL;
+#endif
/* Check current stack */
#if defined(THREADS)||defined(DSTM)||defined(STM)
}
#if defined(THREADS)||defined(DSTM)||defined(STM)
/* Go to next thread */
+#ifndef MAC
+ //skip over us
+ if (listptr==&litem) {
+ listptr=listptr->next;
+ }
+#else
+ {
+ struct listitem *litem=pthread_getspecific(litemkey);
+ if (listptr==litem) {
+ listptr=listptr->next;
+ }
+ }
+#endif
+
if (listptr!=NULL) {
#ifdef THREADS
void * orig=listptr->locklist;
#endif
#ifdef STM
if ((*listptr->tc_table)!=NULL) {
- fixtable(listptr->tc_table, listptr->tc_size);
+ fixtable(listptr->tc_table, listptr->tc_list, listptr->tc_structs, listptr->tc_size);
fixobjlist(listptr->objlist);
- (*listptr->base)=NULL;
+#ifdef STMSTATS
+ fixobjlist(listptr->lockedlist);
+#endif
}
+#endif
+#if defined(STM)||defined(THREADS)
+ *(listptr->base)=NULL;
#endif
stackptr=listptr->stackptr;
listptr=listptr->next;
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 */
struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
SENQUEUE((void *)ao->___objlocation___, *((void **)&ao_cpy->___objlocation___));
#endif
- } else if (((int)pointer)==1) {
+ } else if (((INTPTR)pointer)==1) {
/* Array of pointers */
struct ArrayObject *ao=(struct ArrayObject *) ptr;
struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
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)));
}
}
}
#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;
+#if defined(STMARRAY)&&!defined(DUALVIEW)
+ arraystack.prev=ptr;
+ ptr=(struct garbagelist *) &arraystack;
+#endif
+#endif
+#ifndef MAC
+ litem.stackptr=ptr;
+#ifdef THREADS
+ litem.locklist=pthread_getspecific(threadlocks);
+#endif
+#if defined(STM)||defined(THREADS)
+ litem.base=&memorybase;
+#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
+#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_table=&c_table;
- litem->objlist=newobjs;
- litem->base=&memorybase;
#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
-#ifdef STM
+#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||(memorybase+size)>memorytop) {
+ if (memorybase==NULL||size>(memorytop-memorybase)) {
int toallocate=(size>MEMORYBLOCK)?size:MEMORYBLOCK;
memorybase=helper(stackptr, toallocate);
memorytop=memorybase+toallocate;
#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=(size&~7)+8;
curr_heapptr+=size;
- if (curr_heapptr>curr_heapgcpoint) {
+ if (curr_heapptr>curr_heapgcpoint||curr_heapptr<curr_heapbase) {
if (curr_heapbase==0) {
/* Need to allocate base heap */
curr_heapbase=malloc(INITIALHEAPSIZE);
+ if (curr_heapbase==NULL) {
+ printf("malloc failed. Garbage collector couldn't get enough memory. Try changing heap size.\n");
+ exit(-1);
+ }
bzero(curr_heapbase, INITIALHEAPSIZE);
curr_heaptop=curr_heapbase+INITIALHEAPSIZE;
curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(INITIALHEAPSIZE);
curr_heapptr=curr_heapbase+size;
to_heapbase=malloc(INITIALHEAPSIZE);
+ if (to_heapbase==NULL) {
+ printf("malloc failed. Garbage collector couldn't get enough memory. Try changing heap size.\n");
+ exit(-1);
+ }
to_heaptop=to_heapbase+INITIALHEAPSIZE;
to_heapptr=to_heapbase;
ptr=curr_heapbase;
/* Grow the to heap if necessary */
{
- int curr_heapsize=curr_heaptop-curr_heapbase;
- int to_heapsize=to_heaptop-to_heapbase;
- int last_heapsize=0;
+ INTPTR curr_heapsize=curr_heaptop-curr_heapbase;
+ INTPTR to_heapsize=to_heaptop-to_heapbase;
+ INTPTR last_heapsize=0;
if (lastgcsize>0) {
last_heapsize=HEAPSIZE(lastgcsize, size);
if ((last_heapsize&7)!=0)
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<MAXSTATS;i++) {
+ if (garbagearray[i]!=0)
+ printf("Type=%d Size=%u\n", i, garbagearray[i]);
+ }
+ }
#endif
/* Flip to/curr heaps */
{
}
}
-
int gc_createcopy(void * orig, void ** copy_ptr) {
if (orig==0) {
*copy_ptr=NULL;
int size=classsize[type];
void *newobj=tomalloc(size);
memcpy(newobj, orig, size);
+#endif
+#ifdef GARBAGESTATS
+ garbagearray[type]+=size;
#endif
((int *)orig)[0]=-1;
((void **)orig)[1]=newobj;
int elementsize=classsize[type];
int length=ao->___length___;
#ifdef STM
+#ifdef STMARRAY
+ int basesize=length*elementsize;
+ basesize=(basesize+LOWMASK)&HIGHMASK;
+ int versionspace=sizeof(int)*2*(basesize>>INDEXSHIFT);
+ int size=sizeof(struct ArrayObject)+basesize+sizeof(objheader_t)+versionspace;
+ void *newobj=tomalloc(size);
+ memcpy(newobj, ((char*)orig)-sizeof(objheader_t)-versionspace, size);
+ newobj=((char *)newobj)+sizeof(objheader_t)+versionspace;
+#else
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);
+#endif
#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;