Merge branch 'master' of ssh://demsky.eecs.uci.edu/home/git/model-checker
authorSubramanian Ganapathy <sganapat@uci.edu>
Wed, 30 May 2012 21:25:42 +0000 (14:25 -0700)
committerSubramanian Ganapathy <sganapat@uci.edu>
Wed, 30 May 2012 21:25:42 +0000 (14:25 -0700)
21 files changed:
Makefile
action.cc
action.h
clockvector.cc
clockvector.h
common.h
libthreads.cc
main.cc
model.cc
model.h
mymemory.cc
nodestack.cc
nodestack.h
schedule.h
snapshot-interface.cc
snapshot-interface.h
snapshot.cc
snapshot.h
snapshotimp.h
threads.cc
threads.h

index ef89c5a7e9d924ee97cf5560e32b5e29c5afeadb..de9051cfda92d7d75e1ef4e1b7fbaf6448a3d3e8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,9 @@ LDFLAGS=-ldl -lrt
 
 all: $(BIN)
 
+debug: CPPFLAGS += -DCONFIG_DEBUG
+debug: all
+
 $(BIN): $(USER_O) $(LIB_SO)
        $(CXX) -o $(BIN) $(USER_O) -L. -l$(LIB_NAME)
 
index eb2f0c61f024e64fed76bc85131c47193cfe4d8f..28d95270a7eb19bec65d136034f13e7615edbdec 100644 (file)
--- a/action.cc
+++ b/action.cc
@@ -2,6 +2,8 @@
 
 #include "model.h"
 #include "action.h"
+#include "clockvector.h"
+#include "common.h"
 
 ModelAction::ModelAction(action_type_t type, memory_order order, void *loc, int value)
 {
@@ -14,6 +16,14 @@ ModelAction::ModelAction(action_type_t type, memory_order order, void *loc, int
        act->tid = t->get_id();
        act->value = value;
        act->seq_number = model->get_next_seq_num();
+
+       cv = NULL;
+}
+
+ModelAction::~ModelAction()
+{
+       if (cv)
+               delete cv;
 }
 
 bool ModelAction::is_read()
@@ -52,8 +62,7 @@ bool ModelAction::is_release()
 
 bool ModelAction::same_var(ModelAction *act)
 {
-       return true;
-       // TODO: fix stack allocation... return location == act->location;
+       return location == act->location;
 }
 
 bool ModelAction::same_thread(ModelAction *act)
@@ -73,6 +82,25 @@ bool ModelAction::is_dependent(ModelAction *act)
        return false;
 }
 
+void ModelAction::create_cv(ModelAction *parent)
+{
+       if (cv)
+               return;
+
+       if (parent)
+               cv = new ClockVector(parent->cv, this);
+       else
+               cv = new ClockVector(NULL, this);
+}
+
+void ModelAction::read_from(ModelAction *act)
+{
+       ASSERT(cv);
+       if (act->is_release() && this->is_acquire())
+               cv->merge(act->cv);
+       value = act->value;
+}
+
 void ModelAction::print(void)
 {
        const char *type_str;
@@ -96,6 +124,11 @@ void ModelAction::print(void)
                type_str = "unknown type";
        }
 
-       printf("(%4d) Thread: %d\tAction: %s\tMO: %d\tLoc: %14p\tValue: %d\n",
+       printf("(%3d) Thread: %-2d    Action: %-13s    MO: %d    Loc: %14p    Value: %d",
                        seq_number, id_to_int(tid), type_str, order, location, value);
+       if (cv) {
+               printf("\t");
+               cv->print();
+       } else
+               printf("\n");
 }
index 005e65842e7353f9ca0dc50846eddf9bf054a111..62141749d5efafc34dc1bbe3fef6656b344571ec 100644 (file)
--- a/action.h
+++ b/action.h
@@ -2,6 +2,8 @@
 #define __ACTION_H__
 
 #include <list>
+#include <cstddef>
+
 #include "threads.h"
 #include "libatomic.h"
 #include "mymemory.h"
@@ -17,10 +19,12 @@ typedef enum action_type {
 
 /* Forward declaration */
 class Node;
+class ClockVector;
 
 class ModelAction {
 public:
        ModelAction(action_type_t type, memory_order order, void *loc, int value);
+       ~ModelAction();
        void print(void);
 
        thread_id_t get_tid() { return tid; }
@@ -40,6 +44,9 @@ public:
        bool same_thread(ModelAction *act);
        bool is_dependent(ModelAction *act);
 
+       void create_cv(ModelAction *parent = NULL);
+       void read_from(ModelAction *act);
+
        inline bool operator <(const ModelAction& act) const {
                return get_seq_number() < act.get_seq_number();
        }
@@ -56,8 +63,10 @@ private:
        int value;
        Node *node;
        int seq_number;
+
+       ClockVector *cv;
 };
 
-typedef std::list<class ModelAction *, MyAlloc< class ModelAction * > > action_list_t;
+typedef std::list<class ModelAction *> action_list_t;
 
 #endif /* __ACTION_H__ */
index da459d0e0faf461aab67af55ab7f3338082fdd9d..f411f50d64bcb9ca6c1b7eefe48f871bcc1c1bff 100644 (file)
@@ -1,5 +1,6 @@
 #include <algorithm>
 #include <cstring>
+#include <stdlib.h>
 
 #include "model.h"
 #include "action.h"
@@ -8,14 +9,11 @@
 
 ClockVector::ClockVector(ClockVector *parent, ModelAction *act)
 {
-       num_threads = parent ? parent->num_threads : 1;
-       if (act && act->get_type() == THREAD_CREATE)
-               num_threads++;
+       num_threads = model->get_num_threads();
        clock = (int *)MYMALLOC(num_threads * sizeof(int));
+       memset(clock, 0, 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();
@@ -59,3 +57,11 @@ bool ClockVector::happens_before(ModelAction *act, thread_id_t id)
                return act->get_seq_number() < clock[i];
        return false;
 }
+
+void ClockVector::print()
+{
+       int i;
+       printf("CV: (");
+       for (i = 0; i < num_threads; i++)
+               printf("%2d%s", clock[i], (i == num_threads - 1) ? ")\n" : ", ");
+}
index 615dfeb7e83196dff11213ed589ceaaadc7b2196..eb7086253d7f97e79b0f1d1ce41ef7b4e988e561 100644 (file)
@@ -2,6 +2,7 @@
 #define __CLOCKVECTOR_H__
 
 #include "threads.h"
+#include "mymemory.h"
 
 /* Forward declaration */
 class ModelAction;
@@ -12,6 +13,10 @@ public:
        ~ClockVector();
        void merge(ClockVector *cv);
        bool happens_before(ModelAction *act, thread_id_t id);
+
+       void print();
+
+       MEMALLOC
 private:
        int *clock;
        int num_threads;
index 3e97432cb2c825cbcf56d7fb6c1510bc8e825eb7..656ea3798dde73d08b168fdfe54f5d4c72dcc04d 100644 (file)
--- a/common.h
+++ b/common.h
@@ -2,10 +2,12 @@
 #define __COMMON_H__
 
 #include <stdio.h>
-#include <stdlib.h>
-#include "mymemory.h"
 
-//#define CONFIG_DEBUG
+/*
+#ifndef CONFIG_DEBUG
+#define CONFIG_DEBUG
+#endif
+*/
 
 #ifdef CONFIG_DEBUG
 #define DEBUG(fmt, ...) do { printf("*** %25s(): line %-4d *** " fmt, __func__, __LINE__, ##__VA_ARGS__); } while (0)
@@ -25,8 +27,4 @@ do { \
        } \
 } while (0);
 
-
-#define userMalloc(size)       malloc(size)
-#define userFree(ptr)          free(ptr)
-
 #endif /* __COMMON_H__ */
index e8d3b6e61e78710169d03da5b4d57180a7c388e0..a414686dccb713116bad22a1e6126f590b72cc7b 100644 (file)
  */
 int thrd_create(thrd_t *t, thrd_start_t start_routine, void *arg)
 {
+       Thread *thread;
        int ret;
        DBG();
-       ret = model->add_thread(new Thread(t, start_routine, arg));
+       thread = new Thread(t, start_routine, arg);
+       ret = model->add_thread(thread);
        DEBUG("create thread %d\n", id_to_int(thrd_to_id(*t)));
        /* seq_cst is just a 'don't care' parameter */
-       model->switch_to_master(new ModelAction(THREAD_CREATE, memory_order_seq_cst, NULL, VALUE_NONE));
+       model->switch_to_master(new ModelAction(THREAD_CREATE, memory_order_seq_cst, thread, VALUE_NONE));
        return ret;
 }
 
diff --git a/main.cc b/main.cc
index c5b6028f27536551078a0447d0c57e4d1bb15542..e8a2b3317dc4ebedc235735fef32d272259d4215 100644 (file)
--- a/main.cc
+++ b/main.cc
@@ -4,7 +4,6 @@
 
 /* global "model" object */
 #include "model.h"
-#include "snapshot.h"
 #include "snapshot-interface.h"
 
 /*
@@ -43,8 +42,8 @@ void real_main() {
        thrd_t user_thread;
        ucontext_t main_context;
 
-       //Create the singleton snapshotStack object
-       snapshotObject = new snapshotStack();
+       //Create the singleton SnapshotStack object
+       snapshotObject = new SnapshotStack();
 
        model = new ModelChecker();
 
@@ -53,6 +52,8 @@ void real_main() {
 
        model->set_system_context(&main_context);
 
+       snapshotObject->snapshotStep(0);
+
        do {
                /* Start user program */
                model->add_thread(new Thread(&user_thread, (void (*)(void *)) &user_main, NULL));
index 47b1b4dd666e5043129cda9e35d6cbde0727a754..2ffa22a1028a8008c1c60e52e8e9fee627fac766 100644 (file)
--- a/model.cc
+++ b/model.cc
@@ -24,6 +24,9 @@ ModelChecker::ModelChecker()
        diverge(NULL),
        nextThread(THREAD_ID_T_NONE),
        action_trace(new action_list_t()),
+       thread_map(new std::map<int, class Thread *>),
+       obj_thrd_map(new std::map<void *, std::vector<action_list_t> >()),
+       thrd_last_action(new std::vector<ModelAction *>(1)),
        node_stack(new NodeStack()),
        next_backtrack(NULL)
 {
@@ -31,13 +34,14 @@ ModelChecker::ModelChecker()
 
 ModelChecker::~ModelChecker()
 {
-       std::map<int, class Thread *, std::less< int >, MyAlloc< std::pair< int, class Thread * > > >::iterator it;
-       for (it = thread_map.begin(); it != thread_map.end(); it++)
+       std::map<int, class Thread *>::iterator it;
+       for (it = thread_map->begin(); it != thread_map->end(); it++)
                delete (*it).second;
-       thread_map.clear();
+       delete thread_map;
 
+       delete obj_thrd_map;
        delete action_trace;
-
+       delete thrd_last_action;
        delete node_stack;
        delete scheduler;
 }
@@ -45,19 +49,13 @@ ModelChecker::~ModelChecker()
 void ModelChecker::reset_to_initial_state()
 {
        DEBUG("+++ Resetting to initial state +++\n");
-       std::map<int, class Thread *, std::less< int >, MyAlloc< std::pair< int, class Thread * > > >::iterator it;
-       for (it = thread_map.begin(); it != thread_map.end(); it++)
-               delete (*it).second;
-       thread_map.clear();
-       delete action_trace;
-       action_trace = new action_list_t();
        node_stack->reset_execution();
        current_action = NULL;
        next_thread_id = INITIAL_THREAD_ID;
        used_sequence_numbers = 0;
        nextThread = 0;
        next_backtrack = NULL;
-       /* scheduler reset ? */
+       snapshotObject->backTrackBeforeStep(0);
 }
 
 thread_id_t ModelChecker::get_next_id()
@@ -65,6 +63,11 @@ thread_id_t ModelChecker::get_next_id()
        return next_thread_id++;
 }
 
+int ModelChecker::get_num_threads()
+{
+       return next_thread_id;
+}
+
 int ModelChecker::get_next_seq_num()
 {
        return ++used_sequence_numbers;
@@ -75,7 +78,7 @@ Thread * ModelChecker::schedule_next_thread()
        Thread *t;
        if (nextThread == THREAD_ID_T_NONE)
                return NULL;
-       t = thread_map[id_to_int(nextThread)];
+       t = (*thread_map)[id_to_int(nextThread)];
 
        ASSERT(t != NULL);
 
@@ -209,6 +212,14 @@ void ModelChecker::check_current_action(void)
        }
 
        curr = node_stack->explore_action(curr);
+       curr->create_cv(get_parent_action(curr->get_tid()));
+
+       /* Assign 'creation' parent */
+       if (curr->get_type() == THREAD_CREATE) {
+               Thread *th = (Thread *)curr->get_location();
+               th->set_creation(curr);
+       }
+
        nextThread = get_next_replay_thread();
 
        currnode = curr->get_node();
@@ -218,7 +229,36 @@ void ModelChecker::check_current_action(void)
                        next_backtrack = curr;
 
        set_backtracking(curr);
-       this->action_trace->push_back(curr);
+
+       add_action_to_lists(curr);
+}
+
+void ModelChecker::add_action_to_lists(ModelAction *act)
+{
+       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())
+               vec->resize(next_thread_id);
+       (*vec)[id_to_int(act->get_tid())].push_back(act);
+
+       (*thrd_last_action)[id_to_int(act->get_tid())] = act;
+}
+
+ModelAction * ModelChecker::get_last_action(thread_id_t tid)
+{
+       int nthreads = get_num_threads();
+       if ((int)thrd_last_action->size() < nthreads)
+               thrd_last_action->resize(nthreads);
+       return (*thrd_last_action)[id_to_int(tid)];
+}
+
+ModelAction * ModelChecker::get_parent_action(thread_id_t tid)
+{
+       ModelAction *parent = get_last_action(tid);
+       if (!parent)
+               parent = get_thread(tid)->get_creation();
+       return parent;
 }
 
 void ModelChecker::print_summary(void)
@@ -248,7 +288,7 @@ void ModelChecker::print_list(action_list_t *list)
 
 int ModelChecker::add_thread(Thread *t)
 {
-       thread_map[id_to_int(t->get_id())] = t;
+       (*thread_map)[id_to_int(t->get_id())] = t;
        scheduler->add_thread(t);
        return 0;
 }
diff --git a/model.h b/model.h
index 99ec69e62eb6908e1db1ea104f0c05222b0f3d9c..d89a8a2b123b1743c58f3c5d7c883c87263b45b9 100644 (file)
--- a/model.h
+++ b/model.h
@@ -34,9 +34,10 @@ public:
 
        int add_thread(Thread *t);
        void remove_thread(Thread *t);
-       Thread * get_thread(thread_id_t tid) { return thread_map[id_to_int(tid)]; }
+       Thread * get_thread(thread_id_t tid) { return (*thread_map)[id_to_int(tid)]; }
 
        thread_id_t get_next_id();
+       int get_num_threads();
        int get_next_seq_num();
 
        int switch_to_master(ModelAction *act);
@@ -55,6 +56,10 @@ private:
        ModelAction * get_next_backtrack();
        void reset_to_initial_state();
 
+       void add_action_to_lists(ModelAction *act);
+       ModelAction * get_last_action(thread_id_t tid);
+       ModelAction * get_parent_action(thread_id_t tid);
+
        void print_list(action_list_t *list);
 
        ModelAction *current_action;
@@ -63,7 +68,9 @@ private:
 
        ucontext_t *system_context;
        action_list_t *action_trace;
-       std::map<int, class Thread *, std::less< int >, MyAlloc< std::pair< const int, class Thread * > > > thread_map;
+       std::map<int, class Thread *> *thread_map;
+       std::map<void *, std::vector<action_list_t> > *obj_thrd_map;
+       std::vector<ModelAction *> *thrd_last_action;
        class NodeStack *node_stack;
        ModelAction *next_backtrack;
 };
index a825bb940f66f4331e723eadd8983f9bd8d05e70..80c1b953ff6855e24d058ddffa6589f29a6dda1f 100644 (file)
@@ -3,12 +3,12 @@
 #include "snapshotimp.h"
 #include <stdio.h>
 #include <dlfcn.h>
-#if !USE_CHECKPOINTING
+#if !USE_MPROTECT_SNAPSHOT
 static mspace sStaticSpace = NULL;
 #endif
 
 void *MYMALLOC(size_t size) {
-#if USE_CHECKPOINTING
+#if USE_MPROTECT_SNAPSHOT
        static void *(*mallocp)(size_t size);
        char *error;
        void *ptr;
@@ -34,7 +34,7 @@ void *MYMALLOC(size_t size) {
 }
 
 void MYFREE(void *ptr) {
-#if USE_CHECKPOINTING
+#if USE_MPROTECT_SNAPSHOT
        static void (*freep)(void *);
        char *error;
 
@@ -63,9 +63,17 @@ void free( void * ptr ){
 }
 
 void * operator new(size_t size) throw(std::bad_alloc) {
-       return MYMALLOC(size);
+       return malloc(size);
 }
 
 void operator delete(void *p) throw() {
-       MYFREE(p);
+       free(p);
+}
+
+void * operator new[](size_t size) throw(std::bad_alloc) {
+       return malloc(size);
+}
+
+void operator delete[](void *p, size_t size) {
+       free(p);
 }
index 379fb3b1fc15f219cdd870b4976af0e394fd2263..df5fc633ac37aba0b6df464f51be996ab8403eb6 100644 (file)
@@ -1,21 +1,17 @@
 #include "nodestack.h"
 #include "action.h"
 #include "common.h"
+#include "model.h"
 
 int Node::total_nodes = 0;
 
-Node::Node(ModelAction *act, Node *parent)
+Node::Node(ModelAction *act, int nthreads)
        : action(act),
-       num_threads(parent ? parent->num_threads : 1),
+       num_threads(nthreads),
        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()
@@ -139,7 +135,7 @@ ModelAction * NodeStack::explore_action(ModelAction *act)
 
                /* Record action */
                get_head()->explore_child(act);
-               node_list.push_back(new Node(act, get_head()));
+               node_list.push_back(new Node(act, model->get_num_threads()));
                iter++;
        }
        return (*iter)->get_action();
index 3a0ee74cf0c47a3717997d7a47c04d0a9b824b4f..cf3c6db146675c0cb7f41d994f988925209fc976 100644 (file)
@@ -11,7 +11,7 @@ class ModelAction;
 
 class Node {
 public:
-       Node(ModelAction *act = NULL, Node *parent = NULL);
+       Node(ModelAction *act = NULL, int nthreads = 1);
        ~Node();
        /* return true = thread choice has already been explored */
        bool has_been_explored(thread_id_t tid);
@@ -35,11 +35,11 @@ private:
        static int total_nodes;
        ModelAction *action;
        int num_threads;
-       std::vector<bool> explored_children;
-       std::vector<bool> backtrack;
+       std::vector< bool, MyAlloc<bool> > explored_children;
+       std::vector< bool, MyAlloc<bool> > backtrack;
 };
 
-typedef std::list<class Node *> node_list_t;
+typedef std::list<class Node *, MyAlloc< class Node * > > node_list_t;
 
 class NodeStack {
 public:
index c99748c730a4812a303eecf2d30cfc0876a17bd5..f4965369b2a62be67a124ae29a44b4172c28f0eb 100644 (file)
@@ -16,9 +16,9 @@ public:
        Thread * get_current_thread(void);
        void print();
 
-       MEMALLOC
+       SNAPSHOTALLOC
 private:
-       std::list<Thread *, MyAlloc< Thread * > > readyList;
+       std::list<Thread *> readyList;
        Thread *current;
 };
 
index 76cb8f4ea2635afc940fec658477840d9933dbc1..2ef7e4ba94f9ef88b250b9dce1d5d3b3ff551efd 100644 (file)
@@ -1,19 +1,24 @@
 #include "snapshot-interface.h"
+#include "snapshot.h"
 #include <iostream>
 #include <fstream>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sstream>
 #include <cstring>
+#include <string>
 #include <cassert>
+#include <vector>
+#include <utility>
 
 #define MYBINARYNAME "model"
 #define MYLIBRARYNAME "libmodel.so"
 #define PROCNAME      "/proc/*/maps"
 #define REPLACEPOS             6
-#define PAGESIZE 4096
 
-snapshotStack * snapshotObject;
+typedef std::basic_string<char, std::char_traits<char>, MyAlloc<char> > MyString;
+
+SnapshotStack * snapshotObject;
 
 /*This looks like it might leak memory...  Subramanian should fix this. */
 
@@ -61,11 +66,11 @@ void SnapshotGlobalSegments(){
                MyString line;
                while( procName.good() ){
                        getline( procName, line );
-                       int i  = 0;
-                       for( i = 0; i < 3; ++i ){
+                       int i;
+                       for( i = 0; i < 2; ++i ){
                                if( MyString::npos != line.find( dataSect[ i ].first ) ) break;                 
                        }
-                       if( i >= 3 || dataSect[ i ].second == true ) continue;
+                       if( i >= 2 || dataSect[ i ].second == true ) continue;
                        dataSect[ i ].second = true;
                        if( !procName.good() )return;
                        getline( procName, line );
@@ -74,17 +79,17 @@ void SnapshotGlobalSegments(){
        }
 }
 
-//class definition of snapshotStack.....
+//class definition of SnapshotStack.....
 //declaration of constructor....
-snapshotStack::snapshotStack(){
+SnapshotStack::SnapshotStack(){
        SnapshotGlobalSegments();
        stack=NULL;
 }
        
-snapshotStack::~snapshotStack(){
+SnapshotStack::~SnapshotStack(){
 }
        
-int snapshotStack::backTrackBeforeStep(int seqindex) {
+int SnapshotStack::backTrackBeforeStep(int seqindex) {
        while(true) {
                if (stack->index<=seqindex) {
                        //have right entry
@@ -97,7 +102,7 @@ int snapshotStack::backTrackBeforeStep(int seqindex) {
        }
 }
 
-void snapshotStack::snapshotStep(int seqindex) {
+void SnapshotStack::snapshotStep(int seqindex) {
        struct stackEntry *tmp=(struct stackEntry *)MYMALLOC(sizeof(struct stackEntry));
        tmp->next=stack;
        tmp->index=seqindex;
index cbebcd58f84a5902fcb784de16f0d439b137513b..e9746e1ebb35468ff20e0ea68fd9ee364a0e7cd6 100644 (file)
@@ -1,17 +1,13 @@
 #ifndef __SNAPINTERFACE_H
 #define __SNAPINTERFACE_H
-#include "snapshot.h"
 #include "mymemory.h"
-#include <vector>
-#include <utility>
-#include <string>
-#include <map>
-#include <set>
-#include "snapshot.h"
-#include "libthreads.h"
 
-class snapshotStack;
-typedef std::basic_string<char, std::char_traits<char>, MyAlloc<char> > MyString;
+typedef unsigned int snapshot_id;
+
+typedef void (*VoidFuncPtr)();
+void initSnapShotLibrary(unsigned int numbackingpages,
+               unsigned int numsnapshots, unsigned int nummemoryregions,
+               unsigned int numheappages, VoidFuncPtr entryPoint);
 
 void SnapshotGlobalSegments();
 
@@ -21,11 +17,11 @@ struct stackEntry {
   int index;
 };
 
-class snapshotStack {
+class SnapshotStack {
  public:
   MEMALLOC
-  snapshotStack( );
-  ~snapshotStack();
+  SnapshotStack( );
+  ~SnapshotStack();
   int backTrackBeforeStep(int seq_index);
   void snapshotStep(int seq_index);
 
@@ -36,5 +32,5 @@ class snapshotStack {
 /* Not sure what it even means to have more than one snapshot object,
    so let's just make a global reference to it.*/
 
-extern snapshotStack * snapshotObject;
+extern SnapshotStack * snapshotObject;
 #endif
index 20980015fe50d9678e67a606f37e2a3b934aa3e6..7cea7d6191ca457b5c7b98cd1e45dc2c15596e22 100644 (file)
@@ -4,7 +4,6 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <map>
-#include <set>
 #include <cstring>
 #include <cstdio>
 #include "snapshot.h"
 #include <errno.h>
 #include <sys/wait.h>
 #include <ucontext.h>
-#include <sys/time.h>
+
 //extern declaration definition
 #define FAILURE(mesg) { printf("failed in the API: %s with errno relative message: %s\n", mesg, strerror( errno ) ); exit( -1 ); }
-#if USE_CHECKPOINTING
+#if USE_MPROTECT_SNAPSHOT
 struct SnapShot * snapshotrecord = NULL;
 struct Snapshot_t * sTheRecord = NULL;
 #else
 struct Snapshot_t * sTheRecord = NULL;
 #endif
-void BeginOperation( struct timeval * theStartTime ){
-#if 1
-       gettimeofday( theStartTime, NULL );
-#endif
-}
-#if SSDEBUG
-struct timeval *starttime = NULL;
-#endif
 void DumpIntoLog( const char * filename, const char * message ){
 #if SSDEBUG
        static pid_t thePID = getpid();
        char newFn[ 1024 ] ={ 0 };
        sprintf( newFn,"%s-%d.txt", filename, thePID );
        FILE * myFile = fopen( newFn, "w+" );
-       struct timeval theEndTime;
-       BeginOperation( &theEndTime );
-       double elapsed = ( theEndTime.tv_sec - starttime->tv_sec ) + ( theEndTime.tv_usec - starttime->tv_usec ) / 1000000.0;
-       fprintf( myFile, "The timestamp %f:--> the message %s: the process id %d\n", elapsed, message, thePID );
+       fprintf( myFile, "the message %s: the process id %d\n", message, thePID );
        fflush( myFile );
        fclose( myFile );
        myFile = NULL;
 #endif
 }
-#if !USE_CHECKPOINTING
+#if !USE_MPROTECT_SNAPSHOT
 static ucontext_t savedSnapshotContext;
 static ucontext_t savedUserSnapshotContext;
-static int snapshotid = 0;
+static snapshot_id snapshotid = 0;
 #endif
 /* Initialize snapshot data structure */
-#if USE_CHECKPOINTING
+#if USE_MPROTECT_SNAPSHOT
 void initSnapShotRecord(unsigned int numbackingpages, unsigned int numsnapshots, unsigned int nummemoryregions) {
        snapshotrecord=( struct SnapShot * )MYMALLOC(sizeof(struct SnapShot));
        snapshotrecord->regionsToSnapShot=( struct MemoryRegion * )MYMALLOC(sizeof(struct MemoryRegion)*nummemoryregions);
@@ -74,16 +62,16 @@ void initSnapShotRecord(unsigned int numbackingpages, unsigned int numsnapshots,
 #endif //nothing to initialize for the fork based snapshotting.
 
 void HandlePF( int sig, siginfo_t *si, void * unused){
-#if USE_CHECKPOINTING
+#if USE_MPROTECT_SNAPSHOT
        if( si->si_code == SEGV_MAPERR ){
-               printf("Real Fault at %llx\n", ( long long )si->si_addr);
-               exit( EXIT_FAILURE );   
+               printf("Real Fault at %p\n", si->si_addr);
+               exit( EXIT_FAILURE );
        }
        void* addr = ReturnPageAlignedAddress(si->si_addr);
        unsigned int backingpage=snapshotrecord->lastBackingPage++; //Could run out of pages...
        if (backingpage==snapshotrecord->maxBackingPages) {
-               printf("Out of backing pages at %llx\n", ( long long )si->si_addr);
-               exit( EXIT_FAILURE );   
+               printf("Out of backing pages at %p\n", si->si_addr);
+               exit( EXIT_FAILURE );
        }
 
        //copy page
@@ -113,7 +101,7 @@ void * PageAlignAddressUpward(void * addr) {
 extern "C" {
 #endif
        void createSharedLibrary(){
-#if !USE_CHECKPOINTING
+#if !USE_MPROTECT_SNAPSHOT
                //step 1. create shared memory.
                if( sTheRecord ) return;
                int fd = shm_open( "/ModelChecker-Snapshotter", O_RDWR | O_CREAT, 0777 ); //universal permissions.
@@ -132,10 +120,19 @@ extern "C" {
 #ifdef __cplusplus
 }
 #endif
-void initSnapShotLibrary(unsigned int numbackingpages, unsigned int numsnapshots, unsigned int nummemoryregions, unsigned int numheappages, MyFuncPtr entryPoint){
-#if USE_CHECKPOINTING
+void initSnapShotLibrary(unsigned int numbackingpages,
+               unsigned int numsnapshots, unsigned int nummemoryregions,
+               unsigned int numheappages, VoidFuncPtr entryPoint) {
+#if USE_MPROTECT_SNAPSHOT
+       /* Setup a stack for our signal handler....  */
+       stack_t ss;
+       ss.ss_sp = MYMALLOC(SIGSTACKSIZE);
+       ss.ss_size = SIGSTACKSIZE;
+       ss.ss_flags = 0;
+       sigaltstack(&ss, NULL);
+
        struct sigaction sa;
-       sa.sa_flags = SA_SIGINFO | SA_NODEFER | SA_RESTART;
+       sa.sa_flags = SA_SIGINFO | SA_NODEFER | SA_RESTART | SA_ONSTACK;
        sigemptyset( &sa.sa_mask );
        sa.sa_sigaction = HandlePF;
        if( sigaction( SIGSEGV, &sa, NULL ) == -1 ){
@@ -143,7 +140,7 @@ void initSnapShotLibrary(unsigned int numbackingpages, unsigned int numsnapshots
                exit(-1);
        }
        initSnapShotRecord(numbackingpages, numsnapshots, nummemoryregions);
-       
+
        basemySpace=MYMALLOC((numheappages+1)*PAGESIZE);
        void * pagealignedbase=PageAlignAddressUpward(basemySpace);
        mySpace = create_mspace_with_base(pagealignedbase,  numheappages*PAGESIZE, 1 );
@@ -160,12 +157,9 @@ void initSnapShotLibrary(unsigned int numbackingpages, unsigned int numsnapshots
                exit(-1);
        }
        createSharedLibrary();
-#if SSDEBUG
-       starttime = &(sTheRecord->startTimeGlobal);
-       gettimeofday( starttime, NULL );
-#endif
+
        //step 2 setup the stack context.
+
        int alreadySwapped = 0;
        getcontext( &savedSnapshotContext );
        if( !alreadySwapped ){
@@ -178,7 +172,7 @@ void initSnapShotLibrary(unsigned int numbackingpages, unsigned int numsnapshots
                makecontext( &newContext, entryPoint, 0 );
                swapcontext( &swappedContext, &newContext );
        }
-  
+
        //add the code to take a snapshot here...
        //to return to user process, do a second swapcontext...
        pid_t forkedID = 0;
@@ -187,7 +181,7 @@ void initSnapShotLibrary(unsigned int numbackingpages, unsigned int numsnapshots
        while( !sTheRecord->mbFinalize ){
                sTheRecord->currSnapShotID=snapshotid+1;
                forkedID = fork();
-               if( 0 == forkedID ){ 
+               if( 0 == forkedID ){
                        ucontext_t currentContext;
 #if 0
                        int dbg = 0;
@@ -196,7 +190,7 @@ void initSnapShotLibrary(unsigned int numbackingpages, unsigned int numsnapshots
                        if( swapContext )
                                swapcontext( &currentContext, &( sTheRecord->mContextToRollback ) );
                        else{
-                               swapcontext( &currentContext, &savedUserSnapshotContext );      
+                               swapcontext( &currentContext, &savedUserSnapshotContext );
                        }
                } else {
                        int status;
@@ -206,7 +200,7 @@ void initSnapShotLibrary(unsigned int numbackingpages, unsigned int numsnapshots
                        sprintf( mesg, "The process id of child is %d and the process id of this process is %d and snapshot id is %d", forkedID, getpid(), snapshotid );
                        DumpIntoLog( "ModelSnapshot", mesg );
 #endif
-                       do { 
+                       do {
                                retVal=waitpid( forkedID, &status, 0 );
                        } while( -1 == retVal && errno == EINTR );
 
@@ -217,31 +211,31 @@ void initSnapShotLibrary(unsigned int numbackingpages, unsigned int numsnapshots
                        }
                }
        }
-  
+
 #endif
 }
 /* This function assumes that addr is page aligned */
 void addMemoryRegionToSnapShot( void * addr, unsigned int numPages) {
-#if USE_CHECKPOINTING
+#if USE_MPROTECT_SNAPSHOT
        unsigned int memoryregion=snapshotrecord->lastRegion++;
        if (memoryregion==snapshotrecord->maxRegions) {
                printf("Exceeded supported number of memory regions!\n");
                exit(-1);
        }
-  
+
        snapshotrecord->regionsToSnapShot[ memoryregion ].basePtr=addr;
        snapshotrecord->regionsToSnapShot[ memoryregion ].sizeInPages=numPages;
 #endif //NOT REQUIRED IN THE CASE OF FORK BASED SNAPSHOTS.
 }
 //take snapshot
 snapshot_id takeSnapshot( ){
-#if USE_CHECKPOINTING
+#if USE_MPROTECT_SNAPSHOT
        for(unsigned int region=0; region<snapshotrecord->lastRegion;region++) {
                if( mprotect(snapshotrecord->regionsToSnapShot[region].basePtr, snapshotrecord->regionsToSnapShot[region].sizeInPages*sizeof(struct SnapShotPage), PROT_READ ) == -1 ){
                        perror("mprotect");
                        printf("Failed to mprotect inside of takeSnapShot\n");
                        exit(-1);
-               }               
+               }
        }
        unsigned int snapshot=snapshotrecord->lastSnapShot++;
        if (snapshot==snapshotrecord->maxSnapShots) {
@@ -249,7 +243,7 @@ snapshot_id takeSnapshot( ){
                exit(-1);
        }
        snapshotrecord->snapShots[snapshot].firstBackingPage=snapshotrecord->lastBackingPage;
-  
+
        return snapshot;
 #else
        swapcontext( &savedUserSnapshotContext, &savedSnapshotContext );
@@ -257,22 +251,22 @@ snapshot_id takeSnapshot( ){
 #endif
 }
 void rollBack( snapshot_id theID ){
-#if USE_CHECKPOINTING
+#if USE_MPROTECT_SNAPSHOT
        std::map< void *, bool, std::less< void * >, MyAlloc< std::pair< const void *, bool > > > duplicateMap;
        for(unsigned int region=0; region<snapshotrecord->lastRegion;region++) {
                if( mprotect(snapshotrecord->regionsToSnapShot[region].basePtr, snapshotrecord->regionsToSnapShot[region].sizeInPages*sizeof(struct SnapShotPage), PROT_READ | PROT_WRITE ) == -1 ){
                        perror("mprotect");
                        printf("Failed to mprotect inside of takeSnapShot\n");
                        exit(-1);
-               }               
+               }
        }
        for(unsigned int page=snapshotrecord->snapShots[theID].firstBackingPage; page<snapshotrecord->lastBackingPage; page++) {
                bool oldVal = false;
                if( duplicateMap.find( snapshotrecord->backingRecords[page].basePtrOfPage ) != duplicateMap.end() ){
-                       oldVal = true;          
+                       oldVal = true;
                }
                else{
-                       duplicateMap[ snapshotrecord->backingRecords[page].basePtrOfPage ] = true;    
+                       duplicateMap[ snapshotrecord->backingRecords[page].basePtrOfPage ] = true;
                }
                if(  !oldVal ){
                        memcpy(snapshotrecord->backingRecords[page].basePtrOfPage, &snapshotrecord->backingStore[page], sizeof(struct SnapShotPage));
@@ -288,7 +282,7 @@ void rollBack( snapshot_id theID ){
        if( !sTemp ){
                sTemp = 1;
 #if SSDEBUG
-               DumpIntoLog( "ModelSnapshot", "Invoked rollback" ); 
+               DumpIntoLog( "ModelSnapshot", "Invoked rollback" );
 #endif
                exit( 0 );
        }
@@ -296,7 +290,7 @@ void rollBack( snapshot_id theID ){
 }
 
 void finalize(){
-#if !USE_CHECKPOINTING
+#if !USE_MPROTECT_SNAPSHOT
        sTheRecord->mbFinalize = true;
 #endif
 }
index 4625c5d5cfaa7c39cd03087462da86858da0c371..39e294a8c60f1c0d781fdafb43a6162b6475f1af 100644 (file)
@@ -1,12 +1,16 @@
 #ifndef _SNAPSHOT_H
 #define _SNAPSHOT_H
+
+#include "snapshot-interface.h"
+
 #define PAGESIZE 4096
-#define USE_CHECKPOINTING 1
 
+/* If USE_MPROTECT_SNAPSHOT=1, then snapshot by using mmap() and mprotect()
+   If USE_MPROTECT_SNAPSHOT=0, then snapshot by using fork() */
+#define USE_MPROTECT_SNAPSHOT 1
 
-typedef unsigned int snapshot_id;
-typedef void (*MyFuncPtr)();
-void initSnapShotLibrary(unsigned int numbackingpages, unsigned int numsnapshots, unsigned int nummemoryregions, unsigned int numheappages, MyFuncPtr entryPoint);
+/* Size of signal stack */
+#define SIGSTACKSIZE 16384
 
 void addMemoryRegionToSnapShot( void * ptr, unsigned int numPages );
 
index 4991845ce37921c4cf1aa1f7d9045b08ca2994a1..8d935f238b81e3d43cf5ea1d7fdac07f583bc470 100644 (file)
@@ -10,7 +10,7 @@
 #define SHARED_MEMORY_DEFAULT ( 100 * ( 1 << 20 ) ) // 100mb for the shared memory
 #define STACK_SIZE_DEFAULT  ( ( 1 << 20 ) * 20 ) //20 mb out of the above 100 mb for my stack.
 
-#if USE_CHECKPOINTING
+#if USE_MPROTECT_SNAPSHOT
 //Each snapshotrecord lists the firstbackingpage that must be written to revert to that snapshot
 struct SnapShotRecord {
   unsigned int firstBackingPage;
@@ -61,9 +61,6 @@ size_t mStackSize;
 snapshot_id mIDToRollback;
 ucontext_t mContextToRollback;
 snapshot_id currSnapShotID;
-#if SSDEBUG
-struct timeval startTimeGlobal;
-#endif
 volatile bool mbFinalize;
 };
 extern struct Snapshot_t * sTheRecord;
index d00e21228295b0f9bc7f86902a2a9bfcc2577947..37b0f1a87ee6fb9ac975a84c8df9adf018d808c5 100644 (file)
@@ -9,12 +9,12 @@
 
 static void * stack_allocate(size_t size)
 {
-       return userMalloc(size);
+       return malloc(size);
 }
 
 static void stack_free(void *stack)
 {
-       userFree(stack);
+       free(stack);
 }
 
 Thread * thread_current(void)
index ebe33a3631d3e6815b33ed12b1e47ba972f1a8b1..7d2189b49d9f098a775b1cc158390cf76f49cbf4 100644 (file)
--- a/threads.h
+++ b/threads.h
@@ -16,6 +16,8 @@ typedef enum thread_state {
        THREAD_COMPLETED
 } thread_state;
 
+class ModelAction;
+
 class Thread {
 public:
        Thread(thrd_t *t, void (*func)(void *), void *a);
@@ -31,12 +33,16 @@ public:
        thrd_t get_thrd_t() { return *user_thread; }
        Thread * get_parent() { return parent; }
 
+       void set_creation(ModelAction *act) { creation = act; }
+       ModelAction * get_creation() { return creation; }
+
        friend void thread_startup();
 
-       MEMALLOC
+       SNAPSHOTALLOC
 private:
        int create_context();
        Thread *parent;
+       ModelAction *creation;
 
        void (*start_routine)(void *);
        void *arg;