#include <stdio.h>
+#include <algorithm>
#include "model.h"
#include "action.h"
#include "clockvector.h"
#include "cyclegraph.h"
#include "promise.h"
+#include "datarace.h"
#define INITIAL_THREAD_ID 0
node_stack(new NodeStack()),
next_backtrack(NULL),
mo_graph(new CycleGraph()),
- failed_promise(false)
+ failed_promise(false),
+ asserted(false)
{
}
nextThread = NULL;
next_backtrack = NULL;
failed_promise = false;
+ reset_asserted();
snapshotObject->backTrackBeforeStep(0);
}
if (isfinalfeasible() || DBG_ENABLED())
print_summary();
- if ((diverge = model->get_next_backtrack()) == NULL)
+ if ((diverge = get_next_backtrack()) == NULL)
return false;
if (DBG_ENABLED()) {
diverge->print();
}
- model->reset_to_initial_state();
+ reset_to_initial_state();
return true;
}
Thread *wake = th->pop_wait_list();
scheduler->wake(wake);
}
+ th->complete();
}
/* Deal with new thread */
}
} else if (curr->is_write()) {
if (w_modification_order(curr))
- updated = true;;
+ updated = true;
if (resolve_promises(curr))
updated = true;
}
/* Do not split atomic actions. */
if (curr->is_rmwr())
return thread_current();
+ /* The THREAD_CREATE action points to the created Thread */
+ else if (curr->get_type() == THREAD_CREATE)
+ return (Thread *)curr->get_location();
else
return get_next_replay_thread();
}
+/** @returns whether the current partial trace must be a prefix of a
+ * feasible trace. */
+
+bool ModelChecker::isfeasibleprefix() {
+ return promises->size()==0;
+}
+
/** @returns whether the current partial trace is feasible. */
bool ModelChecker::isfeasible() {
return !mo_graph->checkForCycles() && !failed_promise;
action_list_t::const_reverse_iterator rit;
/* Find rf in the thread list */
- for (rit = list->rbegin(); rit != list->rend(); rit++)
- if (*rit == rf)
- break;
+ rit = std::find(list->rbegin(), list->rend(), rf);
+ ASSERT(rit != list->rend());
/* Find the last write/release */
for (; rit != list->rend(); rit++)
if (id_to_int(rf->get_tid()) == (int)i)
continue;
list = &(*thrd_lists)[i];
+
+ /* Can we ensure no future writes from this thread may break
+ * the release seq? */
+ bool future_ordered = false;
+
for (rit = list->rbegin(); rit != list->rend(); rit++) {
const ModelAction *act = *rit;
if (!act->is_write())
/* Reach synchronization -> this thread is complete */
if (act->happens_before(release))
break;
- if (rf->happens_before(act))
+ if (rf->happens_before(act)) {
+ future_ordered = true;
continue;
+ }
/* Check modification order */
- if (mo_graph->checkReachable(rf, act))
+ if (mo_graph->checkReachable(rf, act)) {
/* rf --mo--> act */
+ future_ordered = true;
continue;
+ }
if (mo_graph->checkReachable(act, release))
/* act --mo--> release */
break;
}
certain = false;
}
+ if (!future_ordered)
+ return false; /* This thread is uncertain */
}
if (certain)
it++;
}
+ // If we resolved promises or data races, see if we have realized a data race.
+ if (checkDataRaces()) {
+ set_assert();
+ }
+
return updated;
}
} else
promise_index++;
}
+
return resolved;
}
merge_cv->synchronized_since(act)) {
//This thread is no longer able to send values back to satisfy the promise
int num_synchronized_threads = promise->increment_threads();
- if (num_synchronized_threads == model->get_num_threads()) {
+ if (num_synchronized_threads == get_num_threads()) {
//Promise has failed
failed_promise = true;
return;
bool ModelChecker::take_step() {
Thread *curr, *next;
+ if (has_asserted())
+ return false;
+
curr = thread_current();
if (curr) {
if (curr->get_state() == THREAD_READY) {
ASSERT(current_action);
nextThread = check_current_action(current_action);
current_action = NULL;
- if (!curr->is_blocked())
+ if (!curr->is_blocked() && !curr->is_complete())
scheduler->add_thread(curr);
- } else if (curr->get_state() == THREAD_RUNNING) {
- /* Stopped while running; i.e., completed */
- curr->complete();
} else {
ASSERT(false);
}