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 obj_thrd_map(new std::map<void *, std::vector<action_list_t> >()),
29 thrd_last_action(new std::vector<ModelAction *>(1)),
30 node_stack(new NodeStack()),
35 ModelChecker::~ModelChecker()
37 std::map<int, class Thread *>::iterator it;
38 for (it = thread_map->begin(); it != thread_map->end(); it++)
44 delete thrd_last_action;
49 void ModelChecker::reset_to_initial_state()
51 DEBUG("+++ Resetting to initial state +++\n");
52 node_stack->reset_execution();
53 current_action = NULL;
54 next_thread_id = INITIAL_THREAD_ID;
55 used_sequence_numbers = 0;
57 next_backtrack = NULL;
58 snapshotObject->backTrackBeforeStep(0);
61 thread_id_t ModelChecker::get_next_id()
63 return next_thread_id++;
66 int ModelChecker::get_num_threads()
68 return next_thread_id;
71 int ModelChecker::get_next_seq_num()
73 return ++used_sequence_numbers;
76 Thread * ModelChecker::schedule_next_thread()
79 if (nextThread == THREAD_ID_T_NONE)
81 t = (*thread_map)[id_to_int(nextThread)];
89 * get_next_replay_thread() - Choose the next thread in the replay sequence
91 * If we've reached the 'diverge' point, then we pick a thread from the
93 * Otherwise, we simply return the next thread in the sequence.
95 thread_id_t ModelChecker::get_next_replay_thread()
100 /* Have we completed exploring the preselected path? */
102 return THREAD_ID_T_NONE;
104 /* Else, we are trying to replay an execution */
105 next = node_stack->get_next()->get_action();
107 if (next == diverge) {
108 Node *node = next->get_node();
110 /* Reached divergence point */
111 DEBUG("*** Divergence point ***\n");
112 tid = node->get_next_backtrack();
115 tid = next->get_tid();
117 DEBUG("*** ModelChecker chose next thread = %d ***\n", tid);
121 bool ModelChecker::next_execution()
127 if ((diverge = model->get_next_backtrack()) == NULL)
131 printf("Next execution will diverge at:\n");
135 model->reset_to_initial_state();
139 ModelAction * ModelChecker::get_last_conflict(ModelAction *act)
141 action_type type = act->get_type();
153 /* linear search: from most recent to oldest */
154 action_list_t::reverse_iterator rit;
155 for (rit = action_trace->rbegin(); rit != action_trace->rend(); rit++) {
156 ModelAction *prev = *rit;
157 if (act->is_dependent(prev))
163 void ModelChecker::set_backtracking(ModelAction *act)
167 Thread *t = get_thread(act->get_tid());
169 prev = get_last_conflict(act);
173 node = prev->get_node();
175 while (!node->is_enabled(t))
178 /* Check if this has been explored already */
179 if (node->has_been_explored(t->get_id()))
182 if (!next_backtrack || *prev > *next_backtrack)
183 next_backtrack = prev;
185 /* If this is a new backtracking point, mark the tree */
186 if (!node->set_backtrack(t->get_id()))
188 DEBUG("Setting backtrack: conflict = %d, instead tid = %d\n",
189 prev->get_tid(), t->get_id());
196 ModelAction * ModelChecker::get_next_backtrack()
198 ModelAction *next = next_backtrack;
199 next_backtrack = NULL;
203 void ModelChecker::check_current_action(void)
207 ModelAction *curr = this->current_action;
208 current_action = NULL;
210 DEBUG("trying to push NULL action...\n");
214 curr = node_stack->explore_action(curr, get_parent_action(curr->get_tid()));
216 /* Assign 'creation' parent */
217 if (curr->get_type() == THREAD_CREATE) {
218 Thread *th = (Thread *)curr->get_location();
219 th->set_creation(curr);
222 nextThread = get_next_replay_thread();
224 currnode = curr->get_node();
226 if (!currnode->backtrack_empty())
227 if (!next_backtrack || *curr > *next_backtrack)
228 next_backtrack = curr;
230 set_backtracking(curr);
232 add_action_to_lists(curr);
235 void ModelChecker::add_action_to_lists(ModelAction *act)
237 action_trace->push_back(act);
239 std::vector<action_list_t> *vec = &(*obj_thrd_map)[act->get_location()];
240 if (id_to_int(act->get_tid()) >= (int)vec->size())
241 vec->resize(next_thread_id);
242 (*vec)[id_to_int(act->get_tid())].push_back(act);
244 (*thrd_last_action)[id_to_int(act->get_tid())] = act;
247 ModelAction * ModelChecker::get_last_action(thread_id_t tid)
249 int nthreads = get_num_threads();
250 if ((int)thrd_last_action->size() < nthreads)
251 thrd_last_action->resize(nthreads);
252 return (*thrd_last_action)[id_to_int(tid)];
255 ModelAction * ModelChecker::get_parent_action(thread_id_t tid)
257 ModelAction *parent = get_last_action(tid);
259 parent = get_thread(tid)->get_creation();
263 void ModelChecker::print_summary(void)
266 printf("Number of executions: %d\n", num_executions);
267 printf("Total nodes created: %d\n", Node::get_total_nodes());
271 print_list(action_trace);
275 void ModelChecker::print_list(action_list_t *list)
277 action_list_t::iterator it;
279 printf("---------------------------------------------------------------------\n");
282 for (it = list->begin(); it != list->end(); it++) {
285 printf("---------------------------------------------------------------------\n");
288 int ModelChecker::add_thread(Thread *t)
290 (*thread_map)[id_to_int(t->get_id())] = t;
291 scheduler->add_thread(t);
295 void ModelChecker::remove_thread(Thread *t)
297 scheduler->remove_thread(t);
300 int ModelChecker::switch_to_master(ModelAction *act)
305 old = thread_current();
306 set_current_action(act);
307 old->set_state(THREAD_READY);
308 return Thread::swap(old, get_system_context());