/* 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);
}
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();
}
}
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;
{
DBG();
Thread *old = thread_current();
+ ASSERT(!old->get_pending());
old->set_pending(act);
if (Thread::swap(old, &system_context) < 0) {
perror("swap threads");
*/
Thread * ModelChecker::take_step(ModelAction *curr)
{
- if (has_asserted())
- return NULL;
-
Thread *curr_thrd = get_thread(curr);
ASSERT(curr_thrd->get_state() == THREAD_READY);
return model_thread;
}
- /* next_thrd == NULL -> don't take any more steps */
- if (!next_thrd)
- return NULL;
-
return next_thrd;
}
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();