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, 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) > 0) {
63 /* Get current state */
65 xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_stack));
67 XBT_DEBUG("**************************************************");
68 XBT_DEBUG("Exploration depth=%d (state=%p)(%u interleave)",
69 xbt_fifo_size(mc_stack), 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) < 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, 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);
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)) != NULL) {
140 req = MC_state_get_internal_request(state);
141 xbt_fifo_foreach(mc_stack, 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, state);
166 XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_stack));
171 MC_state_delete(state);
182 /********************* DPOR without replay *********************/
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_snapshot_stack, initial_state);
226 void MC_dpor_stateful(){
228 smx_process_t process = NULL;
230 if(xbt_fifo_size(mc_snapshot_stack) == 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_snapshot_stack) > 0){
246 current_state = (mc_state_ws_t)xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_snapshot_stack));
249 XBT_DEBUG("**************************************************");
250 XBT_DEBUG("Depth : %d, State : %p , %u interleave", xbt_fifo_size(mc_snapshot_stack),current_state, MC_state_interleave_size(current_state->graph_state));
252 mc_stats->visited_states++;
255 if((xbt_fifo_size(mc_snapshot_stack) < MAX_DEPTH) && (req = MC_state_get_request(current_state->graph_state, &value))){
257 /* Debug information */
258 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
259 req_str = MC_request_to_string(req, value);
260 XBT_DEBUG("Execute: %s", req_str);
264 MC_state_set_executed_request(current_state->graph_state, req, value);
265 mc_stats->executed_transitions++;
267 /* Answer the request */
268 SIMIX_request_pre(req, value);
270 /* Wait for requests (schedules processes) */
271 MC_wait_for_requests();
273 /* Create the new expanded graph_state */
276 next_graph_state = MC_state_new();
278 /* Get an enabled process and insert it in the interleave set of the next graph_state */
279 xbt_swag_foreach(process, simix_global->process_list){
280 if(MC_process_is_enabled(process)){
281 MC_state_interleave_process(next_graph_state, process);
286 next_snapshot = xbt_new0(s_mc_snapshot_t, 1);
287 MC_take_snapshot(next_snapshot);
289 next_state = new_state_ws(next_snapshot, next_graph_state);
290 xbt_fifo_unshift(mc_snapshot_stack, next_state);
295 XBT_DEBUG("There are no more processes to interleave.");
297 /* Trash the current state, no longer needed */
299 xbt_fifo_shift(mc_snapshot_stack);
302 /* Check for deadlocks */
303 if(MC_deadlock_check()){
304 MC_show_deadlock_stateful(NULL);
309 while((current_state = xbt_fifo_shift(mc_snapshot_stack)) != NULL){
310 req = MC_state_get_internal_request(current_state->graph_state);
311 xbt_fifo_foreach(mc_snapshot_stack, item, prev_state, mc_state_ws_t) {
312 if(MC_request_depend(req, MC_state_get_internal_request(prev_state->graph_state))){
313 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
314 XBT_DEBUG("Dependent Transitions:");
315 prev_req = MC_state_get_executed_request(prev_state->graph_state, &value);
316 req_str = MC_request_to_string(prev_req, value);
317 XBT_DEBUG("%s (state=%p)", req_str, prev_state->graph_state);
319 prev_req = MC_state_get_executed_request(current_state->graph_state, &value);
320 req_str = MC_request_to_string(prev_req, value);
321 XBT_DEBUG("%s (state=%p)", req_str, current_state->graph_state);
325 if(!MC_state_process_is_done(prev_state->graph_state, req->issuer)){
326 MC_state_interleave_process(prev_state->graph_state, req->issuer);
329 XBT_DEBUG("Process %p is in done set", req->issuer);
336 if(MC_state_interleave_size(current_state->graph_state)){
337 MC_restore_snapshot(current_state->system_state);
338 xbt_fifo_unshift(mc_snapshot_stack, current_state);
339 XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_snapshot_stack));
355 /************ DPOR 2 (invisible and independant transitions) ************/
357 xbt_dynar_t reached_pairs_prop;
358 xbt_dynar_t visible_transitions;
359 xbt_dynar_t enabled_processes;
361 mc_prop_ato_t new_proposition(char* id, int value){
362 mc_prop_ato_t prop = NULL;
363 prop = xbt_new0(s_mc_prop_ato_t, 1);
364 prop->id = strdup(id);
369 mc_pair_prop_t new_pair_prop(mc_snapshot_t sn, mc_state_t sg, xbt_state_t st){
370 mc_pair_prop_t pair = NULL;
371 pair = xbt_new0(s_mc_pair_prop_t, 1);
372 pair->system_state = sn;
373 pair->automaton_state = st;
374 pair->graph_state = sg;
375 pair->propositions = xbt_dynar_new(sizeof(mc_prop_ato_t), NULL);
376 pair->fully_expanded = 0;
377 pair->interleave = 0;
378 mc_stats_pair->expanded_pairs++;
382 int reached_prop(mc_pair_prop_t pair){
384 char* hash_reached = malloc(sizeof(char)*160);
388 char *hash = malloc(sizeof(char)*160);
389 xbt_sha((char *)&pair, hash);
390 xbt_dynar_foreach(reached_pairs_prop, c, hash_reached){
391 if(strcmp(hash, hash_reached) == 0){
401 void set_pair_prop_reached(mc_pair_prop_t pair){
403 if(reached_prop(pair) == 0){
405 char *hash = malloc(sizeof(char)*160) ;
406 xbt_sha((char *)&pair, hash);
407 xbt_dynar_push(reached_pairs_prop, &hash);
413 int invisible(mc_pair_prop_t p, mc_pair_prop_t np){
417 for(i=0;i<xbt_dynar_length(p->propositions); i++){
418 prop1 = xbt_dynar_get_as(p->propositions, i, mc_prop_ato_t);
419 prop2 = xbt_dynar_get_as(np->propositions, i, mc_prop_ato_t);
420 //XBT_DEBUG("test invisible : prop 1 = %s : %d / prop 2 = %s : %d", prop1->id, prop1->value, prop2->id, prop2->value);
421 if(prop1->value != prop2->value)
428 void set_fully_expanded(mc_pair_prop_t pair){
429 pair->fully_expanded = 1;
432 void MC_dpor2_init(xbt_automaton_t a)
434 mc_pair_prop_t initial_pair = NULL;
435 mc_state_t initial_graph_state = NULL;
436 mc_snapshot_t initial_system_state = NULL;
437 xbt_state_t initial_automaton_state = NULL;
441 initial_graph_state = MC_state_new();
444 /* Wait for requests (schedules processes) */
445 MC_wait_for_requests();
447 unsigned int cursor = 0;
448 unsigned int cursor2 = 0;
449 xbt_state_t automaton_state = NULL;
451 xbt_transition_t transition_succ;
453 xbt_dynar_foreach(a->states, cursor, automaton_state){
454 if(automaton_state->type == -1){
455 xbt_dynar_foreach(automaton_state->out, cursor2, transition_succ){
456 res = MC_automaton_evaluate_label(a, transition_succ->label);
457 if((res == 1) || (res == 2)){
458 initial_automaton_state = transition_succ->dst;
464 if(xbt_fifo_size(mc_snapshot_stack) > 0)
468 if(xbt_fifo_size(mc_snapshot_stack) == 0){
470 xbt_dynar_foreach(a->states, cursor, automaton_state){
471 if(automaton_state->type == -1){
472 initial_automaton_state = automaton_state;
478 reached_pairs_prop = xbt_dynar_new(sizeof(char *), NULL);
479 visible_transitions = xbt_dynar_new(sizeof(s_smx_req_t), NULL);
480 enabled_processes = xbt_dynar_new(sizeof(smx_process_t), NULL);
483 initial_system_state = xbt_new0(s_mc_snapshot_t, 1);
484 MC_take_snapshot(initial_system_state);
485 initial_pair = new_pair_prop(initial_system_state, initial_graph_state, initial_automaton_state);
487 xbt_propositional_symbol_t ps;
488 xbt_dynar_foreach(a->propositional_symbols, cursor, ps){
489 int (*f)() = ps->function;
491 mc_prop_ato_t pa = new_proposition(ps->pred, val);
492 xbt_dynar_push(initial_pair->propositions, &pa);
494 xbt_fifo_unshift(mc_snapshot_stack, initial_pair);
498 XBT_DEBUG("**************************************************");
499 XBT_DEBUG("Initial pair");
506 void MC_dpor2(xbt_automaton_t a, int search_cycle)
510 smx_req_t req = NULL, prev_req = NULL;
511 mc_state_t next_graph_state = NULL;
512 mc_snapshot_t next_system_state = NULL;
513 xbt_state_t next_automaton_state = NULL;
514 xbt_transition_t transition_succ;
517 mc_pair_prop_t pair = NULL, next_pair = NULL, prev_pair = NULL;
518 smx_process_t process = NULL;
519 xbt_fifo_item_t item = NULL;
523 while (xbt_fifo_size(mc_snapshot_stack) > 0) {
525 /* Get current pair */
526 pair = (mc_pair_prop_t)
527 xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_snapshot_stack));
529 XBT_DEBUG("**************************************************");
530 XBT_DEBUG("Exploration depth=%d (pair=%p) (%d interleave)",
531 xbt_fifo_size(mc_snapshot_stack), pair, MC_state_interleave_size(pair->graph_state));
533 if(MC_state_interleave_size(pair->graph_state) == 0){
535 xbt_dynar_reset(enabled_processes);
539 xbt_swag_foreach(process, simix_global->process_list){
540 if(MC_process_is_enabled(process)){
541 xbt_dynar_push(enabled_processes, &process);
542 //XBT_DEBUG("Process : pid=%lu",process->pid);
546 //XBT_DEBUG("Enabled processes before pop : %lu", xbt_dynar_length(enabled_processes));
548 //XBT_DEBUG("Processes already interleaved : %d", pair->interleave);
550 if(xbt_dynar_length(enabled_processes) > 0){
551 for(d=0;d<pair->interleave;d++){
552 xbt_dynar_shift(enabled_processes, NULL);
556 //XBT_DEBUG("Enabled processes after pop : %lu", xbt_dynar_length(enabled_processes));
558 if(pair->fully_expanded == 0){
559 if(xbt_dynar_length(enabled_processes) > 0){
560 MC_state_interleave_process(pair->graph_state, xbt_dynar_get_as(enabled_processes, 0, smx_process_t));
561 //XBT_DEBUG("Interleave process");
570 /* Update statistics */
571 mc_stats_pair->visited_pairs++;
576 xbt_dynar_foreach(pair->propositions, cursor, pato){
577 XBT_DEBUG("%s : %d", pato->id, pato->value);
580 /* Test acceptance pair and acceptance cycle*/
582 if(pair->automaton_state->type == 1){
583 if(search_cycle == 0){
584 set_pair_prop_reached(pair);
585 XBT_DEBUG("Acceptance pair : graph=%p, automaton=%p(%s)", pair->graph_state, pair->automaton_state, pair->automaton_state->id);
587 if(reached_prop(pair) == 1){
588 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
589 XBT_INFO("| ACCEPTANCE CYCLE |");
590 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
591 XBT_INFO("Counter-example that violates formula :");
592 MC_show_snapshot_stack(mc_snapshot_stack);
593 MC_dump_snapshot_stack(mc_snapshot_stack);
594 MC_print_statistics_pairs(mc_stats_pair);
600 /* If there are processes to interleave and the maximum depth has not been reached
601 then perform one step of the exploration algorithm */
602 if (xbt_fifo_size(mc_snapshot_stack) < MAX_DEPTH &&
603 (req = MC_state_get_request(pair->graph_state, &value))) {
605 /* Debug information */
606 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
607 req_str = MC_request_to_string(req, value);
608 XBT_DEBUG("Execute: %s", req_str);
612 MC_state_set_executed_request(pair->graph_state, req, value);
613 //mc_stats_pairs->executed_transitions++;
615 /* Answer the request */
616 SIMIX_request_pre(req, value); /* After this call req is no longer usefull */
618 /* Wait for requests (schedules processes) */
619 MC_wait_for_requests();
621 /* Create the new expanded state */
625 //XBT_DEBUG("Process interleaved in pair %p : %u", pair, MC_state_interleave_size(pair->graph_state));
626 //xbt_dynar_pop(enabled_processes, NULL);
628 next_graph_state = MC_state_new();
630 next_system_state = xbt_new0(s_mc_snapshot_t, 1);
631 MC_take_snapshot(next_system_state);
635 xbt_dynar_foreach(pair->automaton_state->out, cursor, transition_succ){
636 res = MC_automaton_evaluate_label(a, transition_succ->label);
637 if((res == 1) || (res == 2)){ // enabled transition in automaton
638 next_automaton_state = transition_succ->dst;
643 if(next_automaton_state == NULL){
644 next_automaton_state = pair->automaton_state;
649 next_pair = new_pair_prop(next_system_state, next_graph_state, next_automaton_state);
651 xbt_propositional_symbol_t ps;
652 xbt_dynar_foreach(a->propositional_symbols, cursor, ps){
653 int (*f)() = ps->function;
655 mc_prop_ato_t pa = new_proposition(ps->pred, val);
656 xbt_dynar_push(next_pair->propositions, &pa);
657 //XBT_DEBUG("%s : %d", pa->id, pa->value);
659 xbt_fifo_unshift(mc_snapshot_stack, next_pair);
662 if((invisible(pair, next_pair) == 0) && (pair->fully_expanded == 0)){
663 set_fully_expanded(pair);
664 if(xbt_dynar_length(enabled_processes) > 1){ // Si 1 seul process activé, déjà exécuté juste avant donc état complètement étudié
665 xbt_dynar_foreach(enabled_processes, cursor, process){
666 MC_state_interleave_process(pair->graph_state, process);
669 XBT_DEBUG("Pair %p fully expanded (%u interleave)", pair, MC_state_interleave_size(pair->graph_state));
675 /* Let's loop again */
677 /* The interleave set is empty or the maximum depth is reached, let's back-track */
679 XBT_DEBUG("There are no more processes to interleave.");
681 /* Trash the current state, no longer needed */
683 xbt_fifo_shift(mc_snapshot_stack);
684 //MC_state_delete(state);
687 /* Check for deadlocks */
688 if(MC_deadlock_check()){
689 MC_show_deadlock(NULL);
694 /* Traverse the stack backwards until a state with a non empty interleave
695 set is found, deleting all the states that have it empty in the way.
696 For each deleted state, check if the request that has generated it
697 (from it's predecesor state), depends on any other previous request
698 executed before it. If it does then add it to the interleave set of the
699 state that executed that previous request. */
700 while ((pair = xbt_fifo_shift(mc_snapshot_stack)) != NULL) {
701 req = MC_state_get_internal_request(pair->graph_state);
702 xbt_fifo_foreach(mc_snapshot_stack, item, prev_pair, mc_pair_prop_t) {
703 if(MC_request_depend(req, MC_state_get_internal_request(prev_pair->graph_state))){
704 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
705 XBT_DEBUG("Dependent Transitions:");
706 prev_req = MC_state_get_executed_request(prev_pair->graph_state, &value);
707 req_str = MC_request_to_string(prev_req, value);
708 XBT_DEBUG("%s (pair=%p)", req_str, prev_pair);
710 prev_req = MC_state_get_executed_request(pair->graph_state, &value);
711 req_str = MC_request_to_string(prev_req, value);
712 XBT_DEBUG("%s (pair=%p)", req_str, pair);
716 if(prev_pair->fully_expanded == 0){
717 if(!MC_state_process_is_done(prev_pair->graph_state, req->issuer)){
718 MC_state_interleave_process(prev_pair->graph_state, req->issuer);
719 XBT_DEBUG("Process %p (%lu) interleaved in pair %p", req->issuer, req->issuer->pid, prev_pair);
721 XBT_DEBUG("Process %p (%lu) is in done set", req->issuer, req->issuer->pid);
730 if (MC_state_interleave_size(pair->graph_state) > 0) {
731 /* We found a back-tracking point, let's loop */
732 MC_restore_snapshot(pair->system_state);
733 xbt_fifo_unshift(mc_snapshot_stack, pair);
734 XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_snapshot_stack));
738 //MC_state_delete(state);
748 /************ DPOR 3 (invisible and independant transitions with coloration of pairs) ************/
751 xbt_dynar_t reached_pairs_prop_col;
752 xbt_dynar_t visited_pairs_prop_col;
756 mc_pair_prop_col_t new_pair_prop_col(mc_snapshot_t sn, mc_state_t sg, xbt_state_t st){
758 mc_pair_prop_col_t pair = NULL;
759 pair = xbt_new0(s_mc_pair_prop_col_t, 1);
760 pair->system_state = sn;
761 pair->automaton_state = st;
762 pair->graph_state = sg;
763 pair->propositions = xbt_dynar_new(sizeof(mc_prop_ato_t), NULL);
764 pair->fully_expanded = 0;
765 pair->interleave = 0;
767 mc_stats_pair->expanded_pairs++;
768 //XBT_DEBUG("New pair %p : automaton=%p", pair, st);
772 void set_expanded(mc_pair_prop_col_t pair){
773 pair->expanded = expanded;
776 int reached_prop_col(mc_pair_prop_col_t pair){
778 char* hash_reached = malloc(sizeof(char)*160);
782 char *hash = malloc(sizeof(char)*160);
783 xbt_sha((char *)&pair, hash);
784 xbt_dynar_foreach(reached_pairs_prop_col, c, hash_reached){
785 if(strcmp(hash, hash_reached) == 0){
795 void set_pair_prop_col_reached(mc_pair_prop_col_t pair){
797 if(reached_prop_col(pair) == 0){
799 char *hash = malloc(sizeof(char)*160) ;
800 xbt_sha((char *)&pair, hash);
801 xbt_dynar_push(reached_pairs_prop_col, &hash);
807 int invisible_col(mc_pair_prop_col_t p, mc_pair_prop_col_t np){
811 for(i=0;i<xbt_dynar_length(p->propositions); i++){
812 prop1 = xbt_dynar_get_as(p->propositions, i, mc_prop_ato_t);
813 prop2 = xbt_dynar_get_as(np->propositions, i, mc_prop_ato_t);
814 //XBT_DEBUG("test invisible : prop 1 = %s : %d / prop 2 = %s : %d", prop1->id, prop1->value, prop2->id, prop2->value);
815 if(prop1->value != prop2->value)
822 void set_fully_expanded_col(mc_pair_prop_col_t pair){
823 pair->fully_expanded = 1;
827 void set_pair_prop_col_visited(mc_pair_prop_col_t pair, int sc){
830 mc_visited_pair_prop_col_t p = NULL;
831 p = xbt_new0(s_mc_visited_pair_prop_col_t, 1);
833 p->search_cycle = sc;
834 char *hash = malloc(sizeof(char)*160);
835 xbt_sha((char *)&p, hash);
836 xbt_dynar_push(visited_pairs_prop_col, &hash);
841 int visited_pair_prop_col(mc_pair_prop_col_t pair, int sc){
843 char* hash_visited = malloc(sizeof(char)*160);
847 mc_visited_pair_prop_col_t p = NULL;
848 p = xbt_new0(s_mc_visited_pair_prop_col_t, 1);
850 p->search_cycle = sc;
851 char *hash = malloc(sizeof(char)*160);
852 xbt_sha((char *)&p, hash);
853 xbt_dynar_foreach(visited_pairs_prop_col, c, hash_visited){
854 if(strcmp(hash, hash_visited) == 0){
865 void MC_dpor3_init(xbt_automaton_t a)
867 mc_pair_prop_col_t initial_pair = NULL;
868 mc_state_t initial_graph_state = NULL;
869 mc_snapshot_t initial_system_state = NULL;
870 xbt_state_t initial_automaton_state = NULL;
874 initial_graph_state = MC_state_new();
877 /* Wait for requests (schedules processes) */
878 MC_wait_for_requests();
880 unsigned int cursor = 0;
881 unsigned int cursor2 = 0;
882 xbt_state_t automaton_state = NULL;
884 xbt_transition_t transition_succ;
886 xbt_dynar_foreach(a->states, cursor, automaton_state){
887 if(automaton_state->type == -1){
888 xbt_dynar_foreach(automaton_state->out, cursor2, transition_succ){
889 res = MC_automaton_evaluate_label(a, transition_succ->label);
890 if((res == 1) || (res == 2)){
891 initial_automaton_state = transition_succ->dst;
897 if(initial_automaton_state != NULL)
901 if(initial_automaton_state == NULL){
903 xbt_dynar_foreach(a->states, cursor, automaton_state){
904 if(automaton_state->type == -1){
905 initial_automaton_state = automaton_state;
911 reached_pairs_prop_col = xbt_dynar_new(sizeof(char *), NULL);
912 visited_pairs_prop_col = xbt_dynar_new(sizeof(char *), NULL);
913 visible_transitions = xbt_dynar_new(sizeof(s_smx_req_t), NULL);
914 enabled_processes = xbt_dynar_new(sizeof(smx_process_t), NULL);
918 initial_system_state = xbt_new0(s_mc_snapshot_t, 1);
919 MC_take_snapshot(initial_system_state);
920 initial_pair = new_pair_prop_col(initial_system_state, initial_graph_state, initial_automaton_state);
922 xbt_propositional_symbol_t ps;
923 xbt_dynar_foreach(a->propositional_symbols, cursor, ps){
924 int (*f)() = ps->function;
926 mc_prop_ato_t pa = new_proposition(ps->pred, val);
927 xbt_dynar_push(initial_pair->propositions, &pa);
929 xbt_fifo_unshift(mc_snapshot_stack, initial_pair);
933 XBT_DEBUG("**************************************************");
934 XBT_DEBUG("Initial pair");
941 void MC_dpor3(xbt_automaton_t a, int search_cycle)
945 smx_req_t req = NULL, prev_req = NULL;
946 mc_state_t next_graph_state = NULL;
947 mc_snapshot_t next_system_state = NULL;
948 xbt_state_t next_automaton_state = NULL;
949 xbt_transition_t transition_succ;
952 mc_pair_prop_col_t pair = NULL, next_pair = NULL, prev_pair = NULL;
953 smx_process_t process = NULL;
954 xbt_fifo_item_t item = NULL;
958 while (xbt_fifo_size(mc_snapshot_stack) > 0) {
960 /* Get current pair */
961 pair = (mc_pair_prop_col_t)
962 xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_snapshot_stack));
964 XBT_DEBUG("**************************************************");
965 XBT_DEBUG("Exploration depth=%d (pair=%p) (%d interleave)",
966 xbt_fifo_size(mc_snapshot_stack), pair, MC_state_interleave_size(pair->graph_state));
968 if(MC_state_interleave_size(pair->graph_state) == 0){
970 xbt_dynar_reset(enabled_processes);
974 xbt_swag_foreach(process, simix_global->process_list){
975 if(MC_process_is_enabled(process)){
976 xbt_dynar_push(enabled_processes, &process);
977 //XBT_DEBUG("Process : pid=%lu",process->pid);
981 //XBT_DEBUG("Enabled processes before pop : %lu", xbt_dynar_length(enabled_processes));
983 //XBT_DEBUG("Processes already interleaved : %d", pair->interleave);
985 if(xbt_dynar_length(enabled_processes) > 0){
986 for(d=0;d<pair->interleave;d++){
987 xbt_dynar_shift(enabled_processes, NULL);
991 //XBT_DEBUG("Enabled processes after pop : %lu", xbt_dynar_length(enabled_processes));
993 if(pair->fully_expanded == 0){
994 if(xbt_dynar_length(enabled_processes) > 0){
995 MC_state_interleave_process(pair->graph_state, xbt_dynar_get_as(enabled_processes, 0, smx_process_t));
996 //XBT_DEBUG("Interleave process");
1005 /* Update statistics */
1006 mc_stats_pair->visited_pairs++;
1009 /* Test acceptance pair and acceptance cycle*/
1011 if(pair->automaton_state->type == 1){
1012 if(search_cycle == 0){
1013 set_pair_prop_col_reached(pair);
1014 XBT_DEBUG("Acceptance pair : graph=%p, automaton=%p(%s)", pair->graph_state, pair->automaton_state, pair->automaton_state->id);
1016 if(reached_prop_col(pair) == 1){
1017 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
1018 XBT_INFO("| ACCEPTANCE CYCLE |");
1019 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
1020 XBT_INFO("Counter-example that violates formula :");
1021 MC_show_snapshot_stack(mc_snapshot_stack);
1022 MC_dump_snapshot_stack(mc_snapshot_stack);
1023 MC_print_statistics_pairs(mc_stats_pair);
1029 /* If there are processes to interleave and the maximum depth has not been reached
1030 then perform one step of the exploration algorithm */
1031 if (xbt_fifo_size(mc_snapshot_stack) < MAX_DEPTH &&
1032 (req = MC_state_get_request(pair->graph_state, &value))) {
1034 set_pair_prop_col_visited(pair, search_cycle);
1036 /* Debug information */
1037 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
1038 req_str = MC_request_to_string(req, value);
1039 XBT_DEBUG("Execute: %s", req_str);
1043 MC_state_set_executed_request(pair->graph_state, req, value);
1045 /* Answer the request */
1046 SIMIX_request_pre(req, value); /* After this call req is no longer usefull */
1048 /* Wait for requests (schedules processes) */
1049 MC_wait_for_requests();
1051 /* Create the new expanded state */
1056 next_graph_state = MC_state_new();
1058 next_system_state = xbt_new0(s_mc_snapshot_t, 1);
1059 MC_take_snapshot(next_system_state);
1063 xbt_dynar_foreach(pair->automaton_state->out, cursor, transition_succ){
1064 res = MC_automaton_evaluate_label(a, transition_succ->label);
1065 if((res == 1) || (res == 2)){ // enabled transition in automaton
1066 next_automaton_state = transition_succ->dst;
1071 if(next_automaton_state == NULL)
1072 next_automaton_state = pair->automaton_state;
1076 next_pair = new_pair_prop_col(next_system_state, next_graph_state, next_automaton_state);
1078 xbt_propositional_symbol_t ps;
1079 xbt_dynar_foreach(a->propositional_symbols, cursor, ps){
1080 int (*f)() = ps->function;
1082 mc_prop_ato_t pa = new_proposition(ps->pred, val);
1083 xbt_dynar_push(next_pair->propositions, &pa);
1085 xbt_fifo_unshift(mc_snapshot_stack, next_pair);
1088 if((invisible_col(pair, next_pair) == 0) && (pair->fully_expanded == 0)){
1089 set_fully_expanded_col(pair);
1090 if(xbt_dynar_length(enabled_processes) > 1){ // Si 1 seul process activé, déjà exécuté juste avant donc état complètement étudié
1091 xbt_dynar_foreach(enabled_processes, cursor, process){
1092 MC_state_interleave_process(pair->graph_state, process);
1095 XBT_DEBUG("Pair %p fully expanded (%u interleave)", pair, MC_state_interleave_size(pair->graph_state));
1101 /* Let's loop again */
1103 /* The interleave set is empty or the maximum depth is reached, let's back-track */
1105 XBT_DEBUG("There are no more processes to interleave.");
1107 /* Trash the current state, no longer needed */
1109 xbt_fifo_shift(mc_snapshot_stack);
1110 //MC_state_delete(state);
1113 /* Check for deadlocks */
1114 if(MC_deadlock_check()){
1115 MC_show_deadlock(NULL);
1120 /* Traverse the stack backwards until a state with a non empty interleave
1121 set is found, deleting all the states that have it empty in the way.
1122 For each deleted state, check if the request that has generated it
1123 (from it's predecesor state), depends on any other previous request
1124 executed before it. If it does then add it to the interleave set of the
1125 state that executed that previous request. */
1126 while ((pair = xbt_fifo_shift(mc_snapshot_stack)) != NULL) {
1127 req = MC_state_get_internal_request(pair->graph_state);
1128 xbt_fifo_foreach(mc_snapshot_stack, item, prev_pair, mc_pair_prop_col_t) {
1129 if(MC_request_depend(req, MC_state_get_internal_request(prev_pair->graph_state))){
1130 if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
1131 XBT_DEBUG("Dependent Transitions:");
1132 prev_req = MC_state_get_executed_request(prev_pair->graph_state, &value);
1133 req_str = MC_request_to_string(prev_req, value);
1134 XBT_DEBUG("%s (pair=%p)", req_str, prev_pair);
1136 prev_req = MC_state_get_executed_request(pair->graph_state, &value);
1137 req_str = MC_request_to_string(prev_req, value);
1138 XBT_DEBUG("%s (pair=%p)", req_str, pair);
1142 if(prev_pair->fully_expanded == 0){
1143 if(!MC_state_process_is_done(prev_pair->graph_state, req->issuer)){
1144 MC_state_interleave_process(prev_pair->graph_state, req->issuer);
1145 XBT_DEBUG("Process %p (%lu) interleaved in pair %p", req->issuer, req->issuer->pid, prev_pair);
1147 XBT_DEBUG("Process %p (%lu) is in done set", req->issuer, req->issuer->pid);
1156 if (MC_state_interleave_size(pair->graph_state) > 0) {
1157 /* We found a back-tracking point, let's loop */
1158 MC_restore_snapshot(pair->system_state);
1159 xbt_fifo_unshift(mc_snapshot_stack, pair);
1160 XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_snapshot_stack));
1164 //MC_state_delete(state);