change
[IRC.git] / Robust / src / Runtime / STM / stm.c
index ae19d71181fbe95172bc0b1a4d13fa20cca9a137..76e6ac7206b330fc22e60da9fd7e4bb6d9cbb3ff 100644 (file)
 /* ============================================================
- * 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"
-/* Thread transaction variables */
+#include "garbage.h"
+
+/* 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;
+int nSoftAbort = 0;
+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
  * =======================================================
  */
-objheader_t *transCreateObj(unsigned int size) {
-  objheader_t *tmp = (objheader_t *) objstrAlloc(&t_cache, (sizeof(objheader_t) + size));
-  OID(tmp) = getNewOID();
-  tmp->version = 1;
-  STATUS(tmp) = NEW;
-  t_chashInsert(OID(tmp), tmp);
-
-#ifdef COMPILER
-  return &tmp[1]; //want space after object header
+#ifdef STMARRAY
+objheader_t *transCreateObj(void * ptr, unsigned int size, int bytelength) {
+  int *tmpint = mygcmalloc(ptr, (sizeof(objheader_t) + size));
+  objheader_t *tmp = (objheader_t *) (tmpint+bytelength);
 #else
-  return tmp;
+objheader_t *transCreateObj(void * ptr, unsigned int size) {
+  objheader_t *tmp = mygcmalloc(ptr, (sizeof(objheader_t) + size));
 #endif
+  objheader_t *retval=tmp+1;
+  tmp->lock=RW_LOCK_BIAS;
+  tmp->version = 1;
+  //initialize obj lock to the header
+  STATUS(tmp)=NEW;
+  // don't insert into table
+  if (newobjs->offset<MAXOBJLIST) {
+    newobjs->objs[newobjs->offset++]=retval;
+  } else {
+    struct objlist *tmp=malloc(sizeof(struct objlist));
+    tmp->next=newobjs;
+    tmp->objs[0]=retval;
+    tmp->offset=1;
+    newobjs=tmp;
+  }
+  return retval; //want space after object header
 }
 
 /* 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)(1000 + (t%10000)); //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=store;
-    (*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)) objheader_t *transRead(unsigned int oid) {
-  unsigned int machinenumber;
+
+//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;
 
-  /* Read from the main heap */
-  objheader_t *header = (objheader_t *)(((char *)(&oid)) - sizeof(objheader_t)); 
-  if(read_trylock(STATUSPTR(header))) { //Can further acquire read locks
+  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;
+    char *tmpptr = (char *) objstrAlloc(size);
+    bzero(objcopy, 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(&t_cache, size);
-    memcpy(objcopy, header, size);
-    /* Insert into cache's lookup table */
-    STATUS(objcopy)=0;
-    t_chashInsert(OID(header), objcopy);
-#ifdef COMPILER
-    return &objcopy[1];
+    objcopy = (objheader_t *) objstrAlloc(size);
+    A_memcpy(objcopy, header, size);
+  }
 #else
-    return objcopy;
+  GETSIZE(size, header);
+  size += sizeof(objheader_t);
+  objcopy = (objheader_t *) objstrAlloc(size);
+  A_memcpy(objcopy, header, size);
 #endif
-  }
-  read_unlock(STATUSPTR(header));
-}
-
-/* ================================================================
- * transCommit
- * - This function initiates the transaction commit process
- * - goes through the transaction cache and decides
- * - a final response 
- * ================================================================
- */
-int transCommit() {
-  char finalResponse;
-  char treplyretry; /* keeps track of the common response that needs to be sent */
-
-  do {
-    treplyretry = 0;
-    /* Look through all the objects in the transaction hash table */
-    finalResponse = traverseCache(&treplyretry);
-    if(finalResponse == TRANS_ABORT) {
-      break;
-    }
-    if(finalResponse == TRANS_COMMIT) {
-      break;
-    }
-    /* wait a random amount of time before retrying to commit transaction*/
-    if(treplyretry && (finalResponse == TRANS_SOFT_ABORT)) {
-      randomdelay();
-    }
-    if(finalResponse != TRANS_ABORT || finalResponse != TRANS_COMMIT || finalResponse != TRANS_SOFT_ABORT) {
-      printf("Error: in %s() Unknown outcome", __func__);
-      exit(-1);
-    }
-    /* Retry trans commit procedure during soft_abort case */
-  } while (treplyretry);
-
-  if(finalResponse == TRANS_ABORT) {
-    /* Free Resources */
-    objstrDelete(t_cache);
-    t_chashDelete();
-    return TRANS_ABORT;
-  } else if(finalResponse == TRANS_COMMIT) {
-    /* Free Resources */
-    objstrDelete(t_cache);
-    t_chashDelete();
-    return 0;
-  } else {
-    //TODO Add other cases
-    printf("Error: in %s() THIS SHOULD NOT HAPPEN.....EXIT PROGRAM\n", __func__);
-    exit(-1);
-  }
-  return 0;
-}
-
-/* ==================================================
- * traverseCache
- * - goes through the transaction cache and
- * - decides if a transaction should commit or abort
- * ==================================================
- */
-char traverseCache(char *treplyretry) {
-  /* Create info for newly creately objects */
-  int numcreated=0;
-  unsigned int oidcreated[c_numelements];
-  /* Create info to keep track of objects that can be locked */
-  int numoidrdlocked=0;
-  int numoidwrlocked=0;
-  unsigned int oidrdlocked[c_numelements];
-  unsigned int oidwrlocked[c_numelements];
-  /* Counters to decide final response of this transaction */
-  int vmatch_lock;
-  int vmatch_nolock;
-  int vnomatch;
-  int numoidread;
-  int numoidmod;
-  char response;
-
-  int i;
-  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 == 0)
-        break;
-      objheader_t * headeraddr=(objheader_t *) curr->val;
-      response = decideResponse(headeraddr, oidcreated, &numcreated, oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked,
-                                &vmatch_lock, &vmatch_nolock, &vnomatch, &numoidmod, &numoidread);
-      if(response == TRANS_ABORT) {
-        *treplyretry = 0;
-        transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
-        return TRANS_ABORT;
-      }
-      curr = curr->next;
-    }
-  } //end of for
-  
-  /* Decide the final response */
-  if(vmatch_nolock == (numoidread + numoidmod)) {
-    *treplyretry = 0;
-    transCommitProcess(oidcreated, &numcreated, oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
-    response = TRANS_COMMIT;
-  }
-  if(vmatch_lock > 0 && vnomatch == 0) {
-    *treplyretry = 1;
-    response = TRANS_SOFT_ABORT;
-  }
-  return response;
-}
-
-/* ===========================================================================
- * decideResponse
- * - increments counters that keep track of objects read, modified or locked
- * - updates the oids locked and oids newly created 
- * ===========================================================================
- */
-char decideResponse(objheader_t *headeraddr, unsigned int *oidcreated, int *numcreated, unsigned int* oidrdlocked, int *numoidrdlocked,
-    unsigned int*oidwrlocked, int *numoidwrlocked, int *vmatch_lock, int *vmatch_nolock, int *vnomatch, int *numoidmod, int *numoidread) {
-  unsigned short version = headeraddr->version;
-  unsigned int oid = OID(headeraddr);
-  if(STATUS(headeraddr) & NEW) {
-    oidcreated[(*numcreated)++] = OID(headeraddr);
-  } else if(STATUS(headeraddr) & DIRTY) {
-    (*numoidmod)++;
-    /* Read from the main heap  and compare versions */
-    objheader_t *header = (objheader_t *)(((char *)(&oid)) - sizeof(objheader_t)); 
-    if(write_trylock(STATUSPTR(header))) { //can aquire write lock
-      if (version == header->version) {/* versions match */
-        /* Keep track of objects locked */
-        (*vmatch_nolock)++;
-        oidwrlocked[(*numoidwrlocked)++] = OID(header);
-      } else { 
-        (*vnomatch)++;
-        oidwrlocked[(*numoidwrlocked)++] = OID(header);
-        return TRANS_ABORT;
-      }
-    } else { /* cannot aquire lock */
-      if(version == header->version) /* versions match */
-        (*vmatch_lock)++;
-      else {
-        (*vnomatch)++;
-        return TRANS_ABORT;
-      }
-    }
-  } else {
-    (*numoidread)++;
-    /* Read from the main heap  and compare versions */
-    objheader_t *header = (objheader_t *)(((char *)(&oid)) - sizeof(objheader_t)); 
-    if(read_trylock(STATUSPTR(header))) { //can further aquire read locks
-      if(version == header->version) {/* versions match */
-        (*vmatch_nolock)++;
-        oidrdlocked[(*numoidrdlocked)++] = OID(header);
-      } else {
-        (*vnomatch)++;
-        oidrdlocked[(*numoidrdlocked)++] = OID(header);
-        return TRANS_ABORT;
-      }
-    } else { /* cannot aquire lock */
-      if(version == header->version)
-        (*vmatch_lock)++;
-      else {
-        (*vnomatch)++;
-        return TRANS_ABORT;
-      }
-    }
-  }
-  return 0;
-}
-
-/* ==================================
- * transAbortProcess
- *
- * =================================
- */
-int transAbortProcess(unsigned int *oidrdlocked, int *numoidrdlocked, unsigned int *oidwrlocked, int *numoidwrlocked) {
-  int i;
-  objheader_t *header;
-  /* Release read locks */
-  for(i=0; i< *numoidrdlocked; i++) {
-    /* Read from the main heap */
-    if((header = (objheader_t *)(((char *)(&oidrdlocked[i])) - sizeof(objheader_t))) == NULL) {
-      printf("Error: %s() main heap returned NULL at %s, %d\n", __func__, __FILE__, __LINE__);
-      return 1;
-    }
-    read_unlock(STATUSPTR(header));
-  }
-
-  /* Release write locks */
-  for(i=0; i< *numoidwrlocked; i++) {
-    /* Read from the main heap */
-    if((header = (objheader_t *)(((char *)(&oidwrlocked[i])) - sizeof(objheader_t))) == NULL) {
-      printf("Error: %s() main heap returned NULL at %s, %d\n", __func__, __FILE__, __LINE__);
-      return 1;
-    }
-    write_unlock(STATUSPTR(header));
-  }
+#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];
 }
 
-/* ==================================
- * transCommitProcess
- *
- * =================================
- */
-int transCommitProcess(unsigned int *oidcreated, int *numoidcreated, unsigned int *oidrdlocked, int *numoidrdlocked,
-                    unsigned int *oidwrlocked, int *numoidwrlocked) {
-  objheader_t *header, *tcptr;
-  void *ptrcreate;
-
-  int i;
-  /* If object is newly created inside transaction then commit it */
-  for (i = 0; i < *numoidcreated; i++) {
-    if ((header = ((objheader_t *) t_chashSearch(oidcreated[i]))) == NULL) {
-      printf("Error: %s() chashSearch returned NULL for oid = %x at %s, %d\n", __func__, oidcreated[i], __FILE__, __LINE__);
-      return 1;
-    }
-    int tmpsize;
-    GETSIZE(tmpsize, header);
-    tmpsize += sizeof(objheader_t);
-    /* FIXME Is this correct? */
-#ifdef PRECISE_GC
-    ptrcreate = mygcmalloc((struct garbagelist *)header, tmpsize);
-#else
-    ptrcreate = FREEMALLOC(tmpsize);
+#ifdef STMARRAY
+//caller needs to mark data as present
+ void arraycopy(struct ArrayObject *oid, int byteindex) {
+   struct ArrayObject * orig=oid->___objlocation___;
+   int baseoffset=byteindex&HIGHMASK;
+   A_memcpy(((char *)&oid[1])+baseoffset, ((char *)&orig[1])+baseoffset, INDEXLENGTH);
+   if (oid->lowoffset>baseoffset)
+     oid->lowoffset=baseoffset;
+   if (oid->highoffset<baseoffset)
+     oid->highoffset=baseoffset;
+ }
 #endif
-    /* Initialize read and write locks */
-    initdsmlocks(STATUSPTR(header));
-    memcpy(ptrcreate, header, tmpsize);
-  }
-
-  /* Copy from transaction cache -> main object store */
-  for (i = 0; i < *numoidwrlocked; i++) {
-    /* Read from the main heap */ 
-    if((header = (objheader_t *)(((char *)(&oidwrlocked[i])) - sizeof(objheader_t))) == NULL) {
-      printf("Error: %s() main heap returns NULL at %s, %d\n", __func__, __FILE__, __LINE__);
-      return 1;
-    }
-    if ((tcptr = ((objheader_t *) t_chashSearch(oidwrlocked[i]))) == NULL) {
-      printf("Error: %s() chashSearch returned NULL at %s, %d\n", __func__, __FILE__, __LINE__);
-      return 1;
-    }
-    int tmpsize;
-    GETSIZE(tmpsize, header);
-    char *tmptcptr = (char *) tcptr;
-    {
-      struct ___Object___ *dst=(struct ___Object___*)((char*)header+sizeof(objheader_t));
-      struct ___Object___ *src=(struct ___Object___*)((char*)tmptcptr+sizeof(objheader_t));
-      dst->___cachedCode___=src->___cachedCode___;
-      dst->___cachedHash___=src->___cachedHash___;
-
-      memcpy(&dst[1], &src[1], tmpsize-sizeof(struct ___Object___));
-    }
 
-    header->version += 1;
+void freenewobjs() {
+  struct objlist *ptr=newobjs;
+  while(ptr->next!=NULL) {
+    struct objlist *tmp=ptr->next;
+    free(ptr);
+    ptr=tmp;
   }
-  
-  /* 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(STATUSPTR(header));
-  }
-
-  /* Release write locks */
-  for(i=0; i< *numoidwrlocked; i++) {
-    header = (objheader_t *)(((char *)(&oidwrlocked[i])) - sizeof(objheader_t)); 
-    write_unlock(STATUSPTR(header));
-  }
-
-  return 0;
+  ptr->offset=0;
+  newobjs=ptr;
 }