earliest_diverge=diverge;
Node *nextnode = next->get_node();
+ Node *prevnode = nextnode->get_parent();
+ scheduler->update_sleep_set(prevnode);
+
/* Reached divergence point */
if (nextnode->increment_promise()) {
/* The next node will try to satisfy a different set of promises. */
node_stack->pop_restofstack(2);
} else {
/* Make a different thread execute for next step */
- Node *node = nextnode->get_parent();
- tid = node->get_next_backtrack();
+ scheduler->add_sleep(thread_map->get(id_to_int(next->get_tid())));
+ tid = prevnode->get_next_backtrack();
+ /* Make sure the backtracked thread isn't sleeping. */
+ scheduler->remove_sleep(thread_map->get(id_to_int(tid)));
node_stack->pop_restofstack(1);
if (diverge==earliest_diverge) {
- earliest_diverge=node->get_action();
+ earliest_diverge=prevnode->get_action();
}
}
+ /* The correct sleep set is in the parent node. */
+ execute_sleep_set();
+
DEBUG("*** Divergence point ***\n");
diverge = NULL;
return thread_map->get(id_to_int(tid));
}
+/**
+ * We need to know what the next actions of all threads in the sleep
+ * set will be. This method computes them and stores the actions at
+ * the corresponding thread object's pending action.
+ */
+
+void ModelChecker::execute_sleep_set() {
+ 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->get_enabled(thr) == THREAD_SLEEP_SET ) {
+ thr->set_state(THREAD_RUNNING);
+ scheduler->next_thread(thr);
+ Thread::swap(&system_context, thr);
+ thr->set_pending(priv->current_action);
+ }
+ }
+ priv->current_action = NULL;
+}
+
+void ModelChecker::wake_up_sleeping_actions(ModelAction * curr) {
+ 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->get_enabled(thr) == THREAD_SLEEP_SET ) {
+ ModelAction *pending_act=thr->get_pending();
+ if (pending_act->could_synchronize_with(curr)) {
+ //Remove this thread from sleep set
+ scheduler->remove_sleep(thr);
+ }
+ }
+ }
+}
+
/**
* Queries the model-checker for more executions to explore and, if one
* exists, resets the model-checker state to execute a new execution.
return NULL;
}
-/** This method find backtracking points where we should try to
+/** This method finds backtracking points where we should try to
* reorder the parameter ModelAction against.
*
* @param the ModelAction to find backtracking points for.
for(int i = low_tid; i < high_tid; i++) {
thread_id_t tid = int_to_id(i);
+
if (!node->is_enabled(tid))
continue;
-
+
/* Check if this has been explored already */
if (node->has_been_explored(tid))
continue;
if (unfair)
continue;
}
-
/* Cache the latest backtracking point */
if (!priv->next_backtrack || *prev > *priv->next_backtrack)
priv->next_backtrack = prev;
Thread * ModelChecker::check_current_action(ModelAction *curr)
{
ASSERT(curr);
-
bool second_part_of_rmw = curr->is_rmwc() || curr->is_rmw();
if (!check_action_enabled(curr)) {
return get_next_thread(NULL);
}
+ wake_up_sleeping_actions(curr);
+
ModelAction *newcurr = initialize_curr_action(curr);
+
/* Add the action to lists before any other model-checking tasks */
if (!second_part_of_rmw)
add_action_to_lists(newcurr);
/* Initialize work_queue with the "current action" work */
work_queue_t work_queue(1, CheckCurrWorkEntry(curr));
-
while (!work_queue.empty()) {
WorkQueueEntry work = work_queue.front();
work_queue.pop_front();
}
check_curr_backtracking(curr);
-
set_backtracking(curr);
-
return get_next_thread(curr);
}
#include "schedule.h"
#include "common.h"
#include "model.h"
+#include "nodestack.h"
/** Constructor */
Scheduler::Scheduler() :
is_enabled[threadid]=enabled_status;
}
+enabled_type_t Scheduler::get_enabled(Thread *t) {
+ return is_enabled[id_to_int(t->get_id())];
+}
+
+void Scheduler::update_sleep_set(Node *n) {
+ enabled_type_t *enabled_array=n->get_enabled_array();
+ for(int i=0;i<enabled_len;i++) {
+ if (enabled_array[i]==THREAD_SLEEP_SET) {
+ is_enabled[i]=THREAD_SLEEP_SET;
+ }
+ }
+}
+
+/**
+ * Add a Thread to the sleep set.
+ * @param t The Thread to add
+ */
+void Scheduler::add_sleep(Thread *t)
+{
+ DEBUG("thread %d\n", id_to_int(t->get_id()));
+ set_enabled(t, THREAD_SLEEP_SET);
+}
+
+/**
+ * Remove a Thread from the sleep set.
+ * @param t The Thread to remove
+ */
+void Scheduler::remove_sleep(Thread *t)
+{
+ DEBUG("thread %d\n", id_to_int(t->get_id()));
+ set_enabled(t, THREAD_ENABLED);
+}
+
/**
* Add a Thread to the scheduler's ready list.
* @param t The Thread to add
int old_curr_thread = curr_thread_index;
while(true) {
curr_thread_index = (curr_thread_index+1) % enabled_len;
- if (is_enabled[curr_thread_index]) {
+ if (is_enabled[curr_thread_index]==THREAD_ENABLED) {
t = model->get_thread(int_to_id(curr_thread_index));
break;
}