Optimizations
[c11tester.git] / model.cc
1 #include <stdio.h>
2 #include <algorithm>
3 #include <new>
4 #include <stdarg.h>
5 #include <string.h>
6 #include <cstdlib>
7
8 #include "model.h"
9 #include "action.h"
10 #include "nodestack.h"
11 #include "schedule.h"
12 #include "snapshot-interface.h"
13 #include "common.h"
14 #include "datarace.h"
15 #include "threads-model.h"
16 #include "output.h"
17 #include "traceanalysis.h"
18 #include "execution.h"
19 #include "bugmessage.h"
20
21 ModelChecker *model;
22
23 /** @brief Constructor */
24 ModelChecker::ModelChecker() :
25         /* Initialize default scheduler */
26         params(),
27         restart_flag(false),
28         scheduler(new Scheduler()),
29         node_stack(new NodeStack()),
30         execution(new ModelExecution(this, scheduler, node_stack)),
31         execution_number(1),
32         trace_analyses(),
33         inspect_plugin(NULL)
34 {
35         memset(&stats,0,sizeof(struct execution_stats));
36 }
37
38 /** @brief Destructor */
39 ModelChecker::~ModelChecker()
40 {
41         delete node_stack;
42         delete scheduler;
43 }
44
45 /** Method to set parameters */
46 void ModelChecker::setParams(struct model_params params) {
47         this->params = params;
48         execution->setParams(&params);
49 }
50
51 /**
52  * Restores user program to initial state and resets all model-checker data
53  * structures.
54  */
55 void ModelChecker::reset_to_initial_state()
56 {
57         DEBUG("+++ Resetting to initial state +++\n");
58         node_stack->reset_execution();
59
60         /**
61          * FIXME: if we utilize partial rollback, we will need to free only
62          * those pending actions which were NOT pending before the rollback
63          * point
64          */
65         for (unsigned int i = 0;i < get_num_threads();i++)
66                 delete get_thread(int_to_id(i))->get_pending();
67
68         snapshot_backtrack_before(0);
69 }
70
71 /** @return the number of user threads created during this execution */
72 unsigned int ModelChecker::get_num_threads() const
73 {
74         return execution->get_num_threads();
75 }
76
77 /**
78  * Must be called from user-thread context (e.g., through the global
79  * thread_current() interface)
80  *
81  * @return The currently executing Thread.
82  */
83 Thread * ModelChecker::get_current_thread() const
84 {
85         return scheduler->get_current_thread();
86 }
87
88 /**
89  * @brief Choose the next thread to execute.
90  *
91  * This function chooses the next thread that should execute. It can enforce
92  * execution replay/backtracking or, if the model-checker has no preference
93  * regarding the next thread (i.e., when exploring a new execution ordering),
94  * we defer to the scheduler.
95  *
96  * @return The next chosen thread to run, if any exist. Or else if the current
97  * execution should terminate, return NULL.
98  */
99 Thread * ModelChecker::get_next_thread()
100 {
101
102         /*
103          * Have we completed exploring the preselected path? Then let the
104          * scheduler decide
105          */
106         return scheduler->select_next_thread(node_stack->get_head());
107 }
108
109 /**
110  * @brief Assert a bug in the executing program.
111  *
112  * Use this function to assert any sort of bug in the user program. If the
113  * current trace is feasible (actually, a prefix of some feasible execution),
114  * then this execution will be aborted, printing the appropriate message. If
115  * the current trace is not yet feasible, the error message will be stashed and
116  * printed if the execution ever becomes feasible.
117  *
118  * @param msg Descriptive message for the bug (do not include newline char)
119  * @return True if bug is immediately-feasible
120  */
121 bool ModelChecker::assert_bug(const char *msg, ...)
122 {
123         char str[800];
124
125         va_list ap;
126         va_start(ap, msg);
127         vsnprintf(str, sizeof(str), msg, ap);
128         va_end(ap);
129
130         return execution->assert_bug(str);
131 }
132
133 /**
134  * @brief Assert a bug in the executing program, asserted by a user thread
135  * @see ModelChecker::assert_bug
136  * @param msg Descriptive message for the bug (do not include newline char)
137  */
138 void ModelChecker::assert_user_bug(const char *msg)
139 {
140         /* If feasible bug, bail out now */
141         if (assert_bug(msg))
142                 switch_to_master(NULL);
143 }
144
145 /** @brief Print bug report listing for this execution (if any bugs exist) */
146 void ModelChecker::print_bugs() const
147 {
148         SnapVector<bug_message *> *bugs = execution->get_bugs();
149
150         model_print("Bug report: %zu bug%s detected\n",
151                                                         bugs->size(),
152                                                         bugs->size() > 1 ? "s" : "");
153         for (unsigned int i = 0;i < bugs->size();i++)
154                 (*bugs)[i] -> print();
155 }
156
157 /**
158  * @brief Record end-of-execution stats
159  *
160  * Must be run when exiting an execution. Records various stats.
161  * @see struct execution_stats
162  */
163 void ModelChecker::record_stats()
164 {
165         stats.num_total ++;
166         if (!execution->isfeasibleprefix())
167                 stats.num_infeasible ++;
168         else if (execution->have_bug_reports())
169                 stats.num_buggy_executions ++;
170         else if (execution->is_complete_execution())
171                 stats.num_complete ++;
172         else {
173                 stats.num_redundant ++;
174
175                 /**
176                  * @todo We can violate this ASSERT() when fairness/sleep sets
177                  * conflict to cause an execution to terminate, e.g. with:
178                  * Scheduler: [0: disabled][1: disabled][2: sleep][3: current, enabled]
179                  */
180                 //ASSERT(scheduler->all_threads_sleeping());
181         }
182 }
183
184 /** @brief Print execution stats */
185 void ModelChecker::print_stats() const
186 {
187         model_print("Number of complete, bug-free executions: %d\n", stats.num_complete);
188         model_print("Number of redundant executions: %d\n", stats.num_redundant);
189         model_print("Number of buggy executions: %d\n", stats.num_buggy_executions);
190         model_print("Number of infeasible executions: %d\n", stats.num_infeasible);
191         model_print("Total executions: %d\n", stats.num_total);
192 }
193
194 /**
195  * @brief End-of-exeuction print
196  * @param printbugs Should any existing bugs be printed?
197  */
198 void ModelChecker::print_execution(bool printbugs) const
199 {
200         model_print("Program output from execution %d:\n",
201                                                         get_execution_number());
202         print_program_output();
203
204         if (params.verbose >= 3) {
205                 print_stats();
206         }
207
208         /* Don't print invalid bugs */
209         if (printbugs && execution->have_bug_reports()) {
210                 model_print("\n");
211                 print_bugs();
212         }
213
214         model_print("\n");
215         execution->print_summary();
216 }
217
218 /**
219  * Queries the model-checker for more executions to explore and, if one
220  * exists, resets the model-checker state to execute a new execution.
221  *
222  * @return If there are more executions to explore, return true. Otherwise,
223  * return false.
224  */
225 bool ModelChecker::next_execution()
226 {
227         DBG();
228         /* Is this execution a feasible execution that's worth bug-checking? */
229         bool complete = execution->isfeasibleprefix() &&
230                                                                         (execution->is_complete_execution() ||
231                                                                          execution->have_bug_reports());
232
233         /* End-of-execution bug checks */
234         if (complete) {
235                 if (execution->is_deadlocked())
236                         assert_bug("Deadlock detected");
237
238                 checkDataRaces();
239                 run_trace_analyses();
240         }
241
242         record_stats();
243         /* Output */
244         if ( (complete && params.verbose) || params.verbose>1 || (complete && execution->have_bug_reports()))
245                 print_execution(complete);
246         else
247                 clear_program_output();
248
249         if (restart_flag) {
250                 do_restart();
251                 return true;
252         }
253 // test code
254         execution_number ++;
255         reset_to_initial_state();
256         node_stack->full_reset();
257         return false;
258 }
259
260 /** @brief Run trace analyses on complete trace */
261 void ModelChecker::run_trace_analyses() {
262         for (unsigned int i = 0;i < trace_analyses.size();i ++)
263                 trace_analyses[i] -> analyze(execution->get_action_trace());
264 }
265
266 /**
267  * @brief Get a Thread reference by its ID
268  * @param tid The Thread's ID
269  * @return A Thread reference
270  */
271 Thread * ModelChecker::get_thread(thread_id_t tid) const
272 {
273         return execution->get_thread(tid);
274 }
275
276 /**
277  * @brief Get a reference to the Thread in which a ModelAction was executed
278  * @param act The ModelAction
279  * @return A Thread reference
280  */
281 Thread * ModelChecker::get_thread(const ModelAction *act) const
282 {
283         return execution->get_thread(act);
284 }
285
286 /**
287  * Switch from a model-checker context to a user-thread context. This is the
288  * complement of ModelChecker::switch_to_master and must be called from the
289  * model-checker context
290  *
291  * @param thread The user-thread to switch to
292  */
293 void ModelChecker::switch_from_master(Thread *thread)
294 {
295         scheduler->set_current_thread(thread);
296         Thread::swap(&system_context, thread);
297 }
298
299 /**
300  * Switch from a user-context to the "master thread" context (a.k.a. system
301  * context). This switch is made with the intention of exploring a particular
302  * model-checking action (described by a ModelAction object). Must be called
303  * from a user-thread context.
304  *
305  * @param act The current action that will be explored. May be NULL only if
306  * trace is exiting via an assertion (see ModelExecution::set_assert and
307  * ModelExecution::has_asserted).
308  * @return Return the value returned by the current action
309  */
310 uint64_t ModelChecker::switch_to_master(ModelAction *act)
311 {
312         DBG();
313         Thread *old = thread_current();
314         scheduler->set_current_thread(NULL);
315         ASSERT(!old->get_pending());
316 /* W: No plugin
317         if (inspect_plugin != NULL) {
318                 inspect_plugin->inspectModelAction(act);
319         }*/
320         old->set_pending(act);
321         if (Thread::swap(old, &system_context) < 0) {
322                 perror("swap threads");
323                 exit(EXIT_FAILURE);
324         }
325         return old->get_return_value();
326 }
327
328 /** Wrapper to run the user's main function, with appropriate arguments */
329 void user_main_wrapper(void *)
330 {
331         user_main(model->params.argc, model->params.argv);
332 }
333
334 bool ModelChecker::should_terminate_execution()
335 {
336         /* Infeasible -> don't take any more steps */
337         if (execution->is_infeasible())
338                 return true;
339         else if (execution->isfeasibleprefix() && execution->have_bug_reports()) {
340                 execution->set_assert();
341                 return true;
342         }
343         return false;
344 }
345
346 /** @brief Restart ModelChecker upon returning to the run loop of the
347  *      model checker. */
348 void ModelChecker::restart()
349 {
350         restart_flag = true;
351 }
352
353 void ModelChecker::do_restart()
354 {
355         restart_flag = false;
356         reset_to_initial_state();
357         node_stack->full_reset();
358         memset(&stats,0,sizeof(struct execution_stats));
359         execution_number = 1;
360 }
361
362 /** @brief Run ModelChecker for the user program */
363 void ModelChecker::run()
364 {
365         //Need to initial random number generator state to avoid resets on rollback
366         char random_state[256];
367         initstate(423121, random_state, sizeof(random_state));
368
369         for(int exec = 0;exec < params.maxexecutions;exec ++) {
370                 thrd_t user_thread;
371                 Thread *t = new Thread(execution->get_next_id(), &user_thread, &user_main_wrapper, NULL, NULL); // L: user_main_wrapper passes the user program
372                 execution->add_thread(t);
373                 //Need to seed random number generator, otherwise its state gets reset
374                 do {
375                         /*
376                          * Stash next pending action(s) for thread(s). There
377                          * should only need to stash one thread's action--the
378                          * thread which just took a step--plus the first step
379                          * for any newly-created thread
380                          */
381
382                         for (unsigned int i = 0;i < get_num_threads();i++) {
383                                 thread_id_t tid = int_to_id(i);
384                                 Thread *thr = get_thread(tid);
385                                 if (!thr->is_model_thread() && !thr->is_complete() && !thr->get_pending()) {
386                                         switch_from_master(thr);        // L: context swapped, and action type of thr changed.
387                                         if (thr->is_waiting_on(thr))
388                                                 assert_bug("Deadlock detected (thread %u)", i);
389                                 }
390                         }
391
392                         /* Don't schedule threads which should be disabled */
393                         for (unsigned int i = 0;i < get_num_threads();i++) {
394                                 Thread *th = get_thread(int_to_id(i));
395                                 ModelAction *act = th->get_pending();
396                                 if (act && execution->is_enabled(th) && !execution->check_action_enabled(act)) {
397                                         scheduler->sleep(th);
398                                 }
399                         }
400
401                         for (unsigned int i = 1;i < get_num_threads();i++) {
402                                 Thread *th = get_thread(int_to_id(i));
403                                 ModelAction *act = th->get_pending();
404                                 if (act && execution->is_enabled(th) && (th->get_state() != THREAD_BLOCKED) ) {
405                                         if (act->is_write()) {
406                                                 std::memory_order order = act->get_mo();
407                                                 if (order == std::memory_order_relaxed || \
408                                                                 order == std::memory_order_release) {
409                                                         t = th;
410                                                         break;
411                                                 }
412                                         } else if (act->get_type() == THREAD_CREATE || \
413                                                                                  act->get_type() == PTHREAD_CREATE || \
414                                                                                  act->get_type() == THREAD_START || \
415                                                                                  act->get_type() == THREAD_FINISH) {
416                                                 t = th;
417                                                 break;
418                                         }
419                                 }
420                         }
421
422                         /* Catch assertions from prior take_step or from
423                         * between-ModelAction bugs (e.g., data races) */
424
425                         if (execution->has_asserted())
426                                 break;
427                         if (!t)
428                                 t = get_next_thread();
429                         if (!t || t->is_model_thread())
430                                 break;
431
432                         /* Consume the next action for a Thread */
433                         ModelAction *curr = t->get_pending();
434                         t->set_pending(NULL);
435                         t = execution->take_step(curr);
436                 } while (!should_terminate_execution());
437                 next_execution();
438                 //restore random number generator state after rollback
439                 setstate(random_state);
440         }
441
442         model_print("******* Model-checking complete: *******\n");
443         print_stats();
444
445         /* Have the trace analyses dump their output. */
446         for (unsigned int i = 0;i < trace_analyses.size();i++)
447                 trace_analyses[i]->finish();
448 }