locking technique for risky objects enabled
authoradash <adash>
Wed, 6 May 2009 21:06:38 +0000 (21:06 +0000)
committeradash <adash>
Wed, 6 May 2009 21:06:38 +0000 (21:06 +0000)
Robust/src/Runtime/STM/stm.c
Robust/src/Runtime/STM/tm.h
Robust/src/Runtime/garbage.c
Robust/src/Runtime/garbage.h
Robust/src/Runtime/thread.c

index ed87d172a5397da1b5775faba9b6c42c24d3a854..71bb12148faf27520a9df5a67e131b525bb72a9d 100644 (file)
@@ -26,12 +26,18 @@ int nSoftAbortAbort = 0;
 #endif
 
 #ifdef STMSTATS
+/* Thread variable for locking/unlocking */
+__thread threadrec_t trec;
+__thread struct objlist * lockedobjs;
 int typesCausingAbort[TOTALNUMCLASSANDARRAY];
 /******Keep track of objects and types causing aborts******/
+/*TODO
 #define DEBUGSTMSTAT(args...) { \
-    printf(args); \
-    fflush(stdout); \
+  printf(args); \
+  fflush(stdout); \
 }
+*/
+#define DEBUGSTMSTAT(args...)
 #else
 #define DEBUGSTMSTAT(args...)
 #endif
@@ -110,6 +116,12 @@ objheader_t *transCreateObj(void * ptr, unsigned int size) {
   objheader_t *retval=&tmp[1];
   tmp->lock=RW_LOCK_BIAS;
   tmp->version = 1;
+  tmp->abortCount = 0;
+  tmp->accessCount = 0;
+  tmp->riskyflag = 0;
+  tmp->trec = NULL;
+  //initialize obj lock
+  pthread_mutex_init(&tmp->objlock, NULL);
   STATUS(tmp)=NEW;
   // don't insert into table
   if (newobjs->offset<MAXOBJLIST) {
@@ -206,6 +218,17 @@ __attribute__((pure)) void *transRead(void * oid) {
   memcpy(objcopy, header, size);
 #ifdef STMSTATS
   header->accessCount++;
+  //FIXME riskratio fix
+  //float riskratio = ((header->abortCount)/(header->accessCount));
+  //DEBUGSTMSTAT("type: %d, header->abortCount: %d, header->accessCount: %d, riskratio: %f\n", TYPE(header), header->abortCount, header->accessCount, riskratio);
+  //DEBUGSTMSTAT("type: %d, header->abortCount: %d, header->accessCount: %d\n", TYPE(header), header->abortCount, header->accessCount);
+  //if(header->abortCount > MAXABORTS &&  riskratio > NEED_LOCK_THRESHOLD) {
+  if(header->abortCount > MAXABORTS) {
+    /* Set risky flag */
+    header->riskyflag = 1;
+    /* Need locking */
+    needLock(header);
+  }
 #endif
   /* Insert into cache's lookup table */
   STATUS(objcopy)=0;
@@ -224,6 +247,19 @@ 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
@@ -248,6 +284,9 @@ int transCommit() {
       }
 #endif
       freenewobjs();
+#ifdef STMSTATS
+      freelockedobjs();
+#endif
       objstrReset();
       t_chashreset();
       return TRANS_ABORT;
@@ -260,6 +299,9 @@ int transCommit() {
       }
 #endif
       freenewobjs();
+#ifdef STMSTATS
+      freelockedobjs();
+#endif
       objstrReset();
       t_chashreset();
       return 0;
@@ -273,6 +315,9 @@ int transCommit() {
       if (softaborted>4) {
        //retry if too many soft aborts
        freenewobjs();
+#ifdef STMSTATS
+    freelockedobjs();
+#endif
        objstrReset();
        t_chashreset();
        return TRANS_ABORT;
@@ -617,6 +662,20 @@ int transAbortProcess(void **oidwrlocked, int numoidwrlocked) {
     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=0; i<max; i++) {
+      header = (objheader_t *)((char *)(ptr->objs[i]) - sizeof(objheader_t));
+      header->trec = NULL;
+      pthread_mutex_unlock(&(header->objlock));
+    }
+    ptr=ptr->next;
+  }
+#endif
 }
 
 /* ==================================
@@ -657,6 +716,21 @@ int transCommitProcess(void ** oidwrlocked, int numoidwrlocked) {
     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=0; i<max; i++) {
+      header = (objheader_t *)(((char *)(ptr->objs[i])) - sizeof(objheader_t));
+      header->trec = NULL;
+      pthread_mutex_unlock(&(header->objlock));
+      //TODO printf("%s() Unlock type= %d\n", __func__, TYPE(header));
+    }
+    ptr=ptr->next;
+  }
+#endif
   return 0;
 }
 
@@ -670,7 +744,6 @@ int transCommitProcess(void ** oidwrlocked, int numoidwrlocked) {
  **/
 #ifdef STMSTATS
 void getTotalAbortCount(int start, int stop, void *startptr, void *checkptr, char type) {
-  printf("Inside %s()\n", __func__);
   int i;
   if(type == 'w') {
     int isFirstTime = 0;
@@ -707,8 +780,44 @@ void getTotalAbortCount(int start, int stop, void *startptr, void *checkptr, cha
     }
   }
 }
-#else
-void getTotalAbortCount(int start, int stop, void *startptr, void *checkptr, char type) {
-  return;
+
+/**
+ * needLock
+ * params: Object header
+ * Locks an object that causes aborts
+ **/
+void needLock(objheader_t *header) {
+  if(pthread_mutex_trylock(&(header->objlock))) { //busy and failed to get locked
+    trec.blocked = 1; //set blocked flag
+    while(header->trec == NULL) { //retry
+      ;
+    }
+    if(header->trec->blocked == 1) { //ignore locking
+      return;
+    } else { //lock that blocks
+      pthread_mutex_lock(&(header->objlock));
+      //TODO printf("%s() Got lock on type= %d in second try\n", __func__, TYPE(header));
+      /* Reset blocked field */
+      trec.blocked = 0;
+      /* Set trec */
+      header->trec = &trec;
+    }
+  } else { //acquired lock
+    //TODO printf("%s() Got lock on type= %d in first try\n", __func__, TYPE(header));
+    /* Reset blocked field */
+    trec.blocked = 0;
+    /* Set trec */
+    header->trec = &trec;
+  }
+  /* 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;
+  }
 }
 #endif
index 1fe0380cdf8ff9d74abd53dcb32c37c9b2d51c0d..a1668206c2914caeb81386edad82bdbd7b2090e3 100644 (file)
 
 #ifdef COMPILER
 #include "structdefs.h"
+
+typedef struct threadrec {
+  int blocked;
+} threadrec_t;
+
 typedef struct objheader {
   unsigned int version;
-  unsigned int lock;
-  int abortCount;
-  int accessCount;
+  unsigned int lock;          /* reader and writer lock for object header */
+  int abortCount;             /* track how many times does this object cause abort */
+  int accessCount;            /* track how many times is this object accessed */
+  threadrec_t *trec;           /* some thread that locked this object */
+  int riskyflag;              /* track how risky is the object */
+  pthread_mutex_t objlock;    /* lock this object */
 } objheader_t;
 
 #define OID(x) \
@@ -80,6 +88,8 @@ typedef struct objheader {
  * ================================
  */
 #define DEFAULT_OBJ_STORE_SIZE 1048510 //1MB
+#define MAXABORTS 2
+#define NEED_LOCK_THRESHOLD 0.020000
 #define OSUSED(x) (((unsigned INTPTR)(x)->top)-((unsigned INTPTR) (x+1)))
 #define OSFREE(x) ((x)->size-OSUSED(x))
 #define TRANSREAD(x,y) { \
@@ -115,6 +125,10 @@ struct objlist {
 extern __thread struct objlist * newobjs;
 extern __thread objstr_t *t_cache;
 extern __thread objstr_t *t_reserve;
+#ifdef STMSTATS
+extern __thread threadrec_t trec;
+extern __thread struct objlist * lockedobjs;
+#endif
 
 
 /***********************************
@@ -152,6 +166,8 @@ int alttraverseCache();
 int transAbortProcess(void **, int);
 int transCommmitProcess(void **, int);
 void randomdelay(int);
+#ifdef STMSTATS
 void getTotalAbortCount(int, int, void *, void *, char);
-
+void needLock(objheader_t *);
+#endif
 #endif
index a565825da519676e6efe935a9794851bbdf99b08..42fc413e0243c66286e786a75b5d434443ff3a2b 100644 (file)
@@ -302,6 +302,9 @@ void collect(struct garbagelist * stackptr) {
   if (c_table!=NULL) {
     fixtable(&c_table, &c_list, &c_structs, c_size);
     fixobjlist(newobjs);
+#ifdef STMSTATS
+    fixobjlist(lockedobjs);
+#endif
   }
   memorybase=NULL;
 #endif
@@ -332,6 +335,9 @@ void collect(struct garbagelist * stackptr) {
     if ((*listptr->tc_table)!=NULL) {
       fixtable(listptr->tc_table, listptr->tc_list, listptr->tc_structs, listptr->tc_size);
       fixobjlist(listptr->objlist);
+#ifdef STMSTATS
+      fixobjlist(listptr->lockedlist);
+#endif
     }
     *(listptr->base)=NULL;
 #endif
@@ -604,6 +610,9 @@ struct listitem * stopforgc(struct garbagelist * ptr) {
   litem->tc_list=&c_list;
   litem->tc_structs=&c_structs;
   litem->objlist=newobjs;
+#ifdef STMSTATS
+  litem->lockedlist=lockedobjs;
+#endif
   litem->base=&memorybase;
 #endif
   litem->prev=NULL;
index d402ab920b5bbed8a42c21c582d1020fbbb28929..aa3451e3ffcc18e849aac1eff9dd996c88a12fb2 100644 (file)
@@ -22,6 +22,9 @@ struct listitem {
   chashlistnode_t **tc_table;
   chashlistnode_t **tc_list;
   struct objlist * objlist;
+#ifdef STMSTATS
+  struct objlist * lockedlist;
+#endif
   char **base;
 #endif
 };
index 24eb70cde6f21a7821613754afa50eaa8cfeeff1..3f3a5898f2042f187a4da0f6d1709a6fd3110dbc 100644 (file)
@@ -114,6 +114,10 @@ void initializethreads() {
   t_cache = objstrCreate(1048576);
   t_reserve=NULL;
   t_chashCreate(CHASH_SIZE, CLOADFACTOR);
+#ifdef STMSTATS
+  trec.blocked = 0;
+  lockedobjs=calloc(1, sizeof(struct objlist));
+#endif
 #endif
 }
 
@@ -125,6 +129,10 @@ void initthread(struct ___Thread___ * ___this___) {
   ___Thread______staticStart____L___Thread___((struct ___Thread______staticStart____L___Thread____params *)p);
 #else
   newobjs=calloc(1, sizeof(struct objlist));
+#ifdef STMSTATS
+  trec.blocked = 0;
+  lockedobjs=calloc(1, sizeof(struct objlist));
+#endif
   t_cache = objstrCreate(1048576);
   t_reserve=NULL;
   t_chashCreate(CHASH_SIZE, CLOADFACTOR);
@@ -133,6 +141,9 @@ void initthread(struct ___Thread___ * ___this___) {
  objstrDelete(t_reserve);
  t_chashDelete();
  free(newobjs);
+#ifdef STMSTATS
+ free(lockedobjs);
+#endif
 #endif
   ___this___=(struct ___Thread___ *) p[2];
 #else