action: add ModelAction::is_thread_join() helper
[model-checker.git] / model.cc
index a9d90914afbbe5205cabc01513b25082d4ca2e4b..e6f9afd9c6fd1d2b904e3ea4e23777198b71561f 100644 (file)
--- a/model.cc
+++ b/model.cc
@@ -260,20 +260,8 @@ Thread * ModelChecker::get_next_thread()
                scheduler->update_sleep_set(prevnode);
 
                /* Reached divergence point */
-               if (nextnode->increment_misc()) {
-                       /* The next node will try to satisfy a different misc_index values. */
-                       tid = next->get_tid();
-                       node_stack->pop_restofstack(2);
-               } else if (nextnode->increment_promise()) {
-                       /* The next node will try to satisfy a different set of promises. */
-                       tid = next->get_tid();
-                       node_stack->pop_restofstack(2);
-               } else if (nextnode->increment_read_from()) {
-                       /* The next node will read from a different value. */
-                       tid = next->get_tid();
-                       node_stack->pop_restofstack(2);
-               } else if (nextnode->increment_relseq_break()) {
-                       /* The next node will try to resolve a release sequence differently */
+               if (nextnode->increment_behaviors()) {
+                       /* Execute the same thread with a new behavior */
                        tid = next->get_tid();
                        node_stack->pop_restofstack(2);
                } else {
@@ -409,22 +397,6 @@ bool ModelChecker::is_deadlocked() const
        return blocking_threads;
 }
 
-/**
- * Check if a Thread has entered a circular wait deadlock situation. This will
- * not check other threads for potential deadlock situations, and may miss
- * deadlocks involving WAIT.
- *
- * @param t The thread which may have entered a deadlock
- * @return True if this Thread entered a deadlock; false otherwise
- */
-bool ModelChecker::is_circular_wait(const Thread *t) const
-{
-       for (Thread *waiting = t->waiting_on() ; waiting != NULL; waiting = waiting->waiting_on())
-               if (waiting == t)
-                       return true;
-       return false;
-}
-
 /**
  * Check if this is a complete execution. That is, have all thread completed
  * execution (rather than exiting because sleep sets have forced a redundant
@@ -1056,7 +1028,7 @@ bool ModelChecker::process_mutex(ModelAction *curr)
  *
  * If one of the following is true:
  *  (a) there are no pending promises
- *  (b) the reader is ordered after the latest Promise creation
+ *  (b) the reader and writer do not cross any promises
  * Then, it is safe to pass a future value back now.
  *
  * Otherwise, we must save the pending future value until (a) or (b) is true
@@ -1068,8 +1040,18 @@ bool ModelChecker::process_mutex(ModelAction *curr)
 bool ModelChecker::promises_may_allow(const ModelAction *writer,
                const ModelAction *reader) const
 {
-       return promises->empty() ||
-               *(promises->back()->get_reader(0)) < *reader;
+       if (promises->empty())
+               return true;
+       for(int i=promises->size()-1;i>=0;i--) {
+               ModelAction *pr=(*promises)[i]->get_reader(0);
+               //reader is after promise...doesn't cross any promise
+               if (*reader > *pr)
+                       return true;
+               //writer is after promise, reader before...bad...
+               if (*writer > *pr)
+                       return false;
+       }
+       return true;
 }
 
 /**
@@ -1139,12 +1121,13 @@ bool ModelChecker::process_write(ModelAction *curr)
                }
        }
 
-       if (promises->empty()) {
-               for (unsigned int i = 0; i < futurevalues->size(); i++) {
-                       struct PendingFutureValue pfv = (*futurevalues)[i];
+       /* Check the pending future values */
+       for (int i = (int)futurevalues->size() - 1; i >= 0; i--) {
+               struct PendingFutureValue pfv = (*futurevalues)[i];
+               if (promises_may_allow(pfv.writer, pfv.reader)) {
                        add_future_value(pfv.writer, pfv.reader);
+                       futurevalues->erase(futurevalues->begin() + i);
                }
-               futurevalues->clear();
        }
 
        mo_graph->commitChanges();
@@ -1489,7 +1472,7 @@ bool ModelChecker::check_action_enabled(ModelAction *curr) {
                        get_safe_ptr_action(lock_waiters_map, curr->get_location())->push_back(curr);
                        return false;
                }
-       } else if (curr->get_type() == THREAD_JOIN) {
+       } else if (curr->is_thread_join()) {
                Thread *blocking = (Thread *)curr->get_location();
                if (!blocking->is_complete()) {
                        blocking->push_wait_list(curr);
@@ -3158,7 +3141,7 @@ void ModelChecker::run()
                                Thread *thr = get_thread(tid);
                                if (!thr->is_model_thread() && !thr->is_complete() && !thr->get_pending()) {
                                        switch_from_master(thr);
-                                       if (is_circular_wait(thr))
+                                       if (thr->is_waiting_on(thr))
                                                assert_bug("Deadlock detected");
                                }
                        }