start of new file
[IRC.git] / Robust / src / Runtime / garbage.c
index bbd2f04ffed28e8d71ddf084964b90a70234487a..beb67c8613b1e8fbcf9a4dc3a6e03bb7139962ea 100644 (file)
@@ -5,10 +5,16 @@
 #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,&copy))\
+enqueue(orig);\
+dst=copy;\
+}\
+}
+#else
+#define ENQUEUE(orig, dst) \
+void *copy; \
+if (gc_createcopy(orig,&copy))\
+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;
@@ -77,20 +115,31 @@ int moreItems() {
   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) {
-    pthread_mutex_lock(&gclistlock);
-    pthread_mutex_lock(&threadtable);
     if ((listcount+1)==threadcount) {
-      pthread_mutex_unlock(&threadtable);
-      pthread_mutex_unlock(&gclistlock);      
       break; /* Have all other threads stopped */
     }
-    pthread_mutex_unlock(&threadtable);
     pthread_cond_wait(&gccond, &gclistlock);
-    pthread_mutex_unlock(&gclistlock);
   }
 #endif
 
@@ -99,30 +148,39 @@ void collect(struct garbagelist * stackptr) {
     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,&copy))
-       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;
+    ENQUEUE(orig, listptr->locklist);
     stackptr=listptr->stackptr;
     listptr=listptr->next;
-  }
+  } else
+    break;
    }
  }
 #endif
@@ -132,22 +190,21 @@ void collect(struct garbagelist * stackptr) {
     /* 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, &copy))
-           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
     }
   }
   
@@ -155,11 +212,7 @@ void collect(struct garbagelist * stackptr) {
     struct RuntimeNode * ptr=forward->listhead;
     while(ptr!=NULL) {
       void * orig=(void *)ptr->key;
-      void *copy;
-      if (gc_createcopy(orig, &copy))
-       enqueue(orig);
-      ptr->key=(int)copy;
-
+      ENQUEUE(orig, *((void **)(&ptr->key)));
       ptr=ptr->lnext;
     }
     RuntimeHashrehash(forward); /* Rehash the table */
@@ -169,11 +222,7 @@ void collect(struct garbagelist * stackptr) {
     struct RuntimeNode * ptr=reverse->listhead;
     while(ptr!=NULL) {
       void *orig=(void *)ptr->data;
-      void *copy;
-      if (gc_createcopy(orig, &copy))
-       enqueue(orig);
-      ptr->data=(int)copy;
-
+      ENQUEUE(orig, *((void**)(&ptr->data)));
       ptr=ptr->lnext;
     }
   }
@@ -182,42 +231,46 @@ void collect(struct garbagelist * stackptr) {
     struct RuntimeNode * ptr=fdtoobject->listhead;
     while(ptr!=NULL) {
       void *orig=(void *)ptr->data;
-      void *copy;
-      if (gc_createcopy(orig, &copy))
-       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, &copy))
-         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) {
-      void *orig=ptr->src;
-      void *copy;
-      if (gc_createcopy(orig, &copy))
-       enqueue(orig);
-      ptr->src=copy;
-      ptr->object=copy;
+      struct taskparamdescriptor *tpd=ptr->src;
+      int i;
+      for(i=0;i<tpd->numParameters;i++) {
+       void * orig=tpd->parameterArray[i];
+       ENQUEUE(orig, tpd->parameterArray[i]);
+      }
       ptr=ptr->inext;
     }
     genrehash(failedtasks);
@@ -228,50 +281,119 @@ void collect(struct garbagelist * stackptr) {
     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, &copy))
-         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, &copy))
-         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;
@@ -281,20 +403,35 @@ void * tomalloc(int size) {
   return ptr;
 }
 
-#ifdef THREADS
-
+#if defined(THREADS)||defined(DSTM)
 void checkcollect(void * ptr) {
   if (needtocollect) {
     struct listitem * tmp=stopforgc((struct garbagelist *)ptr);
-    pthread_mutex_lock(&gclock);
+    pthread_mutex_lock(&gclock); // Wait for GC
+    restartaftergc(tmp);
+    pthread_mutex_unlock(&gclock);
+
+  }
+}
+
+#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;
+  litem->locklist=pthread_getspecific(threadlocks);
   litem->prev=NULL;
   pthread_mutex_lock(&gclistlock);
   litem->next=list;
@@ -309,6 +446,7 @@ struct listitem * stopforgc(struct garbagelist * ptr) {
 
 void restartaftergc(struct listitem * litem) {
   pthread_mutex_lock(&gclistlock);
+  pthread_setspecific(threadlocks, litem->locklist);
   if (litem->prev==NULL) {
     list=litem->next;
   } else {
@@ -325,7 +463,7 @@ void restartaftergc(struct listitem * litem) {
 
 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);
@@ -349,7 +487,7 @@ void * mygcmalloc(struct garbagelist * stackptr, int size) {
       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;
@@ -398,20 +536,20 @@ void * mygcmalloc(struct garbagelist * stackptr, int size) {
       
       /* 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;