Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
3dcbfc8ced5a12fc06b2338be64015f72bcb1566
[simgrid.git] / src / mc / mc_global.c
1 #include <unistd.h>
2 #include <sys/types.h>
3 #include <sys/wait.h>
4 #include <sys/time.h>
5
6 #include "../surf/surf_private.h"
7 #include "../simix/private.h"
8 #include "xbt/fifo.h"
9 #include "private.h"
10
11
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_global, mc,
13                                 "Logging specific to MC (global)");
14
15 /* MC global data structures */
16
17 mc_state_t mc_current_state = NULL;
18 char mc_replay_mode = FALSE;
19 double *mc_time = NULL;
20 mc_snapshot_t initial_snapshot = NULL;
21
22 /* Safety */
23
24 xbt_fifo_t mc_stack_safety_stateful = NULL;
25 xbt_fifo_t mc_stack_safety_stateless = NULL;
26 mc_stats_t mc_stats = NULL;
27
28 /* Liveness */
29
30 mc_stats_pair_t mc_stats_pair = NULL;
31 xbt_fifo_t mc_stack_liveness = NULL;
32 mc_snapshot_t initial_snapshot_liveness = NULL;
33
34 xbt_automaton_t automaton;
35 char *prog_name;
36
37 /**
38  *  \brief Initialize the model-checker data structures
39  */
40 void MC_init_safety_stateless(void)
41 {
42
43   /* Check if MC is already initialized */
44   if (initial_snapshot)
45     return;
46
47   mc_time = xbt_new0(double, simix_process_maxpid);
48
49   /* Initialize the data structures that must be persistent across every
50      iteration of the model-checker (in RAW memory) */
51   MC_SET_RAW_MEM;
52
53   /* Initialize statistics */
54   mc_stats = xbt_new0(s_mc_stats_t, 1);
55   mc_stats->state_size = 1;
56
57   /* Create exploration stack */
58   mc_stack_safety_stateless = xbt_fifo_new();
59
60   MC_UNSET_RAW_MEM;
61
62   MC_dpor_init();
63
64   MC_SET_RAW_MEM;
65   /* Save the initial state */
66   initial_snapshot = xbt_new0(s_mc_snapshot_t, 1);
67   MC_take_snapshot(initial_snapshot);
68   MC_UNSET_RAW_MEM;
69 }
70
71 void MC_init_safety_stateful(void){
72
73   
74    /* Check if MC is already initialized */
75   if (initial_snapshot)
76     return;
77
78   mc_time = xbt_new0(double, simix_process_maxpid);
79
80   /* Initialize the data structures that must be persistent across every
81      iteration of the model-checker (in RAW memory) */
82   MC_SET_RAW_MEM;
83
84   /* Initialize statistics */
85   mc_stats = xbt_new0(s_mc_stats_t, 1);
86   mc_stats->state_size = 1;
87
88   /* Create exploration stack */
89   mc_stack_safety_stateful = xbt_fifo_new();
90
91   MC_UNSET_RAW_MEM;
92
93   MC_dpor_stateful_init();
94
95
96 }
97
98 void MC_init_liveness(xbt_automaton_t a, char *prgm){
99
100   XBT_DEBUG("Start init mc");
101   
102   mc_time = xbt_new0(double, simix_process_maxpid);
103
104   /* Initialize the data structures that must be persistent across every
105      iteration of the model-checker (in RAW memory) */
106
107   MC_SET_RAW_MEM;
108
109   /* Initialize statistics */
110   mc_stats_pair = xbt_new0(s_mc_stats_pair_t, 1);
111
112   XBT_DEBUG("Creating stack");
113
114  /* Create exploration stack */
115   mc_stack_liveness = xbt_fifo_new();
116
117   MC_UNSET_RAW_MEM;
118
119   automaton = a;
120   prog_name = strdup(prgm);
121
122   MC_ddfs_init();
123
124   
125 }
126
127
128 void MC_modelcheck(void)
129 {
130   MC_init_safety_stateless();
131   MC_dpor();
132   MC_exit();
133 }
134
135 void MC_modelcheck_stateful(void)
136 {
137   MC_init_safety_stateful();
138   MC_dpor_stateful();
139   MC_exit();
140 }
141
142
143 void MC_modelcheck_liveness(xbt_automaton_t a, char *prgm){
144   MC_init_liveness(a, prgm);
145   MC_exit_liveness();
146 }
147
148 void MC_exit_liveness(void)
149 {
150   MC_print_statistics_pairs(mc_stats_pair);
151   //xbt_free(mc_time);
152   //MC_memory_exit();
153   exit(0);
154 }
155
156
157 void MC_exit(void)
158 {
159   MC_print_statistics(mc_stats);
160   xbt_free(mc_time);
161   MC_memory_exit();
162 }
163
164
165 int MC_random(int min, int max)
166 {
167   /*FIXME: return mc_current_state->executed_transition->random.value;*/
168   return 0;
169 }
170
171 /**
172  * \brief Schedules all the process that are ready to run
173  */
174 void MC_wait_for_requests(void)
175 {
176   smx_process_t process;
177   smx_req_t req;
178   unsigned int iter;
179
180   while (!xbt_dynar_is_empty(simix_global->process_to_run)) {
181     SIMIX_process_runall();
182     xbt_dynar_foreach(simix_global->process_that_ran, iter, process) {
183       req = &process->request;
184       if (req->call != REQ_NO_REQ && !MC_request_is_visible(req))
185           SIMIX_request_pre(req, 0);
186     }
187   }
188 }
189
190 int MC_deadlock_check()
191 {
192   int deadlock = FALSE;
193   smx_process_t process;
194   if(xbt_swag_size(simix_global->process_list)){
195     deadlock = TRUE;
196     xbt_swag_foreach(process, simix_global->process_list){
197       if(process->request.call != REQ_NO_REQ
198          && MC_request_is_enabled(&process->request)){
199         deadlock = FALSE;
200         break;
201       }
202     }
203   }
204   return deadlock;
205 }
206
207 /**
208  * \brief Re-executes from the initial state all the transitions indicated by
209  *        a given model-checker stack.
210  * \param stack The stack with the transitions to execute.
211 */
212 void MC_replay(xbt_fifo_t stack)
213 {
214   int value;
215   char *req_str;
216   smx_req_t req = NULL, saved_req = NULL;
217   xbt_fifo_item_t item;
218   mc_state_t state;
219
220   XBT_DEBUG("**** Begin Replay ****");
221
222   /* Restore the initial state */
223   MC_restore_snapshot(initial_snapshot);
224   /* At the moment of taking the snapshot the raw heap was set, so restoring
225    * it will set it back again, we have to unset it to continue  */
226   MC_UNSET_RAW_MEM;
227
228   /* Traverse the stack from the initial state and re-execute the transitions */
229   for (item = xbt_fifo_get_last_item(stack);
230        item != xbt_fifo_get_first_item(stack);
231        item = xbt_fifo_get_prev_item(item)) {
232
233     state = (mc_state_t) xbt_fifo_get_item_content(item);
234     saved_req = MC_state_get_executed_request(state, &value);
235    
236     if(saved_req){
237       /* because we got a copy of the executed request, we have to fetch the  
238          real one, pointed by the request field of the issuer process */
239       req = &saved_req->issuer->request;
240
241       /* Debug information */
242       if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
243         req_str = MC_request_to_string(req, value);
244         XBT_DEBUG("Replay: %s (%p)", req_str, state);
245         xbt_free(req_str);
246       }
247     }
248          
249     SIMIX_request_pre(req, value);
250     MC_wait_for_requests();
251          
252     /* Update statistics */
253     mc_stats->visited_states++;
254     mc_stats->executed_transitions++;
255   }
256   XBT_DEBUG("**** End Replay ****");
257 }
258
259 void MC_replay_liveness(xbt_fifo_t stack, int all_stack)
260 {
261   int value;
262   char *req_str;
263   smx_req_t req = NULL, saved_req = NULL;
264   xbt_fifo_item_t item;
265   mc_state_t state;
266   mc_pair_stateless_t pair;
267   int depth = 1;
268
269   XBT_DEBUG("**** Begin Replay ****");
270
271   /* Restore the initial state */
272   MC_restore_snapshot(initial_snapshot_liveness);
273   /* At the moment of taking the snapshot the raw heap was set, so restoring
274    * it will set it back again, we have to unset it to continue  */
275   MC_UNSET_RAW_MEM;
276
277   if(all_stack){
278
279     item = xbt_fifo_get_last_item(stack);
280
281     while(depth <= xbt_fifo_size(stack)){
282
283       pair = (mc_pair_stateless_t) xbt_fifo_get_item_content(item);
284       state = (mc_state_t) pair->graph_state;
285
286       if(pair->requests > 0){
287    
288         saved_req = MC_state_get_executed_request(state, &value);
289         //XBT_DEBUG("SavedReq->call %u", saved_req->call);
290       
291         if(saved_req != NULL){
292           /* because we got a copy of the executed request, we have to fetch the  
293              real one, pointed by the request field of the issuer process */
294           req = &saved_req->issuer->request;
295           //XBT_DEBUG("Req->call %u", req->call);
296         
297           /* Debug information */
298           if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
299             req_str = MC_request_to_string(req, value);
300             XBT_DEBUG("Replay (depth = %d) : %s (%p)", depth, req_str, state);
301             xbt_free(req_str);
302           }
303         
304         }
305  
306         SIMIX_request_pre(req, value);
307         MC_wait_for_requests();
308       }
309
310       depth++;
311     
312       /* Update statistics */
313       mc_stats_pair->visited_pairs++;
314
315       item = xbt_fifo_get_prev_item(item);
316     }
317
318   }else{
319
320     /* Traverse the stack from the initial state and re-execute the transitions */
321     for (item = xbt_fifo_get_last_item(stack);
322          item != xbt_fifo_get_first_item(stack);
323          item = xbt_fifo_get_prev_item(item)) {
324
325       pair = (mc_pair_stateless_t) xbt_fifo_get_item_content(item);
326       state = (mc_state_t) pair->graph_state;
327
328       if(pair->requests > 0){
329    
330         saved_req = MC_state_get_executed_request(state, &value);
331         //XBT_DEBUG("SavedReq->call %u", saved_req->call);
332       
333         if(saved_req != NULL){
334           /* because we got a copy of the executed request, we have to fetch the  
335              real one, pointed by the request field of the issuer process */
336           req = &saved_req->issuer->request;
337           //XBT_DEBUG("Req->call %u", req->call);
338         
339           /* Debug information */
340           if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
341             req_str = MC_request_to_string(req, value);
342             XBT_DEBUG("Replay (depth = %d) : %s (%p)", depth, req_str, state);
343             xbt_free(req_str);
344           }
345         
346         }
347  
348         SIMIX_request_pre(req, value);
349         MC_wait_for_requests();
350       }
351
352       depth++;
353     
354       /* Update statistics */
355       mc_stats_pair->visited_pairs++;
356     }
357   }  
358
359   XBT_DEBUG("**** End Replay ****");
360 }
361
362
363 /**
364  * \brief Dumps the contents of a model-checker's stack and shows the actual
365  *        execution trace
366  * \param stack The stack to dump
367 */
368 void MC_dump_stack_safety_stateless(xbt_fifo_t stack)
369 {
370   mc_state_t state;
371
372   MC_show_stack_safety_stateless(stack);
373
374   MC_SET_RAW_MEM;
375   while ((state = (mc_state_t) xbt_fifo_pop(stack)) != NULL)
376     MC_state_delete(state);
377   MC_UNSET_RAW_MEM;
378 }
379
380
381 void MC_show_stack_safety_stateless(xbt_fifo_t stack)
382 {
383   int value;
384   mc_state_t state;
385   xbt_fifo_item_t item;
386   smx_req_t req;
387   char *req_str = NULL;
388   
389   for (item = xbt_fifo_get_last_item(stack);
390        (item ? (state = (mc_state_t) (xbt_fifo_get_item_content(item)))
391         : (NULL)); item = xbt_fifo_get_prev_item(item)) {
392     req = MC_state_get_executed_request(state, &value);
393     if(req){
394       req_str = MC_request_to_string(req, value);
395       XBT_INFO("%s", req_str);
396       xbt_free(req_str);
397     }
398   }
399 }
400
401 void MC_show_deadlock(smx_req_t req)
402 {
403   /*char *req_str = NULL;*/
404   XBT_INFO("**************************");
405   XBT_INFO("*** DEAD-LOCK DETECTED ***");
406   XBT_INFO("**************************");
407   XBT_INFO("Locked request:");
408   /*req_str = MC_request_to_string(req);
409   XBT_INFO("%s", req_str);
410   xbt_free(req_str);*/
411   XBT_INFO("Counter-example execution trace:");
412   MC_dump_stack_safety_stateless(mc_stack_safety_stateless);
413 }
414
415 void MC_show_deadlock_stateful(smx_req_t req)
416 {
417   /*char *req_str = NULL;*/
418   XBT_INFO("**************************");
419   XBT_INFO("*** DEAD-LOCK DETECTED ***");
420   XBT_INFO("**************************");
421   XBT_INFO("Locked request:");
422   /*req_str = MC_request_to_string(req);
423   XBT_INFO("%s", req_str);
424   xbt_free(req_str);*/
425   XBT_INFO("Counter-example execution trace:");
426   MC_show_stack_safety_stateful(mc_stack_safety_stateful);
427 }
428
429 void MC_dump_stack_safety_stateful(xbt_fifo_t stack)
430 {
431   //mc_state_ws_t state;
432
433   MC_show_stack_safety_stateful(stack);
434
435   /*MC_SET_RAW_MEM;
436   while ((state = (mc_state_t) xbt_fifo_pop(stack)) != NULL)
437     MC_state_delete(state);
438     MC_UNSET_RAW_MEM;*/
439 }
440
441
442 void MC_show_stack_safety_stateful(xbt_fifo_t stack)
443 {
444   int value;
445   mc_state_ws_t state;
446   xbt_fifo_item_t item;
447   smx_req_t req;
448   char *req_str = NULL;
449   
450   for (item = xbt_fifo_get_last_item(stack);
451        (item ? (state = (mc_state_ws_t) (xbt_fifo_get_item_content(item)))
452         : (NULL)); item = xbt_fifo_get_prev_item(item)) {
453     req = MC_state_get_executed_request(state->graph_state, &value);
454     if(req){
455       req_str = MC_request_to_string(req, value);
456       XBT_INFO("%s", req_str);
457       xbt_free(req_str);
458     }
459   }
460 }
461
462
463 void MC_show_stack_liveness(xbt_fifo_t stack){
464   int value;
465   mc_pair_stateless_t pair;
466   xbt_fifo_item_t item;
467   smx_req_t req;
468   char *req_str = NULL;
469   
470   for (item = xbt_fifo_get_last_item(stack);
471        (item ? (pair = (mc_pair_stateless_t) (xbt_fifo_get_item_content(item)))
472         : (NULL)); item = xbt_fifo_get_prev_item(item)) {
473     req = MC_state_get_executed_request(pair->graph_state, &value);
474     if(req){
475       if(pair->requests>0){
476         req_str = MC_request_to_string(req, value);
477         XBT_INFO("%s", req_str);
478         xbt_free(req_str);
479       }else{
480         XBT_INFO("End of system requests but evolution in Büchi automaton");
481       }
482     }
483   }
484 }
485
486 void MC_dump_stack_liveness(xbt_fifo_t stack){
487   mc_pair_stateless_t pair;
488
489   MC_SET_RAW_MEM;
490   while ((pair = (mc_pair_stateless_t) xbt_fifo_pop(stack)) != NULL)
491     MC_pair_stateless_delete(pair);
492   MC_UNSET_RAW_MEM;
493 }
494
495
496 void MC_print_statistics(mc_stats_t stats)
497 {
498   XBT_INFO("State space size ~= %lu", stats->state_size);
499   XBT_INFO("Expanded states = %lu", stats->expanded_states);
500   XBT_INFO("Visited states = %lu", stats->visited_states);
501   XBT_INFO("Executed transitions = %lu", stats->executed_transitions);
502   XBT_INFO("Expanded / Visited = %lf",
503         (double) stats->visited_states / stats->expanded_states);
504   /*XBT_INFO("Exploration coverage = %lf",
505      (double)stats->expanded_states / stats->state_size); */
506 }
507
508 void MC_print_statistics_pairs(mc_stats_pair_t stats)
509 {
510   XBT_INFO("Expanded pairs = %lu", stats->expanded_pairs);
511   XBT_INFO("Visited pairs = %lu", stats->visited_pairs);
512   //XBT_INFO("Executed transitions = %lu", stats->executed_transitions);
513   XBT_INFO("Expanded / Visited = %lf",
514         (double) stats->visited_pairs / stats->expanded_pairs);
515   /*XBT_INFO("Exploration coverage = %lf",
516      (double)stats->expanded_states / stats->state_size); */
517 }
518
519 void MC_assert(int prop)
520 {
521   if (MC_IS_ENABLED && !prop) {
522     XBT_INFO("**************************");
523     XBT_INFO("*** PROPERTY NOT VALID ***");
524     XBT_INFO("**************************");
525     XBT_INFO("Counter-example execution trace:");
526     MC_dump_stack_safety_stateless(mc_stack_safety_stateless);
527     MC_print_statistics(mc_stats);
528     xbt_abort();
529   }
530 }
531
532 void MC_assert_stateful(int prop)
533 {
534   if (MC_IS_ENABLED && !prop) {
535     XBT_INFO("**************************");
536     XBT_INFO("*** PROPERTY NOT VALID ***");
537     XBT_INFO("**************************");
538     XBT_INFO("Counter-example execution trace:");
539     MC_dump_stack_safety_stateful(mc_stack_safety_stateful);
540     MC_print_statistics(mc_stats);
541     xbt_abort();
542   }
543 }
544
545
546 void MC_assert_pair(int prop){
547   if (MC_IS_ENABLED && !prop) {
548     XBT_INFO("**************************");
549     XBT_INFO("*** PROPERTY NOT VALID ***");
550     XBT_INFO("**************************");
551     //XBT_INFO("Counter-example execution trace:");
552     MC_show_stack_liveness(mc_stack_liveness);
553     //MC_dump_snapshot_stack(mc_snapshot_stack);
554     MC_print_statistics_pairs(mc_stats_pair);
555     xbt_abort();
556   }
557 }
558
559 void MC_process_clock_add(smx_process_t process, double amount)
560 {
561   mc_time[process->pid] += amount;
562 }
563
564 double MC_process_clock_get(smx_process_t process)
565 {
566   if(mc_time)
567     return mc_time[process->pid];
568   else
569     return 0;
570 }