Logo AND Algorithmique Numérique Distribuée

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