experiment with exponential decay model
[c11tester.git] / execution.cc
index 0710dd6b68b26364591bbc6fa38b92db875c91ba..e1c5e2ddbb06767e13c51d55b230f553d5f2c67d 100644 (file)
@@ -15,6 +15,7 @@
 #include "bugmessage.h"
 #include "history.h"
 #include "fuzzer.h"
+#include "newfuzzer.h"
 
 #define INITIAL_THREAD_ID       0
 
@@ -27,7 +28,6 @@ struct model_snapshot_members {
                next_thread_id(INITIAL_THREAD_ID),
                used_sequence_numbers(0),
                bugs(),
-               bad_synchronization(false),
                asserted(false)
        { }
 
@@ -41,129 +41,11 @@ struct model_snapshot_members {
        modelclock_t used_sequence_numbers;
        SnapVector<bug_message *> bugs;
        /** @brief Incorrectly-ordered synchronization was made */
-       bool bad_synchronization;
        bool asserted;
 
        SNAPSHOTALLOC
 };
 
-
-#ifdef TLS
-#include <dlfcn.h>
-
-//Code taken from LLVM and licensed under the University of Illinois Open Source
-//License.
-static uintptr_t thread_descriptor_size;
-#if __LP64__ || defined(_WIN64)
-#  define SANITIZER_WORDSIZE 64
-#else
-#  define SANITIZER_WORDSIZE 32
-#endif
-
-#if SANITIZER_WORDSIZE == 64
-# define FIRST_32_SECOND_64(a, b) (b)
-#else
-# define FIRST_32_SECOND_64(a, b) (a)
-#endif
-
-#if defined(__x86_64__) && !defined(_LP64)
-# define SANITIZER_X32 1
-#else
-# define SANITIZER_X32 0
-#endif
-
-#if defined(__arm__)
-# define SANITIZER_ARM 1
-#else
-# define SANITIZER_ARM 0
-#endif
-
-uintptr_t ThreadDescriptorSize() {
-       uintptr_t val = thread_descriptor_size;
-       if (val)
-               return val;
-#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
-#ifdef _CS_GNU_LIBC_VERSION
-       char buf[64];
-       uintptr_t len = confstr(_CS_GNU_LIBC_VERSION, buf, sizeof(buf));
-       if (len < sizeof(buf) && strncmp(buf, "glibc 2.", 8) == 0) {
-               char *end;
-               int minor = strtoll(buf + 8, &end, 10);
-               if (end != buf + 8 && (*end == '\0' || *end == '.' || *end == '-')) {
-                       int patch = 0;
-                       if (*end == '.')
-                               // strtoll will return 0 if no valid conversion could be performed
-                               patch = strtoll(end + 1, nullptr, 10);
-
-                       /* sizeof(struct pthread) values from various glibc versions.  */
-                       if (SANITIZER_X32)
-                               val = 1728;// Assume only one particular version for x32.
-                       // For ARM sizeof(struct pthread) changed in Glibc 2.23.
-                       else if (SANITIZER_ARM)
-                               val = minor <= 22 ? 1120 : 1216;
-                       else if (minor <= 3)
-                               val = FIRST_32_SECOND_64(1104, 1696);
-                       else if (minor == 4)
-                               val = FIRST_32_SECOND_64(1120, 1728);
-                       else if (minor == 5)
-                               val = FIRST_32_SECOND_64(1136, 1728);
-                       else if (minor <= 9)
-                               val = FIRST_32_SECOND_64(1136, 1712);
-                       else if (minor == 10)
-                               val = FIRST_32_SECOND_64(1168, 1776);
-                       else if (minor == 11 || (minor == 12 && patch == 1))
-                               val = FIRST_32_SECOND_64(1168, 2288);
-                       else if (minor <= 13)
-                               val = FIRST_32_SECOND_64(1168, 2304);
-                       else
-                               val = FIRST_32_SECOND_64(1216, 2304);
-               }
-       }
-#endif
-#elif defined(__mips__)
-       // TODO(sagarthakur): add more values as per different glibc versions.
-       val = FIRST_32_SECOND_64(1152, 1776);
-#elif defined(__aarch64__)
-       // The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22.
-       val = 1776;
-#elif defined(__powerpc64__)
-       val = 1776;     // from glibc.ppc64le 2.20-8.fc21
-#elif defined(__s390__)
-       val = FIRST_32_SECOND_64(1152, 1776);   // valid for glibc 2.22
-#endif
-       if (val)
-               thread_descriptor_size = val;
-       return val;
-}
-
-#ifdef __i386__
-# define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
-#else
-# define DL_INTERNAL_FUNCTION
-#endif
-
-intptr_t RoundUpTo(uintptr_t size, uintptr_t boundary) {
-       return (size + boundary - 1) & ~(boundary - 1);
-}
-
-uintptr_t getTlsSize() {
-       // all current supported platforms have 16 bytes stack alignment
-       const size_t kStackAlign = 16;
-       typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION;
-       get_tls_func get_tls;
-       void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
-       memcpy(&get_tls, &get_tls_static_info_ptr, sizeof(get_tls_static_info_ptr));
-       ASSERT(get_tls != 0);
-       size_t tls_size = 0;
-       size_t tls_align = 0;
-       get_tls(&tls_size, &tls_align);
-       if (tls_align < kStackAlign)
-               tls_align = kStackAlign;
-       return RoundUpTo(tls_size, tls_align);
-}
-
-#endif
-
 /** @brief Constructor */
 ModelExecution::ModelExecution(ModelChecker *m, Scheduler *scheduler) :
        model(m),
@@ -181,34 +63,18 @@ ModelExecution::ModelExecution(ModelChecker *m, Scheduler *scheduler) :
        thrd_last_fence_release(),
        priv(new struct model_snapshot_members ()),
        mo_graph(new CycleGraph()),
-       fuzzer(new Fuzzer()),
+       fuzzer(new NewFuzzer()),
        thrd_func_list(),
-       thrd_func_inst_lists()
-#ifdef TLS
-       ,tls_base(NULL),
-       tls_addr(0),
-       tls_size(0),
-       thd_desc_size(0)
-#endif
+       thrd_func_act_lists(),
+       isfinished(false)
 {
        /* Initialize a model-checker thread, for special ModelActions */
        model_thread = new Thread(get_next_id());
        add_thread(model_thread);
+       fuzzer->register_engine(m->get_history(), this);
        scheduler->register_engine(this);
 }
 
-#ifdef TLS
-void ModelExecution::initTLS() {
-       tls_addr = get_tls_addr();
-       tls_size = getTlsSize();
-       tls_addr -= tls_size;
-       thd_desc_size = ThreadDescriptorSize();
-       tls_addr += thd_desc_size;
-       tls_base = (char *) snapshot_calloc(tls_size,1);
-       memcpy(tls_base, reinterpret_cast<const char *>(tls_addr), tls_size);
-}
-#endif
-
 /** @brief Destructor */
 ModelExecution::~ModelExecution()
 {
@@ -224,7 +90,7 @@ int ModelExecution::get_execution_number() const
        return model->get_execution_number();
 }
 
-static action_list_t * get_safe_ptr_action(HashTable<const void *, action_list_t *, uintptr_t, 4> * hash, void * ptr)
+static action_list_t * get_safe_ptr_action(HashTable<const void *, action_list_t *, uintptr_t, 2> * hash, void * ptr)
 {
        action_list_t *tmp = hash->get(ptr);
        if (tmp == NULL) {
@@ -234,7 +100,7 @@ static action_list_t * get_safe_ptr_action(HashTable<const void *, action_list_t
        return tmp;
 }
 
-static SnapVector<action_list_t> * get_safe_ptr_vect_action(HashTable<const void *, SnapVector<action_list_t> *, uintptr_t, 4> * hash, void * ptr)
+static SnapVector<action_list_t> * get_safe_ptr_vect_action(HashTable<const void *, SnapVector<action_list_t> *, uintptr_t, 2> * hash, void * ptr)
 {
        SnapVector<action_list_t> *tmp = hash->get(ptr);
        if (tmp == NULL) {
@@ -262,6 +128,12 @@ modelclock_t ModelExecution::get_next_seq_num()
        return ++priv->used_sequence_numbers;
 }
 
+/** Restore the last used sequence number when actions of a thread are postponed by Fuzzer */
+void ModelExecution::restore_last_seq_num()
+{
+       priv->used_sequence_numbers--;
+}
+
 /**
  * @brief Should the current action wake up a given thread?
  *
@@ -287,6 +159,12 @@ bool ModelExecution::should_wake_up(const ModelAction *curr, const Thread *threa
                if (fence_release && *(get_last_action(thread->get_id())) < *fence_release)
                        return true;
        }
+       /* The sleep is literally sleeping */
+       if (asleep->is_sleep()) {
+               if (fuzzer->shouldWake(asleep))
+                       return true;
+       }
+
        return false;
 }
 
@@ -295,29 +173,20 @@ void ModelExecution::wake_up_sleeping_actions(ModelAction *curr)
        for (unsigned int i = 0;i < get_num_threads();i++) {
                Thread *thr = get_thread(int_to_id(i));
                if (scheduler->is_sleep_set(thr)) {
-                       if (should_wake_up(curr, thr))
+                       if (should_wake_up(curr, thr)) {
                                /* Remove this thread from sleep set */
                                scheduler->remove_sleep(thr);
+                               if (thr->get_pending()->is_sleep())
+                                       thr->set_wakeup_state(true);
+                       }
                }
        }
 }
 
-/** @brief Alert the model-checker that an incorrectly-ordered
- * synchronization was made */
-void ModelExecution::set_bad_synchronization()
-{
-       priv->bad_synchronization = true;
-}
-
-bool ModelExecution::assert_bug(const char *msg)
+void ModelExecution::assert_bug(const char *msg)
 {
        priv->bugs.push_back(new bug_message(msg));
-
-       if (isfeasibleprefix()) {
-               set_assert();
-               return true;
-       }
-       return false;
+       set_assert();
 }
 
 /** @return True, if any bugs have been reported for this execution */
@@ -326,16 +195,6 @@ bool ModelExecution::have_bug_reports() const
        return priv->bugs.size() != 0;
 }
 
-/** @return True, if any fatal bugs have been reported for this execution.
- *  Any bug other than a data race is considered a fatal bug. Data races
- *  are not considered fatal unless the number of races is exceeds
- *  a threshold (temporarily set as 15).
- */
-bool ModelExecution::have_fatal_bug_reports() const
-{
-       return priv->bugs.size() != 0;
-}
-
 SnapVector<bug_message *> * ModelExecution::get_bugs() const
 {
        return &priv->bugs;
@@ -409,17 +268,17 @@ ModelAction * ModelExecution::convertNonAtomicStore(void * location) {
        add_normal_write_to_lists(act);
        add_write_to_lists(act);
        w_modification_order(act);
+       model->get_history()->process_action(act, act->get_tid());
        return act;
 }
 
-
 /**
  * Processes a read model action.
  * @param curr is the read model action to process.
  * @param rf_set is the set of model actions we can possibly read from
  * @return True if processing this read updates the mo_graph.
  */
-void ModelExecution::process_read(ModelAction *curr, SnapVector<ModelAction *> * rf_set)
+bool ModelExecution::process_read(ModelAction *curr, SnapVector<ModelAction *> * rf_set)
 {
        SnapVector<const ModelAction *> * priorset = new SnapVector<const ModelAction *>();
        bool hasnonatomicstore = hasNonAtomicStore(curr->get_location());
@@ -428,10 +287,21 @@ void ModelExecution::process_read(ModelAction *curr, SnapVector<ModelAction *> *
                rf_set->push_back(nonatomicstore);
        }
 
+       // Remove writes that violate read modification order
+       uint i = 0;
+       while (i < rf_set->size()) {
+               ModelAction * rf = (*rf_set)[i];
+               if (!r_modification_order(curr, rf, NULL, NULL, true)) {
+                       (*rf_set)[i] = rf_set->back();
+                       rf_set->pop_back();
+               } else
+                       i++;
+       }
+
        while(true) {
                int index = fuzzer->selectWrite(curr, rf_set);
-               ModelAction *rf = (*rf_set)[index];
 
+               ModelAction *rf = (*rf_set)[index];
 
                ASSERT(rf);
                bool canprune = false;
@@ -446,8 +316,11 @@ void ModelExecution::process_read(ModelAction *curr, SnapVector<ModelAction *> *
                                int tid = id_to_int(curr->get_tid());
                                (*obj_thrd_map.get(curr->get_location()))[tid].pop_back();
                        }
-                       return;
+                       return true;
                }
+
+               ASSERT(false);
+               /* TODO: Following code not needed anymore */
                priorset->clear();
                (*rf_set)[index] = rf_set->back();
                rf_set->pop_back();
@@ -502,7 +375,27 @@ bool ModelExecution::process_mutex(ModelAction *curr)
                }
                break;
        }
-       case ATOMIC_WAIT:
+       case ATOMIC_WAIT: {
+               /* wake up the other threads */
+               for (unsigned int i = 0;i < get_num_threads();i++) {
+                       Thread *t = get_thread(int_to_id(i));
+                       Thread *curr_thrd = get_thread(curr);
+                       if (t->waiting_on() == curr_thrd && t->get_pending()->is_lock())
+                               scheduler->wake(t);
+               }
+
+               /* unlock the lock - after checking who was waiting on it */
+               state->locked = NULL;
+
+               if (fuzzer->shouldWait(curr)) {
+                       /* disable this thread */
+                       get_safe_ptr_action(&condvar_waiters_map, curr->get_location())->push_back(curr);
+                       scheduler->sleep(get_thread(curr));
+               }
+
+               break;
+       }
+       case ATOMIC_TIMEDWAIT:
        case ATOMIC_UNLOCK: {
                //TODO: FIX WAIT SITUATION...WAITS CAN SPURIOUSLY FAIL...TIMED WAITS SHOULD PROBABLY JUST BE THE SAME AS NORMAL WAITS...THINK ABOUT PROBABILITIES THOUGH....AS IN TIMED WAIT MUST FAIL TO GUARANTEE PROGRESS...NORMAL WAIT MAY FAIL...SO NEED NORMAL WAIT TO WORK CORRECTLY IN THE CASE IT SPURIOUSLY FAILS AND IN THE CASE IT DOESN'T...  TIMED WAITS MUST EVENMTUALLY RELEASE...
 
@@ -516,17 +409,13 @@ bool ModelExecution::process_mutex(ModelAction *curr)
 
                /* unlock the lock - after checking who was waiting on it */
                state->locked = NULL;
-
-               if (!curr->is_wait())
-                       break;/* The rest is only for ATOMIC_WAIT */
-
                break;
        }
        case ATOMIC_NOTIFY_ALL: {
                action_list_t *waiters = get_safe_ptr_action(&condvar_waiters_map, curr->get_location());
                //activate all the waiting threads
-               for (action_list_t::iterator rit = waiters->begin();rit != waiters->end();rit++) {
-                       scheduler->wake(get_thread(*rit));
+               for (sllnode<ModelAction *> * rit = waiters->begin();rit != NULL;rit=rit->getNext()) {
+                       scheduler->wake(get_thread(rit->getVal()));
                }
                waiters->clear();
                break;
@@ -575,10 +464,10 @@ bool ModelExecution::process_fence(ModelAction *curr)
        bool updated = false;
        if (curr->is_acquire()) {
                action_list_t *list = &action_trace;
-               action_list_t::reverse_iterator rit;
+               sllnode<ModelAction *> * rit;
                /* Find X : is_read(X) && X --sb-> curr */
-               for (rit = list->rbegin();rit != list->rend();rit++) {
-                       ModelAction *act = *rit;
+               for (rit = list->end();rit != NULL;rit=rit->getPrev()) {
+                       ModelAction *act = rit->getVal();
                        if (act == curr)
                                continue;
                        if (act->get_tid() != curr->get_tid())
@@ -596,8 +485,8 @@ bool ModelExecution::process_fence(ModelAction *curr)
                                continue;
 
                        /* Establish hypothetical release sequences */
-                       ClockVector *cv = get_hb_from_write(act);
-                       if (curr->get_cv()->merge(cv))
+                       ClockVector *cv = get_hb_from_write(act->get_reads_from());
+                       if (cv != NULL && curr->get_cv()->merge(cv))
                                updated = true;
                }
        }
@@ -615,10 +504,8 @@ bool ModelExecution::process_fence(ModelAction *curr)
  * @param curr The current action
  * @return True if synchronization was updated or a thread completed
  */
-bool ModelExecution::process_thread_action(ModelAction *curr)
+void ModelExecution::process_thread_action(ModelAction *curr)
 {
-       bool updated = false;
-
        switch (curr->get_type()) {
        case THREAD_CREATE: {
                thrd_t *thrd = (thrd_t *)curr->get_location();
@@ -648,19 +535,25 @@ bool ModelExecution::process_thread_action(ModelAction *curr)
                Thread *blocking = curr->get_thread_operand();
                ModelAction *act = get_last_action(blocking->get_id());
                synchronize(act, curr);
-               updated = true; /* trigger rel-seq checks */
                break;
        }
        case PTHREAD_JOIN: {
                Thread *blocking = curr->get_thread_operand();
                ModelAction *act = get_last_action(blocking->get_id());
                synchronize(act, curr);
-               updated = true; /* trigger rel-seq checks */
                break;  // WL: to be add (modified)
        }
 
+       case THREADONLY_FINISH:
        case THREAD_FINISH: {
                Thread *th = get_thread(curr);
+               if (curr->get_type() == THREAD_FINISH &&
+                               th == model->getInitThread()) {
+                       th->complete();
+                       setFinished();
+                       break;
+               }
+
                /* Wake up any joining threads */
                for (unsigned int i = 0;i < get_num_threads();i++) {
                        Thread *waiting = get_thread(int_to_id(i));
@@ -669,17 +562,20 @@ bool ModelExecution::process_thread_action(ModelAction *curr)
                                scheduler->wake(waiting);
                }
                th->complete();
-               updated = true; /* trigger rel-seq checks */
                break;
        }
        case THREAD_START: {
                break;
        }
+       case THREAD_SLEEP: {
+               Thread *th = get_thread(curr);
+               th->set_pending(curr);
+               scheduler->add_sleep(th);
+               break;
+       }
        default:
                break;
        }
-
-       return updated;
 }
 
 /**
@@ -756,7 +652,7 @@ void ModelExecution::read_from(ModelAction *act, ModelAction *rf)
 bool ModelExecution::synchronize(const ModelAction *first, ModelAction *second)
 {
        if (*second < *first) {
-               set_bad_synchronization();
+               ASSERT(0);      //This should not happend
                return false;
        }
        return second->synchronize_with(first);
@@ -784,6 +680,9 @@ bool ModelExecution::check_action_enabled(ModelAction *curr) {
                if (!blocking->is_complete()) {
                        return false;
                }
+       } else if (curr->is_sleep()) {
+               if (!fuzzer->shouldSleep(curr))
+                       return false;
        }
 
        return true;
@@ -810,26 +709,29 @@ ModelAction * ModelExecution::check_current_action(ModelAction *curr)
 
        wake_up_sleeping_actions(curr);
 
-       /* Add the action to lists before any other model-checking tasks */
-       if (!second_part_of_rmw && curr->get_type() != NOOP)
-               add_action_to_lists(curr);
-
-       if (curr->is_write())
-               add_write_to_lists(curr);
+       /* Add uninitialized actions to lists */
+       if (!second_part_of_rmw)
+               add_uninit_action_to_lists(curr);
 
        SnapVector<ModelAction *> * rf_set = NULL;
        /* Build may_read_from set for newly-created actions */
        if (newly_explored && curr->is_read())
                rf_set = build_may_read_from(curr);
 
-       process_thread_action(curr);
-
        if (curr->is_read() && !second_part_of_rmw) {
                process_read(curr, rf_set);
                delete rf_set;
-       } else {
+       } else
                ASSERT(rf_set == NULL);
-       }
+
+       /* Add the action to lists */
+       if (!second_part_of_rmw)
+               add_action_to_lists(curr);
+
+       if (curr->is_write())
+               add_write_to_lists(curr);
+
+       process_thread_action(curr);
 
        if (curr->is_write())
                process_write(curr);
@@ -843,42 +745,6 @@ ModelAction * ModelExecution::check_current_action(ModelAction *curr)
        return curr;
 }
 
-/**
- * This is the strongest feasibility check available.
- * @return whether the current trace (partial or complete) must be a prefix of
- * a feasible trace.
- */
-bool ModelExecution::isfeasibleprefix() const
-{
-       return !is_infeasible();
-}
-
-/**
- * Print disagnostic information about an infeasible execution
- * @param prefix A string to prefix the output with; if NULL, then a default
- * message prefix will be provided
- */
-void ModelExecution::print_infeasibility(const char *prefix) const
-{
-       char buf[100];
-       char *ptr = buf;
-       if (priv->bad_synchronization)
-               ptr += sprintf(ptr, "[bad sw ordering]");
-       if (ptr != buf)
-               model_print("%s: %s", prefix ? prefix : "Infeasible", buf);
-}
-
-/**
- * Check if the current partial trace is infeasible. Does not check any
- * end-of-execution flags, which might rule out the execution. Thus, this is
- * useful only for ruling an execution as infeasible.
- * @return whether the current partial trace is infeasible.
- */
-bool ModelExecution::is_infeasible() const
-{
-       return priv->bad_synchronization;
-}
-
 /** Close out a RMWR by converting previous RMWR into a RMW or READ. */
 ModelAction * ModelExecution::process_rmw(ModelAction *act) {
        ModelAction *lastread = get_last_action(act->get_tid());
@@ -903,10 +769,14 @@ ModelAction * ModelExecution::process_rmw(ModelAction *act) {
  *
  * @param curr The current action. Must be a read.
  * @param rf The ModelAction or Promise that curr reads from. Must be a write.
+ * @param check_only If true, then only check whether the current action satisfies
+ *        read modification order or not, without modifiying priorset and canprune.
+ *        False by default.
  * @return True if modification order edges were added; false otherwise
  */
 
-bool ModelExecution::r_modification_order(ModelAction *curr, const ModelAction *rf, SnapVector<const ModelAction *> * priorset, bool * canprune)
+bool ModelExecution::r_modification_order(ModelAction *curr, const ModelAction *rf,
+                                                                                                                                                                       SnapVector<const ModelAction *> * priorset, bool * canprune, bool check_only)
 {
        SnapVector<action_list_t> *thrd_lists = obj_thrd_map.get(curr->get_location());
        unsigned int i;
@@ -938,9 +808,9 @@ bool ModelExecution::r_modification_order(ModelAction *curr, const ModelAction *
 
                /* Iterate over actions in thread, starting from most recent */
                action_list_t *list = &(*thrd_lists)[tid];
-               action_list_t::reverse_iterator rit;
-               for (rit = list->rbegin();rit != list->rend();rit++) {
-                       ModelAction *act = *rit;
+               sllnode<ModelAction *> * rit;
+               for (rit = list->end();rit != NULL;rit=rit->getPrev()) {
+                       ModelAction *act = rit->getVal();
 
                        /* Skip curr */
                        if (act == curr)
@@ -959,7 +829,8 @@ bool ModelExecution::r_modification_order(ModelAction *curr, const ModelAction *
                                                *act < *last_sc_fence_thread_local) {
                                        if (mo_graph->checkReachable(rf, act))
                                                return false;
-                                       priorset->push_back(act);
+                                       if (!check_only)
+                                               priorset->push_back(act);
                                        break;
                                }
                                /* C++, Section 29.3 statement 4 */
@@ -967,7 +838,8 @@ bool ModelExecution::r_modification_order(ModelAction *curr, const ModelAction *
                                                                 *act < *last_sc_fence_local) {
                                        if (mo_graph->checkReachable(rf, act))
                                                return false;
-                                       priorset->push_back(act);
+                                       if (!check_only)
+                                               priorset->push_back(act);
                                        break;
                                }
                                /* C++, Section 29.3 statement 6 */
@@ -975,7 +847,8 @@ bool ModelExecution::r_modification_order(ModelAction *curr, const ModelAction *
                                                                 *act < *last_sc_fence_thread_before) {
                                        if (mo_graph->checkReachable(rf, act))
                                                return false;
-                                       priorset->push_back(act);
+                                       if (!check_only)
+                                               priorset->push_back(act);
                                        break;
                                }
                        }
@@ -987,24 +860,27 @@ bool ModelExecution::r_modification_order(ModelAction *curr, const ModelAction *
                        if (act->happens_before(curr)) {
                                if (i==0) {
                                        if (last_sc_fence_local == NULL ||
-                                                       (*last_sc_fence_local < *prev_same_thread)) {
+                                                       (*last_sc_fence_local < *act)) {
                                                prev_same_thread = act;
                                        }
                                }
                                if (act->is_write()) {
                                        if (mo_graph->checkReachable(rf, act))
                                                return false;
-                                       priorset->push_back(act);
+                                       if (!check_only)
+                                               priorset->push_back(act);
                                } else {
                                        const ModelAction *prevrf = act->get_reads_from();
                                        if (!prevrf->equals(rf)) {
                                                if (mo_graph->checkReachable(rf, prevrf))
                                                        return false;
-                                               priorset->push_back(prevrf);
+                                               if (!check_only)
+                                                       priorset->push_back(prevrf);
                                        } else {
                                                if (act->get_tid() == curr->get_tid()) {
                                                        //Can prune curr from obj list
-                                                       *canprune = true;
+                                                       if (!check_only)
+                                                               *canprune = true;
                                                }
                                        }
                                }
@@ -1045,13 +921,17 @@ void ModelExecution::w_modification_order(ModelAction *curr)
        unsigned int i;
        ASSERT(curr->is_write());
 
+       SnapList<ModelAction *> edgeset;
+
        if (curr->is_seqcst()) {
                /* We have to at least see the last sequentially consistent write,
                         so we are initialized. */
                ModelAction *last_seq_cst = get_last_seq_cst_write(curr);
                if (last_seq_cst != NULL) {
-                       mo_graph->addEdge(last_seq_cst, curr);
+                       edgeset.push_back(last_seq_cst);
                }
+               //update map for next query
+               obj_last_sc_map.put(curr->get_location(), curr);
        }
 
        /* Last SC fence in the current thread */
@@ -1066,10 +946,9 @@ void ModelExecution::w_modification_order(ModelAction *curr)
 
                /* Iterate over actions in thread, starting from most recent */
                action_list_t *list = &(*thrd_lists)[i];
-               action_list_t::reverse_iterator rit;
-               bool force_edge = false;
-               for (rit = list->rbegin();rit != list->rend();rit++) {
-                       ModelAction *act = *rit;
+               sllnode<ModelAction*>* rit;
+               for (rit = list->end();rit != NULL;rit=rit->getPrev()) {
+                       ModelAction *act = rit->getVal();
                        if (act == curr) {
                                /*
                                 * 1) If RMW and it actually read from something, then we
@@ -1082,7 +961,6 @@ void ModelExecution::w_modification_order(ModelAction *curr)
                                 * 3) If normal write, we need to look at earlier actions, so
                                 * continue processing list.
                                 */
-                               force_edge = true;
                                if (curr->is_rmw()) {
                                        if (curr->get_reads_from() != NULL)
                                                break;
@@ -1095,7 +973,7 @@ void ModelExecution::w_modification_order(ModelAction *curr)
                        /* C++, Section 29.3 statement 7 */
                        if (last_sc_fence_thread_before && act->is_write() &&
                                        *act < *last_sc_fence_thread_before) {
-                               mo_graph->addEdge(act, curr, force_edge);
+                               edgeset.push_back(act);
                                break;
                        }
 
@@ -1111,15 +989,17 @@ void ModelExecution::w_modification_order(ModelAction *curr)
                                 *   readfrom(act) --mo--> act
                                 */
                                if (act->is_write())
-                                       mo_graph->addEdge(act, curr, force_edge);
+                                       edgeset.push_back(act);
                                else if (act->is_read()) {
                                        //if previous read accessed a null, just keep going
-                                       mo_graph->addEdge(act->get_reads_from(), curr, force_edge);
+                                       edgeset.push_back(act->get_reads_from());
                                }
                                break;
                        }
                }
        }
+       mo_graph->addEdges(&edgeset, curr);
+
 }
 
 /**
@@ -1140,9 +1020,9 @@ bool ModelExecution::mo_may_allow(const ModelAction *writer, const ModelAction *
 
                /* Iterate over actions in thread, starting from most recent */
                action_list_t *list = &(*thrd_lists)[i];
-               action_list_t::reverse_iterator rit;
-               for (rit = list->rbegin();rit != list->rend();rit++) {
-                       ModelAction *act = *rit;
+               sllnode<ModelAction *>* rit;
+               for (rit = list->end();rit != NULL;rit=rit->getPrev()) {
+                       ModelAction *act = rit->getVal();
 
                        /* Don't disallow due to act == reader */
                        if (!reader->happens_before(act) || reader == act)
@@ -1214,13 +1094,15 @@ ClockVector * ModelExecution::get_hb_from_write(ModelAction *rf) const {
 }
 
 /**
- * Performs various bookkeeping operations for the current ModelAction. For
- * instance, adds action to the per-object, per-thread action vector and to the
- * action trace list of all thread actions.
+ * Performs various bookkeeping operations for the current ModelAction when it is
+ * the first atomic action occurred at its memory location.
  *
- * @param act is the ModelAction to add.
+ * For instance, adds uninitialized action to the per-object, per-thread action vector
+ * and to the action trace list of all thread actions.
+ *
+ * @param act is the ModelAction to process.
  */
-void ModelExecution::add_action_to_lists(ModelAction *act)
+void ModelExecution::add_uninit_action_to_lists(ModelAction *act)
 {
        int tid = id_to_int(act->get_tid());
        ModelAction *uninit = NULL;
@@ -1231,31 +1113,69 @@ void ModelExecution::add_action_to_lists(ModelAction *act)
                uninit_id = id_to_int(uninit->get_tid());
                list->push_front(uninit);
                SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_wr_thrd_map, act->get_location());
-               if (uninit_id >= (int)vec->size())
+               if ((int)vec->size() <= uninit_id) {
+                       int oldsize = (int) vec->size();
                        vec->resize(uninit_id + 1);
+                       for(int i = oldsize;i < uninit_id + 1;i++) {
+                               new (&(*vec)[i]) action_list_t();
+                       }
+               }
                (*vec)[uninit_id].push_front(uninit);
        }
-       list->push_back(act);
 
        // Update action trace, a total order of all actions
-       action_trace.push_back(act);
        if (uninit)
                action_trace.push_front(uninit);
 
        // Update obj_thrd_map, a per location, per thread, order of actions
        SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, act->get_location());
-       if (tid >= (int)vec->size())
+       if ((int)vec->size() <= tid) {
+               uint oldsize = vec->size();
                vec->resize(priv->next_thread_id);
-       (*vec)[tid].push_back(act);
+               for(uint i = oldsize;i < priv->next_thread_id;i++)
+                       new (&(*vec)[i]) action_list_t();
+       }
        if (uninit)
                (*vec)[uninit_id].push_front(uninit);
 
        // Update thrd_last_action, the last action taken by each thrad
        if ((int)thrd_last_action.size() <= tid)
                thrd_last_action.resize(get_num_threads());
-       thrd_last_action[tid] = act;
        if (uninit)
                thrd_last_action[uninit_id] = uninit;
+}
+
+
+/**
+ * Performs various bookkeeping operations for the current ModelAction. For
+ * instance, adds action to the per-object, per-thread action vector and to the
+ * action trace list of all thread actions.
+ *
+ * @param act is the ModelAction to add.
+ */
+void ModelExecution::add_action_to_lists(ModelAction *act)
+{
+       int tid = id_to_int(act->get_tid());
+       action_list_t *list = get_safe_ptr_action(&obj_map, act->get_location());
+       list->push_back(act);
+
+       // Update action trace, a total order of all actions
+       action_trace.push_back(act);
+
+       // Update obj_thrd_map, a per location, per thread, order of actions
+       SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, act->get_location());
+       if ((int)vec->size() <= tid) {
+               uint oldsize = vec->size();
+               vec->resize(priv->next_thread_id);
+               for(uint i = oldsize;i < priv->next_thread_id;i++)
+                       new (&(*vec)[i]) action_list_t();
+       }
+       (*vec)[tid].push_back(act);
+
+       // Update thrd_last_action, the last action taken by each thrad
+       if ((int)thrd_last_action.size() <= tid)
+               thrd_last_action.resize(get_num_threads());
+       thrd_last_action[tid] = act;
 
        // Update thrd_last_fence_release, the last release fence taken by each thread
        if (act->is_fence() && act->is_release()) {
@@ -1269,22 +1189,25 @@ void ModelExecution::add_action_to_lists(ModelAction *act)
                get_safe_ptr_action(&obj_map, mutex_loc)->push_back(act);
 
                SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, mutex_loc);
-               if (tid >= (int)vec->size())
+               if ((int)vec->size() <= tid) {
+                       uint oldsize = vec->size();
                        vec->resize(priv->next_thread_id);
+                       for(uint i = oldsize;i < priv->next_thread_id;i++)
+                               new (&(*vec)[i]) action_list_t();
+               }
                (*vec)[tid].push_back(act);
        }
 }
 
 void insertIntoActionList(action_list_t *list, ModelAction *act) {
-       action_list_t::reverse_iterator rit = list->rbegin();
+       sllnode<ModelAction*> * rit = list->end();
        modelclock_t next_seq = act->get_seq_number();
-       if (rit == list->rend() || (*rit)->get_seq_number() == next_seq)
+       if (rit == NULL || (rit->getVal()->get_seq_number() == next_seq))
                list->push_back(act);
        else {
-               for(;rit != list->rend();rit++) {
-                       if ((*rit)->get_seq_number() == next_seq) {
-                               action_list_t::iterator it = rit.base();
-                               list->insert(it, act);
+               for(;rit != NULL;rit=rit->getPrev()) {
+                       if (rit->getVal()->get_seq_number() == next_seq) {
+                               list->insertAfter(rit, act);
                                break;
                        }
                }
@@ -1292,19 +1215,18 @@ void insertIntoActionList(action_list_t *list, ModelAction *act) {
 }
 
 void insertIntoActionListAndSetCV(action_list_t *list, ModelAction *act) {
-       action_list_t::reverse_iterator rit = list->rbegin();
+       sllnode<ModelAction*> * rit = list->end();
        modelclock_t next_seq = act->get_seq_number();
-       if (rit == list->rend()) {
+       if (rit == NULL) {
                act->create_cv(NULL);
-       } else if ((*rit)->get_seq_number() == next_seq) {
-               act->create_cv((*rit));
+       } else if (rit->getVal()->get_seq_number() == next_seq) {
+               act->create_cv(rit->getVal());
                list->push_back(act);
        } else {
-               for(;rit != list->rend();rit++) {
-                       if ((*rit)->get_seq_number() == next_seq) {
-                               act->create_cv((*rit));
-                               action_list_t::iterator it = rit.base();
-                               list->insert(it, act);
+               for(;rit != NULL;rit=rit->getPrev()) {
+                       if (rit->getVal()->get_seq_number() == next_seq) {
+                               act->create_cv(rit->getVal());
+                               list->insertAfter(rit, act);
                                break;
                        }
                }
@@ -1329,8 +1251,12 @@ void ModelExecution::add_normal_write_to_lists(ModelAction *act)
 
        // Update obj_thrd_map, a per location, per thread, order of actions
        SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, act->get_location());
-       if (tid >= (int)vec->size())
+       if (tid >= (int)vec->size()) {
+               uint oldsize =vec->size();
                vec->resize(priv->next_thread_id);
+               for(uint i=oldsize;i<priv->next_thread_id;i++)
+                       new (&(*vec)[i]) action_list_t();
+       }
        insertIntoActionList(&(*vec)[tid],act);
 
        // Update thrd_last_action, the last action taken by each thrad
@@ -1340,14 +1266,14 @@ void ModelExecution::add_normal_write_to_lists(ModelAction *act)
 
 
 void ModelExecution::add_write_to_lists(ModelAction *write) {
-       // Update seq_cst map
-       if (write->is_seqcst())
-               obj_last_sc_map.put(write->get_location(), write);
-
        SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_wr_thrd_map, write->get_location());
        int tid = id_to_int(write->get_tid());
-       if (tid >= (int)vec->size())
+       if (tid >= (int)vec->size()) {
+               uint oldsize =vec->size();
                vec->resize(priv->next_thread_id);
+               for(uint i=oldsize;i<priv->next_thread_id;i++)
+                       new (&(*vec)[i]) action_list_t();
+       }
        (*vec)[tid].push_back(write);
 }
 
@@ -1409,20 +1335,22 @@ ModelAction * ModelExecution::get_last_seq_cst_fence(thread_id_t tid, const Mode
        if (!list)
                return NULL;
 
-       action_list_t::reverse_iterator rit = list->rbegin();
+       sllnode<ModelAction*>* rit = list->end();
 
        if (before_fence) {
-               for (;rit != list->rend();rit++)
-                       if (*rit == before_fence)
+               for (;rit != NULL;rit=rit->getPrev())
+                       if (rit->getVal() == before_fence)
                                break;
 
-               ASSERT(*rit == before_fence);
-               rit++;
+               ASSERT(rit->getVal() == before_fence);
+               rit=rit->getPrev();
        }
 
-       for (;rit != list->rend();rit++)
-               if ((*rit)->is_fence() && (tid == (*rit)->get_tid()) && (*rit)->is_seqcst())
-                       return *rit;
+       for (;rit != NULL;rit=rit->getPrev()) {
+               ModelAction *act = rit->getVal();
+               if (act->is_fence() && (tid == act->get_tid()) && act->is_seqcst())
+                       return act;
+       }
        return NULL;
 }
 
@@ -1440,10 +1368,10 @@ ModelAction * ModelExecution::get_last_unlock(ModelAction *curr) const
 
        action_list_t *list = obj_map.get(location);
        /* Find: max({i in dom(S) | isUnlock(t_i) && samevar(t_i, t)}) */
-       action_list_t::reverse_iterator rit;
-       for (rit = list->rbegin();rit != list->rend();rit++)
-               if ((*rit)->is_unlock() || (*rit)->is_wait())
-                       return *rit;
+       sllnode<ModelAction*>* rit;
+       for (rit = list->end();rit != NULL;rit=rit->getPrev())
+               if (rit->getVal()->is_unlock() || rit->getVal()->is_wait())
+                       return rit->getVal();
        return NULL;
 }
 
@@ -1506,9 +1434,9 @@ SnapVector<ModelAction *> *  ModelExecution::build_may_read_from(ModelAction *cu
        for (i = 0;i < thrd_lists->size();i++) {
                /* Iterate over actions in thread, starting from most recent */
                action_list_t *list = &(*thrd_lists)[i];
-               action_list_t::reverse_iterator rit;
-               for (rit = list->rbegin();rit != list->rend();rit++) {
-                       ModelAction *act = *rit;
+               sllnode<ModelAction *> * rit;
+               for (rit = list->end();rit != NULL;rit=rit->getPrev()) {
+                       ModelAction *act = rit->getVal();
 
                        if (act == curr)
                                continue;
@@ -1571,9 +1499,9 @@ ModelAction * ModelExecution::get_uninitialized_action(ModelAction *curr) const
        return act;
 }
 
-static void print_list(const action_list_t *list)
+static void print_list(action_list_t *list)
 {
-       action_list_t::const_iterator it;
+       sllnode<ModelAction*> *it;
 
        model_print("------------------------------------------------------------------------------------\n");
        model_print("#    t    Action type     MO       Location         Value               Rf  CV\n");
@@ -1581,18 +1509,18 @@ static void print_list(const action_list_t *list)
 
        unsigned int hash = 0;
 
-       for (it = list->begin();it != list->end();it++) {
-               const ModelAction *act = *it;
+       for (it = list->begin();it != NULL;it=it->getNext()) {
+               const ModelAction *act = it->getVal();
                if (act->get_seq_number() > 0)
                        act->print();
-               hash = hash^(hash<<3)^((*it)->hash());
+               hash = hash^(hash<<3)^(it->getVal()->hash());
        }
        model_print("HASH %u\n", hash);
        model_print("------------------------------------------------------------------------------------\n");
 }
 
 #if SUPPORT_MOD_ORDER_DUMP
-void ModelExecution::dumpGraph(char *filename) const
+void ModelExecution::dumpGraph(char *filename)
 {
        char buffer[200];
        sprintf(buffer, "%s.dot", filename);
@@ -1601,8 +1529,8 @@ void ModelExecution::dumpGraph(char *filename) const
        mo_graph->dumpNodes(file);
        ModelAction **thread_array = (ModelAction **)model_calloc(1, sizeof(ModelAction *) * get_num_threads());
 
-       for (action_list_t::const_iterator it = action_trace.begin();it != action_trace.end();it++) {
-               ModelAction *act = *it;
+       for (sllnode<ModelAction*>* it = action_trace.begin();it != NULL;it=it->getNext()) {
+               ModelAction *act = it->getVal();
                if (act->is_read()) {
                        mo_graph->dot_print_node(file, act);
                        mo_graph->dot_print_edge(file,
@@ -1626,7 +1554,7 @@ void ModelExecution::dumpGraph(char *filename) const
 #endif
 
 /** @brief Prints an execution trace summary. */
-void ModelExecution::print_summary() const
+void ModelExecution::print_summary()
 {
 #if SUPPORT_MOD_ORDER_DUMP
        char buffername[100];
@@ -1637,13 +1565,11 @@ void ModelExecution::print_summary() const
 #endif
 
        model_print("Execution trace %d:", get_execution_number());
-       if (isfeasibleprefix()) {
-               if (scheduler->all_threads_sleeping())
-                       model_print(" SLEEP-SET REDUNDANT");
-               if (have_bug_reports())
-                       model_print(" DETECTED BUG(S)");
-       } else
-               print_infeasibility(" INFEASIBLE");
+       if (scheduler->all_threads_sleeping())
+               model_print(" SLEEP-SET REDUNDANT");
+       if (have_bug_reports())
+               model_print(" DETECTED BUG(S)");
+
        model_print("\n");
 
        print_list(&action_trace);
@@ -1739,7 +1665,7 @@ bool ModelExecution::is_enabled(thread_id_t tid) const
 Thread * ModelExecution::action_select_next_thread(const ModelAction *curr) const
 {
        /* Do not split atomic RMW */
-       if (curr->is_rmwr())
+       if (curr->is_rmwr() && !paused_by_fuzzer(curr))
                return get_thread(curr);
        /* Follow CREATE with the created thread */
        /* which is not needed, because model.cc takes care of this */
@@ -1751,6 +1677,15 @@ Thread * ModelExecution::action_select_next_thread(const ModelAction *curr) cons
        return NULL;
 }
 
+/** @param act A read atomic action */
+bool ModelExecution::paused_by_fuzzer(const ModelAction * act) const
+{
+       ASSERT(act->is_read());
+
+       // Actions paused by fuzzer have their sequence number reset to 0
+       return act->get_seq_number() == 0;
+}
+
 /**
  * Takes the next step in the execution, if possible.
  * @param curr The current step to take
@@ -1766,8 +1701,8 @@ Thread * ModelExecution::take_step(ModelAction *curr)
        curr = check_current_action(curr);
        ASSERT(curr);
 
-       /* Process this action in ModelHistory for records*/
-       model->get_history()->process_action( curr, curr_thrd->get_id() );
+       /* Process this action in ModelHistory for records */
+       model->get_history()->process_action( curr, curr->get_tid() );
 
        if (curr_thrd->is_blocked() || curr_thrd->is_complete())
                scheduler->remove_thread(curr_thrd);