1 /* Copyright (c) 2011-2013 Da SimGrid Team. All rights reserved. */
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. */
6 #include "mc_private.h"
10 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_liveness, mc,
11 "Logging specific to algorithms for liveness properties verification");
13 /********* Global variables *********/
15 xbt_dynar_t acceptance_pairs;
16 xbt_dynar_t visited_pairs;
17 xbt_dynar_t successors;
20 /********* Static functions *********/
22 static xbt_dynar_t get_atomic_propositions_values(){
25 unsigned int cursor = 0;
26 xbt_automaton_propositional_symbol_t ps = NULL;
27 xbt_dynar_t values = xbt_dynar_new(sizeof(int), NULL);
29 xbt_dynar_foreach(_mc_property_automaton->propositional_symbols, cursor, ps){
30 f = (int_f_void_t)ps->function;
32 xbt_dynar_push_as(values, int, res);
38 static int is_reached_acceptance_pair(mc_pair_t pair){
40 int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
42 if(xbt_dynar_is_empty(acceptance_pairs)){
45 if(pair->graph_state->system_state == NULL){
46 pair->graph_state->system_state = MC_take_snapshot();
47 pair->heap_bytes_used = mmalloc_get_bytes_used(std_heap);
49 xbt_dynar_push(acceptance_pairs, &pair);
61 if(pair->graph_state->system_state == NULL){
62 pair->graph_state->system_state = MC_take_snapshot();
63 pair->heap_bytes_used = mmalloc_get_bytes_used(std_heap);
66 size_t current_bytes_used = pair->heap_bytes_used;
67 int current_nb_processes = pair->nb_processes;
69 unsigned int cursor = 0;
70 int previous_cursor = 0, next_cursor = 0;
72 int end = xbt_dynar_length(acceptance_pairs) - 1;
74 mc_pair_t pair_test = NULL;
75 size_t bytes_used_test;
76 int nb_processes_test;
77 int same_processes_and_bytes_not_found = 1;
79 while(start <= end && same_processes_and_bytes_not_found){
80 cursor = (start + end) / 2;
81 pair_test = (mc_pair_t)xbt_dynar_get_as(acceptance_pairs, cursor, mc_pair_t);
82 bytes_used_test = pair_test->heap_bytes_used;
83 nb_processes_test = pair_test->nb_processes;
84 if(nb_processes_test < current_nb_processes)
86 else if(nb_processes_test > current_nb_processes)
88 else if(nb_processes_test == current_nb_processes){
89 if(bytes_used_test < current_bytes_used)
91 else if(bytes_used_test > current_bytes_used)
93 else if(bytes_used_test == current_bytes_used){
94 same_processes_and_bytes_not_found = 0;
95 if(xbt_automaton_state_compare(pair_test->automaton_state, pair->automaton_state) == 0){
96 if(xbt_automaton_propositional_symbols_compare_value(pair_test->atomic_propositions, pair->atomic_propositions) == 0){
97 XBT_DEBUG("Compare with state %d", pair_test->num);
98 if(snapshot_compare(pair->graph_state->system_state, pair_test->graph_state->system_state) == 0){
103 return pair_test->num;
107 /* Search another pair with same number of bytes used in std_heap */
108 previous_cursor = cursor - 1;
109 while(previous_cursor >= 0){
110 pair_test = (mc_pair_t)xbt_dynar_get_as(acceptance_pairs, previous_cursor, mc_pair_t);
111 bytes_used_test = pair_test->heap_bytes_used;
112 if(bytes_used_test != current_bytes_used)
114 if(xbt_automaton_state_compare(pair_test->automaton_state, pair->automaton_state) == 0){
115 if(xbt_automaton_propositional_symbols_compare_value(pair_test->atomic_propositions, pair->atomic_propositions) == 0){
116 XBT_DEBUG("Compare with state %d", pair_test->num);
117 if(snapshot_compare(pair->graph_state->system_state, pair_test->graph_state->system_state) == 0){
122 return pair_test->num;
128 next_cursor = cursor + 1;
129 while(next_cursor < xbt_dynar_length(acceptance_pairs)){
130 pair_test = (mc_pair_t)xbt_dynar_get_as(acceptance_pairs, next_cursor, mc_pair_t);
131 bytes_used_test = pair_test->heap_bytes_used;
132 if(bytes_used_test != current_bytes_used)
134 if(xbt_automaton_state_compare(pair_test->automaton_state, pair->automaton_state) == 0){
135 if(xbt_automaton_propositional_symbols_compare_value(pair_test->atomic_propositions, pair->atomic_propositions) == 0){
136 XBT_DEBUG("Compare with state %d", pair_test->num);
137 if(snapshot_compare(pair->graph_state->system_state, pair_test->graph_state->system_state) == 0){
142 return pair_test->num;
152 pair_test = (mc_pair_t)xbt_dynar_get_as(acceptance_pairs, cursor, mc_pair_t);
153 bytes_used_test = pair_test->heap_bytes_used;
155 if(bytes_used_test < current_bytes_used)
156 xbt_dynar_insert_at(acceptance_pairs, cursor + 1, &pair);
158 xbt_dynar_insert_at(acceptance_pairs, cursor, &pair);
173 static void set_acceptance_pair_reached(mc_pair_t pair){
175 int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
177 if(xbt_dynar_is_empty(acceptance_pairs)){
180 if(pair->graph_state->system_state == NULL){
181 pair->graph_state->system_state = MC_take_snapshot();
182 pair->heap_bytes_used = mmalloc_get_bytes_used(std_heap);
184 xbt_dynar_push(acceptance_pairs, &pair);
191 if(pair->graph_state->system_state == NULL){
192 pair->graph_state->system_state = MC_take_snapshot();
193 pair->heap_bytes_used = mmalloc_get_bytes_used(std_heap);
196 size_t current_bytes_used = pair->heap_bytes_used;
197 int current_nb_processes = pair->nb_processes;
199 unsigned int cursor = 0;
201 int end = xbt_dynar_length(acceptance_pairs) - 1;
203 mc_pair_t pair_test = NULL;
204 size_t bytes_used_test = 0;
205 int nb_processes_test;
208 cursor = (start + end) / 2;
209 pair_test = (mc_pair_t)xbt_dynar_get_as(acceptance_pairs, cursor, mc_pair_t);
210 bytes_used_test = pair_test->heap_bytes_used;
211 nb_processes_test = pair_test->nb_processes;
212 if(nb_processes_test < current_nb_processes)
214 if(nb_processes_test > current_nb_processes)
216 if(nb_processes_test == current_nb_processes){
217 if(bytes_used_test < current_bytes_used)
219 if(bytes_used_test > current_bytes_used)
221 if(bytes_used_test == current_bytes_used)
226 if(bytes_used_test < current_bytes_used)
227 xbt_dynar_insert_at(acceptance_pairs, cursor + 1, &pair);
229 xbt_dynar_insert_at(acceptance_pairs, cursor, &pair);
240 static void remove_acceptance_pair(mc_pair_t pair){
242 unsigned int cursor = 0;
246 xbt_dynar_foreach(acceptance_pairs, cursor, pair_test){
247 if(pair_test->num == pair->num){
254 xbt_dynar_remove_at(acceptance_pairs, cursor, NULL);
256 pair->acceptance_removed = 1;
258 if(pair->stack_removed && pair->acceptance_removed){
259 if(_sg_mc_visited == 0){
260 MC_pair_delete(pair);
261 }else if(pair->visited_removed){
262 MC_pair_delete(pair);
268 static int is_visited_pair(mc_pair_t pair){
270 if(_sg_mc_visited == 0)
273 int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
275 if(xbt_dynar_is_empty(visited_pairs)){
278 if(pair->graph_state->system_state == NULL)
279 pair->graph_state->system_state = MC_take_snapshot();
280 xbt_dynar_push(visited_pairs, &pair);
292 if(pair->graph_state->system_state == NULL)
293 pair->graph_state->system_state = MC_take_snapshot();
295 size_t current_bytes_used = pair->heap_bytes_used;
296 int current_nb_processes = pair->nb_processes;
298 unsigned int cursor = 0;
299 int previous_cursor = 0, next_cursor = 0;
301 int end = xbt_dynar_length(visited_pairs) - 1;
303 mc_pair_t pair_test = NULL;
304 size_t bytes_used_test;
305 int nb_processes_test;
306 int same_processes_and_bytes_not_found = 1;
308 while(start <= end && same_processes_and_bytes_not_found){
309 cursor = (start + end) / 2;
310 pair_test = (mc_pair_t)xbt_dynar_get_as(visited_pairs, cursor, mc_pair_t);
311 bytes_used_test = pair_test->heap_bytes_used;
312 nb_processes_test = pair_test->nb_processes;
313 if(nb_processes_test < current_nb_processes)
315 else if(nb_processes_test > current_nb_processes)
317 else if(nb_processes_test == current_nb_processes){
318 if(bytes_used_test < current_bytes_used)
320 else if(bytes_used_test > current_bytes_used)
322 else if(bytes_used_test == current_bytes_used){
323 same_processes_and_bytes_not_found = 0;
324 if(xbt_automaton_state_compare(pair_test->automaton_state, pair->automaton_state) == 0){
325 if(xbt_automaton_propositional_symbols_compare_value(pair_test->atomic_propositions, pair->atomic_propositions) == 0){
326 if(snapshot_compare(pair->graph_state->system_state, pair_test->graph_state->system_state) == 0){
327 if(pair_test->other_num == -1)
328 pair->other_num = pair_test->num;
330 pair->other_num = pair_test->other_num;
331 if(dot_output == NULL)
332 XBT_DEBUG("Pair %d already visited ! (equal to pair %d)", pair->num, pair_test->num);
334 XBT_DEBUG("Pair %d already visited ! (equal to pair %d (pair %d in dot_output))", pair->num, pair_test->num, pair->other_num);
335 xbt_dynar_remove_at(visited_pairs, cursor, NULL);
336 xbt_dynar_insert_at(visited_pairs, cursor, &pair);
337 pair_test->visited_removed = 1;
338 if(pair_test->stack_removed && pair_test->visited_removed){
339 if((pair_test->automaton_state->type == 1) || (pair_test->automaton_state->type == 2)){
340 if(pair_test->acceptance_removed){
341 MC_pair_delete(pair_test);
344 MC_pair_delete(pair_test);
351 return pair->other_num;
355 /* Search another pair with same number of bytes used in std_heap */
356 previous_cursor = cursor - 1;
357 while(previous_cursor >= 0){
358 pair_test = (mc_pair_t)xbt_dynar_get_as(visited_pairs, previous_cursor, mc_pair_t);
359 bytes_used_test = pair_test->heap_bytes_used;
360 if(bytes_used_test != current_bytes_used)
362 if(xbt_automaton_state_compare(pair_test->automaton_state, pair->automaton_state) == 0){
363 if(xbt_automaton_propositional_symbols_compare_value(pair_test->atomic_propositions, pair->atomic_propositions) == 0){
364 if(snapshot_compare(pair->graph_state->system_state, pair_test->graph_state->system_state) == 0){
365 if(pair_test->other_num == -1)
366 pair->other_num = pair_test->num;
368 pair->other_num = pair_test->other_num;
369 if(dot_output == NULL)
370 XBT_DEBUG("Pair %d already visited ! (equal to pair %d)", pair->num, pair_test->num);
372 XBT_DEBUG("Pair %d already visited ! (equal to pair %d (pair %d in dot_output))", pair->num, pair_test->num, pair->other_num);
373 xbt_dynar_remove_at(visited_pairs, previous_cursor, NULL);
374 xbt_dynar_insert_at(visited_pairs, previous_cursor, &pair);
375 pair_test->visited_removed = 1;
376 if(pair_test->stack_removed && pair_test->visited_removed){
377 if((pair_test->automaton_state->type == 1) || (pair_test->automaton_state->type == 2)){
378 if(pair_test->acceptance_removed){
379 MC_pair_delete(pair_test);
382 MC_pair_delete(pair_test);
389 return pair->other_num;
395 next_cursor = cursor + 1;
396 while(next_cursor < xbt_dynar_length(visited_pairs)){
397 pair_test = (mc_pair_t)xbt_dynar_get_as(visited_pairs, next_cursor, mc_pair_t);
398 bytes_used_test = pair_test->heap_bytes_used;
399 if(bytes_used_test != current_bytes_used)
401 if(xbt_automaton_state_compare(pair_test->automaton_state, pair->automaton_state) == 0){
402 if(xbt_automaton_propositional_symbols_compare_value(pair_test->atomic_propositions, pair->atomic_propositions) == 0){
403 if(snapshot_compare(pair->graph_state->system_state, pair_test->graph_state->system_state) == 0){
404 if(pair_test->other_num == -1)
405 pair->other_num = pair_test->num;
407 pair->other_num = pair_test->other_num;
408 if(dot_output == NULL)
409 XBT_DEBUG("Pair %d already visited ! (equal to pair %d)", pair->num, pair_test->num);
411 XBT_DEBUG("Pair %d already visited ! (equal to pair %d (pair %d in dot_output))", pair->num, pair_test->num, pair->other_num);
412 xbt_dynar_remove_at(visited_pairs, next_cursor, NULL);
413 xbt_dynar_insert_at(visited_pairs, next_cursor, &pair);
414 pair_test->visited_removed = 1;
415 if(pair_test->stack_removed && pair_test->visited_removed){
416 if((pair_test->automaton_state->type == 1) || (pair_test->automaton_state->type == 2)){
417 if(pair_test->acceptance_removed){
418 MC_pair_delete(pair_test);
421 MC_pair_delete(pair_test);
428 return pair->other_num;
438 pair_test = (mc_pair_t)xbt_dynar_get_as(visited_pairs, cursor, mc_pair_t);
439 bytes_used_test = pair_test->heap_bytes_used;
441 if(bytes_used_test < current_bytes_used)
442 xbt_dynar_insert_at(visited_pairs, cursor + 1, &pair);
444 xbt_dynar_insert_at(visited_pairs, cursor, &pair);
446 if(xbt_dynar_length(visited_pairs) > _sg_mc_visited){
447 int min = mc_stats->expanded_states;
448 unsigned int cursor2 = 0;
449 unsigned int index = 0;
450 xbt_dynar_foreach(visited_pairs, cursor2, pair_test){
451 if(pair_test->num < min){
453 min = pair_test->num;
456 xbt_dynar_remove_at(visited_pairs, index, &pair_test);
457 pair_test->visited_removed = 1;
458 if(pair_test->stack_removed && pair_test->acceptance_removed && pair_test->visited_removed)
459 MC_pair_delete(pair_test);
474 static int MC_automaton_evaluate_label(xbt_automaton_exp_label_t l, xbt_dynar_t atomic_propositions_values){
478 int left_res = MC_automaton_evaluate_label(l->u.or_and.left_exp, atomic_propositions_values);
479 int right_res = MC_automaton_evaluate_label(l->u.or_and.right_exp, atomic_propositions_values);
480 return (left_res || right_res);
483 int left_res = MC_automaton_evaluate_label(l->u.or_and.left_exp, atomic_propositions_values);
484 int right_res = MC_automaton_evaluate_label(l->u.or_and.right_exp, atomic_propositions_values);
485 return (left_res && right_res);
488 int res = MC_automaton_evaluate_label(l->u.exp_not, atomic_propositions_values);
492 unsigned int cursor = 0;
493 xbt_automaton_propositional_symbol_t p = NULL;
494 xbt_dynar_foreach(_mc_property_automaton->propositional_symbols, cursor, p){
495 if(strcmp(p->pred, l->u.predicat) == 0)
496 return (int)xbt_dynar_get_as(atomic_propositions_values, cursor, int);
509 /********* DDFS Algorithm *********/
512 void MC_ddfs_init(void){
514 initial_state_liveness->raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
516 XBT_DEBUG("**************************************************");
517 XBT_DEBUG("Double-DFS init");
518 XBT_DEBUG("**************************************************");
520 mc_pair_t initial_pair = NULL;
521 smx_process_t process;
523 MC_wait_for_requests();
527 acceptance_pairs = xbt_dynar_new(sizeof(mc_pair_t), NULL);
528 visited_pairs = xbt_dynar_new(sizeof(mc_pair_t), NULL);
529 successors = xbt_dynar_new(sizeof(mc_pair_t), NULL);
531 initial_state_liveness->snapshot = MC_take_snapshot();
532 initial_state_liveness->prev_pair = 0;
536 unsigned int cursor = 0;
537 xbt_automaton_state_t automaton_state;
539 xbt_dynar_foreach(_mc_property_automaton->states, cursor, automaton_state){
540 if(automaton_state->type == -1){ /* Initial automaton state */
544 initial_pair = MC_pair_new();
545 initial_pair->automaton_state = automaton_state;
546 initial_pair->graph_state = MC_state_new();
547 initial_pair->atomic_propositions = get_atomic_propositions_values();
549 /* Get enabled process and insert it in the interleave set of the graph_state */
550 xbt_swag_foreach(process, simix_global->process_list){
551 if(MC_process_is_enabled(process)){
552 MC_state_interleave_process(initial_pair->graph_state, process);
556 initial_pair->requests = MC_state_interleave_size(initial_pair->graph_state);
557 initial_pair->search_cycle = 0;
559 xbt_fifo_unshift(mc_stack_liveness, initial_pair);
566 MC_restore_snapshot(initial_state_liveness->snapshot);
571 }else if(automaton_state->type == 2){ /* Acceptance automaton state */
575 initial_pair = MC_pair_new();
576 initial_pair->automaton_state = automaton_state;
577 initial_pair->graph_state = MC_state_new();
578 initial_pair->atomic_propositions = get_atomic_propositions_values();
580 /* Get enabled process and insert it in the interleave set of the graph_state */
581 xbt_swag_foreach(process, simix_global->process_list){
582 if(MC_process_is_enabled(process)){
583 MC_state_interleave_process(initial_pair->graph_state, process);
587 initial_pair->requests = MC_state_interleave_size(initial_pair->graph_state);
588 initial_pair->search_cycle = 1;
590 xbt_fifo_unshift(mc_stack_liveness, initial_pair);
594 set_acceptance_pair_reached(initial_pair);
599 MC_restore_snapshot(initial_state_liveness->snapshot);
605 if(initial_state_liveness->raw_mem_set)
616 smx_process_t process;
617 mc_pair_t current_pair = NULL;
619 if(xbt_fifo_size(mc_stack_liveness) == 0)
622 /* Get current pair */
623 current_pair = (mc_pair_t)xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_stack_liveness));
625 /* Update current state in buchi automaton */
626 _mc_property_automaton->current_state = current_pair->automaton_state;
628 XBT_DEBUG("********************* ( Depth = %d, search_cycle = %d )", xbt_fifo_size(mc_stack_liveness), current_pair->search_cycle);
630 mc_stats->visited_pairs++;
633 smx_simcall_t req = NULL;
636 xbt_automaton_transition_t transition_succ;
637 unsigned int cursor = 0;
639 int reached_num, visited_num;
642 mc_pair_t next_pair = NULL;
643 xbt_dynar_t prop_values = NULL;
645 if(xbt_fifo_size(mc_stack_liveness) < _sg_mc_max_depth){
647 if(current_pair->requests > 0){
649 if(current_pair->search_cycle){
651 if((current_pair->automaton_state->type == 1) || (current_pair->automaton_state->type == 2)){
653 if((reached_num = is_reached_acceptance_pair(current_pair)) != -1){
655 XBT_INFO("Pair %d already reached (equal to pair %d) !", current_pair->num, reached_num);
658 xbt_fifo_shift(mc_stack_liveness);
659 if(dot_output != NULL)
660 fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", initial_state_liveness->prev_pair, reached_num, initial_state_liveness->prev_req);
663 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
664 XBT_INFO("| ACCEPTANCE CYCLE |");
665 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
666 XBT_INFO("Counter-example that violates formula :");
667 MC_show_stack_liveness(mc_stack_liveness);
668 MC_dump_stack_liveness(mc_stack_liveness);
669 MC_print_statistics(mc_stats);
676 if((visited_num = is_visited_pair(current_pair)) != -1){
679 if(dot_output != NULL)
680 fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", initial_state_liveness->prev_pair, visited_num, initial_state_liveness->prev_req);
686 while((req = MC_state_get_request(current_pair->graph_state, &value)) != NULL){
689 if(dot_output != NULL){
690 if(initial_state_liveness->prev_pair != 0 && initial_state_liveness->prev_pair != current_pair->num){
691 fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", initial_state_liveness->prev_pair, current_pair->num, initial_state_liveness->prev_req);
692 xbt_free(initial_state_liveness->prev_req);
694 initial_state_liveness->prev_pair = current_pair->num;
698 /* Debug information */
699 if(XBT_LOG_ISENABLED(mc_liveness, xbt_log_priority_debug)){
700 req_str = MC_request_to_string(req, value);
701 XBT_DEBUG("Execute: %s", req_str);
706 if(dot_output != NULL){
707 initial_state_liveness->prev_req = MC_request_get_dot_output(req, value);
708 if(current_pair->search_cycle)
709 fprintf(dot_output, "%d [shape=doublecircle];\n", current_pair->num);
713 MC_state_set_executed_request(current_pair->graph_state, req, value);
714 mc_stats->executed_transitions++;
716 /* Answer the request */
717 SIMIX_simcall_pre(req, value);
719 /* Wait for requests (schedules processes) */
720 MC_wait_for_requests();
723 prop_values = get_atomic_propositions_values();
726 /* Evaluate enabled transition according to atomic propositions values */
728 xbt_dynar_foreach(current_pair->automaton_state->out, cursor, transition_succ){
730 res = MC_automaton_evaluate_label(transition_succ->label, prop_values);
732 if(res == 1){ // enabled transition in automaton
735 MC_replay_liveness(mc_stack_liveness, 1);
739 next_pair = MC_pair_new();
740 next_pair->graph_state = MC_state_new();
741 next_pair->automaton_state = transition_succ->dst;
742 next_pair->atomic_propositions = get_atomic_propositions_values();
744 /* Get enabled process and insert it in the interleave set of the next graph_state */
745 xbt_swag_foreach(process, simix_global->process_list){
746 if(MC_process_is_enabled(process)){
747 MC_state_interleave_process(next_pair->graph_state, process);
751 next_pair->requests = MC_state_interleave_size(next_pair->graph_state);
753 if(next_pair->automaton_state->type == 1 || next_pair->automaton_state->type == 2 || current_pair->search_cycle)
754 next_pair->search_cycle = 1;
756 xbt_fifo_unshift(mc_stack_liveness, next_pair);
758 if(mc_stats->expanded_pairs%1000000 == 0)
759 XBT_INFO("Expanded pairs : %lu", mc_stats->expanded_pairs);
771 /* Then, evaluate true transitions (always true, whatever atomic propositions values) */
773 xbt_dynar_foreach(current_pair->automaton_state->out, cursor, transition_succ){
775 res = MC_automaton_evaluate_label(transition_succ->label, prop_values);
777 if(res == 2){ // true transition in automaton
780 MC_replay_liveness(mc_stack_liveness, 1);
784 next_pair = MC_pair_new();
785 next_pair->graph_state = MC_state_new();
786 next_pair->automaton_state = transition_succ->dst;
787 next_pair->atomic_propositions = get_atomic_propositions_values();
789 /* Get enabled process and insert it in the interleave set of the next graph_state */
790 xbt_swag_foreach(process, simix_global->process_list){
791 if(MC_process_is_enabled(process)){
792 MC_state_interleave_process(next_pair->graph_state, process);
796 next_pair->requests = MC_state_interleave_size(next_pair->graph_state);
798 if(next_pair->automaton_state->type == 1 || next_pair->automaton_state->type == 2 || current_pair->search_cycle)
799 next_pair->search_cycle = 1;
801 xbt_fifo_unshift(mc_stack_liveness, next_pair);
803 if(mc_stats->expanded_pairs%1000000 == 0)
804 XBT_INFO("Expanded pairs : %lu", mc_stats->expanded_pairs);
816 if(MC_state_interleave_size(current_pair->graph_state) > 0){
817 XBT_DEBUG("Backtracking to depth %d", xbt_fifo_size(mc_stack_liveness));
818 MC_replay_liveness(mc_stack_liveness, 0);
827 mc_stats->executed_transitions++;
829 XBT_DEBUG("No request to execute in this state, search evolution in Büchi Automaton.");
831 if(current_pair->search_cycle){
833 if((current_pair->automaton_state->type == 1) || (current_pair->automaton_state->type == 2)){
835 if((reached_num = is_reached_acceptance_pair(current_pair)) != -1){
837 XBT_INFO("Pair %d already reached (equal to pair %d) !", current_pair->num, reached_num);
840 xbt_fifo_shift(mc_stack_liveness);
843 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
844 XBT_INFO("| ACCEPTANCE CYCLE |");
845 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
846 XBT_INFO("Counter-example that violates formula :");
847 MC_show_stack_liveness(mc_stack_liveness);
848 MC_dump_stack_liveness(mc_stack_liveness);
849 MC_print_statistics(mc_stats);
856 if((visited_num = is_visited_pair(current_pair)) != -1){
858 XBT_DEBUG("Pair %d already visited ! (equal to pair %d)", current_pair->num, visited_num);
863 prop_values = get_atomic_propositions_values();
866 /* Evaluate enabled transition according to atomic propositions values */
868 xbt_dynar_foreach(current_pair->automaton_state->out, cursor, transition_succ){
870 res = MC_automaton_evaluate_label(transition_succ->label, prop_values);
872 if(res == 1){ // enabled transition in automaton
875 MC_replay_liveness(mc_stack_liveness, 1);
879 next_pair = MC_pair_new();
880 next_pair->graph_state = MC_state_new();
881 next_pair->automaton_state = transition_succ->dst;
882 next_pair->atomic_propositions = get_atomic_propositions_values();
883 next_pair->requests = MC_state_interleave_size(next_pair->graph_state);
885 if(next_pair->automaton_state->type == 1 || next_pair->automaton_state->type == 2 || current_pair->search_cycle)
886 next_pair->search_cycle = 1;
888 xbt_fifo_unshift(mc_stack_liveness, next_pair);
890 if(mc_stats->expanded_pairs%1000 == 0)
891 XBT_INFO("Expanded pairs : %lu", mc_stats->expanded_pairs);
893 if(dot_output != NULL)
894 fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", current_pair->num, next_pair->num, "");
906 /* Then, evaluate true transitions (always true, whatever atomic propositions values) */
908 xbt_dynar_foreach(current_pair->automaton_state->out, cursor, transition_succ){
910 res = MC_automaton_evaluate_label(transition_succ->label, prop_values);
912 if(res == 2){ // true transition in automaton
915 MC_replay_liveness(mc_stack_liveness, 1);
919 next_pair = MC_pair_new();
920 next_pair->graph_state = MC_state_new();
921 next_pair->automaton_state = transition_succ->dst;
922 next_pair->atomic_propositions = get_atomic_propositions_values();
923 next_pair->requests = MC_state_interleave_size(next_pair->graph_state);
925 if(next_pair->automaton_state->type == 1 || next_pair->automaton_state->type == 2 || current_pair->search_cycle)
926 next_pair->search_cycle = 1;
928 xbt_fifo_unshift(mc_stack_liveness, next_pair);
930 if(mc_stats->expanded_pairs%1000 == 0)
931 XBT_INFO("Expanded pairs : %lu", mc_stats->expanded_pairs);
933 if(dot_output != NULL)
934 fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", current_pair->num, next_pair->num, "");
950 XBT_WARN("/!\\ Max depth reached ! /!\\ ");
951 if(MC_state_interleave_size(current_pair->graph_state) > 0){
952 XBT_WARN("/!\\ But, there are still processes to interleave. Model-checker will not be able to ensure the soundness of the verification from now. /!\\ ");
953 if(_sg_mc_max_depth == 1000)
954 XBT_WARN("Notice : the default value of max depth is 1000 but you can change it with cfg=model-check/max_depth:value.");
959 if(xbt_fifo_size(mc_stack_liveness) == _sg_mc_max_depth ){
960 XBT_DEBUG("Pair %d (depth = %d) shifted in stack, maximum depth reached", current_pair->num, xbt_fifo_size(mc_stack_liveness) );
962 XBT_DEBUG("Pair %d (depth = %d) shifted in stack", current_pair->num, xbt_fifo_size(mc_stack_liveness) );
967 xbt_dynar_free(&prop_values);
968 current_pair = xbt_fifo_shift(mc_stack_liveness);
969 current_pair->stack_removed = 1;
970 if(current_pair->search_cycle){
971 remove_acceptance_pair(current_pair);
973 if(_sg_mc_visited == 0)
974 MC_pair_delete(current_pair);
975 else if(current_pair->visited_removed)
976 MC_pair_delete(current_pair);