Merge branch 'master' into brian
authorBrian Norris <banorris@uci.edu>
Thu, 12 Jul 2012 18:18:00 +0000 (11:18 -0700)
committerBrian Norris <banorris@uci.edu>
Thu, 12 Jul 2012 18:18:00 +0000 (11:18 -0700)
16 files changed:
action.cc
action.h
clockvector.cc
cyclegraph.cc
cyclegraph.h
datarace.cc
hashtable.h
librace.cc
main.cc
model.cc
model.h
mymemory.cc
snapshot-interface.cc
snapshot-interface.h
snapshot.cc
threads.cc

index c96949bc906cc02a9ca3cb50af761a92feda94c7..39b0f7f6d4847207f0dc2a18da5b0edeffa5776a 100644 (file)
--- a/action.cc
+++ b/action.cc
@@ -102,7 +102,7 @@ bool ModelAction::is_synchronizing(const ModelAction *act) const
        // Different locations commute
        if (!same_var(act))
                return false;
-       
+
        // Explore interleavings of seqcst writes to guarantee total order
        // of seq_cst operations that don't commute
        if (is_write() && is_seqcst() && act->is_write() && act->is_seqcst())
@@ -155,6 +155,9 @@ void ModelAction::print(void) const
        case THREAD_CREATE:
                type_str = "thread create";
                break;
+       case THREAD_START:
+               type_str = "thread start";
+               break;
        case THREAD_YIELD:
                type_str = "thread yield";
                break;
index 731c3192f747b083bc0f26e6b0961c432bc90514..30c8a35b80ed7681ce74bc5388c0667b9b4e4fec 100644 (file)
--- a/action.h
+++ b/action.h
@@ -19,6 +19,7 @@
  * ModelAction */
 typedef enum action_type {
        THREAD_CREATE,        /**< A thread creation action */
+       THREAD_START,         /**< First action in each thread */
        THREAD_YIELD,         /**< A thread yield action */
        THREAD_JOIN,          /**< A thread join action */
        ATOMIC_READ,          /**< An atomic read action */
@@ -90,7 +91,7 @@ private:
 
        /** The thread id that performed this action. */
        thread_id_t tid;
-       
+
        /** The value read or written (if RMW, then the value written). This
         * should probably be something longer. */
        int value;
@@ -101,7 +102,7 @@ private:
        /** A back reference to a Node in NodeStack, if this ModelAction is
         * saved on the NodeStack. */
        Node *node;
-       
+
        modelclock_t seq_number;
 
        /** The clock vector stored with this action; only needed if this
index 88ea6fdfcf7cc73a8b99239e9128180883ca55bb..190f9216a92b61ad68df0990775d4c978aaa53f9 100644 (file)
@@ -84,7 +84,7 @@ bool ClockVector::synchronized_since(const ModelAction *act) const
        return false;
 }
 
-/** 
+/**
  * Gets the clock corresponding to a given thread id from the clock
  * vector. */
 
index 8788bfeba6c33140c0544a4ed39f8475864f3e8c..324e01cc0312747e4b39ee4b6c37343cfd7d163f 100644 (file)
@@ -1,10 +1,14 @@
 #include "cyclegraph.h"
 #include "action.h"
 
+/** Initializes a CycleGraph object. */
+
 CycleGraph::CycleGraph() {
        hasCycles=false;
 }
 
+/** Returns the CycleNode for a given ModelAction. */
+
 CycleNode * CycleGraph::getNode(ModelAction * action) {
        CycleNode *node=actionToNode.get(action);
        if (node==NULL) {
@@ -14,6 +18,8 @@ CycleNode * CycleGraph::getNode(ModelAction * action) {
        return node;
 }
 
+/** Adds an edge between two ModelActions. */
+
 void CycleGraph::addEdge(ModelAction *from, ModelAction *to) {
        CycleNode *fromnode=getNode(from);
        CycleNode *tonode=getNode(to);
@@ -24,6 +30,8 @@ void CycleGraph::addEdge(ModelAction *from, ModelAction *to) {
        fromnode->addEdge(tonode);
 }
 
+/** Checks whether the first CycleNode can reach the second one. */
+
 bool CycleGraph::checkReachable(CycleNode *from, CycleNode *to) {
        std::vector<CycleNode *> queue;
        HashTable<CycleNode *, CycleNode *, uintptr_t, 4> discovered;
@@ -47,14 +55,25 @@ bool CycleGraph::checkReachable(CycleNode *from, CycleNode *to) {
        return false;
 }
 
+/** Returns whether a CycleGraph contains cycles. */
+bool CycleGraph::checkForCycles() {
+       return hasCycles;
+}
+
+/** Constructor for a CycleNode. */
+
 CycleNode::CycleNode(ModelAction *modelaction) {
        action=modelaction;
 }
 
+/** Returns a vector of the edges from a CycleNode. */
+
 std::vector<CycleNode *> * CycleNode::getEdges() {
        return &edges;
 }
 
+/** Adds an edge to a CycleNode. */
+
 void CycleNode::addEdge(CycleNode * node) {
        edges.push_back(node);
 }
index df9d46c17d108c51af33862cb1777a6b150ab515..a748c7791110f5c37837ff72131bc8901b98e4e5 100644 (file)
@@ -19,7 +19,6 @@ class CycleGraph {
        CycleNode * getNode(ModelAction *);
        HashTable<ModelAction *, CycleNode *, uintptr_t, 4> actionToNode;
        bool checkReachable(CycleNode *from, CycleNode *to);
-
        bool hasCycles;
 
 };
index da9a3fc15c9716a5a0ec7320bf23bccfb5445ef1..5a23d82d5d97d865f486a9ebbd2913b93e9230f9 100644 (file)
@@ -5,14 +5,19 @@
 
 struct ShadowTable *root;
 
+/** This function initialized the data race detector. */
+
 void initRaceDetector() {
        root=(struct ShadowTable *) calloc(sizeof(struct ShadowTable),1);
 }
 
+/** This function looks up the entry in the shadow table corresponding
+               to a given address.*/
+
 static uint64_t * lookupAddressEntry(void * address) {
        struct ShadowTable *currtable=root;
 #ifdef BIT48
-       currtable=(struct ShadowTable *) currtable->array[(((uintptr_t)address)>>32)&0xffff];
+       currtable=(struct ShadowTable *) currtable->array[(((uintptr_t)address)>>32)&MASK16BIT];
        if (currtable==NULL) {
                currtable=(struct ShadowTable *) (root->array[(((uintptr_t)address)>>32)&MASK16BIT]=calloc(sizeof(struct ShadowTable),1));
        }
@@ -25,6 +30,26 @@ static uint64_t * lookupAddressEntry(void * address) {
        return &basetable->array[((uintptr_t)address)&MASK16BIT];
 }
 
+/**
+ * Compares a current clock-vector/thread-ID pair with a clock/thread-ID pair
+ * to check the potential for a data race.
+ * @param clock1 The current clock vector
+ * @param tid1 The current thread; paired with clock1
+ * @param clock2 The clock value for the potentially-racing action
+ * @param tid2 The thread ID for the potentially-racing action
+ * @return true if the current clock allows a race with the event at clock2/tid2
+ */
+static bool clock_may_race(ClockVector *clock1, thread_id_t tid1,
+                           modelclock_t clock2, thread_id_t tid2)
+{
+       return tid1 != tid2 && clock2 != 0 && clock1->getClock(tid2) <= clock2;
+}
+
+/**
+ * Expands a record from the compact form to the full form.  This is
+ * necessary for multiple readers or for very large thread ids or time
+ * stamps. */
+
 static void expandRecord(uint64_t * shadow) {
        uint64_t shadowval=*shadow;
 
@@ -48,10 +73,15 @@ static void expandRecord(uint64_t * shadow) {
        *shadow=(uint64_t) record;
 }
 
+/** This function is called when we detect a data race.*/
+
 static void reportDataRace() {
        printf("The reportDataRace method should report useful things about this datarace!\n");
 }
 
+/** This function does race detection for a write on an expanded
+ *             record. */
+
 void fullRaceCheckWrite(thread_id_t thread, uint64_t * shadow, ClockVector *currClock) {
        struct RaceRecord * record=(struct RaceRecord *) (*shadow);
 
@@ -61,7 +91,10 @@ void fullRaceCheckWrite(thread_id_t thread, uint64_t * shadow, ClockVector *curr
                modelclock_t readClock = record->readClock[i];
                thread_id_t readThread = record->thread[i];
 
-               if (readThread != thread && readClock != 0 && currClock->getClock(readThread) <= readClock) {
+               /* Note that readClock can't actuall be zero here, so it could be
+                        optimized. */
+
+               if (clock_may_race(currClock, thread, readClock, readThread)) {
                        /* We have a datarace */
                        reportDataRace();
                }
@@ -72,7 +105,7 @@ void fullRaceCheckWrite(thread_id_t thread, uint64_t * shadow, ClockVector *curr
        modelclock_t writeClock = record->writeClock;
        thread_id_t writeThread = record->writeThread;
 
-       if (writeThread != thread && writeClock != 0 && currClock->getClock(writeThread) <= writeClock) {
+       if (clock_may_race(currClock, thread, writeClock, writeThread)) {
                /* We have a datarace */
                reportDataRace();
        }
@@ -83,6 +116,9 @@ void fullRaceCheckWrite(thread_id_t thread, uint64_t * shadow, ClockVector *curr
        record->writeClock=ourClock;
 }
 
+/** This function does race detection on a write.
+ */
+
 void raceCheckWrite(thread_id_t thread, void *location, ClockVector *currClock) {
        uint64_t * shadow=lookupAddressEntry(location);
        uint64_t shadowval=*shadow;
@@ -108,7 +144,7 @@ void raceCheckWrite(thread_id_t thread, void *location, ClockVector *currClock)
        modelclock_t readClock = READVECTOR(shadowval);
        thread_id_t readThread = int_to_id(RDTHREADID(shadowval));
 
-       if (readThread != thread && readClock != 0 && currClock->getClock(readThread) <= readClock) {
+       if (clock_may_race(currClock, thread, readClock, readThread)) {
                /* We have a datarace */
                reportDataRace();
        }
@@ -118,13 +154,16 @@ void raceCheckWrite(thread_id_t thread, void *location, ClockVector *currClock)
        modelclock_t writeClock = WRITEVECTOR(shadowval);
        thread_id_t writeThread = int_to_id(WRTHREADID(shadowval));
 
-       if (writeThread != thread && writeClock != 0 && currClock->getClock(writeThread) <= writeClock) {
+       if (clock_may_race(currClock, thread, writeClock, writeThread)) {
                /* We have a datarace */
                reportDataRace();
        }
        *shadow = ENCODEOP(0, 0, threadid, ourClock);
 }
 
+/** This function does race detection on a read for an expanded
+ *     record. */
+
 void fullRaceCheckRead(thread_id_t thread, uint64_t * shadow, ClockVector *currClock) {
        struct RaceRecord * record=(struct RaceRecord *) (*shadow);
 
@@ -133,7 +172,7 @@ void fullRaceCheckRead(thread_id_t thread, uint64_t * shadow, ClockVector *currC
        modelclock_t writeClock = record->writeClock;
        thread_id_t writeThread = record->writeThread;
 
-       if (writeThread != thread && writeClock != 0 && currClock->getClock(writeThread) <= writeClock) {
+       if (clock_may_race(currClock, thread, writeClock, writeThread)) {
                /* We have a datarace */
                reportDataRace();
        }
@@ -146,7 +185,13 @@ void fullRaceCheckRead(thread_id_t thread, uint64_t * shadow, ClockVector *currC
                modelclock_t readClock = record->readClock[i];
                thread_id_t readThread = record->thread[i];
 
-               if (readThread != thread && currClock->getClock(readThread) <= readClock) {
+               /*  Note that is not really a datarace check as reads cannott
+                               actually race.  It is just determining that this read subsumes
+                               another in the sense that either this read races or neither
+                               read races. Note that readClock can't actually be zero, so it
+                               could be optimized.  */
+
+               if (clock_may_race(currClock, thread, readClock, readThread)) {
                        /* Still need this read in vector */
                        if (copytoindex!=i) {
                                record->readClock[copytoindex]=record->readClock[i];
@@ -176,6 +221,8 @@ void fullRaceCheckRead(thread_id_t thread, uint64_t * shadow, ClockVector *currC
        record->numReads=copytoindex+1;
 }
 
+/** This function does race detection on a read. */
+
 void raceCheckRead(thread_id_t thread, void *location, ClockVector *currClock) {
        uint64_t * shadow=lookupAddressEntry(location);
        uint64_t shadowval=*shadow;
@@ -201,7 +248,7 @@ void raceCheckRead(thread_id_t thread, void *location, ClockVector *currClock) {
        modelclock_t writeClock = WRITEVECTOR(shadowval);
        thread_id_t writeThread = int_to_id(WRTHREADID(shadowval));
 
-       if (writeThread != thread && writeClock != 0 && currClock->getClock(writeThread) <= writeClock) {
+       if (clock_may_race(currClock, thread, writeClock, writeThread)) {
                /* We have a datarace */
                reportDataRace();
        }
@@ -209,7 +256,7 @@ void raceCheckRead(thread_id_t thread, void *location, ClockVector *currClock) {
        modelclock_t readClock = READVECTOR(shadowval);
        thread_id_t readThread = int_to_id(RDTHREADID(shadowval));
 
-       if (readThread != thread && readClock != 0 && currClock->getClock(readThread) <= readClock) {
+       if (clock_may_race(currClock, thread, readClock, readThread)) {
                /* We don't subsume this read... Have to expand record. */
                expandRecord(shadow);
                fullRaceCheckRead(thread, shadow, currClock);
index f372f9e7b96f0efb7f08d6574d768a6cc7cdf2db..b1cd3273290a47e94d0c3000c06e88a43e2cb97d 100644 (file)
@@ -19,7 +19,7 @@ template<typename _Key, typename _Val, typename _KeyInt, int _Shift>
                table = (struct hashlistnode<_Key,_Val> **) calloc(initialcapacity, sizeof(struct hashlistnode<_Key,_Val> *));
                loadfactor = factor;
                capacity = initialcapacity;
-               threshold = initialcapacity*loadfactor;
+               threshold = (unsigned int) (initialcapacity*loadfactor);
                mask = (capacity << _Shift)-1;
                size = 0; // Initial number of elements in the hash
        }
@@ -48,14 +48,14 @@ template<typename _Key, typename _Val, typename _KeyInt, int _Shift>
                memset(table, 0, capacity*sizeof(struct hashlistnode<_Key, _Val> *));
                size=0;
        }
-       
+
        void put(_Key key, _Val val) {
                if(size > threshold) {
                        //Resize
                        unsigned int newsize = capacity << 1;
                        resize(newsize);
                }
-               
+
                struct hashlistnode<_Key,_Val> *ptr = table[(((_KeyInt)key) & mask)>>_Shift];
                size++;
                struct hashlistnode<_Key,_Val> *search = ptr;
@@ -77,7 +77,7 @@ template<typename _Key, typename _Val, typename _KeyInt, int _Shift>
 
        _Val get(_Key key) {
                struct hashlistnode<_Key,_Val> *search = table[(((_KeyInt)key) & mask)>>_Shift];
-               
+
                while(search!=NULL) {
                        if (search->key==key) {
                                return search->val;
@@ -89,7 +89,7 @@ template<typename _Key, typename _Val, typename _KeyInt, int _Shift>
 
        bool contains(_Key key) {
                struct hashlistnode<_Key,_Val> *search = table[(((_KeyInt)key) & mask)>>_Shift];
-               
+
                while(search!=NULL) {
                        if (search->key==key) {
                                return true;
@@ -98,29 +98,29 @@ template<typename _Key, typename _Val, typename _KeyInt, int _Shift>
                }
                return false;
        }
-       
+
        void resize(unsigned int newsize) {
                struct hashlistnode<_Key,_Val> ** oldtable = table;
                struct hashlistnode<_Key,_Val> ** newtable;
                unsigned int oldcapacity = capacity;
-               
+
                if((newtable = (struct hashlistnode<_Key,_Val> **) calloc(newsize, sizeof(struct hashlistnode<_Key,_Val> *))) == NULL) {
                        printf("Calloc error %s %d\n", __FILE__, __LINE__);
                        exit(-1);
                }
-               
+
                table = newtable;          //Update the global hashtable upon resize()
                capacity = newsize;
-               threshold = newsize * loadfactor;
+               threshold = (unsigned int) (newsize * loadfactor);
                mask = (newsize << _Shift)-1;
-               
+
                for(unsigned int i = 0; i < oldcapacity; i++) {
                        struct hashlistnode<_Key, _Val> * bin = oldtable[i];
-                       
+
                        while(bin!=NULL) {
                                _Key key=bin->key;
                                struct hashlistnode<_Key, _Val> * next=bin->next;
-                               
+
                                unsigned int index = (((_KeyInt)key) & mask) >>_Shift;
                                struct hashlistnode<_Key, _Val> * tmp=newtable[index];
                                bin->next=tmp;
@@ -128,10 +128,10 @@ template<typename _Key, typename _Val, typename _KeyInt, int _Shift>
                                bin = next;
                        }
                }
-               
+
                free(oldtable);            //Free the memory of the old hash table
        }
-       
+
  private:
        struct hashlistnode<_Key,_Val> **table;
        unsigned int capacity;
index fa9a1101c07c0b05868ea60165d354a9588ef3c5..38434de70f44d4694ed2a268094e19370a2f87d1 100644 (file)
@@ -3,51 +3,99 @@
 
 #include "librace.h"
 #include "common.h"
+#include "datarace.h"
+#include "model.h"
 
 void store_8(void *addr, uint8_t val)
 {
        DEBUG("addr = %p, val = %" PRIu8 "\n", addr, val);
+       thread_id_t tid=thread_current()->get_id();
+       ClockVector * cv=model->get_cv(tid);
+       raceCheckWrite(tid, addr, cv);
        (*(uint8_t *)addr) = val;
 }
 
 void store_16(void *addr, uint16_t val)
 {
        DEBUG("addr = %p, val = %" PRIu16 "\n", addr, val);
+       thread_id_t tid=thread_current()->get_id();
+       ClockVector * cv=model->get_cv(tid);
+       raceCheckWrite(tid, addr, cv);
+       raceCheckWrite(tid, (void *)(((uintptr_t)addr)+1), cv);
        (*(uint16_t *)addr) = val;
 }
 
 void store_32(void *addr, uint32_t val)
 {
        DEBUG("addr = %p, val = %" PRIu32 "\n", addr, val);
+       thread_id_t tid=thread_current()->get_id();
+       ClockVector * cv=model->get_cv(tid);
+       raceCheckWrite(tid, addr, cv);
+       raceCheckWrite(tid, (void *)(((uintptr_t)addr)+1), cv);
+       raceCheckWrite(tid, (void *)(((uintptr_t)addr)+2), cv);
+       raceCheckWrite(tid, (void *)(((uintptr_t)addr)+3), cv);
        (*(uint32_t *)addr) = val;
 }
 
 void store_64(void *addr, uint64_t val)
 {
        DEBUG("addr = %p, val = %" PRIu64 "\n", addr, val);
+       thread_id_t tid=thread_current()->get_id();
+       ClockVector * cv=model->get_cv(tid);
+       raceCheckWrite(tid, addr, cv);
+       raceCheckWrite(tid, (void *)(((uintptr_t)addr)+1), cv);
+       raceCheckWrite(tid, (void *)(((uintptr_t)addr)+2), cv);
+       raceCheckWrite(tid, (void *)(((uintptr_t)addr)+3), cv);
+       raceCheckWrite(tid, (void *)(((uintptr_t)addr)+4), cv);
+       raceCheckWrite(tid, (void *)(((uintptr_t)addr)+5), cv);
+       raceCheckWrite(tid, (void *)(((uintptr_t)addr)+6), cv);
+       raceCheckWrite(tid, (void *)(((uintptr_t)addr)+7), cv);
        (*(uint64_t *)addr) = val;
 }
 
 uint8_t load_8(void *addr)
 {
        DEBUG("addr = %p\n", addr);
+       thread_id_t tid=thread_current()->get_id();
+       ClockVector * cv=model->get_cv(tid);
+       raceCheckRead(tid, addr, cv);
        return *((uint8_t *)addr);
 }
 
 uint16_t load_16(void *addr)
 {
        DEBUG("addr = %p\n", addr);
+       thread_id_t tid=thread_current()->get_id();
+       ClockVector * cv=model->get_cv(tid);
+       raceCheckRead(tid, addr, cv);
+       raceCheckRead(tid, (void *)(((uintptr_t)addr)+1), cv);
        return *((uint16_t *)addr);
 }
 
 uint32_t load_32(void *addr)
 {
        DEBUG("addr = %p\n", addr);
+       thread_id_t tid=thread_current()->get_id();
+       ClockVector * cv=model->get_cv(tid);
+       raceCheckRead(tid, addr, cv);
+       raceCheckRead(tid, (void *)(((uintptr_t)addr)+1), cv);
+       raceCheckRead(tid, (void *)(((uintptr_t)addr)+2), cv);
+       raceCheckRead(tid, (void *)(((uintptr_t)addr)+3), cv);
        return *((uint32_t *)addr);
 }
 
 uint64_t load_64(void *addr)
 {
        DEBUG("addr = %p\n", addr);
+       thread_id_t tid=thread_current()->get_id();
+       ClockVector * cv=model->get_cv(tid);
+       raceCheckRead(tid, addr, cv);
+       raceCheckRead(tid, (void *)(((uintptr_t)addr)+1), cv);
+       raceCheckRead(tid, (void *)(((uintptr_t)addr)+2), cv);
+       raceCheckRead(tid, (void *)(((uintptr_t)addr)+3), cv);
+       raceCheckRead(tid, (void *)(((uintptr_t)addr)+4), cv);
+       raceCheckRead(tid, (void *)(((uintptr_t)addr)+5), cv);
+       raceCheckRead(tid, (void *)(((uintptr_t)addr)+6), cv);
+       raceCheckRead(tid, (void *)(((uintptr_t)addr)+7), cv);
        return *((uint64_t *)addr);
 }
diff --git a/main.cc b/main.cc
index 3dff4f424ce2a2b36aa3c1fa7fc8819f30c89af3..c9ac1d0663206feccb6d05d43803689e7214574e 100644 (file)
--- a/main.cc
+++ b/main.cc
@@ -6,6 +6,8 @@
 #include "common.h"
 #include "threads.h"
 
+#include "datarace.h"
+
 /* global "model" object */
 #include "model.h"
 #include "snapshot-interface.h"
@@ -55,6 +57,9 @@ static void real_main() {
        thrd_t user_thread;
        ucontext_t main_context;
 
+       //Initialize race detector
+       initRaceDetector();
+
        //Create the singleton SnapshotStack object
        snapshotObject = new SnapshotStack();
 
index 07c81b9eed2108a32df8c50b87fb18c38f355d21..d80d1d27be741c749d9f94db4e8c5c9f8c28e6d4 100644 (file)
--- a/model.cc
+++ b/model.cc
@@ -296,14 +296,17 @@ void ModelChecker::check_current_action(void)
  */
 void ModelChecker::add_action_to_lists(ModelAction *act)
 {
+       int tid = id_to_int(act->get_tid());
        action_trace->push_back(act);
 
        std::vector<action_list_t> *vec = &(*obj_thrd_map)[act->get_location()];
-       if (id_to_int(act->get_tid()) >= (int)vec->size())
+       if (tid >= (int)vec->size())
                vec->resize(next_thread_id);
-       (*vec)[id_to_int(act->get_tid())].push_back(act);
+       (*vec)[tid].push_back(act);
 
-       (*thrd_last_action)[id_to_int(act->get_tid())] = act;
+       if ((int)thrd_last_action->size() <= tid)
+               thrd_last_action->resize(get_num_threads());
+       (*thrd_last_action)[tid] = act;
 }
 
 ModelAction * ModelChecker::get_last_action(thread_id_t tid)
@@ -322,6 +325,10 @@ ModelAction * ModelChecker::get_parent_action(thread_id_t tid)
        return parent;
 }
 
+ClockVector * ModelChecker::get_cv(thread_id_t tid) {
+       return get_parent_action(tid)->get_cv();
+}
+
 /**
  * Build up an initial set of all past writes that this 'read' action may read
  * from. This set is determined by the clock vector's "happens before"
diff --git a/model.h b/model.h
index fbf1b3f0909ff3fd67fbb10e905d1c0b7ff9003b..941601b61fba027fe9b4a3dc366eef420aa561e1 100644 (file)
--- a/model.h
+++ b/model.h
@@ -1,5 +1,5 @@
 /** @file model.h
- *  @brief Core model checker. 
+ *  @brief Core model checker.
  */
 
 #ifndef __MODEL_H__
@@ -54,7 +54,7 @@ public:
        modelclock_t get_next_seq_num();
 
        int switch_to_master(ModelAction *act);
-
+       ClockVector * get_cv(thread_id_t tid);
        bool next_execution();
 
        MEMALLOC
index 88018e269093c531a67bde16d27de8a95d6d6305..f3464fc6bff4927e6f1b36d5678b062a1b87519b 100644 (file)
@@ -20,7 +20,7 @@ void *MYMALLOC(size_t size) {
        static void *(*mallocp)(size_t size);
        char *error;
        void *ptr;
-  
+
        /* get address of libc malloc */
        if (!mallocp) {
                mallocp = ( void * ( * )( size_t ) )dlsym(RTLD_NEXT, "malloc");
@@ -29,7 +29,7 @@ void *MYMALLOC(size_t size) {
                        exit(EXIT_FAILURE);
                }
        }
-       ptr = mallocp(size);     
+       ptr = mallocp(size);
        return ptr;
 #else
        if( !sTheRecord ){
index baedf4753a806b5ac47b8079f9227dba4bce3706..fbbc67772b832bb889555ab40907b7e39173d45c 100644 (file)
@@ -56,7 +56,7 @@ static void SnapshotGlobalSegments(){
                //Skip out at the end of the section
                if (buf[0]=='\n')
                        break;
-               
+
                sscanf(buf, "%22s %p-%p [%5dK] %c%c%c/%c%c%c SM=%3s %200s\n", &type, &begin, &end, &size, &r, &w, &x, &mr, &mw, &mx, smstr, regionname);
 
                if (w == 'w' && (strstr(regionname, MYBINARYNAME) || strstr(regionname, MYLIBRARYNAME))) {
@@ -113,11 +113,11 @@ SnapshotStack::~SnapshotStack(){
 
 /** This method returns to the last snapshot before the inputted
  * sequence number.  This function must be called from the model
- * checking thread and not from a snapshotted stack.  
- * @param seqindex is the sequence number to rollback before.  
+ * checking thread and not from a snapshotted stack.
+ * @param seqindex is the sequence number to rollback before.
  * @return is the sequence number we actually rolled back to.
  */
-               
+
 int SnapshotStack::backTrackBeforeStep(int seqindex) {
        while(true) {
                if (stack->index<=seqindex) {
index 5f54edb87f00f3299c20b1dc7beb9b5f4149107d..9912a1b78f2beba07c08b624b483c71492fd9e3a 100644 (file)
@@ -28,7 +28,7 @@ class SnapshotStack {
   int backTrackBeforeStep(int seq_index);
   void snapshotStep(int seq_index);
 
- private: 
+ private:
   struct stackEntry * stack;
 };
 
index 1e7d80b4b5d836d1c4a1cdb653824a626afb82c8..b6e20fd7691a037bab3e5d83b30b860dc6ab713c 100644 (file)
@@ -34,7 +34,7 @@ struct Snapshot * sTheRecord = NULL;
 
 #if !USE_MPROTECT_SNAPSHOT
 /** @statics
-*   These variables are necessary because the stack is shared region and 
+*   These variables are necessary because the stack is shared region and
 *   there exists a race between all processes executing the same function.
 *   To avoid the problem above, we require variables allocated in 'safe' regions.
 *   The bug was actually observed with the forkID, these variables below are
@@ -66,7 +66,7 @@ static void * ReturnPageAlignedAddress(void * addr) {
 }
 
 /** The initSnapShotRecord method initialized the snapshotting data
- *  structures for the mprotect based snapshot. 
+ *  structures for the mprotect based snapshot.
  */
 static void initSnapShotRecord(unsigned int numbackingpages, unsigned int numsnapshots, unsigned int nummemoryregions) {
        snapshotrecord=( struct SnapShot * )MYMALLOC(sizeof(struct SnapShot));
@@ -235,7 +235,7 @@ void initSnapShotLibrary(unsigned int numbackingpages,
 #endif
 }
 
-/** The addMemoryRegionToSnapShot function assumes that addr is page aligned. 
+/** The addMemoryRegionToSnapShot function assumes that addr is page aligned.
  */
 void addMemoryRegionToSnapShot( void * addr, unsigned int numPages) {
 #if USE_MPROTECT_SNAPSHOT
@@ -310,7 +310,7 @@ void rollBack( snapshot_id theID ){
        getcontext( &sTheRecord->mContextToRollback );
        /*
        * This is used to quit the process on rollback, so that
-       * the process which needs to rollback can quit allowing the process whose snapshotid matches the rollbackid to switch to 
+       * the process which needs to rollback can quit allowing the process whose snapshotid matches the rollbackid to switch to
        * this context and continue....
        */
        if( !sTemp ){
index b6eaee4ea18cb511b9d4e37edc78814669e152c8..6a9391f0302467097b415bf4b129eb1b90fffaa5 100644 (file)
@@ -23,10 +23,18 @@ Thread * thread_current(void)
        return model->scheduler->get_current_thread();
 }
 
-/* This method just gets around makecontext not being 64-bit clean */
-
+/**
+ * Provides a startup wrapper for each thread, allowing some initial
+ * model-checking data to be recorded. This method also gets around makecontext
+ * not being 64-bit clean
+ */
 void thread_startup() {
        Thread * curr_thread = thread_current();
+
+       /* Add dummy "start" action, just to create a first clock vector */
+       model->switch_to_master(new ModelAction(THREAD_START, memory_order_seq_cst, curr_thread));
+
+       /* Call the actual thread function */
        curr_thread->start_routine(curr_thread->arg);
 }
 
@@ -70,20 +78,19 @@ void Thread::complete()
 }
 
 Thread::Thread(thrd_t *t, void (*func)(void *), void *a) :
+       start_routine(func),
+       arg(a),
+       user_thread(t),
+       state(THREAD_CREATED),
        last_action_val(VALUE_NONE)
 {
        int ret;
 
-       user_thread = t;
-       start_routine = func;
-       arg = a;
-
        /* Initialize state */
        ret = create_context();
        if (ret)
                printf("Error in create_context\n");
 
-       state = THREAD_CREATED;
        id = model->get_next_id();
        *user_thread = id;
        parent = thread_current();