model: simple refactoring
[c11tester.git] / model.cc
index c832b03710fc360ab17bcb5b3afe7a5920c1cfa6..cc035084b036015b94181ef7c61b17d2bbf77f65 100644 (file)
--- a/model.cc
+++ b/model.cc
@@ -159,6 +159,14 @@ void ModelChecker::reset_to_initial_state()
        /* Print all model-checker output before rollback */
        fflush(model_out);
 
+       /**
+        * FIXME: if we utilize partial rollback, we will need to free only
+        * those pending actions which were NOT pending before the rollback
+        * point
+        */
+       for (unsigned int i = 0; i < get_num_threads(); i++)
+               delete get_thread(int_to_id(i))->get_pending();
+
        snapshot_backtrack_before(0);
 }
 
@@ -293,9 +301,7 @@ void ModelChecker::execute_sleep_set()
        for (unsigned int i = 0; i < get_num_threads(); i++) {
                thread_id_t tid = int_to_id(i);
                Thread *thr = get_thread(tid);
-               if (scheduler->is_sleep_set(thr) && thr->get_pending() == NULL) {
-                       scheduler->next_thread(thr);
-                       Thread::swap(&system_context, thr);
+               if (scheduler->is_sleep_set(thr) && thr->get_pending()) {
                        thr->get_pending()->set_sleep_flag();
                }
        }
@@ -321,11 +327,22 @@ void ModelChecker::set_bad_synchronization()
        priv->bad_synchronization = true;
 }
 
+/**
+ * Check whether the current trace has triggered an assertion which should halt
+ * its execution.
+ *
+ * @return True, if the execution should be aborted; false otherwise
+ */
 bool ModelChecker::has_asserted() const
 {
        return priv->asserted;
 }
 
+/**
+ * Trigger a trace assertion which should cause this execution to be halted.
+ * This can be due to a detected bug or due to an infeasibility that should
+ * halt ASAP.
+ */
 void ModelChecker::set_assert()
 {
        priv->asserted = true;
@@ -2665,6 +2682,7 @@ uint64_t ModelChecker::switch_to_master(ModelAction *act)
 {
        DBG();
        Thread *old = thread_current();
+       ASSERT(!old->get_pending());
        old->set_pending(act);
        if (Thread::swap(old, &system_context) < 0) {
                perror("swap threads");
@@ -2681,9 +2699,6 @@ uint64_t ModelChecker::switch_to_master(ModelAction *act)
  */
 Thread * ModelChecker::take_step(ModelAction *curr)
 {
-       if (has_asserted())
-               return NULL;
-
        Thread *curr_thrd = get_thread(curr);
        ASSERT(curr_thrd->get_state() == THREAD_READY);
 
@@ -2729,10 +2744,6 @@ Thread * ModelChecker::take_step(ModelAction *curr)
                return model_thread;
        }
 
-       /* next_thrd == NULL -> don't take any more steps */
-       if (!next_thrd)
-               return NULL;
-
        return next_thrd;
 }
 
@@ -2751,8 +2762,25 @@ void ModelChecker::run()
                add_thread(t);
 
                do {
-                       scheduler->next_thread(t);
-                       Thread::swap(&system_context, t);
+                       /*
+                        * Stash next pending action(s) for thread(s). There
+                        * should only need to stash one thread's action--the
+                        * thread which just took a step--plus the first step
+                        * for any newly-created thread
+                        */
+                       for (unsigned int i = 0; i < get_num_threads(); i++) {
+                               thread_id_t tid = int_to_id(i);
+                               Thread *thr = get_thread(tid);
+                               if (!thr->is_model_thread() && !thr->is_complete() && !thr->get_pending()) {
+                                       scheduler->next_thread(thr);
+                                       Thread::swap(&system_context, thr);
+                               }
+                       }
+
+                       /* Catch assertions from prior take_step or from
+                        * between-ModelAction bugs (e.g., data races) */
+                       if (has_asserted())
+                               break;
 
                        /* Consume the next action for a Thread */
                        ModelAction *curr = t->get_pending();