add more lock primitives
[IRC.git] / Robust / src / Runtime / STM / stm.c
index abdc0f7e146ffa69fabfc4cefce1c200f80bd27b..45e4dd4cf577433b49efed386c65b6d3f1861054 100644 (file)
@@ -1,10 +1,10 @@
 /* ============================================================
- * singleTMCommit.c 
+ * singleTMCommit.c
  * - single thread commit on local machine
  * =============================================================
  * Copyright (c) 2009, University of California, Irvine, USA.
  * All rights reserved.
- * Author: Alokika Dash 
+ * Author: Alokika Dash
  *         adash@uci.edu
  * =============================================================
  *
 
 #include "tm.h"
 #include "garbage.h"
-/* Thread transaction variables */
+
+/* Per thread transaction variables */
 __thread objstr_t *t_cache;
+__thread objstr_t *t_reserve;
 __thread struct objlist * newobjs;
 
+#ifdef SANDBOX
+#include "sandbox.h"
+#endif
+
+#ifdef DELAYCOMP
+#include "delaycomp.h"
+__thread struct pointerlist ptrstack;
+__thread struct primitivelist primstack;
+__thread struct branchlist branchstack;
+struct pointerlist *c_ptrstack;
+struct primitivelist *c_primstack;
+struct branchlist *c_branchstack;
+#endif
+
 #ifdef TRANSSTATS
 int numTransCommit = 0;
 int numTransAbort = 0;
@@ -24,65 +40,67 @@ int nSoftAbortCommit = 0;
 int nSoftAbortAbort = 0;
 #endif
 
+void * A_memcpy (void * dest, const void * src, size_t count) {
+  int off=0;
+  INTPTR *desti=(INTPTR *)dest;
+  INTPTR *srci=(INTPTR *)src;
+
+  //word copy
+  while(count>=sizeof(INTPTR)) {
+    desti[off]=srci[off];
+    off+=1;
+    count-=sizeof(INTPTR);
+  }
+  off*=sizeof(INTPTR);
+  //byte copy
+  while(count>0) {
+    ((char *)dest)[off]=((char *)src)[off];
+    off++;
+    count--;
+  }
+}
 
 /* ==================================================
  * stmStartup
- * This function starts up the transaction runtime. 
+ * This function starts up the transaction runtime.
  * ==================================================
  */
 int stmStartup() {
   return 0;
 }
 
-/* ======================================
- * objstrCreate
- * - create an object store of given size
- * ======================================
- */
-objstr_t *objstrCreate(unsigned int size) {
-  objstr_t *tmp;
-  if((tmp = calloc(1, (sizeof(objstr_t) + size))) == NULL) {
-    printf("%s() Calloc error at line %d, %s\n", __func__, __LINE__, __FILE__);
-    return NULL;
-  }
-  tmp->size = size;
-  tmp->next = NULL;
-  tmp->top = tmp + 1; //points to end of objstr_t structure!
-  return tmp;
-}
-
-//free entire list, starting at store
-void objstrDelete(objstr_t *store) {
-  objstr_t *tmp;
-  while (store != NULL) {
-    tmp = store->next;
-    free(store);
-    store = tmp;
-  }
-  return;
-}
-
 /* =================================================
  * transStart
- * This function initializes things required in the 
+ * This function initializes things required in the
  * transaction start
  * =================================================
  */
 void transStart() {
-  t_cache = objstrCreate(1048576);
-  t_chashCreate(CHASH_SIZE, CLOADFACTOR);
+  //Transaction start is currently free...commit and aborting is not
+#ifdef DELAYCOMP
+  c_ptrstack=&ptrstack;
+  c_primstack=&primstack;
+  c_branchstack=&branchstack;
+#endif
 }
 
 /* =======================================================
  * transCreateObj
- * This function creates objects in the transaction record 
+ * This function creates objects in the transaction record
  * =======================================================
  */
+#ifdef STMARRAY
+objheader_t *transCreateObj(void * ptr, unsigned int size, int bytelength) {
+  char *tmpchar = mygcmalloc(ptr, (sizeof(objheader_t) + size));
+  objheader_t *tmp = (objheader_t *) (tmpchar+bytelength);
+#else
 objheader_t *transCreateObj(void * ptr, unsigned int size) {
   objheader_t *tmp = mygcmalloc(ptr, (sizeof(objheader_t) + size));
-  objheader_t *retval=&tmp[1];
-  tmp->lock=RW_LOCK_BIAS;
+#endif
+  objheader_t *retval=tmp+1;
+  tmp->lock=SWAP_LOCK_BIAS;
   tmp->version = 1;
+  //initialize obj lock to the header
   STATUS(tmp)=NEW;
   // don't insert into table
   if (newobjs->offset<MAXOBJLIST) {
@@ -99,80 +117,106 @@ objheader_t *transCreateObj(void * ptr, unsigned int size) {
 
 /* This functions inserts randowm wait delays in the order of msec
  * Mostly used when transaction commits retry*/
-void randomdelay() {
+void randomdelay(int softaborted) {
   struct timespec req;
-  time_t t;
+  struct timeval t;
+
+  gettimeofday(&t,NULL);
 
-  t = time(NULL);
   req.tv_sec = 0;
-  req.tv_nsec = (long)(t%4); //1-11 microsec
+  req.tv_nsec = (long)((t.tv_usec)%(1<<softaborted))<<1; //1-11 microsec
   nanosleep(&req, NULL);
   return;
 }
 
-/* ==============================================
- * objstrAlloc
- * - allocate space in an object store
- * ==============================================
- */
-void *objstrAlloc(objstr_t **osptr, unsigned int size) {
-  void *tmp;
-  int i=0;
-  objstr_t *store=*osptr;
-  if ((size&7)!=0) {
-    size+=(8-(size&7));
-  }
-
-  for(;i<3;i++) {
-    if (OSFREE(store)>=size) {
-      tmp=store->top;
-      store->top +=size;
-      return tmp;
-    }
-    if ((store=store->next)==NULL)
-      break;
-  }
-
-  {
-    unsigned int newsize=size>DEFAULT_OBJ_STORE_SIZE?size:DEFAULT_OBJ_STORE_SIZE;
-    objstr_t *os=(objstr_t *)calloc(1,(sizeof(objstr_t) + newsize));
-    void *ptr=&os[1];
-    os->next=*osptr;
-    (*osptr)=os;
-    os->size=newsize;
-    os->top=((char *)ptr)+size;
-    return ptr;
-  }
-}
-
 /* =============================================================
  * transRead
  * -finds the objects either in main heap
  * -copies the object into the transaction cache
  * =============================================================
  */
-__attribute__((pure)) void *transRead(void * oid) {
+
+//void *TR(void *x, void * y, void *z) {
+//  void * inputvalue;                         
+//  if ((inputvalue=y)==NULL) x=NULL;          
+//  else {
+//    chashlistnode_t * cnodetmp=&c_table[(((unsigned INTPTR)inputvalue)&c_mask)>>4]; 
+//    do { 
+//      if (cnodetmp->key==inputvalue) {x=cnodetmp->val; break;} 
+//      cnodetmp=cnodetmp->next; 
+//      if (cnodetmp==NULL) {if (((struct ___Object___*)inputvalue)->___objstatus___&NEW) {x=inputvalue; break;} else
+//                          {x=transRead(inputvalue,z); asm volatile ("" : "=m" (c_table),"\=m" (c_mask)); break;}}
+//    } while(1);
+//  }
+//  return x;
+//}
+
+//__attribute__ ((pure)) 
+void *transRead(void * oid, void *gl) {
   objheader_t *tmp, *objheader;
   objheader_t *objcopy;
   int size;
 
-  //quick case for new objects
-  if (((struct ___Object___ *)oid)->___objstatus___ & NEW)
-    return oid;
-
-  /* Read from the main heap */
-  //No lock for now
-  objheader_t *header = (objheader_t *)(((char *)oid) - sizeof(objheader_t)); 
+  objheader_t *header = (objheader_t *)(((char *)oid) - sizeof(objheader_t));
+#ifdef STMSTATS
+  header->accessCount++;
+  if(header->riskyflag) {
+    header=needLock(header,gl);
+  }
+#endif
+#ifdef STMARRAY
+  int type=TYPE(header);
+  if (type>=NUMCLASSES) {
+    int basesize=((struct ArrayObject *)oid)->___length___*classsize[type];
+    basesize=(basesize+LOWMASK)&HIGHMASK;
+    int metasize=sizeof(int)*2*(basesize>>INDEXSHIFT);
+    size = basesize + sizeof(objheader_t)+metasize+sizeof(struct ArrayObject);
+    char *tmpptr = (char *) objstrAlloc(size);
+    bzero(tmpptr, metasize);//clear out stm data
+    objcopy=(objheader_t *) (tmpptr+metasize);
+    A_memcpy(objcopy, header, sizeof(objheader_t)+sizeof(struct ArrayObject)); //copy the metadata and base array info
+  } else {
+    GETSIZE(size, header);
+    size += sizeof(objheader_t);
+    objcopy = (objheader_t *) objstrAlloc(size);
+    A_memcpy(objcopy, header, size);
+  }
+#else
   GETSIZE(size, header);
   size += sizeof(objheader_t);
-  objcopy = (objheader_t *) objstrAlloc(&t_cache, size);
-  memcpy(objcopy, header, size);
+  objcopy = (objheader_t *) objstrAlloc(size);
+  A_memcpy(objcopy, header, size);
+#endif
+#ifdef STMSTATS
+  /* keep track of the object's access sequence in a transaction */
+  objheader_t *tmpheader = objcopy;
+  tmpheader->accessCount = ++t_objnumcount;
+#endif
   /* Insert into cache's lookup table */
   STATUS(objcopy)=0;
+  if (((unsigned INTPTR)oid)<((unsigned INTPTR ) curr_heapbase)|| ((unsigned INTPTR)oid) >((unsigned INTPTR) curr_heapptr))
+    printf("ERROR! Bad object address!\n");
   t_chashInsert(oid, &objcopy[1]);
   return &objcopy[1];
 }
 
+#ifdef STMARRAY
+//caller needs to mark data as present
+ void arraycopy(struct ArrayObject *oid, int byteindex) {
+   struct ArrayObject * orig=(struct ArrayObject *) oid->___objlocation___;
+   int baseoffset=byteindex&HIGHMASK;
+   unsigned int mainversion;
+   int baseindex=baseoffset>>INDEXSHIFT;
+   GETVERSIONVAL(mainversion, orig, baseindex);
+   SETVERSION(oid, baseindex, mainversion);
+   A_memcpy(((char *)&oid[1])+baseoffset, ((char *)&orig[1])+baseoffset, INDEXLENGTH);
+   if (oid->lowindex>baseoffset)
+     oid->lowindex=baseoffset;
+   if (oid->highindex<baseoffset)
+     oid->highindex=baseoffset;
+ }
+#endif
+
 void freenewobjs() {
   struct objlist *ptr=newobjs;
   while(ptr->next!=NULL) {
@@ -184,230 +228,3 @@ void freenewobjs() {
   newobjs=ptr;
 }
 
-/* ================================================================
- * transCommit
- * - This function initiates the transaction commit process
- * - goes through the transaction cache and decides
- * - a final response 
- * ================================================================
- */
-int transCommit() {
-#ifdef TRANSSTATS
-  int softaborted=0;
-#endif
-  do {
-    /* Look through all the objects in the transaction hash table */
-    int finalResponse = traverseCache();
-    if(finalResponse == TRANS_ABORT) {
-#ifdef TRANSSTATS
-      numTransAbort++;
-      if (softaborted) {
-       nSoftAbortAbort++;
-      }
-#endif
-      freenewobjs();
-      objstrDelete(t_cache);
-      t_cache=NULL;
-      t_chashDelete();
-      return TRANS_ABORT;
-    }
-    if(finalResponse == TRANS_COMMIT) {
-#ifdef TRANSSTATS
-      numTransCommit++;
-      if (softaborted) {
-       nSoftAbortCommit++;
-      }
-#endif
-      freenewobjs();
-      objstrDelete(t_cache);
-      t_cache=NULL;
-      t_chashDelete();
-      return 0;
-    }
-    /* wait a random amount of time before retrying to commit transaction*/
-    if(finalResponse == TRANS_SOFT_ABORT) {
-#ifdef TRANSSTATS
-      nSoftAbort++;
-      softaborted=1;
-#endif
-      randomdelay();
-    } else {
-      printf("Error: in %s() Unknown outcome", __func__);
-      exit(-1);
-    }
-  } while (1);
-}
-
-/* ==================================================
- * traverseCache
- * - goes through the transaction cache and
- * - decides if a transaction should commit or abort
- * ==================================================
- */
-int traverseCache() {
-  /* Create info to keep track of objects that can be locked */
-  int numoidrdlocked=0;
-  int numoidwrlocked=0;
-  void * rdlocked[200];
-  void * wrlocked[200];
-  int softabort=0;
-  int i;
-  void ** oidrdlocked;
-  void ** oidwrlocked;
-  if (c_numelements<200) {
-    oidrdlocked=rdlocked;
-    oidwrlocked=wrlocked;
-  } else {
-    int size=c_numelements*sizeof(void*);
-    oidrdlocked=malloc(size);
-    oidwrlocked=malloc(size);
-  }
-  chashlistnode_t *ptr = c_table;
-  /* Represents number of bins in the chash table */
-  unsigned int size = c_size;
-  for(i = 0; i<size; i++) {
-    chashlistnode_t *curr = &ptr[i];
-    /* Inner loop to traverse the linked list of the cache lookupTable */
-    while(curr != NULL) {
-      //if the first bin in hash table is empty
-      if(curr->key == NULL)
-        break;
-      objheader_t * headeraddr=&((objheader_t *) curr->val)[-1];
-      
-      unsigned int version = headeraddr->version;
-      objheader_t *header=(objheader_t *) (((char *)curr->key)-sizeof(objheader_t));
-      
-      if(STATUS(headeraddr) & DIRTY) {
-       /* Read from the main heap  and compare versions */
-       if(write_trylock(&header->lock)) { //can aquire write lock
-         if (version == header->version) {/* versions match */
-           /* Keep track of objects locked */
-           oidwrlocked[numoidwrlocked++] = OID(header);
-         } else { 
-           oidwrlocked[numoidwrlocked++] = OID(header);
-           transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
-           return TRANS_ABORT;
-         }
-       } else { /* cannot aquire lock */
-         if(version == header->version) /* versions match */
-           softabort=1;
-         else {
-           transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
-           return TRANS_ABORT;
-         }
-       }
-      } else {
-       /* Read from the main heap  and compare versions */
-       if(read_trylock(&header->lock)) { //can further aquire read locks
-         if(version == header->version) {/* versions match */
-           oidrdlocked[numoidrdlocked++] = OID(header);
-         } else {
-           oidrdlocked[numoidrdlocked++] = OID(header);
-           transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
-           return TRANS_ABORT;
-         }
-       } else { /* cannot aquire lock */
-         if(version == header->version)
-           softabort=1;
-         else {
-           transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
-           return TRANS_ABORT;
-         }
-       }
-      }
-    
-      curr = curr->next;
-    }
-  } //end of for
-  
-  /* Decide the final response */
-  if (softabort) {
-    transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
-    return TRANS_SOFT_ABORT;
-  } else {
-    transCommitProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
-    return TRANS_COMMIT;
-  }
-}
-
-
-/* ==================================
- * transAbortProcess
- *
- * =================================
- */
-int transAbortProcess(void **oidrdlocked, int *numoidrdlocked, void **oidwrlocked, int *numoidwrlocked) {
-  int i;
-  objheader_t *header;
-  /* Release read locks */
-  for(i=0; i< *numoidrdlocked; i++) {
-    /* Read from the main heap */
-    header = (objheader_t *)(((char *)(oidrdlocked[i])) - sizeof(objheader_t));
-    read_unlock(&header->lock);
-  }
-
-  /* Release write locks */
-  for(i=0; i< *numoidwrlocked; i++) {
-    /* Read from the main heap */
-    header = (objheader_t *)(((char *)(oidwrlocked[i])) - sizeof(objheader_t));
-    write_unlock(&header->lock);
-  }
-  if (c_numelements>=200) {
-    free(oidrdlocked);
-    free(oidwrlocked);
-  }
-}
-
-/* ==================================
- * transCommitProcess
- *
- * =================================
- */
-int transCommitProcess(void ** oidrdlocked, int *numoidrdlocked,
-                    void ** oidwrlocked, int *numoidwrlocked) {
-  objheader_t *header;
-  void *ptrcreate;
-  int i;
-  struct objlist *ptr=newobjs;
-  while(ptr!=NULL) {
-    int max=ptr->offset;
-    for(i=0;i<max;i++) {
-      //clear the new flag
-      ((struct ___Object___ *)ptr->objs[i])->___objstatus___=0;
-    }
-    ptr=ptr->next;
-  }
-  
-  /* Copy from transaction cache -> main object store */
-  for (i = 0; i < *numoidwrlocked; i++) {
-    /* Read from the main heap */ 
-    header = (objheader_t *)(((char *)(oidwrlocked[i])) - sizeof(objheader_t));
-    int tmpsize;
-    GETSIZE(tmpsize, header);
-    struct ___Object___ *dst=(struct ___Object___*)oidwrlocked[i];
-    struct ___Object___ *src=t_chashSearch(oidwrlocked[i]);
-    dst->___cachedCode___=src->___cachedCode___;
-    dst->___cachedHash___=src->___cachedHash___;
-    memcpy(&dst[1], &src[1], tmpsize-sizeof(struct ___Object___));
-    header->version += 1;
-  }
-  
-  /* Release read locks */
-  for(i=0; i< *numoidrdlocked; i++) {
-    /* Read from the main heap */
-    header = (objheader_t *)(((char *)(oidrdlocked[i])) - sizeof(objheader_t)); 
-    read_unlock(&header->lock);
-  }
-
-  /* Release write locks */
-  for(i=0; i< *numoidwrlocked; i++) {
-    header = (objheader_t *)(((char *)(oidwrlocked[i])) - sizeof(objheader_t)); 
-    write_unlock(&header->lock);
-  }
-  if (c_numelements>=200) {
-    free(oidrdlocked);
-    free(oidwrlocked);
-  }
-  return 0;
-}
-