1 /* Copyright (c) 2008 Martin Quinson, Cristian Rosa.
2 All rights reserved. */
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. */
9 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dpor, mc,
10 "Logging specific to MC DPOR exploration");
13 * \brief Initialize the DPOR exploration algorithm
17 mc_state_t initial_state = NULL;
18 smx_process_t process;
20 /* Create the initial state and push it into the exploration stack */
22 initial_state = MC_state_new();
23 xbt_fifo_unshift(mc_stack_safety_stateless, initial_state);
26 XBT_DEBUG("**************************************************");
27 XBT_DEBUG("Initial state");
29 /* Wait for requests (schedules processes) */
30 MC_wait_for_requests();
33 /* Get an enabled process and insert it in the interleave set of the initial state */
34 xbt_swag_foreach(process, simix_global->process_list){
35 if(MC_process_is_enabled(process)){
36 MC_state_interleave_process(initial_state, process);
42 /* FIXME: Update Statistics
43 mc_stats->state_size +=
44 xbt_setset_set_size(initial_state->enabled_transitions); */
49 * \brief Perform the model-checking operation using a depth-first search exploration
50 * with Dynamic Partial Order Reductions
56 smx_req_t req = NULL, prev_req = NULL;
57 mc_state_t state = NULL, prev_state = NULL, next_state = NULL;
58 smx_process_t process = NULL;
59 xbt_fifo_item_t item = NULL;
61 while (xbt_fifo_size(mc_stack_safety_stateless) > 0) {
63 /* Get current state */
65 xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_stack_safety_stateless));
67 XBT_DEBUG("**************************************************");
68 XBT_DEBUG("Exploration depth=%d (state=%p)(%u interleave)",
69 xbt_fifo_size(mc_stack_safety_stateless), state,
70 MC_state_interleave_size(state));
72 /* Update statistics */
73 mc_stats->visited_states++;
75 /* If there are processes to interleave and the maximum depth has not been reached
76 then perform one step of the exploration algorithm */
77 if (xbt_fifo_size(mc_stack_safety_stateless) < MAX_DEPTH &&
78 (req = MC_state_get_request(state, &value))) {
80 /* Debug information */
81 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
82 req_str = MC_request_to_string(req, value);
83 XBT_DEBUG("Execute: %s", req_str);
87 MC_state_set_executed_request(state, req, value);
88 mc_stats->executed_transitions++;
90 /* Answer the request */
91 SIMIX_request_pre(req, value); /* After this call req is no longer usefull */
93 /* Wait for requests (schedules processes) */
94 MC_wait_for_requests();
96 /* Create the new expanded state */
98 next_state = MC_state_new();
99 xbt_fifo_unshift(mc_stack_safety_stateless, next_state);
101 /* Get an enabled process and insert it in the interleave set of the next state */
102 xbt_swag_foreach(process, simix_global->process_list){
103 if(MC_process_is_enabled(process)){
104 MC_state_interleave_process(next_state, process);
110 /* FIXME: Update Statistics
111 mc_stats->state_size +=
112 xbt_setset_set_size(next_state->enabled_transitions);*/
114 /* Let's loop again */
116 /* The interleave set is empty or the maximum depth is reached, let's back-track */
118 XBT_DEBUG("There are no more processes to interleave.");
120 /* Trash the current state, no longer needed */
122 xbt_fifo_shift(mc_stack_safety_stateless);
123 MC_state_delete(state);
126 /* Check for deadlocks */
127 if(MC_deadlock_check()){
128 MC_show_deadlock(NULL);
133 /* Traverse the stack backwards until a state with a non empty interleave
134 set is found, deleting all the states that have it empty in the way.
135 For each deleted state, check if the request that has generated it
136 (from it's predecesor state), depends on any other previous request
137 executed before it. If it does then add it to the interleave set of the
138 state that executed that previous request. */
139 while ((state = xbt_fifo_shift(mc_stack_safety_stateless)) != NULL) {
140 req = MC_state_get_internal_request(state);
141 xbt_fifo_foreach(mc_stack_safety_stateless, item, prev_state, mc_state_t) {
142 if(MC_request_depend(req, MC_state_get_internal_request(prev_state))){
143 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
144 XBT_DEBUG("Dependent Transitions:");
145 prev_req = MC_state_get_executed_request(prev_state, &value);
146 req_str = MC_request_to_string(prev_req, value);
147 XBT_DEBUG("%s (state=%p)", req_str, prev_state);
149 prev_req = MC_state_get_executed_request(state, &value);
150 req_str = MC_request_to_string(prev_req, value);
151 XBT_DEBUG("%s (state=%p)", req_str, state);
155 if(!MC_state_process_is_done(prev_state, req->issuer))
156 MC_state_interleave_process(prev_state, req->issuer);
158 XBT_DEBUG("Process %p is in done set", req->issuer);
163 if (MC_state_interleave_size(state)) {
164 /* We found a back-tracking point, let's loop */
165 xbt_fifo_unshift(mc_stack_safety_stateless, state);
166 XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_stack_safety_stateless));
168 MC_replay(mc_stack_safety_stateless);
171 MC_state_delete(state);
182 /********************* DPOR stateful *********************/
184 mc_state_ws_t new_state_ws(mc_snapshot_t s, mc_state_t gs){
185 mc_state_ws_t sws = NULL;
186 sws = xbt_new0(s_mc_state_ws_t, 1);
187 sws->system_state = s;
188 sws->graph_state = gs;
192 void MC_dpor_stateful_init(){
194 XBT_DEBUG("**************************************************");
195 XBT_DEBUG("DPOR (stateful) init");
196 XBT_DEBUG("**************************************************");
198 mc_state_t initial_graph_state;
199 smx_process_t process;
200 mc_snapshot_t initial_system_snapshot;
201 mc_state_ws_t initial_state ;
203 MC_wait_for_requests();
207 initial_system_snapshot = xbt_new0(s_mc_snapshot_t, 1);
209 initial_graph_state = MC_state_new();
210 xbt_swag_foreach(process, simix_global->process_list){
211 if(MC_process_is_enabled(process)){
212 MC_state_interleave_process(initial_graph_state, process);
217 MC_take_snapshot(initial_system_snapshot);
219 initial_state = new_state_ws(initial_system_snapshot, initial_graph_state);
220 xbt_fifo_unshift(mc_stack_safety_stateful, initial_state);
226 void MC_dpor_stateful(){
228 smx_process_t process = NULL;
230 if(xbt_fifo_size(mc_stack_safety_stateful) == 0)
234 mc_state_t next_graph_state = NULL;
235 smx_req_t req = NULL, prev_req = NULL;
237 xbt_fifo_item_t item = NULL;
239 mc_snapshot_t next_snapshot;
240 mc_state_ws_t current_state;
241 mc_state_ws_t prev_state;
242 mc_state_ws_t next_state;
244 while(xbt_fifo_size(mc_stack_safety_stateful) > 0){
246 current_state = (mc_state_ws_t)xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_stack_safety_stateful));
249 XBT_DEBUG("**************************************************");
250 XBT_DEBUG("Depth : %d, State : %p , %u interleave", xbt_fifo_size(mc_stack_safety_stateful),current_state, MC_state_interleave_size(current_state->graph_state));
252 mc_stats->visited_states++;
253 if(mc_stats->expanded_states>1100)
257 if((xbt_fifo_size(mc_stack_safety_stateful) < MAX_DEPTH) && (req = MC_state_get_request(current_state->graph_state, &value))){
259 /* Debug information */
260 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
261 req_str = MC_request_to_string(req, value);
262 //XBT_INFO("Visited states = %lu",mc_stats->visited_states );
263 XBT_DEBUG("Execute: %s",req_str);
267 MC_state_set_executed_request(current_state->graph_state, req, value);
268 mc_stats->executed_transitions++;
270 /* Answer the request */
271 SIMIX_request_pre(req, value);
273 /* Wait for requests (schedules processes) */
274 MC_wait_for_requests();
276 /* Create the new expanded graph_state */
279 next_graph_state = MC_state_new();
281 /* Get an enabled process and insert it in the interleave set of the next graph_state */
282 xbt_swag_foreach(process, simix_global->process_list){
283 if(MC_process_is_enabled(process)){
284 MC_state_interleave_process(next_graph_state, process);
289 next_snapshot = xbt_new0(s_mc_snapshot_t, 1);
290 MC_take_snapshot(next_snapshot);
292 next_state = new_state_ws(next_snapshot, next_graph_state);
293 xbt_fifo_unshift(mc_stack_safety_stateful, next_state);
298 XBT_DEBUG("There are no more processes to interleave.");
300 /* Trash the current state, no longer needed */
302 xbt_fifo_shift(mc_stack_safety_stateful);
305 /* Check for deadlocks */
306 if(MC_deadlock_check()){
307 MC_show_deadlock_stateful(NULL);
312 while((current_state = xbt_fifo_shift(mc_stack_safety_stateful)) != NULL){
313 req = MC_state_get_internal_request(current_state->graph_state);
314 xbt_fifo_foreach(mc_stack_safety_stateful, item, prev_state, mc_state_ws_t) {
315 if(MC_request_depend(req, MC_state_get_internal_request(prev_state->graph_state))){
316 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
317 XBT_DEBUG("Dependent Transitions:");
318 prev_req = MC_state_get_executed_request(prev_state->graph_state, &value);
319 req_str = MC_request_to_string(prev_req, value);
320 XBT_DEBUG("%s (state=%p)", req_str, prev_state->graph_state);
322 prev_req = MC_state_get_executed_request(current_state->graph_state, &value);
323 req_str = MC_request_to_string(prev_req, value);
324 XBT_DEBUG("%s (state=%p)", req_str, current_state->graph_state);
328 if(!MC_state_process_is_done(prev_state->graph_state, req->issuer)){
329 MC_state_interleave_process(prev_state->graph_state, req->issuer);
332 XBT_DEBUG("Process %p is in done set", req->issuer);
339 if(MC_state_interleave_size(current_state->graph_state)){
340 MC_restore_snapshot(current_state->system_state);
341 xbt_fifo_unshift(mc_stack_safety_stateful, current_state);
342 XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_stack_safety_stateful));
358 /************ DPOR 2 (invisible and independant transitions) ************/
360 xbt_dynar_t reached_pairs_prop;
361 xbt_dynar_t visible_transitions;
362 xbt_dynar_t enabled_processes;
364 mc_prop_ato_t new_proposition(char* id, int value){
365 mc_prop_ato_t prop = NULL;
366 prop = xbt_new0(s_mc_prop_ato_t, 1);
367 prop->id = strdup(id);
372 mc_pair_prop_t new_pair_prop(mc_snapshot_t sn, mc_state_t sg, xbt_state_t st){
373 mc_pair_prop_t pair = NULL;
374 pair = xbt_new0(s_mc_pair_prop_t, 1);
375 pair->system_state = sn;
376 pair->automaton_state = st;
377 pair->graph_state = sg;
378 pair->propositions = xbt_dynar_new(sizeof(mc_prop_ato_t), NULL);
379 pair->fully_expanded = 0;
380 pair->interleave = 0;
381 mc_stats_pair->expanded_pairs++;
385 int reached_prop(mc_pair_prop_t pair){
387 char* hash_reached = malloc(sizeof(char)*160);
391 char *hash = malloc(sizeof(char)*160);
392 xbt_sha((char *)&pair, hash);
393 xbt_dynar_foreach(reached_pairs_prop, c, hash_reached){
394 if(strcmp(hash, hash_reached) == 0){
404 void set_pair_prop_reached(mc_pair_prop_t pair){
406 if(reached_prop(pair) == 0){
408 char *hash = malloc(sizeof(char)*160) ;
409 xbt_sha((char *)&pair, hash);
410 xbt_dynar_push(reached_pairs_prop, &hash);
416 int invisible(mc_pair_prop_t p, mc_pair_prop_t np){
420 for(i=0;i<xbt_dynar_length(p->propositions); i++){
421 prop1 = xbt_dynar_get_as(p->propositions, i, mc_prop_ato_t);
422 prop2 = xbt_dynar_get_as(np->propositions, i, mc_prop_ato_t);
423 //XBT_DEBUG("test invisible : prop 1 = %s : %d / prop 2 = %s : %d", prop1->id, prop1->value, prop2->id, prop2->value);
424 if(prop1->value != prop2->value)
431 void set_fully_expanded(mc_pair_prop_t pair){
432 pair->fully_expanded = 1;
435 void MC_dpor2_init(xbt_automaton_t a)
437 mc_pair_prop_t initial_pair = NULL;
438 mc_state_t initial_graph_state = NULL;
439 mc_snapshot_t initial_system_state = NULL;
440 xbt_state_t initial_automaton_state = NULL;
444 initial_graph_state = MC_state_new();
447 /* Wait for requests (schedules processes) */
448 MC_wait_for_requests();
450 unsigned int cursor = 0;
451 unsigned int cursor2 = 0;
452 xbt_state_t automaton_state = NULL;
454 xbt_transition_t transition_succ;
456 xbt_dynar_foreach(a->states, cursor, automaton_state){
457 if(automaton_state->type == -1){
458 xbt_dynar_foreach(automaton_state->out, cursor2, transition_succ){
459 res = MC_automaton_evaluate_label(a, transition_succ->label);
460 if((res == 1) || (res == 2)){
461 initial_automaton_state = transition_succ->dst;
467 if(initial_automaton_state != NULL)
471 if(initial_automaton_state == NULL){
473 xbt_dynar_foreach(a->states, cursor, automaton_state){
474 if(automaton_state->type == -1){
475 initial_automaton_state = automaton_state;
481 reached_pairs_prop = xbt_dynar_new(sizeof(char *), NULL);
482 visible_transitions = xbt_dynar_new(sizeof(s_smx_req_t), NULL);
483 enabled_processes = xbt_dynar_new(sizeof(smx_process_t), NULL);
486 initial_system_state = xbt_new0(s_mc_snapshot_t, 1);
487 MC_take_snapshot(initial_system_state);
488 initial_pair = new_pair_prop(initial_system_state, initial_graph_state, initial_automaton_state);
490 xbt_propositional_symbol_t ps;
491 xbt_dynar_foreach(a->propositional_symbols, cursor, ps){
492 int (*f)() = ps->function;
494 mc_prop_ato_t pa = new_proposition(ps->pred, val);
495 xbt_dynar_push(initial_pair->propositions, &pa);
497 xbt_fifo_unshift(mc_stack_liveness_stateful, initial_pair);
501 XBT_DEBUG("**************************************************");
502 XBT_DEBUG("Initial pair");
509 void MC_dpor2(xbt_automaton_t a, int search_cycle)
513 smx_req_t req = NULL, prev_req = NULL;
514 mc_state_t next_graph_state = NULL;
515 mc_snapshot_t next_system_state = NULL;
516 xbt_state_t next_automaton_state = NULL;
517 xbt_transition_t transition_succ;
520 mc_pair_prop_t pair = NULL, next_pair = NULL, prev_pair = NULL;
521 smx_process_t process = NULL;
522 xbt_fifo_item_t item = NULL;
526 while (xbt_fifo_size(mc_stack_liveness_stateful) > 0) {
528 /* Get current pair */
529 pair = (mc_pair_prop_t)
530 xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_stack_liveness_stateful));
532 XBT_DEBUG("**************************************************");
533 XBT_DEBUG("Exploration depth=%d (pair=%p) (%d interleave)",
534 xbt_fifo_size(mc_stack_liveness_stateful), pair, MC_state_interleave_size(pair->graph_state));
536 if(MC_state_interleave_size(pair->graph_state) == 0){
538 xbt_dynar_reset(enabled_processes);
542 xbt_swag_foreach(process, simix_global->process_list){
543 if(MC_process_is_enabled(process)){
544 xbt_dynar_push(enabled_processes, &process);
545 //XBT_DEBUG("Process : pid=%lu",process->pid);
549 //XBT_DEBUG("Enabled processes before pop : %lu", xbt_dynar_length(enabled_processes));
551 //XBT_DEBUG("Processes already interleaved : %d", pair->interleave);
553 if(xbt_dynar_length(enabled_processes) > 0){
554 for(d=0;d<pair->interleave;d++){
555 xbt_dynar_shift(enabled_processes, NULL);
559 //XBT_DEBUG("Enabled processes after pop : %lu", xbt_dynar_length(enabled_processes));
561 if(pair->fully_expanded == 0){
562 if(xbt_dynar_length(enabled_processes) > 0){
563 MC_state_interleave_process(pair->graph_state, xbt_dynar_get_as(enabled_processes, 0, smx_process_t));
564 //XBT_DEBUG("Interleave process");
573 /* Update statistics */
574 mc_stats_pair->visited_pairs++;
579 xbt_dynar_foreach(pair->propositions, cursor, pato){
580 XBT_DEBUG("%s : %d", pato->id, pato->value);
583 /* Test acceptance pair and acceptance cycle*/
585 if(pair->automaton_state->type == 1){
586 if(search_cycle == 0){
587 set_pair_prop_reached(pair);
588 XBT_DEBUG("Acceptance pair : graph=%p, automaton=%p(%s)", pair->graph_state, pair->automaton_state, pair->automaton_state->id);
590 if(reached_prop(pair) == 1){
591 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
592 XBT_INFO("| ACCEPTANCE CYCLE |");
593 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
594 XBT_INFO("Counter-example that violates formula :");
595 MC_show_stack_liveness_stateful(mc_stack_liveness_stateful);
596 MC_dump_stack_liveness_stateful(mc_stack_liveness_stateful);
597 MC_print_statistics_pairs(mc_stats_pair);
603 /* If there are processes to interleave and the maximum depth has not been reached
604 then perform one step of the exploration algorithm */
605 if (xbt_fifo_size(mc_stack_liveness_stateful) < MAX_DEPTH &&
606 (req = MC_state_get_request(pair->graph_state, &value))) {
608 /* Debug information */
609 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
610 req_str = MC_request_to_string(req, value);
611 XBT_DEBUG("Execute: %s", req_str);
615 MC_state_set_executed_request(pair->graph_state, req, value);
616 //mc_stats_pairs->executed_transitions++;
618 /* Answer the request */
619 SIMIX_request_pre(req, value); /* After this call req is no longer usefull */
621 /* Wait for requests (schedules processes) */
622 MC_wait_for_requests();
624 /* Create the new expanded state */
628 //XBT_DEBUG("Process interleaved in pair %p : %u", pair, MC_state_interleave_size(pair->graph_state));
629 //xbt_dynar_pop(enabled_processes, NULL);
631 next_graph_state = MC_state_new();
633 next_system_state = xbt_new0(s_mc_snapshot_t, 1);
634 MC_take_snapshot(next_system_state);
638 xbt_dynar_foreach(pair->automaton_state->out, cursor, transition_succ){
639 res = MC_automaton_evaluate_label(a, transition_succ->label);
640 if((res == 1) || (res == 2)){ // enabled transition in automaton
641 next_automaton_state = transition_succ->dst;
646 if(next_automaton_state == NULL){
647 next_automaton_state = pair->automaton_state;
652 next_pair = new_pair_prop(next_system_state, next_graph_state, next_automaton_state);
654 xbt_propositional_symbol_t ps;
655 xbt_dynar_foreach(a->propositional_symbols, cursor, ps){
656 int (*f)() = ps->function;
658 mc_prop_ato_t pa = new_proposition(ps->pred, val);
659 xbt_dynar_push(next_pair->propositions, &pa);
660 //XBT_DEBUG("%s : %d", pa->id, pa->value);
662 xbt_fifo_unshift(mc_stack_liveness_stateful, next_pair);
665 if((invisible(pair, next_pair) == 0) && (pair->fully_expanded == 0)){
666 set_fully_expanded(pair);
667 if(xbt_dynar_length(enabled_processes) > 1){ // Si 1 seul process activé, déjà exécuté juste avant donc état complètement étudié
668 xbt_dynar_foreach(enabled_processes, cursor, process){
669 MC_state_interleave_process(pair->graph_state, process);
672 XBT_DEBUG("Pair %p fully expanded (%u interleave)", pair, MC_state_interleave_size(pair->graph_state));
678 /* Let's loop again */
680 /* The interleave set is empty or the maximum depth is reached, let's back-track */
682 XBT_DEBUG("There are no more processes to interleave.");
684 /* Trash the current state, no longer needed */
686 xbt_fifo_shift(mc_stack_liveness_stateful);
687 //MC_state_delete(state);
690 /* Check for deadlocks */
691 if(MC_deadlock_check()){
692 MC_show_deadlock(NULL);
697 /* Traverse the stack backwards until a state with a non empty interleave
698 set is found, deleting all the states that have it empty in the way.
699 For each deleted state, check if the request that has generated it
700 (from it's predecesor state), depends on any other previous request
701 executed before it. If it does then add it to the interleave set of the
702 state that executed that previous request. */
703 while ((pair = xbt_fifo_shift(mc_stack_liveness_stateful)) != NULL) {
704 req = MC_state_get_internal_request(pair->graph_state);
705 xbt_fifo_foreach(mc_stack_liveness_stateful, item, prev_pair, mc_pair_prop_t) {
706 if(MC_request_depend(req, MC_state_get_internal_request(prev_pair->graph_state))){
707 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
708 XBT_DEBUG("Dependent Transitions:");
709 prev_req = MC_state_get_executed_request(prev_pair->graph_state, &value);
710 req_str = MC_request_to_string(prev_req, value);
711 XBT_DEBUG("%s (pair=%p)", req_str, prev_pair);
713 prev_req = MC_state_get_executed_request(pair->graph_state, &value);
714 req_str = MC_request_to_string(prev_req, value);
715 XBT_DEBUG("%s (pair=%p)", req_str, pair);
719 if(prev_pair->fully_expanded == 0){
720 if(!MC_state_process_is_done(prev_pair->graph_state, req->issuer)){
721 MC_state_interleave_process(prev_pair->graph_state, req->issuer);
722 XBT_DEBUG("Process %p (%lu) interleaved in pair %p", req->issuer, req->issuer->pid, prev_pair);
724 XBT_DEBUG("Process %p (%lu) is in done set", req->issuer, req->issuer->pid);
733 if (MC_state_interleave_size(pair->graph_state) > 0) {
734 /* We found a back-tracking point, let's loop */
735 MC_restore_snapshot(pair->system_state);
736 xbt_fifo_unshift(mc_stack_liveness_stateful, pair);
737 XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_stack_liveness_stateful));
741 //MC_state_delete(state);
751 /************ DPOR 3 (invisible and independant transitions with coloration of pairs) ************/
754 xbt_dynar_t reached_pairs_prop_col;
755 xbt_dynar_t visited_pairs_prop_col;
759 mc_pair_prop_col_t new_pair_prop_col(mc_snapshot_t sn, mc_state_t sg, xbt_state_t st){
761 mc_pair_prop_col_t pair = NULL;
762 pair = xbt_new0(s_mc_pair_prop_col_t, 1);
763 pair->system_state = sn;
764 pair->automaton_state = st;
765 pair->graph_state = sg;
766 pair->propositions = xbt_dynar_new(sizeof(mc_prop_ato_t), NULL);
767 pair->fully_expanded = 0;
768 pair->interleave = 0;
770 mc_stats_pair->expanded_pairs++;
771 //XBT_DEBUG("New pair %p : automaton=%p", pair, st);
775 void set_expanded(mc_pair_prop_col_t pair){
776 pair->expanded = expanded;
779 int reached_prop_col(mc_pair_prop_col_t pair){
781 char* hash_reached = malloc(sizeof(char)*160);
785 char *hash = malloc(sizeof(char)*160);
786 xbt_sha((char *)&pair, hash);
787 xbt_dynar_foreach(reached_pairs_prop_col, c, hash_reached){
788 if(strcmp(hash, hash_reached) == 0){
798 void set_pair_prop_col_reached(mc_pair_prop_col_t pair){
800 if(reached_prop_col(pair) == 0){
802 char *hash = malloc(sizeof(char)*160) ;
803 xbt_sha((char *)&pair, hash);
804 xbt_dynar_push(reached_pairs_prop_col, &hash);
810 int invisible_col(mc_pair_prop_col_t p, mc_pair_prop_col_t np){
814 for(i=0;i<xbt_dynar_length(p->propositions); i++){
815 prop1 = xbt_dynar_get_as(p->propositions, i, mc_prop_ato_t);
816 prop2 = xbt_dynar_get_as(np->propositions, i, mc_prop_ato_t);
817 //XBT_DEBUG("test invisible : prop 1 = %s : %d / prop 2 = %s : %d", prop1->id, prop1->value, prop2->id, prop2->value);
818 if(prop1->value != prop2->value)
825 void set_fully_expanded_col(mc_pair_prop_col_t pair){
826 pair->fully_expanded = 1;
830 void set_pair_prop_col_visited(mc_pair_prop_col_t pair, int sc){
833 mc_visited_pair_prop_col_t p = NULL;
834 p = xbt_new0(s_mc_visited_pair_prop_col_t, 1);
836 p->search_cycle = sc;
837 char *hash = malloc(sizeof(char)*160);
838 xbt_sha((char *)&p, hash);
839 xbt_dynar_push(visited_pairs_prop_col, &hash);
844 int visited_pair_prop_col(mc_pair_prop_col_t pair, int sc){
846 char* hash_visited = malloc(sizeof(char)*160);
850 mc_visited_pair_prop_col_t p = NULL;
851 p = xbt_new0(s_mc_visited_pair_prop_col_t, 1);
853 p->search_cycle = sc;
854 char *hash = malloc(sizeof(char)*160);
855 xbt_sha((char *)&p, hash);
856 xbt_dynar_foreach(visited_pairs_prop_col, c, hash_visited){
857 if(strcmp(hash, hash_visited) == 0){
868 void MC_dpor3_init(xbt_automaton_t a)
870 mc_pair_prop_col_t initial_pair = NULL;
871 mc_state_t initial_graph_state = NULL;
872 mc_snapshot_t initial_system_state = NULL;
873 xbt_state_t initial_automaton_state = NULL;
877 initial_graph_state = MC_state_new();
880 /* Wait for requests (schedules processes) */
881 MC_wait_for_requests();
883 unsigned int cursor = 0;
884 unsigned int cursor2 = 0;
885 xbt_state_t automaton_state = NULL;
887 xbt_transition_t transition_succ;
889 xbt_dynar_foreach(a->states, cursor, automaton_state){
890 if(automaton_state->type == -1){
891 xbt_dynar_foreach(automaton_state->out, cursor2, transition_succ){
892 res = MC_automaton_evaluate_label(a, transition_succ->label);
893 if((res == 1) || (res == 2)){
894 initial_automaton_state = transition_succ->dst;
900 if(initial_automaton_state != NULL)
904 if(initial_automaton_state == NULL){
906 xbt_dynar_foreach(a->states, cursor, automaton_state){
907 if(automaton_state->type == -1){
908 initial_automaton_state = automaton_state;
914 reached_pairs_prop_col = xbt_dynar_new(sizeof(char *), NULL);
915 visited_pairs_prop_col = xbt_dynar_new(sizeof(char *), NULL);
916 visible_transitions = xbt_dynar_new(sizeof(s_smx_req_t), NULL);
917 enabled_processes = xbt_dynar_new(sizeof(smx_process_t), NULL);
921 initial_system_state = xbt_new0(s_mc_snapshot_t, 1);
922 MC_take_snapshot(initial_system_state);
923 initial_pair = new_pair_prop_col(initial_system_state, initial_graph_state, initial_automaton_state);
925 xbt_propositional_symbol_t ps;
926 xbt_dynar_foreach(a->propositional_symbols, cursor, ps){
927 int (*f)() = ps->function;
929 mc_prop_ato_t pa = new_proposition(ps->pred, val);
930 xbt_dynar_push(initial_pair->propositions, &pa);
932 xbt_fifo_unshift(mc_stack_liveness_stateful, initial_pair);
936 XBT_DEBUG("**************************************************");
937 XBT_DEBUG("Initial pair");
944 void MC_dpor3(xbt_automaton_t a, int search_cycle)
948 smx_req_t req = NULL, prev_req = NULL;
949 mc_state_t next_graph_state = NULL;
950 mc_snapshot_t next_system_state = NULL;
951 xbt_state_t next_automaton_state = NULL;
952 xbt_transition_t transition_succ;
955 mc_pair_prop_col_t pair = NULL, next_pair = NULL, prev_pair = NULL;
956 smx_process_t process = NULL;
957 xbt_fifo_item_t item = NULL;
961 while (xbt_fifo_size(mc_stack_liveness_stateful) > 0) {
963 /* Get current pair */
964 pair = (mc_pair_prop_col_t)
965 xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_stack_liveness_stateful));
967 XBT_DEBUG("**************************************************");
968 XBT_DEBUG("Exploration depth=%d (pair=%p) (%d interleave)",
969 xbt_fifo_size(mc_stack_liveness_stateful), pair, MC_state_interleave_size(pair->graph_state));
971 if(MC_state_interleave_size(pair->graph_state) == 0){
973 xbt_dynar_reset(enabled_processes);
977 xbt_swag_foreach(process, simix_global->process_list){
978 if(MC_process_is_enabled(process)){
979 xbt_dynar_push(enabled_processes, &process);
980 //XBT_DEBUG("Process : pid=%lu",process->pid);
984 //XBT_DEBUG("Enabled processes before pop : %lu", xbt_dynar_length(enabled_processes));
986 //XBT_DEBUG("Processes already interleaved : %d", pair->interleave);
988 if(xbt_dynar_length(enabled_processes) > 0){
989 for(d=0;d<pair->interleave;d++){
990 xbt_dynar_shift(enabled_processes, NULL);
994 //XBT_DEBUG("Enabled processes after pop : %lu", xbt_dynar_length(enabled_processes));
996 if(pair->fully_expanded == 0){
997 if(xbt_dynar_length(enabled_processes) > 0){
998 MC_state_interleave_process(pair->graph_state, xbt_dynar_get_as(enabled_processes, 0, smx_process_t));
999 //XBT_DEBUG("Interleave process");
1008 /* Update statistics */
1009 mc_stats_pair->visited_pairs++;
1012 /* Test acceptance pair and acceptance cycle*/
1014 if(pair->automaton_state->type == 1){
1015 if(search_cycle == 0){
1016 set_pair_prop_col_reached(pair);
1017 XBT_DEBUG("Acceptance pair : graph=%p, automaton=%p(%s)", pair->graph_state, pair->automaton_state, pair->automaton_state->id);
1019 if(reached_prop_col(pair) == 1){
1020 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
1021 XBT_INFO("| ACCEPTANCE CYCLE |");
1022 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
1023 XBT_INFO("Counter-example that violates formula :");
1024 MC_show_stack_liveness_stateful(mc_stack_liveness_stateful);
1025 MC_dump_stack_liveness_stateful(mc_stack_liveness_stateful);
1026 MC_print_statistics_pairs(mc_stats_pair);
1032 /* If there are processes to interleave and the maximum depth has not been reached
1033 then perform one step of the exploration algorithm */
1034 if (xbt_fifo_size(mc_stack_liveness_stateful) < MAX_DEPTH &&
1035 (req = MC_state_get_request(pair->graph_state, &value))) {
1037 set_pair_prop_col_visited(pair, search_cycle);
1039 /* Debug information */
1040 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
1041 req_str = MC_request_to_string(req, value);
1042 XBT_DEBUG("Execute: %s", req_str);
1046 MC_state_set_executed_request(pair->graph_state, req, value);
1048 /* Answer the request */
1049 SIMIX_request_pre(req, value); /* After this call req is no longer usefull */
1051 /* Wait for requests (schedules processes) */
1052 MC_wait_for_requests();
1054 /* Create the new expanded state */
1059 next_graph_state = MC_state_new();
1061 next_system_state = xbt_new0(s_mc_snapshot_t, 1);
1062 MC_take_snapshot(next_system_state);
1066 xbt_dynar_foreach(pair->automaton_state->out, cursor, transition_succ){
1067 res = MC_automaton_evaluate_label(a, transition_succ->label);
1068 if((res == 1) || (res == 2)){ // enabled transition in automaton
1069 next_automaton_state = transition_succ->dst;
1074 if(next_automaton_state == NULL)
1075 next_automaton_state = pair->automaton_state;
1079 next_pair = new_pair_prop_col(next_system_state, next_graph_state, next_automaton_state);
1081 xbt_propositional_symbol_t ps;
1082 xbt_dynar_foreach(a->propositional_symbols, cursor, ps){
1083 int (*f)() = ps->function;
1085 mc_prop_ato_t pa = new_proposition(ps->pred, val);
1086 xbt_dynar_push(next_pair->propositions, &pa);
1088 xbt_fifo_unshift(mc_stack_liveness_stateful, next_pair);
1091 if((invisible_col(pair, next_pair) == 0) && (pair->fully_expanded == 0)){
1092 set_fully_expanded_col(pair);
1093 if(xbt_dynar_length(enabled_processes) > 1){ // Si 1 seul process activé, déjà exécuté juste avant donc état complètement étudié
1094 xbt_dynar_foreach(enabled_processes, cursor, process){
1095 MC_state_interleave_process(pair->graph_state, process);
1098 XBT_DEBUG("Pair %p fully expanded (%u interleave)", pair, MC_state_interleave_size(pair->graph_state));
1104 /* Let's loop again */
1106 /* The interleave set is empty or the maximum depth is reached, let's back-track */
1108 XBT_DEBUG("There are no more processes to interleave.");
1110 /* Trash the current state, no longer needed */
1112 xbt_fifo_shift(mc_stack_liveness_stateful);
1113 //MC_state_delete(state);
1116 /* Check for deadlocks */
1117 if(MC_deadlock_check()){
1118 MC_show_deadlock(NULL);
1123 /* Traverse the stack backwards until a state with a non empty interleave
1124 set is found, deleting all the states that have it empty in the way.
1125 For each deleted state, check if the request that has generated it
1126 (from it's predecesor state), depends on any other previous request
1127 executed before it. If it does then add it to the interleave set of the
1128 state that executed that previous request. */
1129 while ((pair = xbt_fifo_shift(mc_stack_liveness_stateful)) != NULL) {
1130 req = MC_state_get_internal_request(pair->graph_state);
1131 xbt_fifo_foreach(mc_stack_liveness_stateful, item, prev_pair, mc_pair_prop_col_t) {
1132 if(MC_request_depend(req, MC_state_get_internal_request(prev_pair->graph_state))){
1133 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
1134 XBT_DEBUG("Dependent Transitions:");
1135 prev_req = MC_state_get_executed_request(prev_pair->graph_state, &value);
1136 req_str = MC_request_to_string(prev_req, value);
1137 XBT_DEBUG("%s (pair=%p)", req_str, prev_pair);
1139 prev_req = MC_state_get_executed_request(pair->graph_state, &value);
1140 req_str = MC_request_to_string(prev_req, value);
1141 XBT_DEBUG("%s (pair=%p)", req_str, pair);
1145 if(prev_pair->fully_expanded == 0){
1146 if(!MC_state_process_is_done(prev_pair->graph_state, req->issuer)){
1147 MC_state_interleave_process(prev_pair->graph_state, req->issuer);
1148 XBT_DEBUG("Process %p (%lu) interleaved in pair %p", req->issuer, req->issuer->pid, prev_pair);
1150 XBT_DEBUG("Process %p (%lu) is in done set", req->issuer, req->issuer->pid);
1159 if (MC_state_interleave_size(pair->graph_state) > 0) {
1160 /* We found a back-tracking point, let's loop */
1161 MC_restore_snapshot(pair->system_state);
1162 xbt_fifo_unshift(mc_stack_liveness_stateful, pair);
1163 XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_stack_liveness_stateful));
1167 //MC_state_delete(state);