model: JOIN/LOCK unification
authorBrian Norris <banorris@uci.edu>
Wed, 3 Oct 2012 19:07:33 +0000 (12:07 -0700)
committerBrian Norris <banorris@uci.edu>
Tue, 9 Oct 2012 02:59:37 +0000 (19:59 -0700)
Make join and lock actions use similar code paths.

This used to trigger a bug, due to the lack of a private snapshotting
heap.

model.cc
model.h

index 02f290d0a4e29efe8954eaf56f1075955182e9ea..e11dcf716939e1a13f1dd08f6b252ab60fef1b9b 100644 (file)
--- a/model.cc
+++ b/model.cc
@@ -557,26 +557,17 @@ bool ModelChecker::process_thread_action(ModelAction *curr)
                break;
        }
        case THREAD_JOIN: {
-               Thread *waiting, *blocking;
-               waiting = get_thread(curr);
-               blocking = (Thread *)curr->get_location();
-               if (!blocking->is_complete()) {
-                       blocking->push_wait_list(curr);
-                       scheduler->sleep(waiting);
-               } else {
-                       do_complete_join(curr);
-                       updated = true; /* trigger rel-seq checks */
-               }
+               Thread *blocking = (Thread *)curr->get_location();
+               ModelAction *act = get_last_action(blocking->get_id());
+               curr->synchronize_with(act);
+               updated = true; /* trigger rel-seq checks */
                break;
        }
        case THREAD_FINISH: {
                Thread *th = get_thread(curr);
                while (!th->wait_list_empty()) {
                        ModelAction *act = th->pop_wait_list();
-                       Thread *wake = get_thread(act);
-                       scheduler->wake(wake);
-                       do_complete_join(act);
-                       updated = true; /* trigger rel-seq checks */
+                       scheduler->wake(get_thread(act));
                }
                th->complete();
                updated = true; /* trigger rel-seq checks */
@@ -721,9 +712,12 @@ ModelAction * ModelChecker::initialize_curr_action(ModelAction *curr)
 }
 
 /**
- * This method checks whether a model action is enabled at the given point.
- * At this point, it checks whether a lock operation would be successful at this point.
- * If not, it puts the thread in a waiter list.
+ * @brief Check whether a model action is enabled.
+ *
+ * Checks whether a lock or join operation would be successful (i.e., is the
+ * lock already locked, or is the joined thread already complete). If not, put
+ * the action in a waiter list.
+ *
  * @param curr is the ModelAction to check whether it is enabled.
  * @return a bool that indicates whether the action is enabled.
  */
@@ -736,6 +730,12 @@ bool ModelChecker::check_action_enabled(ModelAction *curr) {
                        lock_waiters_map->get_safe_ptr(curr->get_location())->push_back(curr);
                        return false;
                }
+       } else if (curr->get_type() == THREAD_JOIN) {
+               Thread *blocking = (Thread *)curr->get_location();
+               if (!blocking->is_complete()) {
+                       blocking->push_wait_list(curr);
+                       return false;
+               }
        }
 
        return true;
@@ -760,7 +760,7 @@ Thread * ModelChecker::check_current_action(ModelAction *curr)
 
        if (!check_action_enabled(curr)) {
                /* Make the execution look like we chose to run this action
-                * much later, when a lock is actually available to release */
+                * much later, when a lock/join can succeed */
                get_current_thread()->set_pending(curr);
                scheduler->sleep(get_current_thread());
                return get_next_thread(NULL);
@@ -847,19 +847,6 @@ Thread * ModelChecker::check_current_action(ModelAction *curr)
        return get_next_thread(curr);
 }
 
-/**
- * Complete a THREAD_JOIN operation, by synchronizing with the THREAD_FINISH
- * operation from the Thread it is joining with. Must be called after the
- * completion of the Thread in question.
- * @param join The THREAD_JOIN action
- */
-void ModelChecker::do_complete_join(ModelAction *join)
-{
-       Thread *blocking = (Thread *)join->get_location();
-       ModelAction *act = get_last_action(blocking->get_id());
-       join->synchronize_with(act);
-}
-
 void ModelChecker::check_curr_backtracking(ModelAction * curr) {
        Node *currnode = curr->get_node();
        Node *parnode = currnode->get_parent();
diff --git a/model.h b/model.h
index c99e0f8b424ddbe8079593713e498e53fe6fb80e..6e470c0eaa66a9b126d3f223080bf9114d7d1afc 100644 (file)
--- a/model.h
+++ b/model.h
@@ -169,7 +169,6 @@ private:
        bool w_modification_order(ModelAction *curr);
        bool release_seq_heads(const ModelAction *rf, rel_heads_list_t *release_heads, struct release_seq *pending) const;
        bool resolve_release_sequences(void *location, work_queue_t *work_queue);
-       void do_complete_join(ModelAction *join);
 
        ModelAction *diverge;
        ModelAction *earliest_diverge;