Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
model-checker : cleanup for heap comparison
[simgrid.git] / src / mc / mc_liveness.c
1 /* Copyright (c) 2008-2012 Da SimGrid Team. All rights reserved.            */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "mc_private.h"
7 #include <unistd.h>
8 #include <sys/wait.h>
9
10 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_liveness, mc,
11                                 "Logging specific to algorithms for liveness properties verification");
12
13 xbt_dynar_t reached_pairs;
14 xbt_dynar_t successors;
15
16 int create_dump(int pair)
17 {
18    // Try to enable core dumps
19   struct rlimit core_limit;
20   core_limit.rlim_cur = RLIM_INFINITY;
21   core_limit.rlim_max = RLIM_INFINITY;
22   
23   if(setrlimit(RLIMIT_CORE, &core_limit) < 0)
24     fprintf(stderr, "setrlimit: %s\nWarning: core dumps may be truncated or non-existant\n", strerror(errno));
25   
26   int status;
27   switch(fork()){
28   case 0:
29     // We are the child process -- run the actual program
30     abort();
31     break;
32     
33   case -1:
34     // An error occurred, shouldn't happen
35     perror("fork");
36     return -1;
37     
38   default:
39     // We are the parent process -- wait for the child process to exit
40     if(wait(&status) < 0)
41       perror("wait");
42     if(WIFSIGNALED(status) && WCOREDUMP(status)){
43       char *core_name = malloc(20);
44       sprintf(core_name,"core_%d", pair); 
45       rename("core", core_name);
46       free(core_name);
47     }
48   }
49
50   return 0;
51 }
52
53 int reached(xbt_state_t st){
54
55   raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
56
57   MC_SET_RAW_MEM;
58
59   mc_pair_reached_t new_pair = NULL;
60   new_pair = xbt_new0(s_mc_pair_reached_t, 1);
61   new_pair->nb = xbt_dynar_length(reached_pairs) + 1;
62   new_pair->automaton_state = st;
63   new_pair->prop_ato = xbt_dynar_new(sizeof(int), NULL);
64   new_pair->system_state = xbt_new0(s_mc_snapshot_t, 1); 
65   MC_take_snapshot_liveness(new_pair->system_state);  
66   
67   /* Get values of propositional symbols */
68   int res;
69   int_f_void_t f;
70   unsigned int cursor = 0;
71   xbt_propositional_symbol_t ps = NULL;
72   xbt_dynar_foreach(_mc_property_automaton->propositional_symbols, cursor, ps){
73     f = (int_f_void_t)ps->function;
74     res = (*f)();
75     xbt_dynar_push_as(new_pair->prop_ato, int, res);
76   }
77   
78   MC_UNSET_RAW_MEM;
79   
80   if(xbt_dynar_is_empty(reached_pairs) || !compare){
81
82     MC_SET_RAW_MEM;
83     /* New pair reached */
84     xbt_dynar_push(reached_pairs, &new_pair); 
85     MC_UNSET_RAW_MEM;
86  
87     return 0;
88
89   }else{
90
91     MC_SET_RAW_MEM;
92     
93     cursor = 0;
94     mc_pair_reached_t pair_test = NULL;
95      
96     xbt_dynar_foreach(reached_pairs, cursor, pair_test){
97       XBT_INFO("Pair reached #%d", pair_test->nb);
98       if(automaton_state_compare(pair_test->automaton_state, st) == 0){
99         if(propositional_symbols_compare_value(pair_test->prop_ato, new_pair->prop_ato) == 0){
100           if(snapshot_compare(new_pair->system_state, pair_test->system_state) == 0){
101             
102             if(raw_mem_set)
103               MC_SET_RAW_MEM;
104             else
105               MC_UNSET_RAW_MEM;
106             
107             return 1;
108           }       
109         }else{
110           XBT_INFO("Different values of propositional symbols");
111         }
112       }else{
113         XBT_INFO("Different automaton state");
114       }
115     }
116
117     /* New pair reached */
118     xbt_dynar_push(reached_pairs, &new_pair); 
119     
120     MC_UNSET_RAW_MEM;
121
122     if(raw_mem_set)
123       MC_SET_RAW_MEM;
124     else
125       MC_UNSET_RAW_MEM;
126
127     compare = 0;
128     
129     return 0;
130     
131   }
132 }
133
134
135 void set_pair_reached(xbt_state_t st){
136
137   raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
138  
139   MC_SET_RAW_MEM;
140
141   mc_pair_reached_t pair = NULL;
142   pair = xbt_new0(s_mc_pair_reached_t, 1);
143   pair->nb = xbt_dynar_length(reached_pairs) + 1;
144   pair->automaton_state = st;
145   pair->prop_ato = xbt_dynar_new(sizeof(int), NULL);
146   pair->system_state = xbt_new0(s_mc_snapshot_t, 1); 
147   MC_take_snapshot_liveness(pair->system_state);
148
149   /* Get values of propositional symbols */
150   unsigned int cursor = 0;
151   xbt_propositional_symbol_t ps = NULL;
152   int res;
153   int_f_void_t f;
154
155   xbt_dynar_foreach(_mc_property_automaton->propositional_symbols, cursor, ps){
156     f = (int_f_void_t)ps->function;
157     res = (*f)();
158     xbt_dynar_push_as(pair->prop_ato, int, res);
159   }
160
161   xbt_dynar_push(reached_pairs, &pair); 
162   
163   MC_UNSET_RAW_MEM;
164
165   if(raw_mem_set)
166     MC_SET_RAW_MEM;
167   else
168     MC_UNSET_RAW_MEM;
169     
170 }
171
172 void MC_pair_delete(mc_pair_t pair){
173   xbt_free(pair->graph_state->proc_status);
174   xbt_free(pair->graph_state);
175   xbt_free(pair);
176 }
177
178
179
180 int MC_automaton_evaluate_label(xbt_exp_label_t l){
181   
182   switch(l->type){
183   case 0 : {
184     int left_res = MC_automaton_evaluate_label(l->u.or_and.left_exp);
185     int right_res = MC_automaton_evaluate_label(l->u.or_and.right_exp);
186     return (left_res || right_res);
187   }
188   case 1 : {
189     int left_res = MC_automaton_evaluate_label(l->u.or_and.left_exp);
190     int right_res = MC_automaton_evaluate_label(l->u.or_and.right_exp);
191     return (left_res && right_res);
192   }
193   case 2 : {
194     int res = MC_automaton_evaluate_label(l->u.exp_not);
195     return (!res);
196   }
197   case 3 : { 
198     unsigned int cursor = 0;
199     xbt_propositional_symbol_t p = NULL;
200     int_f_void_t f;
201     xbt_dynar_foreach(_mc_property_automaton->propositional_symbols, cursor, p){
202       if(strcmp(p->pred, l->u.predicat) == 0){
203         f = (int_f_void_t)p->function;
204         return (*f)();
205       }
206     }
207     return -1;
208   }
209   case 4 : {
210     return 2;
211   }
212   default : 
213     return -1;
214   }
215 }
216
217
218 /********************* Double-DFS stateless *******************/
219
220 void MC_pair_stateless_delete(mc_pair_stateless_t pair){
221   xbt_free(pair->graph_state->proc_status);
222   xbt_free(pair->graph_state);
223   xbt_free(pair);
224 }
225
226 mc_pair_stateless_t new_pair_stateless(mc_state_t sg, xbt_state_t st, int r){
227   mc_pair_stateless_t p = NULL;
228   p = xbt_new0(s_mc_pair_stateless_t, 1);
229   p->automaton_state = st;
230   p->graph_state = sg;
231   p->requests = r;
232   mc_stats_pair->expanded_pairs++;
233   return p;
234 }
235
236 void MC_ddfs_init(void){
237
238   raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
239
240   XBT_INFO("**************************************************");
241   XBT_INFO("Double-DFS init");
242   XBT_INFO("**************************************************");
243
244   mc_pair_stateless_t mc_initial_pair = NULL;
245   mc_state_t initial_graph_state = NULL;
246   smx_process_t process; 
247
248  
249   MC_wait_for_requests();
250
251   MC_SET_RAW_MEM;
252
253   initial_graph_state = MC_state_pair_new();
254   xbt_swag_foreach(process, simix_global->process_list){
255     if(MC_process_is_enabled(process)){
256       MC_state_interleave_process(initial_graph_state, process);
257     }
258   }
259
260   reached_pairs = xbt_dynar_new(sizeof(mc_pair_reached_t), NULL);
261   successors = xbt_dynar_new(sizeof(mc_pair_stateless_t), NULL);
262
263   /* Save the initial state */
264   initial_snapshot_liveness = xbt_new0(s_mc_snapshot_t, 1);
265   MC_take_snapshot_liveness(initial_snapshot_liveness);
266
267   MC_UNSET_RAW_MEM; 
268
269   unsigned int cursor = 0;
270   xbt_state_t state;
271
272   xbt_dynar_foreach(_mc_property_automaton->states, cursor, state){
273     if(state->type == -1){
274       
275       MC_SET_RAW_MEM;
276       mc_initial_pair = new_pair_stateless(initial_graph_state, state, MC_state_interleave_size(initial_graph_state));
277       xbt_fifo_unshift(mc_stack_liveness, mc_initial_pair);
278       MC_UNSET_RAW_MEM;
279       
280       if(cursor != 0){
281         MC_restore_snapshot(initial_snapshot_liveness);
282         MC_UNSET_RAW_MEM;
283       }
284
285       MC_ddfs(0);
286
287     }else{
288       if(state->type == 2){
289       
290         MC_SET_RAW_MEM;
291         mc_initial_pair = new_pair_stateless(initial_graph_state, state, MC_state_interleave_size(initial_graph_state));
292         xbt_fifo_unshift(mc_stack_liveness, mc_initial_pair);
293         MC_UNSET_RAW_MEM;
294
295         set_pair_reached(state);
296
297         if(cursor != 0){
298           MC_restore_snapshot(initial_snapshot_liveness);
299           MC_UNSET_RAW_MEM;
300         }
301   
302         MC_ddfs(1);
303   
304       }
305     }
306   }
307
308   if(raw_mem_set)
309     MC_SET_RAW_MEM;
310   else
311     MC_UNSET_RAW_MEM;
312   
313
314 }
315
316
317 void MC_ddfs(int search_cycle){
318
319   raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
320
321   smx_process_t process;
322   mc_pair_stateless_t current_pair = NULL;
323
324   if(xbt_fifo_size(mc_stack_liveness) == 0)
325     return;
326
327
328   /* Get current pair */
329   current_pair = (mc_pair_stateless_t)xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_stack_liveness));
330
331   /* Update current state in buchi automaton */
332   _mc_property_automaton->current_state = current_pair->automaton_state;
333
334  
335   XBT_INFO("********************* ( Depth = %d, search_cycle = %d )", xbt_fifo_size(mc_stack_liveness), search_cycle);
336  
337   mc_stats_pair->visited_pairs++;
338
339   //sleep(1);
340
341   int value;
342   mc_state_t next_graph_state = NULL;
343   smx_simcall_t req = NULL;
344   char *req_str;
345
346   xbt_transition_t transition_succ;
347   unsigned int cursor = 0;
348   int res;
349
350   mc_pair_stateless_t next_pair = NULL;
351   mc_pair_stateless_t pair_succ;
352   
353   if(xbt_fifo_size(mc_stack_liveness) < MAX_DEPTH_LIVENESS){
354
355     if(current_pair->requests > 0){
356
357       while((req = MC_state_get_request(current_pair->graph_state, &value)) != NULL){
358    
359         /* Debug information */
360        
361         req_str = MC_request_to_string(req, value);
362         XBT_INFO("Execute: %s", req_str);
363         xbt_free(req_str);
364
365         MC_state_set_executed_request(current_pair->graph_state, req, value);   
366
367         /* Answer the request */
368         SIMIX_simcall_pre(req, value);
369
370         /* Wait for requests (schedules processes) */
371         MC_wait_for_requests();
372
373         MC_SET_RAW_MEM;
374
375         /* Create the new expanded graph_state */
376         next_graph_state = MC_state_pair_new();
377
378         /* Get enabled process and insert it in the interleave set of the next graph_state */
379         xbt_swag_foreach(process, simix_global->process_list){
380           if(MC_process_is_enabled(process)){
381             MC_state_interleave_process(next_graph_state, process);
382           }
383         }
384
385         xbt_dynar_reset(successors);
386
387         MC_UNSET_RAW_MEM;
388
389
390         cursor= 0;
391         xbt_dynar_foreach(current_pair->automaton_state->out, cursor, transition_succ){
392
393           res = MC_automaton_evaluate_label(transition_succ->label);
394
395           if(res == 1){ // enabled transition in automaton
396             MC_SET_RAW_MEM;
397             next_pair = new_pair_stateless(next_graph_state, transition_succ->dst, MC_state_interleave_size(next_graph_state));
398             xbt_dynar_push(successors, &next_pair);
399             MC_UNSET_RAW_MEM;
400           }
401
402         }
403
404         cursor = 0;
405    
406         xbt_dynar_foreach(current_pair->automaton_state->out, cursor, transition_succ){
407       
408           res = MC_automaton_evaluate_label(transition_succ->label);
409   
410           if(res == 2){ // true transition in automaton
411             MC_SET_RAW_MEM;
412             next_pair = new_pair_stateless(next_graph_state, transition_succ->dst, MC_state_interleave_size(next_graph_state));
413             xbt_dynar_push(successors, &next_pair);
414             MC_UNSET_RAW_MEM;
415           }
416
417         }
418
419         cursor = 0; 
420   
421         xbt_dynar_foreach(successors, cursor, pair_succ){
422
423           if(search_cycle == 1){
424
425             if((pair_succ->automaton_state->type == 1) || (pair_succ->automaton_state->type == 2)){ 
426           
427               if(reached(pair_succ->automaton_state)){
428         
429                 XBT_INFO("Next pair (depth = %d, %u interleave) already reached !", xbt_fifo_size(mc_stack_liveness) + 1, MC_state_interleave_size(pair_succ->graph_state));
430
431                 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
432                 XBT_INFO("|             ACCEPTANCE CYCLE            |");
433                 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
434                 XBT_INFO("Counter-example that violates formula :");
435                 MC_show_stack_liveness(mc_stack_liveness);
436                 MC_dump_stack_liveness(mc_stack_liveness);
437                 MC_print_statistics_pairs(mc_stats_pair);
438                 exit(0);
439
440               }else{
441
442                 XBT_INFO("Next pair (depth =%d) -> Acceptance pair : graph=%p, automaton=%p(%s)", xbt_fifo_size(mc_stack_liveness) + 1, pair_succ->graph_state, pair_succ->automaton_state, pair_succ->automaton_state->id);
443
444                 XBT_INFO("Reached pairs : %lu", xbt_dynar_length(reached_pairs));
445
446                 MC_SET_RAW_MEM;
447                 xbt_fifo_unshift(mc_stack_liveness, pair_succ);
448                 MC_UNSET_RAW_MEM;
449     
450                 MC_ddfs(search_cycle);
451
452               }
453
454             }else{
455
456               MC_SET_RAW_MEM;
457               xbt_fifo_unshift(mc_stack_liveness, pair_succ);
458               MC_UNSET_RAW_MEM;
459               
460               MC_ddfs(search_cycle);
461                
462             }
463
464           }else{
465     
466             if(((pair_succ->automaton_state->type == 1) || (pair_succ->automaton_state->type == 2))){
467
468               XBT_INFO("Next pair (depth =%d) -> Acceptance pair : graph=%p, automaton=%p(%s)", xbt_fifo_size(mc_stack_liveness) + 1, pair_succ->graph_state, pair_succ->automaton_state, pair_succ->automaton_state->id);
469       
470               set_pair_reached(pair_succ->automaton_state); 
471
472               search_cycle = 1;
473
474               XBT_INFO("Reached pairs : %lu", xbt_dynar_length(reached_pairs));
475
476             }
477
478             MC_SET_RAW_MEM;
479             xbt_fifo_unshift(mc_stack_liveness, pair_succ);
480             MC_UNSET_RAW_MEM;
481             
482             MC_ddfs(search_cycle);
483            
484           }
485
486    
487           /* Restore system before checking others successors */
488           if(cursor != (xbt_dynar_length(successors) - 1))
489             MC_replay_liveness(mc_stack_liveness, 1);
490   
491     
492         }
493
494         if(MC_state_interleave_size(current_pair->graph_state) > 0){
495           XBT_INFO("Backtracking to depth %d", xbt_fifo_size(mc_stack_liveness));
496           MC_replay_liveness(mc_stack_liveness, 0);
497         }
498       }
499
500  
501     }else{  /*No request to execute, search evolution in Büchi automaton */
502
503       MC_SET_RAW_MEM;
504
505       /* Create the new expanded graph_state */
506       next_graph_state = MC_state_pair_new();
507
508       xbt_dynar_reset(successors);
509
510       MC_UNSET_RAW_MEM;
511
512
513       cursor= 0;
514       xbt_dynar_foreach(current_pair->automaton_state->out, cursor, transition_succ){
515
516         res = MC_automaton_evaluate_label(transition_succ->label);
517
518         if(res == 1){ // enabled transition in automaton
519           MC_SET_RAW_MEM;
520           next_pair = new_pair_stateless(next_graph_state, transition_succ->dst, MC_state_interleave_size(next_graph_state));
521           xbt_dynar_push(successors, &next_pair);
522           MC_UNSET_RAW_MEM;
523         }
524
525       }
526
527       cursor = 0;
528    
529       xbt_dynar_foreach(current_pair->automaton_state->out, cursor, transition_succ){
530       
531         res = MC_automaton_evaluate_label(transition_succ->label);
532   
533         if(res == 2){ // true transition in automaton
534           MC_SET_RAW_MEM;
535           next_pair = new_pair_stateless(next_graph_state, transition_succ->dst, MC_state_interleave_size(next_graph_state));
536           xbt_dynar_push(successors, &next_pair);
537           MC_UNSET_RAW_MEM;
538         }
539
540       }
541
542       cursor = 0; 
543      
544       xbt_dynar_foreach(successors, cursor, pair_succ){
545
546         if(search_cycle == 1){
547
548           if((pair_succ->automaton_state->type == 1) || (pair_succ->automaton_state->type == 2)){ 
549
550             if(reached(pair_succ->automaton_state)){
551            
552               XBT_INFO("Next pair (depth = %d) already reached !", xbt_fifo_size(mc_stack_liveness) + 1);
553         
554               XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
555               XBT_INFO("|             ACCEPTANCE CYCLE            |");
556               XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
557               XBT_INFO("Counter-example that violates formula :");
558               MC_show_stack_liveness(mc_stack_liveness);
559               MC_dump_stack_liveness(mc_stack_liveness);
560               MC_print_statistics_pairs(mc_stats_pair);
561               exit(0);
562
563             }else{
564
565               XBT_INFO("Next pair (depth = %d) -> Acceptance pair : graph=%p, automaton=%p(%s)", xbt_fifo_size(mc_stack_liveness) + 1, pair_succ->graph_state, pair_succ->automaton_state, pair_succ->automaton_state->id);
566         
567               XBT_INFO("Reached pairs : %lu", xbt_dynar_length(reached_pairs));
568
569               MC_SET_RAW_MEM;
570               xbt_fifo_unshift(mc_stack_liveness, pair_succ);
571               MC_UNSET_RAW_MEM;
572         
573               MC_ddfs(search_cycle);
574
575             }
576
577           }else{
578
579             MC_SET_RAW_MEM;
580             xbt_fifo_unshift(mc_stack_liveness, pair_succ);
581             MC_UNSET_RAW_MEM;
582             
583             MC_ddfs(search_cycle);
584             
585           }
586       
587
588         }else{
589       
590           if(((pair_succ->automaton_state->type == 1) || (pair_succ->automaton_state->type == 2))){
591
592             set_pair_reached(pair_succ->automaton_state);
593          
594             search_cycle = 1;
595
596             XBT_INFO("Reached pairs : %lu", xbt_dynar_length(reached_pairs));
597
598           }
599
600           MC_SET_RAW_MEM;
601           xbt_fifo_unshift(mc_stack_liveness, pair_succ);
602           MC_UNSET_RAW_MEM;
603           
604           MC_ddfs(search_cycle);
605           
606         }
607
608         /* Restore system before checking others successors */
609         if(cursor != xbt_dynar_length(successors) - 1)
610           MC_replay_liveness(mc_stack_liveness, 1);
611
612    
613       }
614            
615     }
616     
617   }else{
618     
619     XBT_INFO("Max depth reached");
620
621   }
622
623   if(xbt_fifo_size(mc_stack_liveness) == MAX_DEPTH_LIVENESS ){
624     XBT_INFO("Pair (graph=%p, automaton =%p, search_cycle = %d, depth = %d) shifted in stack, maximum depth reached", current_pair->graph_state, current_pair->automaton_state, search_cycle, xbt_fifo_size(mc_stack_liveness) );
625   }else{
626     XBT_INFO("Pair (graph=%p, automaton =%p, search_cycle = %d, depth = %d) shifted in stack", current_pair->graph_state, current_pair->automaton_state, search_cycle, xbt_fifo_size(mc_stack_liveness) );
627   }
628
629   
630   MC_SET_RAW_MEM;
631   xbt_fifo_shift(mc_stack_liveness);
632   if((current_pair->automaton_state->type == 1) || (current_pair->automaton_state->type == 2)){
633     xbt_dynar_pop(reached_pairs, NULL);
634   }
635   MC_UNSET_RAW_MEM;
636
637   if(raw_mem_set)
638     MC_SET_RAW_MEM;
639   else
640     MC_UNSET_RAW_MEM;
641
642 }