7 #include "snapshot-interface.h"
10 #define INITIAL_THREAD_ID 0
14 ModelChecker::ModelChecker()
16 /* Initialize default scheduler */
17 scheduler(new Scheduler()),
18 /* First thread created will have id INITIAL_THREAD_ID */
19 next_thread_id(INITIAL_THREAD_ID),
20 used_sequence_numbers(0),
25 nextThread(THREAD_ID_T_NONE),
26 action_trace(new action_list_t()),
27 thread_map(new std::map<int, class Thread *>),
28 node_stack(new NodeStack()),
33 ModelChecker::~ModelChecker()
35 std::map<int, class Thread *>::iterator it;
36 for (it = thread_map->begin(); it != thread_map->end(); it++)
46 void ModelChecker::reset_to_initial_state()
48 DEBUG("+++ Resetting to initial state +++\n");
49 node_stack->reset_execution();
50 current_action = NULL;
51 next_thread_id = INITIAL_THREAD_ID;
52 used_sequence_numbers = 0;
54 next_backtrack = NULL;
55 snapshotObject->backTrackBeforeStep(0);
58 thread_id_t ModelChecker::get_next_id()
60 return next_thread_id++;
63 int ModelChecker::get_num_threads()
65 return next_thread_id;
68 int ModelChecker::get_next_seq_num()
70 return ++used_sequence_numbers;
73 Thread * ModelChecker::schedule_next_thread()
76 if (nextThread == THREAD_ID_T_NONE)
78 t = (*thread_map)[id_to_int(nextThread)];
86 * get_next_replay_thread() - Choose the next thread in the replay sequence
88 * If we've reached the 'diverge' point, then we pick a thread from the
90 * Otherwise, we simply return the next thread in the sequence.
92 thread_id_t ModelChecker::get_next_replay_thread()
97 /* Have we completed exploring the preselected path? */
99 return THREAD_ID_T_NONE;
101 /* Else, we are trying to replay an execution */
102 next = node_stack->get_next()->get_action();
104 if (next == diverge) {
105 Node *node = next->get_node();
107 /* Reached divergence point */
108 DEBUG("*** Divergence point ***\n");
109 tid = node->get_next_backtrack();
112 tid = next->get_tid();
114 DEBUG("*** ModelChecker chose next thread = %d ***\n", tid);
118 bool ModelChecker::next_execution()
124 if ((diverge = model->get_next_backtrack()) == NULL)
128 printf("Next execution will diverge at:\n");
132 model->reset_to_initial_state();
136 ModelAction * ModelChecker::get_last_conflict(ModelAction *act)
138 action_type type = act->get_type();
150 /* linear search: from most recent to oldest */
151 action_list_t::reverse_iterator rit;
152 for (rit = action_trace->rbegin(); rit != action_trace->rend(); rit++) {
153 ModelAction *prev = *rit;
154 if (act->is_dependent(prev))
160 void ModelChecker::set_backtracking(ModelAction *act)
164 Thread *t = get_thread(act->get_tid());
166 prev = get_last_conflict(act);
170 node = prev->get_node();
172 while (!node->is_enabled(t))
175 /* Check if this has been explored already */
176 if (node->has_been_explored(t->get_id()))
179 if (!next_backtrack || *prev > *next_backtrack)
180 next_backtrack = prev;
182 /* If this is a new backtracking point, mark the tree */
183 if (!node->set_backtrack(t->get_id()))
185 DEBUG("Setting backtrack: conflict = %d, instead tid = %d\n",
186 prev->get_tid(), t->get_id());
193 ModelAction * ModelChecker::get_next_backtrack()
195 ModelAction *next = next_backtrack;
196 next_backtrack = NULL;
200 void ModelChecker::check_current_action(void)
204 ModelAction *curr = this->current_action;
205 current_action = NULL;
207 DEBUG("trying to push NULL action...\n");
211 curr = node_stack->explore_action(curr);
212 nextThread = get_next_replay_thread();
214 currnode = curr->get_node();
216 if (!currnode->backtrack_empty())
217 if (!next_backtrack || *curr > *next_backtrack)
218 next_backtrack = curr;
220 set_backtracking(curr);
221 this->action_trace->push_back(curr);
224 void ModelChecker::print_summary(void)
227 printf("Number of executions: %d\n", num_executions);
228 printf("Total nodes created: %d\n", Node::get_total_nodes());
232 print_list(action_trace);
236 void ModelChecker::print_list(action_list_t *list)
238 action_list_t::iterator it;
240 printf("---------------------------------------------------------------------\n");
243 for (it = list->begin(); it != list->end(); it++) {
246 printf("---------------------------------------------------------------------\n");
249 int ModelChecker::add_thread(Thread *t)
251 (*thread_map)[id_to_int(t->get_id())] = t;
252 scheduler->add_thread(t);
256 void ModelChecker::remove_thread(Thread *t)
258 scheduler->remove_thread(t);
261 int ModelChecker::switch_to_master(ModelAction *act)
266 old = thread_current();
267 set_current_action(act);
268 old->set_state(THREAD_READY);
269 return Thread::swap(old, get_system_context());