merging stuff...made need to clean up some stuff...but need to push it somewhere...
authorBrian Demsky <bdemsky@uci.edu>
Fri, 18 May 2012 23:32:38 +0000 (16:32 -0700)
committerBrian Demsky <bdemsky@uci.edu>
Fri, 18 May 2012 23:32:38 +0000 (16:32 -0700)
Merge branch 'subramanian'

Conflicts:
.gitignore
Makefile
action.h
userprog.c

14 files changed:
.gitignore
Makefile
action.h
clockvector.cc [new file with mode: 0644]
clockvector.h [new file with mode: 0644]
libatomic.cc
librace.cc
main.cc
model.cc
model.h
nodestack.cc [new file with mode: 0644]
nodestack.h [new file with mode: 0644]
threads.cc
userprog.c

index 6223e7e247fe260fa7f4aa31f9203c88dace4695..f9a26768ae7410a9403f3d87bec5d3829bcb0ab9 100644 (file)
@@ -3,7 +3,10 @@
 .*.swp
 *.so
 *~
+<<<<<<< HEAD
+=======
 *.*~
+>>>>>>> subramanian
 
 # files in this directory
 /model
index 8344effd65c0bc1ab51863901cd19eea584ebf74..b67d9947501e7685da888f8dc200a32516ee6348 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,9 +10,9 @@ LIB_MEM_SO=lib$(LIB_MEM).so
 USER_O=userprog.o
 USER_H=libthreads.h libatomic.h
 
-MODEL_CC=libthreads.cc schedule.cc libatomic.cc model.cc threads.cc tree.cc librace.cc action.cc main.cc snapshot-interface.cc
-MODEL_O=libthreads.o schedule.o libatomic.o model.o threads.o tree.o librace.o action.o main.o snapshot-interface.o
-MODEL_H=libthreads.h schedule.h common.h libatomic.h model.h threads.h tree.h librace.h action.h snapshot-interface.h
+MODEL_CC=libthreads.cc schedule.cc libatomic.cc model.cc malloc.c threads.cc tree.cc librace.cc action.cc nodestack.cc clockvector.cc main.cc snapshot-interface.cc
+MODEL_O=libthreads.o schedule.o libatomic.o model.o malloc.o threads.o tree.o librace.o action.o nodestack.o clockvector.o main.o snapshot-interface.o
+MODEL_H=libthreads.h schedule.h common.h libatomic.h model.h threads.h tree.h librace.h action.h nodestack.h clockvector.h snapshot-interface.h
 
 SHMEM_CC=snapshot.cc malloc.c mymemory.cc
 SHMEM_O=snapshot.o malloc.o mymemory.o
index c069cab3a3c5c3a7e6804498a2f6262b753a6f20..2f856e9dfa9be1363dacd91ac84384a52d93cd07 100644 (file)
--- a/action.h
+++ b/action.h
@@ -17,6 +17,7 @@ typedef enum action_type {
 
 /* Forward declaration */
 class TreeNode;
+class Node;
 
 class ModelAction {
 public:
@@ -27,10 +28,12 @@ public:
        action_type get_type() { return type; }
        memory_order get_mo() { return order; }
        void * get_location() { return location; }
-       int get_seq_number() { return seq_number; }
+       int get_seq_number() const { return seq_number; }
 
-       TreeNode * get_node() { return node; }
-       void set_node(TreeNode *n) { node = n; }
+       TreeNode * get_treenode() { return treenode; }
+       void set_node(TreeNode *n) { treenode = n; }
+       Node * get_node() { return node; }
+       void set_node(Node *n) { node = n; }
 
        bool is_read();
        bool is_write();
@@ -39,6 +42,13 @@ public:
        bool same_var(ModelAction *act);
        bool same_thread(ModelAction *act);
        bool is_dependent(ModelAction *act);
+
+       inline bool operator <(const ModelAction& act) const {
+               return get_seq_number() < act.get_seq_number();
+       }
+       inline bool operator >(const ModelAction& act) const {
+               return get_seq_number() > act.get_seq_number();
+       }
   MEMALLOC
 private:
        action_type type;
@@ -46,7 +56,8 @@ private:
        void *location;
        thread_id_t tid;
        int value;
-       TreeNode *node;
+       TreeNode *treenode;
+       Node *node;
        int seq_number;
 };
 
diff --git a/clockvector.cc b/clockvector.cc
new file mode 100644 (file)
index 0000000..15e6590
--- /dev/null
@@ -0,0 +1,61 @@
+#include <algorithm>
+#include <cstring>
+
+#include "model.h"
+#include "action.h"
+#include "clockvector.h"
+#include "common.h"
+
+ClockVector::ClockVector(ClockVector *parent, ModelAction *act)
+{
+       num_threads = parent ? parent->num_threads : 1;
+       if (act && act->get_type() == THREAD_CREATE)
+               num_threads++;
+       clock = (int *)myMalloc(num_threads * sizeof(int));
+       if (parent)
+               std::memcpy(clock, parent->clock, parent->num_threads * sizeof(int));
+       else
+               clock[0] = 0;
+
+       if (act)
+               clock[id_to_int(act->get_tid())] = act->get_seq_number();
+}
+
+ClockVector::~ClockVector()
+{
+       myFree(clock);
+}
+
+void ClockVector::merge(ClockVector *cv)
+{
+       int *clk = clock;
+       bool resize = false;
+
+       ASSERT(cv != NULL);
+
+       if (cv->num_threads > num_threads) {
+               resize = true;
+               clk = (int *)myMalloc(cv->num_threads * sizeof(int));
+       }
+
+       /* Element-wise maximum */
+       for (int i = 0; i < num_threads; i++)
+               clk[i] = std::max(clock[i], cv->clock[i]);
+
+       if (resize) {
+               for (int i = num_threads; i < cv->num_threads; i++)
+                       clk[i] = cv->clock[i];
+               num_threads = cv->num_threads;
+               myFree(clock);
+       }
+       clock = clk;
+}
+
+bool ClockVector::happens_before(ModelAction *act, thread_id_t id)
+{
+       int i = id_to_int(id);
+
+       if (i < num_threads)
+               return act->get_seq_number() < clock[i];
+       return false;
+}
diff --git a/clockvector.h b/clockvector.h
new file mode 100644 (file)
index 0000000..615dfeb
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __CLOCKVECTOR_H__
+#define __CLOCKVECTOR_H__
+
+#include "threads.h"
+
+/* Forward declaration */
+class ModelAction;
+
+class ClockVector {
+public:
+       ClockVector(ClockVector *parent = NULL, ModelAction *act = NULL);
+       ~ClockVector();
+       void merge(ClockVector *cv);
+       bool happens_before(ModelAction *act, thread_id_t id);
+private:
+       int *clock;
+       int num_threads;
+};
+
+#endif /* __CLOCKVECTOR_H__ */
index f552d93dd80a127b32a4f7ea76ec7cc3e8d5d6c6..88d7fbf79900859575b7b6d3bf1b78609caddd3b 100644 (file)
@@ -11,9 +11,10 @@ void atomic_store_explicit(struct atomic_object *obj, int value, memory_order or
 
 int atomic_load_explicit(struct atomic_object *obj, memory_order order)
 {
+       int value = obj->value;
        DBG();
-       model->switch_to_master(new ModelAction(ATOMIC_READ, order, obj, VALUE_NONE));
-       return obj->value;
+       model->switch_to_master(new ModelAction(ATOMIC_READ, order, obj, value));
+       return value;
 }
 
 void atomic_init(struct atomic_object *obj, int value)
index 42ed9c194d8134abc3980ac7651b81be3098669c..fa9a1101c07c0b05868ea60165d354a9588ef3c5 100644 (file)
@@ -7,43 +7,47 @@
 void store_8(void *addr, uint8_t val)
 {
        DEBUG("addr = %p, val = %" PRIu8 "\n", addr, val);
+       (*(uint8_t *)addr) = val;
 }
 
 void store_16(void *addr, uint16_t val)
 {
        DEBUG("addr = %p, val = %" PRIu16 "\n", addr, val);
+       (*(uint16_t *)addr) = val;
 }
 
 void store_32(void *addr, uint32_t val)
 {
        DEBUG("addr = %p, val = %" PRIu32 "\n", addr, val);
+       (*(uint32_t *)addr) = val;
 }
 
 void store_64(void *addr, uint64_t val)
 {
        DEBUG("addr = %p, val = %" PRIu64 "\n", addr, val);
+       (*(uint64_t *)addr) = val;
 }
 
 uint8_t load_8(void *addr)
 {
        DEBUG("addr = %p\n", addr);
-       return 0;
+       return *((uint8_t *)addr);
 }
 
 uint16_t load_16(void *addr)
 {
        DEBUG("addr = %p\n", addr);
-       return 0;
+       return *((uint16_t *)addr);
 }
 
 uint32_t load_32(void *addr)
 {
        DEBUG("addr = %p\n", addr);
-       return 0;
+       return *((uint32_t *)addr);
 }
 
 uint64_t load_64(void *addr)
 {
        DEBUG("addr = %p\n", addr);
-       return 0;
+       return *((uint64_t *)addr);
 }
diff --git a/main.cc b/main.cc
index 9af745d4280d865dab0c350a306e3594640a4968..e456ac6b326469a85383af6a97a422e9a2c65f92 100644 (file)
--- a/main.cc
+++ b/main.cc
@@ -1,7 +1,4 @@
-#include <stdlib.h>
-
 #include "libthreads.h"
-#include "schedule.h"
 #include "common.h"
 #include "threads.h"
 
index 51715d22614afaa3e61afa05df063cddba64c4a6..e068a089c162a292ba141351df5e217f26ab65bb 100644 (file)
--- a/model.cc
+++ b/model.cc
@@ -41,21 +41,21 @@ void free_action_list(action_list_t *list)
 }
 
 ModelChecker::ModelChecker()
-{
-       /* First thread created will have id INITIAL_THREAD_ID */
-       this->next_thread_id = INITIAL_THREAD_ID;
-       used_sequence_numbers = 0;
+       :
        /* Initialize default scheduler */
-       this->scheduler = new Scheduler();
-
-       num_executions = 0;
-       this->current_action = NULL;
-       this->exploring = NULL;
-       this->nextThread = THREAD_ID_T_NONE;
-
-       rootNode = new TreeNode();
-       currentNode = rootNode;
-       action_trace = new action_list_t();
+       scheduler(new Scheduler()),
+       /* First thread created will have id INITIAL_THREAD_ID */
+       next_thread_id(INITIAL_THREAD_ID),
+       used_sequence_numbers(0),
+
+       num_executions(0),
+       current_action(NULL),
+       exploring(NULL),
+       nextThread(THREAD_ID_T_NONE),
+       action_trace(new action_list_t()),
+       rootNode(new TreeNode()),
+       currentNode(rootNode)
+{
 }
 
 ModelChecker::~ModelChecker()
@@ -67,7 +67,7 @@ ModelChecker::~ModelChecker()
 
        free_action_list(action_trace);
 
-       delete this->scheduler;
+       delete scheduler;
        delete rootNode;
 }
 
@@ -83,6 +83,7 @@ void ModelChecker::reset_to_initial_state()
        current_action = NULL;
        next_thread_id = INITIAL_THREAD_ID;
        used_sequence_numbers = 0;
+       nextThread = 0;
        /* scheduler reset ? */
 }
 
@@ -120,10 +121,19 @@ thread_id_t ModelChecker::get_next_replay_thread()
        ModelAction *next;
        thread_id_t tid;
 
+       /* Have we completed exploring the preselected path? */
+       if (exploring == NULL)
+               return THREAD_ID_T_NONE;
+
+       /* Else, we are trying to replay an execution */
+       exploring->advance_state();
+
+       ASSERT(exploring->get_state() != NULL);
+
        next = exploring->get_state();
 
        if (next == exploring->get_diverge()) {
-               TreeNode *node = next->get_node();
+               TreeNode *node = next->get_treenode();
 
                /* Reached divergence point; discard our current 'exploring' */
                DEBUG("*** Discard 'Backtrack' object ***\n");
@@ -137,20 +147,6 @@ thread_id_t ModelChecker::get_next_replay_thread()
        return tid;
 }
 
-thread_id_t ModelChecker::advance_backtracking_state()
-{
-       /* Have we completed exploring the preselected path? */
-       if (exploring == NULL)
-               return THREAD_ID_T_NONE;
-
-       /* Else, we are trying to replay an execution */
-       exploring->advance_state();
-
-       ASSERT(exploring->get_state() != NULL);
-
-       return get_next_replay_thread();
-}
-
 bool ModelChecker::next_execution()
 {
        DBG();
@@ -167,7 +163,6 @@ bool ModelChecker::next_execution()
        }
 
        model->reset_to_initial_state();
-       nextThread = get_next_replay_thread();
        return true;
 }
 
@@ -205,7 +200,7 @@ void ModelChecker::set_backtracking(ModelAction *act)
        if (prev == NULL)
                return;
 
-       node = prev->get_node();
+       node = prev->get_treenode();
 
        while (t && !node->is_enabled(t))
                t = t->get_parent();
@@ -240,18 +235,18 @@ Backtrack * ModelChecker::get_next_backtrack()
 
 void ModelChecker::check_current_action(void)
 {
-       ModelAction *next = this->current_action;
-
-       if (!next) {
+       ModelAction *curr = this->current_action;
+       current_action = NULL;
+       if (!curr) {
                DEBUG("trying to push NULL action...\n");
                return;
        }
-       current_action = NULL;
-       nextThread = advance_backtracking_state();
-       next->set_node(currentNode);
-       set_backtracking(next);
-       currentNode = currentNode->explore_child(next);
-       this->action_trace->push_back(next);
+
+       nextThread = get_next_replay_thread();
+       curr->set_node(currentNode);
+       set_backtracking(curr);
+       currentNode = currentNode->explore_child(curr);
+       this->action_trace->push_back(curr);
 }
 
 void ModelChecker::print_summary(void)
diff --git a/model.h b/model.h
index d3b42053fcee011ed32e47df7fef9822aadd144d..1dc6a158d3aa63247d1051977fe734f1b9cf042f 100644 (file)
--- a/model.h
+++ b/model.h
@@ -51,7 +51,6 @@ private:
 
        ModelAction * get_last_conflict(ModelAction *act);
        void set_backtracking(ModelAction *act);
-       thread_id_t advance_backtracking_state();
        thread_id_t get_next_replay_thread();
        Backtrack * get_next_backtrack();
        void reset_to_initial_state();
diff --git a/nodestack.cc b/nodestack.cc
new file mode 100644 (file)
index 0000000..379fb3b
--- /dev/null
@@ -0,0 +1,173 @@
+#include "nodestack.h"
+#include "action.h"
+#include "common.h"
+
+int Node::total_nodes = 0;
+
+Node::Node(ModelAction *act, Node *parent)
+       : action(act),
+       num_threads(parent ? parent->num_threads : 1),
+       explored_children(num_threads),
+       backtrack(num_threads)
+{
+       total_nodes++;
+       if (act && act->get_type() == THREAD_CREATE) {
+               num_threads++;
+               explored_children.resize(num_threads);
+               backtrack.resize(num_threads);
+       }
+}
+
+Node::~Node()
+{
+       if (action)
+               delete action;
+}
+
+void Node::print()
+{
+       if (action)
+               action->print();
+       else
+               printf("******** empty action ********\n");
+}
+
+bool Node::has_been_explored(thread_id_t tid)
+{
+       int id = id_to_int(tid);
+       return explored_children[id];
+}
+
+bool Node::backtrack_empty()
+{
+       unsigned int i;
+       for (i = 0; i < backtrack.size(); i++)
+               if (backtrack[i] == true)
+                       return false;
+       return true;
+}
+
+void Node::explore_child(ModelAction *act)
+{
+       act->set_node(this);
+       explore(act->get_tid());
+}
+
+bool Node::set_backtrack(thread_id_t id)
+{
+       int i = id_to_int(id);
+       if (backtrack[i])
+               return false;
+       backtrack[i] = true;
+       return true;
+}
+
+thread_id_t Node::get_next_backtrack()
+{
+       /* TODO: find next backtrack */
+       unsigned int i;
+       for (i = 0; i < backtrack.size(); i++)
+               if (backtrack[i] == true)
+                       break;
+       if (i >= backtrack.size())
+               return THREAD_ID_T_NONE;
+       backtrack[i] = false;
+       return int_to_id(i);
+}
+
+bool Node::is_enabled(Thread *t)
+{
+       return id_to_int(t->get_id()) < num_threads;
+}
+
+void Node::explore(thread_id_t tid)
+{
+       int i = id_to_int(tid);
+       backtrack[i] = false;
+       explored_children[i] = true;
+}
+
+static void clear_node_list(node_list_t *list, node_list_t::iterator start,
+                                              node_list_t::iterator end)
+{
+       node_list_t::iterator it;
+
+       for (it = start; it != end; it++)
+               delete (*it);
+       list->erase(start, end);
+}
+
+NodeStack::NodeStack()
+{
+       node_list.push_back(new Node());
+       iter = node_list.begin();
+}
+
+NodeStack::~NodeStack()
+{
+       clear_node_list(&node_list, node_list.begin(), node_list.end());
+}
+
+void NodeStack::print()
+{
+       node_list_t::iterator it;
+       printf("............................................\n");
+       printf("NodeStack printing node_list:\n");
+       for (it = node_list.begin(); it != node_list.end(); it++) {
+               if (it == this->iter)
+                       printf("vvv following action is the current iterator vvv\n");
+               (*it)->print();
+       }
+       printf("............................................\n");
+}
+
+ModelAction * NodeStack::explore_action(ModelAction *act)
+{
+       DBG();
+
+       ASSERT(!node_list.empty());
+
+       if (get_head()->has_been_explored(act->get_tid())) {
+               /* Discard duplicate ModelAction */
+               delete act;
+               iter++;
+       } else { /* Diverging from previous execution */
+               /* Clear out remainder of list */
+               node_list_t::iterator it = iter;
+               it++;
+               clear_node_list(&node_list, it, node_list.end());
+
+               /* Record action */
+               get_head()->explore_child(act);
+               node_list.push_back(new Node(act, get_head()));
+               iter++;
+       }
+       return (*iter)->get_action();
+}
+
+Node * NodeStack::get_head()
+{
+       if (node_list.empty())
+               return NULL;
+       return *iter;
+}
+
+Node * NodeStack::get_next()
+{
+       node_list_t::iterator it = iter;
+       if (node_list.empty()) {
+               DEBUG("Empty\n");
+               return NULL;
+       }
+       it++;
+       if (it == node_list.end()) {
+               DEBUG("At end\n");
+               return NULL;
+       }
+       return *it;
+}
+
+void NodeStack::reset_execution()
+{
+       iter = node_list.begin();
+}
diff --git a/nodestack.h b/nodestack.h
new file mode 100644 (file)
index 0000000..2fd84dd
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __NODESTACK_H__
+#define __NODESTACK_H__
+
+#include <list>
+#include <vector>
+#include <cstddef>
+#include "threads.h"
+
+class ModelAction;
+
+class Node {
+public:
+       Node(ModelAction *act = NULL, Node *parent = NULL);
+       ~Node();
+       /* return true = thread choice has already been explored */
+       bool has_been_explored(thread_id_t tid);
+       /* return true = backtrack set is empty */
+       bool backtrack_empty();
+       void explore_child(ModelAction *act);
+       /* return false = thread was already in backtrack */
+       bool set_backtrack(thread_id_t id);
+       thread_id_t get_next_backtrack();
+       bool is_enabled(Thread *t);
+       ModelAction * get_action() { return action; }
+
+       void print();
+
+       static int get_total_nodes() { return total_nodes; }
+private:
+       void explore(thread_id_t tid);
+
+       static int total_nodes;
+       ModelAction *action;
+       int num_threads;
+       std::vector<bool> explored_children;
+       std::vector<bool> backtrack;
+};
+
+typedef std::list<class Node *> node_list_t;
+
+class NodeStack {
+public:
+       NodeStack();
+       ~NodeStack();
+       ModelAction * explore_action(ModelAction *act);
+       Node * get_head();
+       Node * get_next();
+       void reset_execution();
+
+       void print();
+private:
+       node_list_t node_list;
+       node_list_t::iterator iter;
+};
+
+#endif /* __NODESTACK_H__ */
index 10ff3c5d6b437fadcc4945f94102207e1d9cca5f..99297749a800987b48a157570daf0820aeb5715d 100644 (file)
@@ -1,7 +1,4 @@
-#include <stdlib.h>
-
 #include "libthreads.h"
-#include "schedule.h"
 #include "common.h"
 #include "threads.h"
 
index 5598bfb4b7b6558496b2ea5383d90500d8e014a2..0948f0bc395a5d103963e99d81592ac6e2307072 100644 (file)
@@ -2,13 +2,17 @@
 
 #include "libthreads.h"
 #include "libatomic.h"
+#include "librace.h"
 
 static void a(atomic_int *obj)
 {
        int i;
        int ret;
 
-       for (i = 0; i < 7; i++) {
+       store_32(&i, 10);
+       printf("load 32 yields: %d\n", load_32(&i));
+
+       for (i = 0; i < 2; i++) {
                printf("Thread %d, loop %d\n", thrd_current(), i);
                switch (i  ) {
                case 1:
@@ -16,8 +20,8 @@ static void a(atomic_int *obj)
                        printf("Read value: %d\n", ret);
                        break;
                case 0:
-                       atomic_store(obj, i);
-                       printf("Write value: %d\n", i);
+                       atomic_store(obj, i + 1);
+                       printf("Write value: %d\n", i + 1);
                        break;
                }
        }