complete sandbox implementation
authoradash <adash>
Fri, 5 Feb 2010 02:50:47 +0000 (02:50 +0000)
committeradash <adash>
Fri, 5 Feb 2010 02:50:47 +0000 (02:50 +0000)
Robust/src/Runtime/DSTM/interface/dsmlock.c
Robust/src/Runtime/DSTM/interface/dsmlock.h
Robust/src/Runtime/DSTM/interface/dstm.h
Robust/src/Runtime/DSTM/interface/dstmserver.c
Robust/src/Runtime/DSTM/interface/sandbox.c
Robust/src/Runtime/DSTM/interface/sandbox.h
Robust/src/Runtime/DSTM/interface/trans.c

index e9839362bbe38557feb643b53d76354ca523b517..69cb4d67e84786e65424f811c67fa29a32ad7d67 100644 (file)
@@ -61,3 +61,11 @@ inline void write_unlock(volatile int *rw) {
   __asm__ __volatile__ (LOCK_PREFIX "addl %1, %0"
                        : "+m" (*rw) : "i" (RW_LOCK_BIAS) : "memory");
 }
+
+inline int is_write_locked(volatile int *lock) {
+  return lock < 0;
+}
+
+inline int is_read_locked(volatile int *lock) {
+  return lock > 0;
+}
index f95edf675238e3569d03adca6918bbb97616d04c..d0a5df849be6d97482675f1c42f91403c31569ae 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _DSMLOCK_H_
 #define _DSMLOCK_H_
 
+#define CFENCE   asm volatile("":::"memory");
 #define RW_LOCK_BIAS             0x01000000
 #define atomic_read(v)          (*v)
 #define RW_LOCK_UNLOCKED          { RW_LOCK_BIAS }
@@ -22,4 +23,6 @@ static void atomic_add(int i, volatile int *v);
 static int atomic_sub_and_test(int i, volatile int *v);
 void read_unlock(volatile int *rw);
 void write_unlock(volatile int *rw);
+int is_write_locked(volatile int *lock);
+int is_read_locked(volatile int *lock);
 #endif
index 5220a82dbc644faa3989f23fc0881215f8e7a10f..b9791968ebd96592bea10cc13eae73600d8ef6f7 100644 (file)
@@ -220,6 +220,7 @@ int dstmInit(void);
 void send_data(int fd, void *buf, int buflen);
 void recv_data(int fd, void *buf, int buflen);
 int recv_data_errorcode(int fd, void *buf, int buflen);
+void recv_data_buf(int fd, struct readstruct *, void *, int);
 
 /* Prototypes for object header */
 unsigned int getNewOID(void);
index 64a7eb95cb5c34e8a011a650e55f96ccf524efe6..40554000b6307f6eff36d58850e0fca41822efc8 100644 (file)
@@ -14,6 +14,9 @@
 #include "gCollect.h"
 #include "readstruct.h"
 #include "debugmacro.h"
+#ifdef SANDBOX
+#include "sandbox.h"
+#endif
 
 #define BACKLOG 10 //max pending connections
 #define RECEIVE_BUFFER_SIZE 2048
@@ -157,7 +160,6 @@ void *dstmAccept(void *acceptfd) {
   unsigned int oid;
   char *buffer;
   char control,ctrl;
-  char *ptr;
   void *srcObj;
   objheader_t *h;
   trans_commit_data_t transinfo;
@@ -166,6 +168,11 @@ void *dstmAccept(void *acceptfd) {
   struct readstruct readbuffer;
   readbuffer.head=0;
   readbuffer.tail=0;
+  unsigned int numread=0, nummod=0;
+#ifdef SANDBOX
+  objData_t odata;
+  char *ptr;
+#endif
 
   /* Receive control messages from other machines */
   while(1) {
@@ -300,6 +307,17 @@ void *dstmAccept(void *acceptfd) {
       free(buffer);
       break;
 
+#ifdef SANDBOX
+    case CHECK_OBJECTS: // check if versions of objects match
+      size = sizeof(odata) - 1;
+      ptr = (char*)&odata;
+      recv_data_buf((int)acceptfd, &readbuffer, ptr+1, size);
+      numread = odata.numread;
+      nummod = odata.nummod;
+      checkObjVersion(&readbuffer, (int) acceptfd, numread, nummod);
+      break;
+#endif
+
     case CLOSE_CONNECTION:
       goto closeconnection;
 
@@ -329,7 +347,7 @@ int readClientReq(trans_commit_data_t *transinfo, int acceptfd, struct readstruc
 
   /* Read fixed_data_t data structure */
   size = sizeof(fixed) - 1;
-  ptr = (char *)&fixed;;
+  ptr = (char *)&fixed;
   fixed.control = TRANS_REQUEST;
   recv_data_buf((int)acceptfd, readbuffer, ptr+1, size);
 
index e4eea7a1505491a9f1b442aa4b98b05d5587b1af..f1c0c7d7aee240e18bc97d4e39b79ffeb5fce1c6 100644 (file)
@@ -1,26 +1,38 @@
-#include "sanbox.h"
-#include "dstm.h"
+#include "sandbox.h"
 #include "runtime.h"
+#include "methodheaders.h"
+__thread int transaction_check_counter;
+__thread jmp_buf aborttrans;
+__thread int abortenabled;
+__thread int * counter_reset_pointer;
+extern unsigned int myIpAddr;
+extern sockPoolHashTable_t *transRequestSockPool;
 
 /* Do sandboxing */
 void errorhandler(int sig, struct sigcontext ctx) {
-  //TODO modify this
-  if (sig == SIGSEGV) //Invalid memory segment access
-      printf("Got signal %d, faulty address is %p, "
-                 "from %p\n", sig, ctx.cr2, ctx.eip);
-   else
-      printf("Got signal %d\n", sig);
-
+  if (abortenabled&&checktrans()) {
+    sigset_t toclear;
+    sigemptyset(&toclear);
+    sigaddset(&toclear, sig);
+    sigprocmask(SIG_UNBLOCK, &toclear,NULL); 
+#ifdef TRANSSTATS
+    numTransAbort++;
+#endif
+    objstrDelete(t_cache);
+    t_chashDelete();
+    _longjmp(aborttrans, 1);
+  }
   threadhandler(sig, ctx);
 }
 
 int checktrans() {
  /* Create info to keep track of numelements */ 
   unsigned int size = c_size;
-  chashlistnode_t *curr = c_table;
+  chashlistnode_t *ptr = c_table;
   int i;
   nodeElem_t *head=NULL;
 
+  numNode = 0;
   for(i = 0; i< size; i++) {
     chashlistnode_t *curr = &ptr[i];
     /* Inner loop to traverse the linked list of the cache lookupTable */
@@ -32,19 +44,35 @@ int checktrans() {
       if (STATUS(headeraddr) & NEW || (mhashSearch(curr->key) != NULL)) {
         machinenum = myIpAddr;
       } else if ((machinenum = lhashSearch(curr->key)) == 0) {
-        printf("Error: No such machine %s, %d\n", __FILE__, __LINE__);
+        printf("Error: No such machine %s, %d\n", __func__, __LINE__);
         return 0;
       }
-      head = createList(head, headeraddr, machinenum, c_numelements);
+      if(machinenum != myIpAddr)
+        head = createList(head, headeraddr, machinenum, c_numelements);
       curr = curr->next;
     }
   }
   /* Send oid and versions for checking */
-  verify();
+  int retval=-1;
+  if(head != NULL) {
+    retval = verify(head);
+  }
+
+  if(retval == 1) {
+    printf("Error in System at %s, %s(), %d\n", __FILE__, __func__, __LINE__);
+    print_trace();
+    /* free head */
+    deletehead(head);
+    exit(-1);
+  }
+
+  if(retval == 0) {
+    /* free head */
+    deletehead(head);
+    return 1;
+  }
 
-  //free head
-  deletehead(head);
-  return 0;
+  return 0; // return when objects inconsistent
 }
 
 nodeElem_t * createList(nodeElem_t *head, objheader_t *headeraddr, unsigned int mid,
@@ -57,12 +85,16 @@ nodeElem_t * createList(nodeElem_t *head, objheader_t *headeraddr, unsigned int
   while(tmp != NULL) {
     if(tmp->mid == mid) {
       if (STATUS(headeraddr) & DIRTY) {
-        tmp->oidmod[tmp->nummod]->oid = OID(headeraddr);
-        tmp->oidmod[tmp->nummod]->version = headeraddr->version;
+        offset = (sizeof(unsigned int) + sizeof(short)) * tmp->nummod;
+        *((unsigned int *)(((char *)tmp->objmod) + offset))=OID(headeraddr);
+        offset += sizeof(unsigned int);
+        *((unsigned short *)(((char *)tmp->objmod) + offset)) = headeraddr->version;
         tmp->nummod++;
       } else {
-        tmp->oidread[tmp->numread]->oid = OID(headeraddr);
-        tmp->oidread[tmp->numread]->version = headeraddr->version;
+        offset = (sizeof(unsigned int) + sizeof(short)) * tmp->numread;
+        *((unsigned int *)(((char *)tmp->objread) + offset))=OID(headeraddr);
+        offset += sizeof(unsigned int);
+        *((unsigned short *)(((char *)tmp->objread) + offset)) = headeraddr->version;
         tmp->numread++;
       }
       found = 1;
@@ -72,18 +104,24 @@ nodeElem_t * createList(nodeElem_t *head, objheader_t *headeraddr, unsigned int
   }
   //Add oid for any new machine
   if (!found) {
+    numNode++;
     ptr = makehead(c_numelements);
     if((ptr = makehead(c_numelements)) == NULL) {
+      printf("Error in Allocating memory %s, %d\n", __func__, __LINE__);
       return NULL;
     }
     ptr->mid = mid;
     if (STATUS(headeraddr) & DIRTY) {
-      ptr->oidmod[tmp->nummod]->oid = OID(headeraddr);
-      ptr->oidmod[tmp->nummod]->version = headeraddr->version;
+      offset = (sizeof(unsigned int) + sizeof(short)) * ptr->nummod;
+      *((unsigned int *)(((char *)ptr->objmod) + offset))=OID(headeraddr);
+      offset += sizeof(unsigned int);
+      *((unsigned short *)(((char *)ptr->objmod) + offset)) = headeraddr->version;
       ptr->nummod++;
     } else {
-      ptr->oidread[tmp->numread]->oid = OID(headeraddr);
-      ptr->oidread[tmp->numread]->version = headeraddr->version;
+      offset = (sizeof(unsigned int) + sizeof(short)) * ptr->numread;
+      *((unsigned int *)(((char *)ptr->objread) + offset))=OID(headeraddr);
+      offset += sizeof(unsigned int);
+      *((unsigned short *)(((char *)ptr->objread) + offset)) = headeraddr->version;
       ptr->numread++;
     }
     ptr->next = head;
@@ -96,20 +134,23 @@ nodeElem_t * makehead(unsigned int numelements) {
   nodeElem_t *head;
   //Create the first element 
   if((head = calloc(1, sizeof(nodeElem_t))) == NULL) {
-    printf("Calloc error %s %d\n", __FILE__, __LINE__);
+    printf("Calloc error %s %d\n", __func__, __LINE__);
     return NULL;
   }
-  if ((head->oidmod = calloc(numelements, sizeof(elem_t))) == NULL) {
-    printf("Calloc error %s %d\n", __FILE__, __LINE__);
+  
+  if ((head->objmod = calloc(numelements,sizeof(unsigned int) + sizeof(unsigned short))) == NULL) {
+    printf("Calloc error %s %d\n", __func__, __LINE__);
     free(head);
     return NULL;
   }
-  if ((head->oidread = calloc(numelements, sizeof(elem_t))) == NULL) {
-    printf("Calloc error %s %d\n", __FILE__, __LINE__);
+
+  if ((head->objread = calloc(numelements,sizeof(unsigned int) + sizeof(unsigned short))) == NULL) {
+    printf("Calloc error %s %d\n", __func__, __LINE__);
     free(head);
-    free(head->oidmod);
+    free(head->objmod);
     return NULL;
   }
+
   head->mid = 0;
   head->nummod = head->numread = 0;
   head->next = NULL;
@@ -117,18 +158,207 @@ nodeElem_t * makehead(unsigned int numelements) {
 }
 
 //Delete the entire list
-void pDelete(nodeElem_t *head) {
+void deletehead(nodeElem_t *head) {
   nodeElem_t *next, *tmp;
   tmp = head;
   while(tmp != NULL) {
     next = tmp->next;
-    free(tmp->oidmod);
-    free(tmp->oidread);
+    free(tmp->objmod);
+    free(tmp->objread);
     free(tmp);
     tmp = next;
   }
   return;
 }
 
-void verify() {
+/* Process the linked list of objects */
+int verify(nodeElem_t *pile) {
+  /* create and initialize an array of sockets and reply receiving buffer */
+  int sock[numNode];
+  char getReplyCtrl[numNode];
+  int i;
+  for(i=0; i<numNode; i++) {
+    sock[i] = 0;
+    getReplyCtrl[i] = 0;
+  }
+
+  /* send objects for consistency check to remote machine */
+  objData_t tosend[numNode];
+  int pilecount = 0;
+  while(pile != NULL) {
+    /* send total bytes */
+    tosend[pilecount].control = CHECK_OBJECTS;  
+    tosend[pilecount].numread = pile->numread;  
+    tosend[pilecount].nummod = pile->nummod;  
+    int sd = 0;
+    if((sd = getSock2WithLock(transRequestSockPool, pile->mid)) < 0) {
+      printf("Error: Getting a socket descriptor at %s(), %s(), %d\n", __FILE__, __func__, __LINE__);
+      exit(-1);
+    }
+    sock[pilecount] = sd;
+
+    /* Send starting information of data */
+    send_data(sd, &(tosend[pilecount]), sizeof(objData_t));
+
+    int size;
+    /* Send objetcs that are read */
+    {
+      size=(sizeof(unsigned int)+sizeof(unsigned short)) * pile->numread;
+      send_data(sd, (char *)pile->objread, size);
+    }
+
+    /* Send objects that are modified */
+    {
+      size=(sizeof(unsigned int)+sizeof(unsigned short)) * pile->nummod;
+      send_data(sd, (char *)pile->objmod, size);
+    }
+    pilecount++;
+    pile = pile->next;
+  }// end of pile processing
+
+  int checkObj = 0;
+  int countConsistent = 0;
+
+  /* Recv replies from remote machines */
+  for(i = 0; i<numNode; i++) {
+    int sd = sock[i];
+    if(sd != 0) {
+      char control;
+      recv_data(sd, &control, sizeof(char));
+      getReplyCtrl[i] = control;
+      if(control == OBJ_INCONSISTENT) { /* Inconsistent */
+        checkObj = 1;
+        break;
+      }
+      countConsistent++;
+    }
+  }
+
+  /* Decide final response */
+  if(checkObj) {
+    printf("Inconsistent Object-> Abort Transaction\n");
+    return 0;
+  }
+
+  if(countConsistent == numNode) {
+    return 1;
+  }
+
+  return -1;
+}
+
+void checkObjects() {
+  if (abortenabled&&checktrans()) {
+    printf("Loop Abort\n");
+    transaction_check_counter=(*counter_reset_pointer=HIGH_CHECK_FREQUENCY);
+#ifdef TRANSSTATS
+    numTransAbort++;
+#endif
+    objstrDelete(t_cache);
+    t_chashDelete();
+    _longjmp(aborttrans, 1);
+  }
+  transaction_check_counter=*counter_reset_pointer;
+}
+
+/* Obtain a backtrace and print it to stdout */
+void print_trace() {
+  void *array[100];
+  size_t size;
+  char ** strings;
+  size_t i;
+
+  size = backtrace(array, 100);
+  strings = backtrace_symbols(array, size);
+
+  printf ("Obtained %zd stack frames.\n", size);
+  for (i = 0; i < size; i++)
+    printf ("%s\n", strings[i]);
+  free (strings);
+}
+
+void checkObjVersion(struct readstruct * readbuffer, int sd, unsigned int numread, unsigned int nummod) {
+
+  int v_match=0;
+
+  /* Recv objects read with versions */
+  int size=(sizeof(unsigned int)+sizeof(unsigned short)) * numread;
+  char objread[size];
+  if(numread != 0) {
+    recv_data_buf(sd, readbuffer, objread, size);
+  }
+
+  /* Recv objects modified with versions */
+  size=(sizeof(unsigned int)+sizeof(unsigned short)) * nummod;
+  char objmod[size];
+  if(nummod != 0) {
+    recv_data_buf(sd, readbuffer, objmod, size);
+  }
+
+  int i;
+  char control;
+  for(i=0; i<numread; i++) {
+    size = sizeof(unsigned int)+sizeof(unsigned short);
+    size *= i;
+    unsigned int oid = *((unsigned int *)(objread + size));
+    size += sizeof(unsigned int);
+    unsigned short version = *((unsigned short *)(objread + size));
+    objheader_t *header;
+    if((header = mhashSearch(oid)) == NULL) {    /* Obj not found */
+      control = OBJ_INCONSISTENT;
+      send_data(sd, &control, sizeof(char));
+      return;
+    } else {
+      if(is_write_locked(STATUSPTR(header))) { //object write locked
+        control = OBJ_INCONSISTENT;
+        send_data(sd, &control, sizeof(char));
+        return;
+      }
+      CFENCE;
+      //compare versions
+      if(version == header->version)
+        v_match++;
+      else {
+        control = OBJ_INCONSISTENT;
+        send_data(sd, &control, sizeof(char));
+        return;
+      }
+    }
+  } // end of objects read 
+
+  for(i=0; i<nummod; i++) {
+    //unsigned int oid = objmod[i].oid;
+    //unsigned short version = objmod[i].version;
+    size = sizeof(unsigned int)+sizeof(unsigned short);
+    size *= i;
+    unsigned int oid = *((unsigned int *)(objmod + size));
+    size += sizeof(unsigned int);
+    unsigned short version = *((unsigned short *)(objmod + size));
+    objheader_t *header;
+    if((header = mhashSearch(oid)) == NULL) {    /* Obj not found */
+      control = OBJ_INCONSISTENT;
+      send_data(sd, &control, sizeof(char));
+      return;
+    } else {
+      if(is_write_locked(STATUSPTR(header))) { //object write locked
+        control = OBJ_INCONSISTENT;
+        send_data(sd, &control, sizeof(char));
+        return;
+      }
+      //compare versions
+      if(version == header->version)
+        v_match++;
+      else {
+        control = OBJ_INCONSISTENT;
+        send_data(sd, &control, sizeof(char));
+        return;
+      }
+    }
+  } // end of objects modified
+
+  if(v_match = (numread + nummod)) {
+    control = OBJ_CONSISTENT;
+    send_data(sd, &control, sizeof(char));
+  }
+  return;
 }
index b9844dff651aa9fe309807f886f7712933ac6d79..d2f5fd6b8b7305361f92d87ba8f0c51f5ee2e0e4 100644 (file)
@@ -1,10 +1,30 @@
 #ifndef SANDBOX_H
 #define SANDBOX_H
 
+#include <setjmp.h>
 #include <signal.h>
+#include "dstm.h"
+#include "altmlookup.h"
+#include <execinfo.h>
+#include "readstruct.h"
+#include "dsmlock.h"
+
 extern __thread chashlistnode_t *c_table;
 extern __thread unsigned int c_size;
 extern __thread unsigned int c_numelements;
+extern __thread jmp_buf aborttrans;
+extern __thread int abortenabled;
+extern __thread int* counter_reset_pointer;
+extern __thread int transaction_check_counter;
+
+
+/* Global Variables */
+#define CHECK_OBJECTS   51
+#define OBJ_INCONSISTENT 52
+#define OBJ_CONSISTENT 53
+#define LOW_CHECK_FREQUENCY 1000000
+#define HIGH_CHECK_FREQUENCY 100000
+int numNode; //variable to keep track of the length of the linked list of objects
 
 typedef struct elem {
   unsigned int oid;
@@ -12,19 +32,28 @@ typedef struct elem {
 } elem_t;
 
 typedef struct nodeElem {
- unsigned int mid;
- unsigned int numread;
- unsigned int nummod;
elem_t *oidread;
elem_t *oidmod;
- struct nodeElem *next;
 unsigned int mid;
 unsigned int numread;
 unsigned int nummod;
 elem_t *objread;
 elem_t *objmod;
 struct nodeElem *next;
 } nodeElem_t;
 
+typedef struct objData {
+  char control;
+  unsigned int numread;
+  unsigned int nummod;
+} objData_t;
+
 
 int checktrans();
 void errorhandler(int sig, struct sigcontext ctx);
 nodeElem_t * makehead(unsigned int numelements);
 void deletehead(nodeElem_t *head);
 nodeElem_t * createList(nodeElem_t *, objheader_t *, unsigned int, unsigned int);
+int verify(nodeElem_t *pile);
+void print_trace();
+void checkObjVersion(struct readstruct*, int, unsigned int, unsigned int);
 
 #endif
index 564100b7b6feab8eeeffd6225e9300aea0686b86..d233b2dfa82fffff122e34fe671427aeeef34632 100644 (file)
@@ -914,6 +914,9 @@ int transCommit() {
   int firsttime=1;
   trans_commit_data_t transinfo; /* keeps track of objs locked during transaction */
   char finalResponse;
+#ifdef SANDBOX
+  abortenabled=0;
+#endif
 
 #ifdef LOGEVENTS
   int iii;
@@ -1172,6 +1175,9 @@ int transCommit() {
     /* Free Resources */
     objstrDelete(t_cache);
     t_chashDelete();
+#ifdef SANDBOX
+      abortenabled=1;
+#endif
     return TRANS_ABORT;
   } else if(finalResponse == TRANS_COMMIT) {
 #ifdef TRANSSTATS