check in my changes
[IRC.git] / Robust / src / Runtime / STM / stm.c
index 0d3ec4648058237c64d224a198d91082577ac737..57610e216f7189a61097fb2b8b774f477b2d835e 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"
-
-/* =======================
- * Global variables
- * ======================
- */
-unsigned int oidMin;
-unsigned int oidMax;
-extern int classsize[];
-/* Thread transaction variables */
+#include "garbage.h"
+#define likely(x) x
+/* Per thread transaction variables */
 __thread objstr_t *t_cache;
+__thread objstr_t *t_reserve;
+__thread struct objlist * newobjs;
+
+#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
+
+#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
+
+#ifdef FASTMEMCPY
+void * A_memcpy (void * dest, const void * src, size_t count);
+#else
+#define A_memcpy memcpy
+#endif
 
+extern void * curr_heapbase;
+extern void * curr_heapptr;
+extern void * curr_heaptop;
+
+#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;                   
+  }
+}
+#endif
 
 /* ==================================================
- * dstmStartup
- * This function starts up the transaction runtime. 
+ * stmStartup
+ * This function starts up the transaction runtime.
  * ==================================================
  */
 int stmStartup() {
-  oidMax = 0xFFFFFFFF;
-  oidMin = 0;
-
   return 0;
 }
 
@@ -52,56 +126,77 @@ objstr_t *objstrCreate(unsigned int size) {
   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 
+ * 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();
+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;
   tmp->version = 1;
-  tmp->rcount = 1;
-  STATUS(tmp) = NEW;
-  t_chashInsert(OID(tmp), tmp);
-
-#ifdef COMPILER
-  return &tmp[1]; //want space after object header
-#else
-  return tmp;
-#endif
-}
-
-//TODO: when reusing oids, make sure they are not already in use!
-static unsigned int id = 0xFFFFFFFF;
-unsigned int getNewOID(void) {
-  id += 2;
-  if (id > oidMax || id < oidMin) {
-    id = (oidMin | 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 id;
+  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;
 }
@@ -111,15 +206,15 @@ void randomdelay() {
  * - allocate space in an object store
  * ==============================================
  */
-void *objstrAlloc(objstr_t **osptr, unsigned int size) {
+void *objstrAlloc(unsigned int size) {
   void *tmp;
   int i=0;
-  objstr_t *store=*osptr;
+  objstr_t *store=t_cache;
   if ((size&7)!=0) {
     size+=(8-(size&7));
   }
 
-  for(;i<3;i++) {
+  for(; i<2; i++) {
     if (OSFREE(store)>=size) {
       tmp=store->top;
       store->top +=size;
@@ -130,138 +225,253 @@ void *objstrAlloc(objstr_t **osptr, unsigned int size) {
   }
 
   {
-    unsigned int newsize=size>DEFAULT_OBJ_STORE_SIZE?size:DEFAULT_OBJ_STORE_SIZE;
+    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 *ptr=&os[1];
-    os->next=store;
-    (*osptr)=os;
+    void *nptr=&os[1];
+    os->next=t_cache;
+    t_cache=os;
     os->size=newsize;
-    os->top=((char *)ptr)+size;
-    return ptr;
+    os->top=((char *)nptr)+size;
+    return nptr;
   }
 }
 
 /* =============================================================
  * transRead
- * -finds the objects either in transaction cache or main heap
+ * -finds the objects either in main heap
  * -copies the object into the transaction cache
  * =============================================================
  */
-__attribute__((pure)) objheader_t *transRead(unsigned int oid) {
-  int size;
+__attribute__ ((pure)) void *transRead(void * oid, void *gl) {
+  objheader_t *tmp, *objheader;
   objheader_t *objcopy;
-  chashlistnode_t *node;
+  int size;
 
-  if(oid == 0) {
-    return NULL;
+  /* 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);
   }
-  
-  /* Read from the transaction cache */
-  node= &c_table[(oid & c_mask)>>1];
-  do {
-    if(node->key == oid) {
-#ifdef COMPILER
-    return &((objheader_t*)node->val)[1];
-#else
-    return node->val;
 #endif
-    }
-    node = node->next;
-  } while(node != NULL);
+  A_memcpy(objcopy, header, size);
+  /* 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];
+}
 
-  /* 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
-    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];
-#else
-    return objcopy;
-#endif
+void freenewobjs() {
+  struct objlist *ptr=newobjs;
+  while(ptr->next!=NULL) {
+    struct objlist *tmp=ptr->next;
+    free(ptr);
+    ptr=tmp;
+  }
+  ptr->offset=0;
+  newobjs=ptr;
+}
+
+#ifdef STMSTATS
+void freelockedobjs() {
+  struct objlist *ptr=lockedobjs;
+  while(ptr->next!=NULL) {
+    struct objlist *tmp=ptr->next;
+    free(ptr);
+    ptr=tmp;
   }
-  read_unlock(STATUSPTR(header));
+  ptr->offset=0;
+  lockedobjs=ptr;
 }
+#endif
 
 /* ================================================================
  * transCommit
  * - This function initiates the transaction commit process
  * - goes through the transaction cache and decides
- * - a final response 
+ * - a final response
  * ================================================================
  */
+#ifdef DELAYCOMP
+int transCommit(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
+#else
 int transCommit() {
-  char finalResponse;
-  char treplyretry; /* keeps track of the common response that needs to be sent */
-
+#endif
+  int softaborted=0;
   do {
-    treplyretry = 0;
     /* Look through all the objects in the transaction hash table */
-    finalResponse = traverseCache(&treplyretry);
+    int finalResponse;
+#ifdef DELAYCOMP
+    if (c_numelements<(c_size>>3))
+      finalResponse= alttraverseCache(commitmethod, primitives, locals, params);
+    else
+      finalResponse= traverseCache(commitmethod, primitives, locals, params);
+#else
+    if (c_numelements<(c_size>>3))
+      finalResponse= alttraverseCache();
+    else
+      finalResponse= traverseCache();
+#endif
     if(finalResponse == TRANS_ABORT) {
-      break;
+#ifdef TRANSSTATS
+      numTransAbort++;
+      if (softaborted) {
+       nSoftAbortAbort++;
+      }
+#endif
+      freenewobjs();
+#ifdef STMSTATS
+      freelockedobjs();
+#endif
+      objstrReset();
+      t_chashreset();
+#ifdef DELAYCOMP
+      dc_t_chashreset();
+      ptrstack.count=0;
+      primstack.count=0;
+      branchstack.count=0;
+#endif
+      return TRANS_ABORT;
     }
     if(finalResponse == TRANS_COMMIT) {
-      break;
+#ifdef TRANSSTATS
+      numTransCommit++;
+      if (softaborted) {
+       nSoftAbortCommit++;
+      }
+#endif
+      freenewobjs();
+#ifdef STMSTATS
+      freelockedobjs();
+#endif
+      objstrReset();
+      t_chashreset();
+#ifdef DELAYCOMP
+      dc_t_chashreset();
+      ptrstack.count=0;
+      primstack.count=0;
+      branchstack.count=0;
+#endif
+      return 0;
     }
     /* 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) {
+    if(finalResponse == TRANS_SOFT_ABORT) {
+#ifdef TRANSSTATS
+      nSoftAbort++;
+#endif
+      softaborted++;
+#ifdef SOFTABORT
+      if (softaborted>1) {
+#else
+      if (1) {
+#endif
+       //retry if too many soft aborts
+       freenewobjs();
+#ifdef STMSTATS
+    freelockedobjs();
+#endif
+       objstrReset();
+       t_chashreset();
+#ifdef DELAYCOMP
+       dc_t_chashreset();
+       ptrstack.count=0;
+       primstack.count=0;
+       branchstack.count=0;
+#endif
+       return TRANS_ABORT;
+      }
+      //randomdelay(softaborted);
+    } else {
       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;
+  } while (1);
 }
 
+#ifdef DELAYCOMP
+#define freearrays   if (c_numelements>=200) { \
+    free(oidrdlocked); \
+    free(oidrdversion); \
+  } \
+  if (t_numelements>=200) { \
+    free(oidwrlocked); \
+  }
+#else
+#define freearrays   if (c_numelements>=200) { \
+    free(oidrdlocked); \
+    free(oidrdversion); \
+    free(oidwrlocked); \
+  }
+#endif
 /* ==================================================
  * 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];
+#ifdef DELAYCOMP
+int traverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
+#else
+int traverseCache() {
+#endif
   /* 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;
-
+  void * rdlocked[200];
+  int rdversion[200];
+  void * wrlocked[200];
+  int softabort=0;
   int i;
+  void ** oidrdlocked;
+  void ** oidwrlocked;
+  int * oidrdversion;
+#ifdef DELAYCOMP
+  int t_numelements=c_numelements+dc_c_numelements;
+  if (t_numelements<200) {
+    oidwrlocked=wrlocked;
+  } else {
+    oidwrlocked=malloc(t_numelements*sizeof(void *));
+  }
+  if (c_numelements<200) {
+    oidrdlocked=rdlocked;
+    oidrdversion=rdversion;
+  } else {
+    int size=c_numelements*sizeof(void*);
+    oidrdlocked=malloc(size);
+    oidrdversion=malloc(size);
+  }
+#else
+  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);
+  }
+#endif
   chashlistnode_t *ptr = c_table;
   /* Represents number of bins in the chash table */
   unsigned int size = c_size;
@@ -270,90 +480,417 @@ char traverseCache(char *treplyretry) {
     /* 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;
+      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++] = header;
+         } else {
+           oidwrlocked[numoidwrlocked++] = header;
+           transAbortProcess(oidwrlocked, numoidwrlocked);
+#ifdef STMSTATS
+           ABORTCOUNT(header);
+           (typesCausingAbort[TYPE(header)])++;
+        getTotalAbortCount(i+1, size, (void *)(curr->next), numoidrdlocked, oidrdlocked, oidrdversion);
+#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);
+           freearrays;
+           if (softabort)
+           return TRANS_SOFT_ABORT;
+             else 
+           return TRANS_ABORT;
+          
+         }
+       } else {
+#ifdef DELAYCOMP
+      //TODO: check to see if we already have lock
+#endif
+         if(version == header->version) {
+           /* versions match */
+           softabort=1;
+         }
+         transAbortProcess(oidwrlocked, numoidwrlocked);
+#ifdef STMSTATS
+         ABORTCOUNT(header);
+         (typesCausingAbort[TYPE(header)])++;
+#endif
+#if defined(STMSTATS)||defined(SOFTABORT)
+      if(getTotalAbortCount(i+1, size, (void *)(curr->next), numoidrdlocked, oidrdlocked, oidrdversion))
+           softabort=0;
+#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);
+         freearrays;
+         if (softabort)
+           return TRANS_SOFT_ABORT;
+         else 
+           return TRANS_ABORT;
+      
+       }
+      } else {
+       oidrdversion[numoidrdlocked]=version;
+       oidrdlocked[numoidrdlocked++] = header;
       }
       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;
+
+#ifdef DELAYCOMP
+  //acquire other locks
+  unsigned int numoidwrtotal=numoidwrlocked;
+
+  chashlistnode_t *dc_curr = dc_c_list;
+  /* Inner loop to traverse the linked list of the cache lookupTable */
+  while(likely(dc_curr != NULL)) {
+    //if the first bin in hash table is empty
+    objheader_t * headeraddr=&((objheader_t *) dc_curr->val)[-1];
+    objheader_t *header=(objheader_t *)(((char *)dc_curr->key)-sizeof(objheader_t));
+    if(write_trylock(&header->lock)) { //can aquire write lock    
+      oidwrlocked[numoidwrtotal++] = header;
+    } else {
+      //maybe we already have lock
+      void * key=dc_curr->key;
+      chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
+      
+      do {
+       if(node->key == key) {
+         objheader_t * headeraddr=&((objheader_t *) node->val)[-1];      
+         if(STATUS(headeraddr) & DIRTY) {
+           goto nextloop;
+         } else
+           break;
+       }
+       node = node->next;
+      } while(node != NULL);
+
+      //have to abort to avoid deadlock
+      transAbortProcess(oidwrlocked, numoidwrtotal);
+#ifdef STMSTATS
+      ABORTCOUNT(header);
+      (typesCausingAbort[TYPE(header)])++;
+#endif
+#if defined(STMSTATS)||defined(SOFTABORT)
+      if(getTotalAbortCount(i+1, size, (void *)(curr->next), numoidrdlocked, oidrdlocked, oidrdversion))
+       softabort=0;
+#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);
+      freearrays;
+      if (softabort)
+       return TRANS_SOFT_ABORT;
+      else
+       return TRANS_ABORT;
+    }
+  nextloop:
+    dc_curr = dc_curr->lnext;
   }
-  return response;
-}
+#endif
 
-/* ===========================================================================
- * 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)++;
+  //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
+
+  for(i=0; i<numoidrdlocked; i++) {
     /* 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;
+    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 */
+#ifdef DELAYCOMP
+       transAbortProcess(oidwrlocked, numoidwrtotal);
+#else
+       transAbortProcess(oidwrlocked, numoidwrlocked);
+#endif
+#ifdef STMSTATS
+       ABORTCOUNT(header);
+       (typesCausingAbort[TYPE(header)])++;
+       getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion);
+#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);
+       freearrays;
+       return TRANS_ABORT;
       }
+#if DELAYCOMP
+    } else if (dc_t_chashSearch(((char *)header)+sizeof(objheader_t))!=NULL) {
+      //couldn't get lock because we already have it
+      //check if it is the right version number
+      if (version!=header->version) {
+       transAbortProcess(oidwrlocked, numoidwrtotal);
+#ifdef STMSTATS
+       ABORTCOUNT(header);
+       (typesCausingAbort[TYPE(header)])++;
+       getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion);
+#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);
+       freearrays;
+       return TRANS_ABORT;
+      }
+#endif
     } else { /* cannot aquire lock */
-      if(version == header->version) /* versions match */
-        (*vmatch_lock)++;
-      else {
-        (*vnomatch)++;
-        return TRANS_ABORT;
+      //do increment as we didn't get lock
+      if(version == header->version) {
+       softabort=1;
       }
+#ifdef DELAYCOMP
+      transAbortProcess(oidwrlocked, numoidwrtotal);
+#else
+      transAbortProcess(oidwrlocked, numoidwrlocked);
+#endif
+#ifdef STMSTATS
+      ABORTCOUNT(header);
+      (typesCausingAbort[TYPE(header)])++;
+#endif
+#if defined(STMSTATS)||defined(SOFTABORT)
+      if(getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion))
+       softabort=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);
+      freearrays;
+      if (softabort)
+       return TRANS_SOFT_ABORT;
+      else 
+       return TRANS_ABORT;
+      
     }
+  }
+  
+  /* Decide the final response */
+#ifdef DELAYCOMP
+  transCommitProcess(oidwrlocked, numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
+#else
+  transCommitProcess(oidwrlocked, numoidwrlocked);
+#endif
+  DEBUGSTM("Commit: rd: %u wr: %u tot: %u\n", numoidrdlocked, numoidwrlocked, c_numelements);
+  freearrays;
+  return TRANS_COMMIT;
+}
+
+/* ==================================================
+ * alttraverseCache
+ * - goes through the transaction cache and
+ * - decides if a transaction should commit or abort
+ * ==================================================
+ */
+
+#ifdef DELAYCOMP
+int alttraverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
+#else
+int alttraverseCache() {
+#endif
+  /* 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;
+#ifdef DELAYCOMP
+  int t_numelements=c_numelements+dc_c_numelements;
+  if (t_numelements<200) {
+    oidwrlocked=wrlocked;
   } 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;
+    oidwrlocked=malloc(t_numelements*sizeof(void *));
+  }
+  if (c_numelements<200) {
+    oidrdlocked=rdlocked;
+    oidrdversion=rdversion;
+  } else {
+    int size=c_numelements*sizeof(void*);
+    oidrdlocked=malloc(size);
+    oidrdversion=malloc(size);
+  }
+#else
+  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);
+  }
+#endif
+  chashlistnode_t *curr = c_list;
+  /* Inner loop to traverse the linked list of the cache lookupTable */
+  while(likely(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++] = header;
+       } else {
+         oidwrlocked[numoidwrlocked++] = header;
+         transAbortProcess(oidwrlocked, numoidwrlocked);
+#ifdef STMSTATS
+         ABORTCOUNT(header);
+         (typesCausingAbort[TYPE(header)])++;
+      getTotalAbortCount2((void *) curr->next, numoidrdlocked, oidrdlocked, oidrdversion);
+#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);
+         freearrays;
+         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)])++;
+#endif
+#if defined(STMSTATS)||defined(SOFTABORT)
+    if(getTotalAbortCount2((void *) curr->next, numoidrdlocked, oidrdlocked, oidrdversion))
+         softabort=0;
+#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);
+       freearrays;
+       if (softabort)
+         return TRANS_SOFT_ABORT;
+       else 
+         return TRANS_ABORT;
       }
+    } else {
+      /* Read from the main heap  and compare versions */
+      oidrdversion[numoidrdlocked]=version;
+      oidrdlocked[numoidrdlocked++] = header;
+    }
+    curr = curr->lnext;
+  }
+
+#ifdef DELAYCOMP
+  //acquire other locks
+  unsigned int numoidwrtotal=numoidwrlocked;
+  chashlistnode_t *dc_curr = dc_c_list;
+  /* Inner loop to traverse the linked list of the cache lookupTable */
+  while(likely(dc_curr != NULL)) {
+    //if the first bin in hash table is empty
+    objheader_t * headeraddr=&((objheader_t *) dc_curr->val)[-1];
+    objheader_t *header=(objheader_t *)(((char *)dc_curr->key)-sizeof(objheader_t));
+    if(write_trylock(&header->lock)) { //can aquire write lock    
+      oidwrlocked[numoidwrtotal++] = header;
+    } else {
+      //maybe we already have lock
+      void * key=dc_curr->key;
+      chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
+      
+      do {
+       if(node->key == key) {
+         objheader_t * headeraddr=&((objheader_t *) node->val)[-1];      
+         if(STATUS(headeraddr) & DIRTY) {
+           goto nextloop;
+         }
+       }
+       node = node->next;
+      } while(node != NULL);
+
+      //have to abort to avoid deadlock
+      transAbortProcess(oidwrlocked, numoidwrtotal);
+#ifdef STMSTATS
+      ABORTCOUNT(header);
+      (typesCausingAbort[TYPE(header)])++;
+#endif
+#if defined(STMSTATS)||defined(SOFTABORT)
+      if(getTotalAbortCount2((void *) curr->next, numoidrdlocked, oidrdlocked, oidrdversion))
+       softabort=0;
+#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);
+      freearrays;
+      if (softabort)
+       return TRANS_SOFT_ABORT;
+      else
+       return TRANS_ABORT;
+    }
+  nextloop:
+    dc_curr = dc_curr->lnext;
+  }
+#endif
+
+  //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
+
+  for(i=0; i<numoidrdlocked; i++) {
+    objheader_t * header=oidrdlocked[i];
+    unsigned int version=oidrdversion[i];
+    if(header->lock>=0) {
+      if(version != header->version) {
+#ifdef DELAYCOMP
+       transAbortProcess(oidwrlocked, numoidwrtotal);
+#else
+       transAbortProcess(oidwrlocked, numoidwrlocked);
+#endif
+#ifdef STMSTATS
+       ABORTCOUNT(header);
+       (typesCausingAbort[TYPE(header)])++;
+       getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion);
+#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);
+       freearrays;
+       return TRANS_ABORT;
+      }
+#ifdef DELAYCOMP
+      //TODO: check to see if we already have lock
+#endif
     } else { /* cannot aquire lock */
-      if(version == header->version)
-        (*vmatch_lock)++;
-      else {
-        (*vnomatch)++;
-        return TRANS_ABORT;
+      if(version == header->version) {
+       softabort=1;
       }
+#ifdef DELAYCOMP
+      transAbortProcess(oidwrlocked, numoidwrtotal);
+#else
+      transAbortProcess(oidwrlocked, numoidwrlocked);
+#endif
+#ifdef STMSTATS
+      ABORTCOUNT(header);
+      (typesCausingAbort[TYPE(header)])++;
+#endif
+#if defined(STMSTATS)||defined(SOFTABORT)
+      if(getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion))
+       softabort=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);
+      freearrays;
+      if (softabort)
+       return TRANS_SOFT_ABORT;
+      else 
+       return TRANS_ABORT;
     }
   }
-  return 0;
+
+  /* Decide the final response */
+#ifdef DELAYCOMP
+  transCommitProcess(oidwrlocked, numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
+#else
+  transCommitProcess(oidwrlocked, numoidwrlocked);
+#endif
+  DEBUGSTM("Commit: rd: %u wr: %u tot: %u\n", numoidrdlocked, numoidwrlocked, c_numelements);
+  freearrays;
+  return TRANS_COMMIT;
 }
 
 /* ==================================
@@ -361,28 +898,31 @@ char decideResponse(objheader_t *headeraddr, unsigned int *oidcreated, int *numc
  *
  * =================================
  */
-int transAbortProcess(unsigned int *oidrdlocked, int *numoidrdlocked, unsigned int *oidwrlocked, int *numoidwrlocked) {
+void transAbortProcess(void **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++) {
+  for(i=numoidwrlocked-1; i>=0; 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;
+    header = (objheader_t *)oidwrlocked[i];
+    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 *)ptr->objs[i];
+      header->trec = NULL;
+      pthread_mutex_unlock(header->objlock);
     }
-    write_unlock(STATUSPTR(header));
+    ptr=ptr->next;
   }
+#endif
 }
 
 /* ==================================
@@ -390,74 +930,263 @@ int transAbortProcess(unsigned int *oidrdlocked, int *numoidrdlocked, unsigned i
  *
  * =================================
  */
-int transCommmitProcess(unsigned int *oidcreated, int *numoidcreated, unsigned int *oidrdlocked, int *numoidrdlocked,
-                    unsigned int *oidwrlocked, int *numoidwrlocked) {
-  objheader_t *header, *tcptr;
+#ifdef DELAYCOMP
+ void transCommitProcess(void ** oidwrlocked, int numoidwrlocked, int numoidwrtotal, void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
+#else
+   void transCommitProcess(void ** oidwrlocked, int numoidwrlocked) {
+#endif
+  objheader_t *header;
   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;
+  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 *)oidwrlocked[i];
     int tmpsize;
     GETSIZE(tmpsize, header);
-    tmpsize += sizeof(objheader_t);
-    /* FIXME Is this correct? */
-#ifdef PRECISE_GC
-    ptrcreate = mygcmalloc((struct garbagelist *)header, tmpsize);
+    struct ___Object___ *dst=(struct ___Object___*)(((char *)oidwrlocked[i])+sizeof(objheader_t));
+    struct ___Object___ *src=t_chashSearch(dst);
+    dst->___cachedCode___=src->___cachedCode___;
+    dst->___cachedHash___=src->___cachedHash___;
+    A_memcpy(&dst[1], &src[1], tmpsize-sizeof(struct ___Object___));
+    __asm__ __volatile__("": : :"memory");
+#ifndef DELAYCOMP
+    header->version++;
+#endif
+  }
+  __asm__ __volatile__("": : :"memory");
+
+#ifdef DELAYCOMP
+  //  call commit method
+  ptrstack.count=0;
+  primstack.count=0;
+  branchstack.count=0;
+  commitmethod(params, locals, primitives);
+#endif
+
+  /* Release write locks */
+#ifdef DELAYCOMP
+  for(i=numoidwrtotal-1; i>=0; i--) {
 #else
-    ptrcreate = FREEMALLOC(tmpsize);
+  for(i=numoidwrlocked-1; i>=0; i--) {
 #endif
-    /* Initialize read and write locks */
-    initdsmlocks(STATUSPTR(header));
-    memcpy(ptrcreate, header, tmpsize);
+    header = (objheader_t *)oidwrlocked[i];
+#ifdef DELAYCOMP
+    header->version++;
+#endif
+    write_unlock(&header->lock);
   }
 
-  /* 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;
+#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 *)ptr->objs[i];
+      header->trec = NULL;
+      pthread_mutex_unlock(header->objlock);
     }
-    if ((tcptr = ((objheader_t *) t_chashSearch(oidwrlocked[i]))) == NULL) {
-      printf("Error: %s() chashSearch returned NULL at %s, %d\n", __func__, __FILE__, __LINE__);
-      return 1;
+    ptr=ptr->next;
+  }
+#endif
+}
+
+#if defined(STMSTATS)||defined(SOFTABORT)
+/** ========================================================================================
+ * getTotalAbortCount (for traverseCache only)
+ * params : start: start index of the loop
+ *        : stop: stop index of the loop
+ *        : startptr: pointer that points to where to start looking in the cache hash table
+ *        : numoidrdlocked : number of objects read that are locked
+ *        : oidrdlocked : array of objects read and currently locked
+ *        : oidrdversion : array of versions of object read
+ * =========================================================================================
+ **/
+int getTotalAbortCount(int start, int stop, void *startptr, int numoidrdlocked, void *oidrdlocked, int *oidrdversion) {
+  int i;
+  int hardabort=0;
+  int isFirstTime=0;
+  chashlistnode_t *curr = (chashlistnode_t *) startptr;
+  chashlistnode_t *ptr = c_table;
+  /* First go through all objects left in the cache that have not been covered yet */
+  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) {
+#ifdef STMSTATS
+        ABORTCOUNT(header);
+        (typesCausingAbort[TYPE(header)])++;
+#endif
+        hardabort=1;
+      }
+      curr = curr->next;
     }
-    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___));
+    isFirstTime = 1;
+  }
+
+  /* Then go through all objects that are read and are currently present in the readLockedArray */
+  if(numoidrdlocked>0) {
+    for(i=0; i<numoidrdlocked; i++) {
+      objheader_t *header = ((void **)oidrdlocked)[i];
+      unsigned int version = oidrdversion[i];
+      if(version != header->version) { /* versions do not match */
+#ifdef STMSTATS
+        ABORTCOUNT(header);
+        (typesCausingAbort[TYPE(header)])++;
+#endif
+        hardabort=1;
+      }
     }
+  }
+
+  return hardabort;
+}
 
-    header->version += 1;
-    if(header->notifylist != NULL) {
-      notifyAll(&header->notifylist, OID(header), header->version);
+/** ========================================================================================
+ * getTotalAbortCount2 (for alttraverseCache only)
+ * params : startptr: pointer that points to where to start looking in the cache hash table
+ *        : numoidrdlocked : number of objects read that are locked
+ *        : oidrdlocked : array of objects read and currently locked
+ *        : oidrdversion : array of versions of object read
+ * =========================================================================================
+ **/
+int getTotalAbortCount2(void *startptr, int numoidrdlocked, void *oidrdlocked, int *oidrdversion) {
+  int hardabort=0;
+  chashlistnode_t *curr = (chashlistnode_t *) startptr;
+  /* Inner loop to traverse the linked list of the cache lookupTable */
+  while(curr != NULL) {
+    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) {
+#ifdef STMSTATS
+      ABORTCOUNT(header);
+      (typesCausingAbort[TYPE(header)])++;
+#endif
+      hardabort=1;
     }
+    curr = curr->next;
   }
-  
-  /* 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));
+
+  /* Then go through all objects that are read and are currently present in the readLockedArray */
+  if(numoidrdlocked>0) {
+    int i;
+    for(i=0; i<numoidrdlocked; i++) {
+      objheader_t *header = ((void **)oidrdlocked)[i];
+      unsigned int version = oidrdversion[i];
+      if(version != header->version) { /* versions do not match */
+#ifdef STMSTATS
+        ABORTCOUNT(header);
+        (typesCausingAbort[TYPE(header)])++;
+#endif
+        hardabort=1;
+      }
+    }
   }
 
-  /* Release write locks */
-  for(i=0; i< *numoidwrlocked; i++) {
-    header = (objheader_t *)(((char *)(&oidwrlocked[i])) - sizeof(objheader_t)); 
-    write_unlock(STATUSPTR(header));
+  return hardabort;
+}
+
+/**
+ * getReadAbortCount : Tells the number of aborts caused by objects that are read by
+ *                    visiting the read array
+ * params: int start, int stop are indexes to readLocked array
+ *         void  *oidrdlocked = readLocked array
+ *         int *oidrdversion = version array
+ **/
+int getReadAbortCount(int start, int stop, void *oidrdlocked, int *oidrdversion) {
+  int i;
+  int hardabort=0;
+  /* Go through oids read that are locked */
+  for(i = start; i < stop; i++) {
+    objheader_t *header = ((void **)oidrdlocked)[i];
+    unsigned int version = oidrdversion[i];
+    if(version != header->version) { /* versions do not match */
+#ifdef STMSTATS
+      ABORTCOUNT(header);
+      (typesCausingAbort[TYPE(header)])++;
+#endif
+      hardabort=1;
+    }
   }
+  return hardabort;
+}
 
-  return 0;
+/**
+ * needLock
+ * params: Object header, ptr to garbage collector
+ * 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++]=header;
+  } else {
+    struct objlist *tmp=malloc(sizeof(struct objlist));
+    tmp->next=lockedobjs;
+    tmp->objs[0]=header;
+    tmp->offset=1;
+    lockedobjs=tmp;
+  }
+  return header;
 }
 
+#endif