add more lock primitives
[IRC.git] / Robust / src / Runtime / STM / stm.c
index 934b1f5a9a38abedf8ec8342739cd989de995817..45e4dd4cf577433b49efed386c65b6d3f1861054 100644 (file)
@@ -18,6 +18,20 @@ __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;
@@ -26,65 +40,25 @@ int nSoftAbortCommit = 0;
 int nSoftAbortAbort = 0;
 #endif
 
-#ifdef STMSTATS
-/* Thread variable for locking/unlocking */
-__thread threadrec_t *trec;
-__thread struct objlist * lockedobjs;
-/** Global lock **/
-int typesCausingAbort[TOTALNUMCLASSANDARRAY];
-/******Keep track of objects and types causing aborts******/
-/* TODO uncomment for later use
-#define DEBUGSTMSTAT(args...) { \
-  printf(args); \
-  fflush(stdout); \
-}
-*/
-#define DEBUGSTMSTAT(args...)
-#else
-#define DEBUGSTMSTAT(args...)
-#endif
-
-#ifdef STMDEBUG
-#define DEBUGSTM(x...) printf(x);
-#else
-#define DEBUGSTM(x...)
-#endif
+void * A_memcpy (void * dest, const void * src, size_t count) {
+  int off=0;
+  INTPTR *desti=(INTPTR *)dest;
+  INTPTR *srci=(INTPTR *)src;
 
-#ifdef FASTMEMCPY
-void * A_memcpy (void * dest, const void * src, size_t count);
-#else
-#define A_memcpy memcpy
-#endif
-
-#ifdef STMSTATS
-/*** Global variables *****/
-objlockstate_t *objlockscope;
-/**
- * ABORTCOUNT
- * params: object header
- * Increments the abort count for each object
- **/
-void ABORTCOUNT(objheader_t * x) {
-  x->abortCount++;  
-  if (x->abortCount > MAXABORTS && (x->riskyflag != 1)) {       
-    //makes riskflag sticky
-    pthread_mutex_lock(&lockedobjstore); 
-    if (objlockscope->offset<MAXOBJLIST) { 
-      x->objlock=&(objlockscope->lock[objlockscope->offset++]);
-    } else { 
-      objlockstate_t *tmp=malloc(sizeof(objlockstate_t)); 
-      tmp->next=objlockscope; 
-      tmp->offset=1; 
-      x->objlock=&(tmp->lock[0]); 
-      objlockscope=tmp;
-    } 
-    pthread_mutex_unlock(&lockedobjstore); 
-    pthread_mutex_init(x->objlock, NULL);
-    //should put a memory barrier here
-    x->riskyflag = 1;                   
+  //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--;
   }
 }
-#endif
 
 /* ==================================================
  * stmStartup
@@ -95,44 +69,6 @@ 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;
-}
-
-void objstrReset() {
-  while(t_cache->next!=NULL) {
-    objstr_t *next=t_cache->next;
-    t_cache->next=t_reserve;
-    t_reserve=t_cache;
-    t_cache=next;
-  }
-  t_cache->top=t_cache+1;
-}
-
-//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
@@ -141,6 +77,11 @@ void objstrDelete(objstr_t *store) {
  */
 void transStart() {
   //Transaction start is currently free...commit and aborting is not
+#ifdef DELAYCOMP
+  c_ptrstack=&ptrstack;
+  c_primstack=&primstack;
+  c_branchstack=&branchstack;
+#endif
 }
 
 /* =======================================================
@@ -148,10 +89,16 @@ void transStart() {
  * 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;
@@ -182,84 +129,94 @@ void randomdelay(int softaborted) {
   return;
 }
 
-/* ==============================================
- * objstrAlloc
- * - allocate space in an object store
- * ==============================================
- */
-void *objstrAlloc(unsigned int size) {
-  void *tmp;
-  int i=0;
-  objstr_t *store=t_cache;
-  if ((size&7)!=0) {
-    size+=(8-(size&7));
-  }
-
-  for(; i<2; 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 **otmp=&t_reserve;
-    objstr_t *ptr;
-    while((ptr=*otmp)!=NULL) {
-      if (ptr->size>=newsize) {
-       //remove from list
-       *otmp=ptr->next;
-       ptr->next=t_cache;
-       t_cache=ptr;
-       ptr->top=((char *)(&ptr[1]))+size;
-       return &ptr[1];
-      }
-    }
-
-    objstr_t *os=(objstr_t *)calloc(1,(sizeof(objstr_t) + newsize));
-    void *nptr=&os[1];
-    os->next=t_cache;
-    t_cache=os;
-    os->size=newsize;
-    os->top=((char *)nptr)+size;
-    return nptr;
-  }
-}
-
 /* =============================================================
  * transRead
  * -finds the objects either in main heap
  * -copies the object into the transaction cache
  * =============================================================
  */
-__attribute__((pure)) void *transRead(void * oid, void *gl) {
+
+//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 */
-  //No lock for now
   objheader_t *header = (objheader_t *)(((char *)oid) - sizeof(objheader_t));
-  GETSIZE(size, header);
-  size += sizeof(objheader_t);
-  objcopy = (objheader_t *) objstrAlloc(size);
 #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(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) {
@@ -271,571 +228,3 @@ void freenewobjs() {
   newobjs=ptr;
 }
 
-#ifdef STMSTATS
-void freelockedobjs() {
-  struct objlist *ptr=lockedobjs;
-  while(ptr->next!=NULL) {
-    struct objlist *tmp=ptr->next;
-    free(ptr);
-    ptr=tmp;
-  }
-  ptr->offset=0;
-  lockedobjs=ptr;
-}
-#endif
-
-/* ================================================================
- * transCommit
- * - This function initiates the transaction commit process
- * - goes through the transaction cache and decides
- * - a final response
- * ================================================================
- */
-int transCommit() {
-  int softaborted=0;
-  do {
-    /* Look through all the objects in the transaction hash table */
-    int finalResponse;
-    if (c_numelements<(c_size>>3))
-      finalResponse= alttraverseCache();
-    else
-      finalResponse= traverseCache();
-    if(finalResponse == TRANS_ABORT) {
-#ifdef TRANSSTATS
-      numTransAbort++;
-      if (softaborted) {
-       nSoftAbortAbort++;
-      }
-#endif
-      freenewobjs();
-#ifdef STMSTATS
-      freelockedobjs();
-#endif
-      objstrReset();
-      t_chashreset();
-      return TRANS_ABORT;
-    }
-    if(finalResponse == TRANS_COMMIT) {
-#ifdef TRANSSTATS
-      numTransCommit++;
-      if (softaborted) {
-       nSoftAbortCommit++;
-      }
-#endif
-      freenewobjs();
-#ifdef STMSTATS
-      freelockedobjs();
-#endif
-      objstrReset();
-      t_chashreset();
-      return 0;
-    }
-    /* wait a random amount of time before retrying to commit transaction*/
-    if(finalResponse == TRANS_SOFT_ABORT) {
-#ifdef TRANSSTATS
-      nSoftAbort++;
-#endif
-      softaborted++;
-      if (1) {
-       //if (softaborted>1) {
-       //retry if too many soft aborts
-       freenewobjs();
-#ifdef STMSTATS
-    freelockedobjs();
-#endif
-       objstrReset();
-       t_chashreset();
-       return TRANS_ABORT;
-      }
-      //randomdelay(softaborted);
-    } 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];
-  int rdversion[200];
-  void * wrlocked[200];
-  int softabort=0;
-  int i;
-  void ** oidrdlocked;
-  void ** oidwrlocked;
-  int * oidrdversion;
-  if (c_numelements<200) {
-    oidrdlocked=rdlocked;
-    oidrdversion=rdversion;
-    oidwrlocked=wrlocked;
-  } else {
-    int size=c_numelements*sizeof(void*);
-    oidrdlocked=malloc(size);
-    oidrdversion=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];
-      objheader_t *header=(objheader_t *)(((char *)curr->key)-sizeof(objheader_t));
-      unsigned int version = headeraddr->version;
-
-      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(oidwrlocked, numoidwrlocked);
-#ifdef STMSTATS
-           ABORTCOUNT(header);
-           (typesCausingAbort[TYPE(header)])++;
-           getTotalAbortCount(i+1, size, (void *)(curr->next), NULL, 1);
-#endif
-           DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
-           DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
-           if (c_numelements>=200) {
-             free(oidrdlocked);
-             free(oidrdversion);
-             free(oidwrlocked);
-           }
-           return TRANS_ABORT;
-         }
-       } else { /* cannot aquire lock */
-         if(version == header->version) {
-           /* versions match */
-           softabort=1;
-         }
-         transAbortProcess(oidwrlocked, numoidwrlocked);
-#ifdef STMSTATS
-         ABORTCOUNT(header);
-         (typesCausingAbort[TYPE(header)])++;
-         getTotalAbortCount(i+1, size, (void *)(curr->next), NULL, 1);
-#endif
-         DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
-         DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
-         if (c_numelements>=200) {
-           free(oidrdlocked);
-           free(oidrdversion);
-           free(oidwrlocked);
-         }
-         return TRANS_ABORT;
-       }
-      } else {
-       oidrdversion[numoidrdlocked]=version;
-       oidrdlocked[numoidrdlocked++] = header;
-      }
-      curr = curr->next;
-    }
-  } //end of for
-
-  //THIS IS THE SERIALIZATION POINT *****
-
-  for(i=0; i<numoidrdlocked; i++) {
-    /* Read from the main heap  and compare versions */
-    objheader_t *header=oidrdlocked[i];
-    unsigned int version=oidrdversion[i];
-    if(header->lock>0) { //not write locked
-      if(version != header->version) { /* versions do not match */
-       oidrdlocked[numoidrdlocked++] = OID(header);
-       transAbortProcess(oidwrlocked, numoidwrlocked);
-#ifdef STMSTATS
-       ABORTCOUNT(header);
-       (typesCausingAbort[TYPE(header)])++;
-       getTotalAbortCount(i+1, numoidrdlocked, oidrdlocked, (void *) oidrdversion, 0);
-#endif
-       DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
-       DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
-       if (c_numelements>=200) {
-         free(oidrdlocked);
-         free(oidrdversion);
-         free(oidwrlocked);
-       }
-       return TRANS_ABORT;
-      }
-    } else { /* cannot aquire lock */
-      //do increment as we didn't get lock
-      if(version == header->version) {
-       softabort=1;
-      }
-      transAbortProcess(oidwrlocked, numoidwrlocked);
-#ifdef STMSTATS
-      ABORTCOUNT(header);
-      (typesCausingAbort[TYPE(header)])++;
-      getTotalAbortCount(i+1, numoidrdlocked, oidrdlocked, (void *) oidrdversion, 0);
-#endif
-      DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
-      DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
-      if (c_numelements>=200) {
-       free(oidrdlocked);
-       free(oidrdversion);
-       free(oidwrlocked);
-      }
-      return TRANS_ABORT;
-    }
-  }
-  
-  /* Decide the final response */
-  transCommitProcess(oidwrlocked, numoidwrlocked);
-  DEBUGSTM("Commit: rd: %u wr: %u tot: %u\n", numoidrdlocked, numoidwrlocked, c_numelements);
-  if (c_numelements>=200) {
-    free(oidrdlocked);
-    free(oidrdversion);
-    free(oidwrlocked);
-  }
-  return TRANS_COMMIT;
-}
-
-/* ==================================================
- * alttraverseCache
- * - goes through the transaction cache and
- * - decides if a transaction should commit or abort
- * ==================================================
- */
-int alttraverseCache() {
-  /* Create info to keep track of objects that can be locked */
-  int numoidrdlocked=0;
-  int numoidwrlocked=0;
-  void * rdlocked[200];
-  int rdversion[200];
-  void * wrlocked[200];
-  int softabort=0;
-  int i;
-  void ** oidrdlocked;
-  int * oidrdversion;
-  void ** oidwrlocked;
-  if (c_numelements<200) {
-    oidrdlocked=rdlocked;
-    oidrdversion=rdversion;
-    oidwrlocked=wrlocked;
-  } else {
-    int size=c_numelements*sizeof(void*);
-    oidrdlocked=malloc(size);
-    oidrdversion=malloc(size);
-    oidwrlocked=malloc(size);
-  }
-  chashlistnode_t *curr = c_list;
-  /* Inner loop to traverse the linked list of the cache lookupTable */
-  while(curr != NULL) {
-    //if the first bin in hash table is empty
-    objheader_t * headeraddr=&((objheader_t *) curr->val)[-1];
-    objheader_t *header=(objheader_t *)(((char *)curr->key)-sizeof(objheader_t));
-    unsigned int version = headeraddr->version;
-
-    if(STATUS(headeraddr) & DIRTY) {
-      /* Read from the main heap  and compare versions */
-      if(likely(write_trylock(&header->lock))) { //can aquire write lock
-       if (likely(version == header->version)) { /* versions match */
-         /* Keep track of objects locked */
-         oidwrlocked[numoidwrlocked++] = OID(header);
-       } else {
-         oidwrlocked[numoidwrlocked++] = OID(header);
-         transAbortProcess(oidwrlocked, numoidwrlocked);
-#ifdef STMSTATS
-         ABORTCOUNT(header);
-         (typesCausingAbort[TYPE(header)])++;
-         getTotalAbortCount(0, 1, (void *) curr->next, NULL, 1);
-#endif
-         DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
-         DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
-         if (c_numelements>=200) {
-           free(oidrdlocked);
-           free(oidrdversion);
-           free(oidwrlocked);
-         }
-         return TRANS_ABORT;
-       }
-      } else { /* cannot aquire lock */
-       if(version == header->version) {
-         /* versions match */
-         softabort=1;
-       }
-       transAbortProcess(oidwrlocked, numoidwrlocked);
-#ifdef STMSTATS
-       ABORTCOUNT(header);
-       (typesCausingAbort[TYPE(header)])++;
-       getTotalAbortCount(0, 1, (void *) curr->next, NULL, 1);
-#endif
-       DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
-       DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
-       if (c_numelements>=200) {
-         free(oidrdlocked);
-         free(oidrdversion);
-         free(oidwrlocked);
-       }
-       return TRANS_ABORT;
-      }
-    } else {
-      /* Read from the main heap  and compare versions */
-      oidrdversion[numoidrdlocked]=version;
-      oidrdlocked[numoidrdlocked++] = header;
-    }
-    curr = curr->lnext;
-  }
-  //THIS IS THE SERIALIZATION POINT *****
-  for(i=0; i<numoidrdlocked; i++) {
-    objheader_t * header = oidrdlocked[i];
-    unsigned int version=oidrdversion[i];
-    if(header->lock>=0) {
-      if(version != header->version) {
-       transAbortProcess(oidwrlocked, numoidwrlocked);
-#ifdef STMSTATS
-       ABORTCOUNT(header);
-       (typesCausingAbort[TYPE(header)])++;
-       getTotalAbortCount(i+1, numoidrdlocked, oidrdlocked, (void *)oidrdversion, 0);
-#endif
-       DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
-       DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
-       if (c_numelements>=200) {
-         free(oidrdlocked);
-         free(oidrdversion);
-         free(oidwrlocked);
-       }
-       return TRANS_ABORT;
-      }
-    } else { /* cannot aquire lock */
-      if(version == header->version) {
-       softabort=1;
-      }
-      transAbortProcess(oidwrlocked, numoidwrlocked);
-#ifdef STMSTATS
-      ABORTCOUNT(header);
-      (typesCausingAbort[TYPE(header)])++;
-      getTotalAbortCount(i+1, numoidrdlocked, oidrdlocked, (void *)oidrdversion, 0);
-#endif
-      DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
-      DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
-      if (c_numelements>=200) {
-       free(oidrdlocked);
-       free(oidrdversion);
-       free(oidwrlocked);
-      }
-      return TRANS_ABORT;
-    }
-  }
-
-  /* Decide the final response */
-  transCommitProcess(oidwrlocked, numoidwrlocked);
-  DEBUGSTM("Commit: rd: %u wr: %u tot: %u\n", numoidrdlocked, numoidwrlocked, c_numelements);
-  if (c_numelements>=200) {
-    free(oidrdlocked);
-    free(oidrdversion);
-    free(oidwrlocked);
-  }
-  return TRANS_COMMIT;
-}
-
-
-/* ==================================
- * transAbortProcess
- *
- * =================================
- */
-void transAbortProcess(void **oidwrlocked, int numoidwrlocked) {
-  int i;
-  objheader_t *header;
-  /* Release read locks */
-
-  /* Release write locks */
-  for(i=numoidwrlocked-1; i>=0; i--) {
-    /* Read from the main heap */
-    header = (objheader_t *)(((char *)(oidwrlocked[i])) - sizeof(objheader_t));
-    write_unlock(&header->lock);
-  }
-
-#ifdef STMSTATS
-  /* clear trec and then release objects locked */
-  struct objlist *ptr=lockedobjs;
-  while(ptr!=NULL) {
-    int max=ptr->offset;
-    for(i=max-1; i>=0; i--) {
-      header = (objheader_t *)((char *)(ptr->objs[i]) - sizeof(objheader_t));
-      header->trec = NULL;
-      pthread_mutex_unlock(header->objlock);
-    }
-    ptr=ptr->next;
-  }
-#endif
-}
-
-/* ==================================
- * transCommitProcess
- *
- * =================================
- */
-int transCommitProcess(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 = numoidwrlocked-1; i >=0; 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___;
-    A_memcpy(&dst[1], &src[1], tmpsize-sizeof(struct ___Object___));
-    __asm__ __volatile__("": : :"memory");
-    header->version++;
-  }
-  __asm__ __volatile__("": : :"memory");
-
-  /* Release write locks */
-  for(i=numoidwrlocked-1; i>=0; i--) {
-    header = (objheader_t *)(((char *)(oidwrlocked[i])) - sizeof(objheader_t));
-    write_unlock(&header->lock);
-  }
-
-#ifdef STMSTATS
-  /* clear trec and then release objects locked */
-  ptr=lockedobjs;
-  while(ptr!=NULL) {
-    int max=ptr->offset;
-    for(i=max-1; i>=0; i--) {
-      header = (objheader_t *)(((char *)(ptr->objs[i])) - sizeof(objheader_t));
-      header->trec = NULL;
-      pthread_mutex_unlock(header->objlock);
-    }
-    ptr=ptr->next;
-  }
-#endif
-
-  return 0;
-}
-
-/** ========================================================================================
- * getTotalAbortCount
- * params : start: start index of the loop
- *        : stop: stop index of the loop
- *        : startptr: pointer that points to where to start looking in the array/ linked list
- *          0='r'/1='w' if found when visiting objects read/ objects modified
- * =========================================================================================
- **/
-#ifdef STMSTATS
-void getTotalAbortCount(int start, int stop, void *startptr, void *checkptr, int type) {
-  int i;
-  if(type) {
-    int isFirstTime = 0;
-    chashlistnode_t *curr = (chashlistnode_t *) startptr;
-    chashlistnode_t *ptr = c_table;
-    for(i = start; i < stop; i++) {
-      if(!isFirstTime)
-       curr = &ptr[i];
-      /* Inner loop to traverse the linked list of the cache lookupTable */
-      while(curr != NULL) {
-       if(curr->key == NULL)
-         break;
-       objheader_t * headeraddr=&((objheader_t *) curr->val)[-1];
-       objheader_t *header=(objheader_t *)(((char *)curr->key)-sizeof(objheader_t));
-       unsigned int version = headeraddr->version;
-       /* versions do not match */
-       if(version != header->version) {
-         ABORTCOUNT(header);
-         (typesCausingAbort[TYPE(header)])++;
-       }
-       curr = curr->next;
-      }
-      isFirstTime = 1;
-    }
-  } else {
-    /* Go through oids read that are locked */
-    for(i = start; i < stop; i++) {
-      objheader_t *header = ((void **)startptr)[i];
-      unsigned int version = ((int *)checkptr)[i];
-      if(version != header->version) { /* versions do not match */
-       ABORTCOUNT(header);
-       (typesCausingAbort[TYPE(header)])++;
-      }
-    }
-  }
-}
-
-/**
- * needLock
- * params: Object header
- * Locks an object that causes aborts
- **/
-objheader_t * needLock(objheader_t *header, void *gl) {
-  int lockstatus;
-  threadrec_t *ptr;
-  while((lockstatus = pthread_mutex_trylock(header->objlock)) 
-      && ((ptr = header->trec) == NULL)) { //retry
-    ;
-  }
-  if(lockstatus==0) { //acquired lock
-    /* Set trec */
-    header->trec = trec;
-  } else { //failed to get lock
-    trec->blocked=1;
-    //memory barrier
-    __asm__ __volatile__("":::"memory");
-    //see if other thread is blocked
-    if(ptr->blocked == 1) {
-      //it might be block, so ignore lock and clear our blocked flag
-      trec->blocked=0;
-      return;
-    } else { 
-#ifdef PRECISE_GC
-      INTPTR ptrarray[]={1, (INTPTR)gl, (INTPTR) header};
-      void *lockptr=header->objlock;
-      stopforgc((struct garbagelist *)ptrarray);
-      //grab lock and wait our turn
-      pthread_mutex_lock(lockptr);
-      restartaftergc();
-      header=(objheader_t *) ptrarray[2];
-#else
-      pthread_mutex_lock(header->objptr);
-#endif
-      /* we have lock, so we are not blocked anymore */
-      trec->blocked = 0;
-      /* Set our trec */
-      header->trec = trec;
-    }
-  }
-  //trec->blocked is zero now
-
-  /* Save the locked object */
-  if (lockedobjs->offset<MAXOBJLIST) {
-    lockedobjs->objs[lockedobjs->offset++]=OID(header);
-  } else {
-    struct objlist *tmp=malloc(sizeof(struct objlist));
-    tmp->next=lockedobjs;
-    tmp->objs[0]=OID(header);
-    tmp->offset=1;
-    lockedobjs=tmp;
-  }
-  return header;
-}
-#endif