Do not allow a thread to stash the next pending action if its last action was a SLEEP...
[c11tester.git] / model.cc
index 5dd5702ebbc824dfaae6453b2fbe7e51aa3d80ca..1e3dd2dee12b0c9071bf0e17e5e2ab273affd488 100644 (file)
--- a/model.cc
+++ b/model.cc
@@ -33,14 +33,14 @@ ModelChecker::ModelChecker() :
        params(),
        restart_flag(false),
        scheduler(new Scheduler()),
-       execution(new ModelExecution(this, scheduler)),
        history(new ModelHistory()),
+       execution(new ModelExecution(this, scheduler)),
        execution_number(1),
        trace_analyses(),
        inspect_plugin(NULL)
 {
        memset(&stats,0,sizeof(struct execution_stats));
-       init_thread = new Thread(execution->get_next_id(), (thrd_t *) model_malloc(sizeof(thrd_t)), &user_main_wrapper, NULL, NULL);    // L: user_main_wrapper passes the user program
+       init_thread = new Thread(execution->get_next_id(), (thrd_t *) model_malloc(sizeof(thrd_t)), &user_main_wrapper, NULL, NULL);
 #ifdef TLS
        init_thread->setTLS((char *)get_tls_addr());
 #endif
@@ -264,6 +264,7 @@ bool ModelChecker::next_execution()
 // test code
        execution_number ++;
        reset_to_initial_state();
+       history->set_new_exec_flag();
        return false;
 }
 
@@ -353,6 +354,8 @@ static void runChecker() {
 
 void ModelChecker::startChecker() {
        startExecution(get_system_context(), runChecker);
+       snapshot_stack_init();
+       snapshot_record(0);
 }
 
 bool ModelChecker::should_terminate_execution()
@@ -360,7 +363,7 @@ bool ModelChecker::should_terminate_execution()
        /* Infeasible -> don't take any more steps */
        if (execution->is_infeasible())
                return true;
-       else if (execution->isfeasibleprefix() && execution->have_fatal_bug_reports()) {
+       else if (execution->isfeasibleprefix() && execution->have_bug_reports()) {
                execution->set_assert();
                return true;
        } else if (execution->isFinished()) {
@@ -390,20 +393,6 @@ void ModelChecker::startMainThread() {
        main_thread_startup();
 }
 
-static bool is_nonsc_write(const ModelAction *act) {
-       if (act->get_type() == ATOMIC_WRITE) {
-               std::memory_order order = act->get_mo();
-               switch(order) {
-               case std::memory_order_relaxed:
-               case std::memory_order_release:
-                       return true;
-               default:
-                       return false;
-               }
-       }
-       return false;
-}
-
 /** @brief Run ModelChecker for the user program */
 void ModelChecker::run()
 {
@@ -421,12 +410,11 @@ void ModelChecker::run()
                         * thread which just took a step--plus the first step
                         * for any newly-created thread
                         */
-                       ModelAction * pending;
                        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() && ((!(pending=thr->get_pending())) || is_nonsc_write(pending)) ) {
-                                       switch_from_master(thr);        // L: context swapped, and action type of thr changed.
+                               if (!thr->is_model_thread() && !thr->is_complete() && !thr->get_pending()) {
+                                       switch_from_master(thr);
                                        if (thr->is_waiting_on(thr))
                                                assert_bug("Deadlock detected (thread %u)", i);
                                }
@@ -471,6 +459,11 @@ void ModelChecker::run()
                                t = get_next_thread();
                        if (!t || t->is_model_thread())
                                break;
+                       if (t->just_woken_up()) {
+                               t->set_wakeup_state(false);
+                               t->set_pending(NULL);
+                               continue;       // Allow this thread to stash the next pending action
+                       }
 
                        /* Consume the next action for a Thread */
                        ModelAction *curr = t->get_pending();
@@ -488,4 +481,9 @@ void ModelChecker::run()
        /* Have the trace analyses dump their output. */
        for (unsigned int i = 0;i < trace_analyses.size();i++)
                trace_analyses[i]->finish();
+
+       /* unlink tmp file created by last child process */
+       char filename[256];
+       snprintf_(filename, sizeof(filename), "C11FuzzerTmp%d", getpid());
+       unlink(filename);
 }