#include "SimpleHash.h"
#include "GenericHashtable.h"
#include <string.h>
-#ifdef THREADS
+#if defined(THREADS) || defined(DSTM)
#include "thread.h"
#endif
+
#ifdef DMALLOC
#include "dmalloc.h"
#endif
-
+#ifdef DSTM
+#include "dstm.h"
+#endif
#define NUMPTRS 100
#define HEAPSIZE(x,y) (((int)((x)/0.6))+y)
#ifdef TASK
-extern struct Queue * activetasks;
+extern struct genhashtable * activetasks;
+#ifndef MULTICORE
extern struct parameterwrapper * objectqueues[NUMCLASSES];
+#endif
extern struct genhashtable * failedtasks;
+extern struct taskparamdescriptor *currtpd;
extern struct RuntimeHash *forward;
extern struct RuntimeHash *reverse;
extern struct RuntimeHash *fdtoobject;
#endif
-#ifdef THREADS
+#if defined(THREADS) || defined(DSTM)
int needtocollect=0;
struct listitem * list=NULL;
int listcount=0;
#endif
+//Need to check if pointers are transaction pointers
+#ifdef DSTM
+#define ENQUEUE(orig, dst) \
+if ((!(((unsigned int)orig)&0x1))) {\
+if (orig>=curr_heapbase&&orig<curr_heaptop) {\
+void *copy;\
+if (gc_createcopy(orig,©))\
+enqueue(orig);\
+dst=copy;\
+}\
+}
+#else
+#define ENQUEUE(orig, dst) \
+void *copy; \
+if (gc_createcopy(orig,©))\
+enqueue(orig);\
+dst=copy
+#endif
+
struct pointerblock {
void * ptrs[NUMPTRS];
struct pointerblock *next;
};
+void * curr_heapbase=0;
+void * curr_heapptr=0;
+void * curr_heapgcpoint=0;
+void * curr_heaptop=0;
+
+void * to_heapbase=0;
+void * to_heapptr=0;
+void * to_heaptop=0;
+long lastgcsize=0;
+
struct pointerblock *head=NULL;
int headindex=0;
struct pointerblock *tail=NULL;
return 1;
}
+#ifdef TASK
+struct pointerblock *taghead=NULL;
+int tagindex=0;
+
+void enqueuetag(struct ___TagDescriptor___ *ptr) {
+ if (tagindex==NUMPTRS) {
+ struct pointerblock * tmp=malloc(sizeof(struct pointerblock));
+ tmp->next=taghead;
+ taghead=tmp;
+ tagindex=0;
+ }
+ taghead->ptrs[tagindex++]=ptr;
+}
+#endif
+
+
void collect(struct garbagelist * stackptr) {
-#ifdef THREADS
+#if defined(THREADS)||defined(DSTM)
needtocollect=1;
pthread_mutex_lock(&gclistlock);
while(1) {
tailindex=0;
head=tail=malloc(sizeof(struct pointerblock));
}
+
+#ifdef TASK
+ if (taghead==NULL) {
+ tagindex=0;
+ taghead=malloc(sizeof(struct pointerblock));
+ taghead->next=NULL;
+ }
+#endif
+
/* Check current stack */
-#ifdef THREADS
+#if defined(THREADS)||defined(DSTM)
{
struct listitem *listptr=list;
- while(stackptr!=NULL) {
+ while(1) {
#endif
while(stackptr!=NULL) {
int i;
for(i=0;i<stackptr->size;i++) {
void * orig=stackptr->array[i];
- void * copy;
- if (gc_createcopy(orig,©))
- enqueue(orig);
- stackptr->array[i]=copy;
+ ENQUEUE(orig, stackptr->array[i]);
}
stackptr=stackptr->next;
}
-#ifdef THREADS
+#if defined(THREADS)||defined(DSTM)
/* Go to next thread */
if (listptr!=NULL) {
void * orig=listptr->locklist;
- void * copy;
- if (gc_createcopy(orig,©))
- enqueue(orig);
- listptr->locklist=copy;
+ ENQUEUE(orig, listptr->locklist);
stackptr=listptr->stackptr;
listptr=listptr->next;
- }
+ } else
+ break;
}
}
#endif
/* Update objectsets */
int i;
for(i=0;i<NUMCLASSES;i++) {
+#ifdef MULTICORE
+#else
struct parameterwrapper * p=objectqueues[i];
while(p!=NULL) {
- struct RuntimeHash * set=p->objectset;
- struct RuntimeNode * ptr=set->listhead;
+ struct ObjectHash * set=p->objectset;
+ struct ObjectNode * ptr=set->listhead;
while(ptr!=NULL) {
void *orig=(void *)ptr->key;
- void *copy;
- if (gc_createcopy(orig, ©))
- enqueue(orig);
- ptr->key=(int)copy;
-
+ ENQUEUE(orig, *((void **)(&ptr->key)));
ptr=ptr->lnext;
}
- RuntimeHashrehash(set); /* Rehash the table */
+ ObjectHashrehash(set); /* Rehash the table */
p=p->next;
}
+#endif
}
}
struct RuntimeNode * ptr=forward->listhead;
while(ptr!=NULL) {
void * orig=(void *)ptr->key;
- void *copy;
- if (gc_createcopy(orig, ©))
- enqueue(orig);
- ptr->key=(int)copy;
-
+ ENQUEUE(orig, *((void **)(&ptr->key)));
ptr=ptr->lnext;
}
RuntimeHashrehash(forward); /* Rehash the table */
struct RuntimeNode * ptr=reverse->listhead;
while(ptr!=NULL) {
void *orig=(void *)ptr->data;
- void *copy;
- if (gc_createcopy(orig, ©))
- enqueue(orig);
- ptr->data=(int)copy;
-
+ ENQUEUE(orig, *((void**)(&ptr->data)));
ptr=ptr->lnext;
}
}
struct RuntimeNode * ptr=fdtoobject->listhead;
while(ptr!=NULL) {
void *orig=(void *)ptr->data;
- void *copy;
- if (gc_createcopy(orig, ©))
- enqueue(orig);
- ptr->data=(int)copy;
-
+ ENQUEUE(orig, *((void**)(&ptr->data)));
ptr=ptr->lnext;
}
}
-
{
+ /* Update current task descriptor */
+ int i;
+ for(i=0;i<currtpd->numParameters;i++) {
+ void *orig=currtpd->parameterArray[i];
+ ENQUEUE(orig, currtpd->parameterArray[i]);
+ }
+
+ }
+
/* Update active tasks */
- struct QueueItem * ptr=activetasks->head;
- while (ptr!=NULL) {
- struct taskparamdescriptor *tpd=ptr->objectptr;
+ {
+ struct genpointerlist * ptr=activetasks->list;
+ while(ptr!=NULL) {
+ struct taskparamdescriptor *tpd=ptr->src;
int i;
for(i=0;i<tpd->numParameters;i++) {
- void *orig=tpd->parameterArray[i];
- void *copy;
- if (gc_createcopy(orig, ©))
- enqueue(orig);
- tpd->parameterArray[i]=copy;
+ void * orig=tpd->parameterArray[i];
+ ENQUEUE(orig, tpd->parameterArray[i]);
}
- ptr=ptr->next;
+ ptr=ptr->inext;
}
+ genrehash(activetasks);
}
+
/* Update failed tasks */
{
struct genpointerlist * ptr=failedtasks->list;
while(ptr!=NULL) {
struct taskparamdescriptor *tpd=ptr->src;
- void *orig;
- void *copy;
int i;
for(i=0;i<tpd->numParameters;i++) {
- orig=tpd->parameterArray[i];
- if (gc_createcopy(orig, ©))
- enqueue(orig);
- tpd->parameterArray[i]=copy;
+ void * orig=tpd->parameterArray[i];
+ ENQUEUE(orig, tpd->parameterArray[i]);
}
ptr=ptr->inext;
}
void * ptr=dequeue();
void *cpy=((void **)ptr)[1];
int type=((int *)cpy)[0];
- int * pointer=pointerarray[type];
+ unsigned int * pointer;
+#ifdef TASK
+ if(type==TAGTYPE) {
+ /* Enqueue Tag */
+ /* Nothing is inside */
+ enqueuetag(ptr);
+ continue;
+ }
+#endif
+ pointer=pointerarray[type];
if (pointer==0) {
/* Array of primitives */
/* Do nothing */
+#ifdef DSTM
+ struct ArrayObject *ao=(struct ArrayObject *) ptr;
+ struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
+ ENQUEUE((void *)ao->___nextobject___, *((void **)&ao_cpy->___nextobject___));
+ ENQUEUE((void *)ao->___localcopy___, *((void **)&ao_cpy->___localcopy___));
+#endif
} else if (((int)pointer)==1) {
/* Array of pointers */
struct ArrayObject *ao=(struct ArrayObject *) ptr;
struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
+#ifdef DSTM
+ ENQUEUE((void *)ao->___nextobject___, *((void **)&ao_cpy->___nextobject___));
+ ENQUEUE((void *)ao->___localcopy___, *((void **)&ao_cpy->___localcopy___));
+#endif
int length=ao->___length___;
int i;
for(i=0;i<length;i++) {
void *objptr=((void **)(((char *)& ao->___length___)+sizeof(int)))[i];
- void * copy;
- if (gc_createcopy(objptr, ©))
- enqueue(objptr);
- ((void **)(((char *)& ao_cpy->___length___)+sizeof(int)))[i]=copy;
+ ENQUEUE(objptr, ((void **)(((char *)& ao_cpy->___length___)+sizeof(int)))[i]);
}
} else {
int size=pointer[0];
int i;
for(i=1;i<=size;i++) {
- int offset=pointer[i];
+ unsigned int offset=pointer[i];
void * objptr=*((void **)(((int)ptr)+offset));
- void * copy;
- if (gc_createcopy(objptr, ©))
- enqueue(objptr);
- *((void **) (((int)cpy)+offset))=copy;
+ ENQUEUE(objptr, *((void **) (((int)cpy)+offset)));
}
}
}
-#ifdef THREADS
+#ifdef TASK
+ fixtags();
+#endif
+
+#if defined(THREADS)||defined(DSTM)
needtocollect=0;
pthread_mutex_unlock(&gclistlock);
#endif
}
-void * curr_heapbase=0;
-void * curr_heapptr=0;
-void * curr_heapgcpoint=0;
-void * curr_heaptop=0;
+#ifdef TASK
-void * to_heapbase=0;
-void * to_heapptr=0;
-void * to_heaptop=0;
-long lastgcsize=0;
+/* Fix up the references from tags. This can't be done earlier,
+ because we don't want tags to keep objects alive */
+void fixtags() {
+ while(taghead!=NULL) {
+ int i;
+ struct pointerblock *tmp=taghead->next;
+ for(i=0;i<tagindex;i++) {
+ struct ___TagDescriptor___ *tagd=taghead->ptrs[i];
+ struct ___Object___ *obj=tagd->flagptr;
+ struct ___TagDescriptor___ *copy=((struct ___TagDescriptor___**)tagd)[1];
+ if (obj==NULL) {
+ /* Zero object case */
+ } else if (obj->type==-1) {
+ /* Single object case */
+ copy->flagptr=((struct ___Object___**)obj)[1];
+ } else if (obj->type==OBJECTARRAYTYPE) {
+ /* Array case */
+ struct ArrayObject *ao=(struct ArrayObject *) obj;
+ int livecount=0;
+ int j;
+ int k=0;
+ struct ArrayObject *aonew;
+
+ /* Count live objects */
+ for(j=0;j<ao->___cachedCode___;j++) {
+ struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, j);
+ if (tobj->type==-1)
+ livecount++;
+ }
+
+ livecount=((livecount-1)/OBJECTARRAYINTERVAL+1)*OBJECTARRAYINTERVAL;
+ aonew=(struct ArrayObject *) tomalloc(sizeof(struct ArrayObject)+sizeof(struct ___Object___*)*livecount);
+ memcpy(aonew, ao, sizeof(struct ArrayObject));
+ aonew->type=OBJECTARRAYTYPE;
+ aonew->___length___=livecount;
+ copy->flagptr=aonew;
+ for(j=0;j<ao->___cachedCode___;j++) {
+ struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, j);
+ if (tobj->type==-1) {
+ struct ___Object___ * tobjcpy=((struct ___Object___**)tobj)[1];
+ ARRAYSET(aonew, struct ___Object___*, k++,tobjcpy);
+ }
+ }
+ aonew->___cachedCode___=k;
+ for(;k<livecount;k++) {
+ ARRAYSET(aonew, struct ___Object___*, k, NULL);
+ }
+ } else {
+ /* No object live anymore */
+ copy->flagptr=NULL;
+ }
+ }
+ free(taghead);
+ taghead=tmp;
+ tagindex=NUMPTRS;
+ }
+}
+#endif
void * tomalloc(int size) {
void * ptr=to_heapptr;
return ptr;
}
-#ifdef THREADS
-
+#if defined(THREADS)||defined(DSTM)
void checkcollect(void * ptr) {
if (needtocollect) {
struct listitem * tmp=stopforgc((struct garbagelist *)ptr);
}
}
+#ifdef DSTM
+void checkcollect2(void * ptr, transrecord_t *trans) {
+ if (needtocollect) {
+ int ptrarray[]={1, (int)ptr, (int) trans->revertlist};
+ struct listitem * tmp=stopforgc((struct garbagelist *)ptrarray);
+ pthread_mutex_lock(&gclock); // Wait for GC
+ restartaftergc(tmp);
+ pthread_mutex_unlock(&gclock);
+ trans->revertlist=(struct ___Object___*)ptrarray[2];
+ }
+}
+#endif
+
+
struct listitem * stopforgc(struct garbagelist * ptr) {
struct listitem * litem=malloc(sizeof(struct listitem));
litem->stackptr=ptr;
void * mygcmalloc(struct garbagelist * stackptr, int size) {
void *ptr;
-#ifdef THREADS
+#if defined(THREADS)||defined(DSTM)
if (pthread_mutex_trylock(&gclock)!=0) {
struct listitem *tmp=stopforgc(stackptr);
pthread_mutex_lock(&gclock);
to_heaptop=to_heapbase+INITIALHEAPSIZE;
to_heapptr=to_heapbase;
ptr=curr_heapbase;
-#ifdef THREADS
+#if defined(THREADS)||defined(DSTM)
pthread_mutex_unlock(&gclock);
#endif
return ptr;
/* Not enough room :(, redo gc */
if (curr_heapptr>curr_heapgcpoint) {
-#ifdef THREADS
+#if defined(THREADS)||defined(DSTM)
pthread_mutex_unlock(&gclock);
#endif
return mygcmalloc(stackptr, size);
}
bzero(tmp, curr_heaptop-tmp);
-#ifdef THREADS
+#if defined(THREADS)||defined(DSTM)
pthread_mutex_unlock(&gclock);
#endif
return tmp;
}
} else {
-#ifdef THREADS
+#if defined(THREADS)||defined(DSTM)
pthread_mutex_unlock(&gclock);
#endif
return ptr;