Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
merge msg_vm.c - adrien (please note that there is one line (destruction of the tx_pr...
[simgrid.git] / src / mc / mc_liveness.c
1 /* Copyright (c) 2011-2014. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "mc_private.h"
8 #include <unistd.h>
9 #include <sys/wait.h>
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_liveness, mc,
12                                 "Logging specific to algorithms for liveness properties verification");
13
14 /********* Global variables *********/
15
16 xbt_dynar_t acceptance_pairs;
17 xbt_dynar_t successors;
18 xbt_parmap_t parmap;
19
20 /********* Static functions *********/
21
22 static xbt_dynar_t get_atomic_propositions_values()
23 {
24   int res;
25   int_f_void_t f;
26   unsigned int cursor = 0;
27   xbt_automaton_propositional_symbol_t ps = NULL;
28   xbt_dynar_t values = xbt_dynar_new(sizeof(int), NULL);
29
30   xbt_dynar_foreach(_mc_property_automaton->propositional_symbols, cursor, ps) {
31     f = (int_f_void_t) ps->function;
32     res = f();
33     xbt_dynar_push_as(values, int, res);
34   }
35
36   return values;
37 }
38
39
40 static mc_visited_pair_t is_reached_acceptance_pair(int pair_num,
41                                                     xbt_automaton_state_t
42                                                     automaton_state,
43                                                     xbt_dynar_t
44                                                     atomic_propositions)
45 {
46
47   int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
48
49   MC_SET_MC_HEAP;
50
51   mc_visited_pair_t pair = NULL;
52   pair = MC_visited_pair_new(pair_num, automaton_state, atomic_propositions);
53   pair->acceptance_pair = 1;
54
55   if (xbt_dynar_is_empty(acceptance_pairs)) {
56
57     xbt_dynar_push(acceptance_pairs, &pair);
58
59   } else {
60
61     int min = -1, max = -1, index;
62     //int res;
63     mc_visited_pair_t pair_test;
64     int cursor;
65
66     index = get_search_interval(acceptance_pairs, pair, &min, &max);
67
68     if (min != -1 && max != -1) {       // Acceptance pair with same number of processes and same heap bytes used exists
69
70       // Parallell implementation
71       /*res = xbt_parmap_mc_apply(parmap, snapshot_compare, xbt_dynar_get_ptr(acceptance_pairs, min), (max-min)+1, pair);
72          if(res != -1){
73          if(!raw_mem_set)
74          MC_SET_STD_HEAP;
75          return ((mc_pair_t)xbt_dynar_get_as(acceptance_pairs, (min+res)-1, mc_pair_t))->num;
76          } */
77
78       cursor = min;
79       while (cursor <= max) {
80         pair_test =
81             (mc_visited_pair_t) xbt_dynar_get_as(acceptance_pairs, cursor,
82                                                  mc_visited_pair_t);
83         if (xbt_automaton_state_compare
84             (pair_test->automaton_state, pair->automaton_state) == 0) {
85           if (xbt_automaton_propositional_symbols_compare_value
86               (pair_test->atomic_propositions,
87                pair->atomic_propositions) == 0) {
88             if (snapshot_compare(pair_test, pair) == 0) {
89               XBT_INFO("Pair %d already reached (equal to pair %d) !",
90                        pair->num, pair_test->num);
91
92               xbt_fifo_shift(mc_stack);
93               if (dot_output != NULL)
94                 fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n",
95                         initial_global_state->prev_pair, pair_test->num,
96                         initial_global_state->prev_req);
97
98               if (!raw_mem_set)
99                 MC_SET_STD_HEAP;
100
101               return NULL;
102             }
103           }
104         }
105         cursor++;
106       }
107       xbt_dynar_insert_at(acceptance_pairs, min, &pair);
108     } else {
109       pair_test =
110           (mc_visited_pair_t) xbt_dynar_get_as(acceptance_pairs, index,
111                                                mc_visited_pair_t);
112       if (pair_test->nb_processes < pair->nb_processes) {
113         xbt_dynar_insert_at(acceptance_pairs, index + 1, &pair);
114       } else {
115         if (pair_test->heap_bytes_used < pair->heap_bytes_used)
116           xbt_dynar_insert_at(acceptance_pairs, index + 1, &pair);
117         else
118           xbt_dynar_insert_at(acceptance_pairs, index, &pair);
119       }
120     }
121
122   }
123
124   if (!raw_mem_set)
125     MC_SET_STD_HEAP;
126
127   return pair;
128
129 }
130
131 static void remove_acceptance_pair(int pair_num)
132 {
133
134   int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
135
136   MC_SET_MC_HEAP;
137
138   unsigned int cursor = 0;
139   mc_visited_pair_t pair_test = NULL;
140
141   xbt_dynar_foreach(acceptance_pairs, cursor, pair_test) {
142     if (pair_test->num == pair_num) {
143       break;
144     }
145   }
146
147   xbt_dynar_remove_at(acceptance_pairs, cursor, &pair_test);
148
149   pair_test->acceptance_removed = 1;
150
151   if (_sg_mc_visited == 0) {
152     MC_visited_pair_delete(pair_test);
153   } else if (pair_test->visited_removed == 1) {
154     MC_visited_pair_delete(pair_test);
155   }
156
157   if (!raw_mem_set)
158     MC_SET_STD_HEAP;
159 }
160
161
162 static int MC_automaton_evaluate_label(xbt_automaton_exp_label_t l,
163                                        xbt_dynar_t atomic_propositions_values)
164 {
165
166   switch (l->type) {
167   case 0:{
168       int left_res =
169           MC_automaton_evaluate_label(l->u.or_and.left_exp,
170                                       atomic_propositions_values);
171       int right_res =
172           MC_automaton_evaluate_label(l->u.or_and.right_exp,
173                                       atomic_propositions_values);
174       return (left_res || right_res);
175     }
176   case 1:{
177       int left_res =
178           MC_automaton_evaluate_label(l->u.or_and.left_exp,
179                                       atomic_propositions_values);
180       int right_res =
181           MC_automaton_evaluate_label(l->u.or_and.right_exp,
182                                       atomic_propositions_values);
183       return (left_res && right_res);
184     }
185   case 2:{
186       int res =
187           MC_automaton_evaluate_label(l->u.exp_not, atomic_propositions_values);
188       return (!res);
189     }
190   case 3:{
191       unsigned int cursor = 0;
192       xbt_automaton_propositional_symbol_t p = NULL;
193       xbt_dynar_foreach(_mc_property_automaton->propositional_symbols, cursor,
194                         p) {
195         if (strcmp(p->pred, l->u.predicat) == 0)
196           return (int) xbt_dynar_get_as(atomic_propositions_values, cursor,
197                                         int);
198       }
199       return -1;
200     }
201   case 4:{
202       return 2;
203     }
204   default:
205     return -1;
206   }
207 }
208
209 void MC_pre_modelcheck_liveness(void)
210 {
211
212   initial_global_state->raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
213
214   mc_pair_t initial_pair = NULL;
215   smx_process_t process;
216
217   MC_wait_for_requests();
218
219   MC_SET_MC_HEAP;
220
221   acceptance_pairs = xbt_dynar_new(sizeof(mc_visited_pair_t), NULL);
222   visited_pairs = xbt_dynar_new(sizeof(mc_visited_pair_t), NULL);
223   successors = xbt_dynar_new(sizeof(mc_pair_t), NULL);
224
225   initial_global_state->snapshot = MC_take_snapshot(0);
226   initial_global_state->prev_pair = 0;
227
228   MC_SET_STD_HEAP;
229
230   unsigned int cursor = 0;
231   xbt_automaton_state_t automaton_state;
232
233   xbt_dynar_foreach(_mc_property_automaton->states, cursor, automaton_state) {
234     if (automaton_state->type == -1) {  /* Initial automaton state */
235
236       MC_SET_MC_HEAP;
237
238       initial_pair = MC_pair_new();
239       initial_pair->automaton_state = automaton_state;
240       initial_pair->graph_state = MC_state_new();
241       initial_pair->atomic_propositions = get_atomic_propositions_values();
242
243       /* Get enabled processes and insert them in the interleave set of the graph_state */
244       xbt_swag_foreach(process, simix_global->process_list) {
245         if (MC_process_is_enabled(process)) {
246           MC_state_interleave_process(initial_pair->graph_state, process);
247         }
248       }
249
250       initial_pair->requests =
251           MC_state_interleave_size(initial_pair->graph_state);
252       initial_pair->search_cycle = 0;
253
254       xbt_fifo_unshift(mc_stack, initial_pair);
255       
256       MC_SET_STD_HEAP;
257
258       MC_modelcheck_liveness();
259
260       if (cursor != 0) {
261         MC_restore_snapshot(initial_global_state->snapshot);
262         MC_SET_STD_HEAP;
263       }
264     }
265   }
266
267   if (initial_global_state->raw_mem_set)
268     MC_SET_MC_HEAP;
269   else
270     MC_SET_STD_HEAP;
271
272
273 }
274
275
276 void MC_modelcheck_liveness()
277 {
278
279   smx_process_t process;
280   mc_pair_t current_pair = NULL;
281
282   if (xbt_fifo_size(mc_stack) == 0)
283     return;
284
285   /* Get current pair */
286   current_pair =
287       (mc_pair_t) xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_stack));
288
289   /* Update current state in buchi automaton */
290   _mc_property_automaton->current_state = current_pair->automaton_state;
291
292   XBT_DEBUG
293       ("********************* ( Depth = %d, search_cycle = %d, interleave size %d, pair_num %d)",
294        xbt_fifo_size(mc_stack), current_pair->search_cycle,
295        MC_state_interleave_size(current_pair->graph_state), current_pair->num);
296
297   mc_stats->visited_pairs++;
298
299   int value;
300   smx_simcall_t req = NULL;
301
302   xbt_automaton_transition_t transition_succ;
303   unsigned int cursor = 0;
304   int res;
305   int visited_num;
306
307   mc_pair_t next_pair = NULL;
308   xbt_dynar_t prop_values = NULL;
309   mc_visited_pair_t reached_pair = NULL;
310   int counter_example_depth = 0;
311
312   if (xbt_fifo_size(mc_stack) < _sg_mc_max_depth) {
313
314     if (current_pair->requests > 0) {
315
316       if (current_pair->search_cycle) {
317
318         if ((current_pair->automaton_state->type == 1)
319             || (current_pair->automaton_state->type == 2)) {
320           if ((reached_pair =
321                is_reached_acceptance_pair(current_pair->num,
322                                           current_pair->automaton_state,
323                                           current_pair->atomic_propositions)) ==
324               NULL) {
325
326             counter_example_depth = xbt_fifo_size(mc_stack);
327             XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
328             XBT_INFO("|             ACCEPTANCE CYCLE            |");
329             XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
330             XBT_INFO("Counter-example that violates formula :");
331             MC_show_stack_liveness(mc_stack);
332             MC_dump_stack_liveness(mc_stack);
333             MC_print_statistics(mc_stats);
334             XBT_INFO("Counter-example depth : %d", counter_example_depth);
335             xbt_abort();
336
337           }
338         }
339       }
340
341       if ((visited_num =
342            is_visited_pair(reached_pair, current_pair->num,
343                            current_pair->automaton_state,
344                            current_pair->atomic_propositions)) != -1) {
345
346         MC_SET_MC_HEAP;
347         if (dot_output != NULL)
348           fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n",
349                   initial_global_state->prev_pair, visited_num,
350                   initial_global_state->prev_req);
351         MC_SET_STD_HEAP;
352
353       } else {
354
355         while ((req =
356                 MC_state_get_request(current_pair->graph_state,
357                                      &value)) != NULL) {
358
359           MC_SET_MC_HEAP;
360           if (dot_output != NULL) {
361             if (initial_global_state->prev_pair != 0
362                 && initial_global_state->prev_pair != current_pair->num) {
363               fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n",
364                       initial_global_state->prev_pair, current_pair->num,
365                       initial_global_state->prev_req);
366               xbt_free(initial_global_state->prev_req);
367             }
368             initial_global_state->prev_pair = current_pair->num;
369           }
370           MC_SET_STD_HEAP;
371
372           MC_LOG_REQUEST(mc_liveness, req, value);
373
374           MC_SET_MC_HEAP;
375           if (dot_output != NULL) {
376             initial_global_state->prev_req =
377                 MC_request_get_dot_output(req, value);
378             if (current_pair->search_cycle)
379               fprintf(dot_output, "%d [shape=doublecircle];\n",
380                       current_pair->num);
381           }
382           MC_SET_STD_HEAP;
383
384           MC_state_set_executed_request(current_pair->graph_state, req, value);
385           mc_stats->executed_transitions++;
386
387           /* Answer the request */
388           SIMIX_simcall_handle(req, value);
389
390           /* Wait for requests (schedules processes) */
391           MC_wait_for_requests();
392
393           MC_SET_MC_HEAP;
394           prop_values = get_atomic_propositions_values();
395           MC_SET_STD_HEAP;
396
397           int new_pair = 0;
398
399           /* Evaluate enabled transition according to atomic propositions values */
400           cursor = 0;
401           xbt_dynar_foreach(current_pair->automaton_state->out, cursor,
402                             transition_succ) {
403
404             res =
405                 MC_automaton_evaluate_label(transition_succ->label,
406                                             prop_values);
407
408             if (res == 1) {     // enabled transition in automaton
409
410               if (new_pair)
411                 MC_replay_liveness(mc_stack, 1);
412
413               MC_SET_MC_HEAP;
414
415               next_pair = MC_pair_new();
416               next_pair->graph_state = MC_state_new();
417               next_pair->automaton_state = transition_succ->dst;
418               next_pair->atomic_propositions = get_atomic_propositions_values();
419
420               /* Get enabled processes and insert them in the interleave set of the next graph_state */
421               xbt_swag_foreach(process, simix_global->process_list) {
422                 if (MC_process_is_enabled(process)) {
423                   MC_state_interleave_process(next_pair->graph_state, process);
424                 }
425               }
426
427               next_pair->requests =
428                   MC_state_interleave_size(next_pair->graph_state);
429
430               if (next_pair->automaton_state->type == 1
431                   || next_pair->automaton_state->type == 2
432                   || current_pair->search_cycle)
433                 next_pair->search_cycle = 1;
434
435               xbt_fifo_unshift(mc_stack, next_pair);
436
437               if (mc_stats->expanded_pairs % 1000000 == 0)
438                 XBT_INFO("Expanded pairs : %lu", mc_stats->expanded_pairs);
439
440               MC_SET_STD_HEAP;
441
442               new_pair = 1;
443
444               MC_modelcheck_liveness();
445
446             }
447
448           }
449
450           /* Then, evaluate true transitions (always true, whatever atomic propositions values) */
451           cursor = 0;
452           xbt_dynar_foreach(current_pair->automaton_state->out, cursor,
453                             transition_succ) {
454
455             res =
456                 MC_automaton_evaluate_label(transition_succ->label,
457                                             prop_values);
458
459             if (res == 2) {     // true transition in automaton
460
461               if (new_pair)
462                 MC_replay_liveness(mc_stack, 1);
463
464               MC_SET_MC_HEAP;
465
466               next_pair = MC_pair_new();
467               next_pair->graph_state = MC_state_new();
468               next_pair->automaton_state = transition_succ->dst;
469               next_pair->atomic_propositions = get_atomic_propositions_values();
470
471               /* Get enabled process and insert it in the interleave set of the next graph_state */
472               xbt_swag_foreach(process, simix_global->process_list) {
473                 if (MC_process_is_enabled(process)) {
474                   MC_state_interleave_process(next_pair->graph_state, process);
475                 }
476               }
477
478               next_pair->requests =
479                   MC_state_interleave_size(next_pair->graph_state);
480
481               if (next_pair->automaton_state->type == 1
482                   || next_pair->automaton_state->type == 2
483                   || current_pair->search_cycle)
484                 next_pair->search_cycle = 1;
485
486               xbt_fifo_unshift(mc_stack, next_pair);
487
488               if (mc_stats->expanded_pairs % 1000000 == 0)
489                 XBT_INFO("Expanded pairs : %lu", mc_stats->expanded_pairs);
490
491               MC_SET_STD_HEAP;
492
493               new_pair = 1;
494
495               MC_modelcheck_liveness();
496
497             }
498
499           }
500
501           if (MC_state_interleave_size(current_pair->graph_state) > 0) {
502             XBT_DEBUG("Backtracking to depth %d", xbt_fifo_size(mc_stack));
503             MC_replay_liveness(mc_stack, 0);
504           }
505
506         }
507
508       }
509
510     }
511
512   } else {
513
514     XBT_WARN("/!\\ Max depth reached ! /!\\ ");
515     if (MC_state_interleave_size(current_pair->graph_state) > 0) {
516       XBT_WARN
517           ("/!\\ But, there are still processes to interleave. Model-checker will not be able to ensure the soundness of the verification from now. /!\\ ");
518       if (_sg_mc_max_depth == 1000)
519         XBT_WARN
520             ("Notice : the default value of max depth is 1000 but you can change it with cfg=model-check/max_depth:value.");
521     }
522
523   }
524
525   if (xbt_fifo_size(mc_stack) == _sg_mc_max_depth) {
526     XBT_DEBUG("Pair %d (depth = %d) shifted in stack, maximum depth reached",
527               current_pair->num, xbt_fifo_size(mc_stack));
528   } else {
529     XBT_DEBUG("Pair %d (depth = %d) shifted in stack", current_pair->num,
530               xbt_fifo_size(mc_stack));
531   }
532
533
534   MC_SET_MC_HEAP;
535   xbt_dynar_free(&prop_values);
536   current_pair = xbt_fifo_shift(mc_stack);
537   if (xbt_fifo_size(mc_stack) != _sg_mc_max_depth - 1
538       && current_pair->requests > 0 && current_pair->search_cycle) {
539     remove_acceptance_pair(current_pair->num);
540   }
541   MC_pair_delete(current_pair);
542
543   MC_SET_STD_HEAP;
544
545 }