Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
077e8faf9fc5e86119ae7eaa5e9225fadb0970b8
[simgrid.git] / src / mc / mc_dpor.c
1 /* Copyright (c) 2008 Martin Quinson, Cristian Rosa.
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 "private.h"
8
9 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dpor, mc,
10                                 "Logging specific to MC DPOR exploration");
11
12 /**
13  *  \brief Initialize the DPOR exploration algorithm
14  */
15 void MC_dpor_init()
16 {
17   mc_state_t initial_state = NULL;
18   smx_process_t process;
19   
20   /* Create the initial state and push it into the exploration stack */
21   MC_SET_RAW_MEM;
22   initial_state = MC_state_new();
23   xbt_fifo_unshift(mc_stack, initial_state);
24   MC_UNSET_RAW_MEM;
25
26   XBT_DEBUG("**************************************************");
27   XBT_DEBUG("Initial state");
28
29   /* Wait for requests (schedules processes) */
30   MC_wait_for_requests();
31
32   MC_SET_RAW_MEM;
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);
37       break;
38     }
39   }
40   MC_UNSET_RAW_MEM;
41     
42   /* FIXME: Update Statistics 
43   mc_stats->state_size +=
44       xbt_setset_set_size(initial_state->enabled_transitions); */
45 }
46
47
48 /**
49  *      \brief Perform the model-checking operation using a depth-first search exploration
50  *         with Dynamic Partial Order Reductions
51  */
52 void MC_dpor(void)
53 {
54   char *req_str;
55   int value;
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;
60
61   while (xbt_fifo_size(mc_stack) > 0) {
62
63     /* Get current state */
64     state = (mc_state_t) 
65       xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_stack));
66
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));
71
72     /* Update statistics */
73     mc_stats->visited_states++;
74
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))) {
79
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);
84         xbt_free(req_str);
85       }
86
87       MC_state_set_executed_request(state, req, value);
88       mc_stats->executed_transitions++;
89
90       /* Answer the request */
91       SIMIX_request_pre(req, value); /* After this call req is no longer usefull */
92
93       /* Wait for requests (schedules processes) */
94       MC_wait_for_requests();
95
96       /* Create the new expanded state */
97       MC_SET_RAW_MEM;
98       next_state = MC_state_new();
99       xbt_fifo_unshift(mc_stack, next_state);
100
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);
105           break;
106         }
107       }
108       MC_UNSET_RAW_MEM;
109
110       /* FIXME: Update Statistics
111       mc_stats->state_size +=
112           xbt_setset_set_size(next_state->enabled_transitions);*/
113
114       /* Let's loop again */
115
116       /* The interleave set is empty or the maximum depth is reached, let's back-track */
117     } else {
118       XBT_DEBUG("There are no more processes to interleave.");
119
120       /* Trash the current state, no longer needed */
121       MC_SET_RAW_MEM;
122       xbt_fifo_shift(mc_stack);
123       MC_state_delete(state);
124       MC_UNSET_RAW_MEM;
125
126       /* Check for deadlocks */
127       if(MC_deadlock_check()){
128         MC_show_deadlock(NULL);
129         return;
130       }
131
132       MC_SET_RAW_MEM;
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);
148               xbt_free(req_str);
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);
152               xbt_free(req_str);              
153             }
154
155             if(!MC_state_process_is_done(prev_state, req->issuer))
156               MC_state_interleave_process(prev_state, req->issuer);
157             else
158               XBT_DEBUG("Process %p is in done set", req->issuer);
159
160             break;
161           }
162         }
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));
167           MC_UNSET_RAW_MEM;
168           MC_replay(mc_stack);
169           break;
170         } else {
171           MC_state_delete(state);
172         }
173       }
174       MC_UNSET_RAW_MEM;
175     }
176   }
177   MC_UNSET_RAW_MEM;
178   return;
179 }
180
181
182 /********************* DPOR without replay *********************/
183
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;
189   return sws;
190 }
191
192 void MC_dpor_with_restore_snapshot_init(){
193
194   XBT_DEBUG("**************************************************");
195   XBT_DEBUG("DPOR (with restore snapshot) init");
196   XBT_DEBUG("**************************************************");
197
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 ;
202   
203   MC_wait_for_requests();
204
205   MC_SET_RAW_MEM;
206
207   initial_system_snapshot = xbt_new0(s_mc_snapshot_t, 1);
208
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);
213       break;
214     }
215   }
216
217   MC_take_snapshot(initial_system_snapshot);
218
219   initial_state = new_state_ws(initial_system_snapshot, initial_graph_state);
220   xbt_fifo_unshift(mc_snapshot_stack, initial_state);
221
222   MC_UNSET_RAW_MEM;
223           
224   MC_dpor_with_restore_snapshot();
225
226 }
227
228 void MC_dpor_with_restore_snapshot(){
229
230   smx_process_t process = NULL;
231   
232   if(xbt_fifo_size(mc_snapshot_stack) == 0)
233     return;
234
235   int value;
236   mc_state_t next_graph_state = NULL;
237   smx_req_t req = NULL, prev_req = NULL;
238   char *req_str;
239   xbt_fifo_item_t item = NULL;
240
241   mc_snapshot_t next_snapshot;
242   mc_state_ws_t current_state;
243   mc_state_ws_t prev_state;
244   mc_state_ws_t next_state;
245  
246   while(xbt_fifo_size(mc_snapshot_stack) > 0){
247
248     current_state = (mc_state_ws_t)xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_snapshot_stack));
249
250     
251     XBT_DEBUG("**************************************************");
252     XBT_DEBUG("Depth : %d, State : %p , %u interleave", xbt_fifo_size(mc_snapshot_stack),current_state, MC_state_interleave_size(current_state->graph_state));
253     
254
255     if((xbt_fifo_size(mc_snapshot_stack) < MAX_DEPTH) && (req = MC_state_get_request(current_state->graph_state, &value))){
256
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);
261         xbt_free(req_str);
262       }
263
264       MC_state_set_executed_request(current_state->graph_state, req, value);
265
266       /* Answer the request */
267       SIMIX_request_pre(req, value);
268       
269       /* Wait for requests (schedules processes) */
270       MC_wait_for_requests();
271       
272       /* Create the new expanded graph_state */
273       MC_SET_RAW_MEM;
274       
275       next_graph_state = MC_state_new();
276       
277       /* Get an enabled process and insert it in the interleave set of the next graph_state */
278       xbt_swag_foreach(process, simix_global->process_list){
279         if(MC_process_is_enabled(process)){
280           MC_state_interleave_process(next_graph_state, process);
281           break;
282         }
283       }
284
285       next_snapshot = xbt_new0(s_mc_snapshot_t, 1);
286       MC_take_snapshot(next_snapshot);
287
288       next_state = new_state_ws(next_snapshot, next_graph_state);
289       xbt_fifo_unshift(mc_snapshot_stack, next_state);
290       
291       MC_UNSET_RAW_MEM;
292
293     }else{
294       XBT_DEBUG("There are no more processes to interleave.");
295       
296       /* Trash the current state, no longer needed */
297       MC_SET_RAW_MEM;
298       xbt_fifo_shift(mc_snapshot_stack);
299       MC_UNSET_RAW_MEM;
300
301       while((current_state = xbt_fifo_shift(mc_snapshot_stack)) != NULL){
302         req = MC_state_get_internal_request(current_state->graph_state);
303         xbt_fifo_foreach(mc_snapshot_stack, item, prev_state, mc_state_ws_t) {
304           if(MC_request_depend(req, MC_state_get_internal_request(prev_state->graph_state))){
305             if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
306               XBT_DEBUG("Dependent Transitions:");
307               prev_req = MC_state_get_executed_request(prev_state->graph_state, &value);
308               req_str = MC_request_to_string(prev_req, value);
309               XBT_DEBUG("%s (state=%p)", req_str, prev_state->graph_state);
310               xbt_free(req_str);
311               prev_req = MC_state_get_executed_request(current_state->graph_state, &value);
312               req_str = MC_request_to_string(prev_req, value);
313               XBT_DEBUG("%s (state=%p)", req_str, current_state->graph_state);
314               xbt_free(req_str);              
315             }
316
317             if(!MC_state_process_is_done(prev_state->graph_state, req->issuer)){
318               MC_state_interleave_process(prev_state->graph_state, req->issuer);
319               
320             } else {
321               XBT_DEBUG("Process %p is in done set", req->issuer);
322             }
323
324             break;
325           }
326         }
327
328         if(MC_state_interleave_size(current_state->graph_state)){
329           MC_restore_snapshot(current_state->system_state);
330           xbt_fifo_unshift(mc_snapshot_stack, current_state);
331           XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_snapshot_stack));
332           MC_UNSET_RAW_MEM;
333           break;
334         }
335       }
336
337       MC_UNSET_RAW_MEM;
338
339     } 
340   }
341   MC_UNSET_RAW_MEM;
342   return;
343 }
344
345
346
347 /************ DPOR 2 (invisible and independant transitions) ************/
348
349 xbt_dynar_t reached_pairs_prop;
350 xbt_dynar_t visible_transitions;
351 xbt_dynar_t enabled_processes;
352
353 mc_prop_ato_t new_proposition(char* id, int value){
354   mc_prop_ato_t prop = NULL;
355   prop = xbt_new0(s_mc_prop_ato_t, 1);
356   prop->id = strdup(id);
357   prop->value = value;
358   return prop;
359 }
360
361 mc_pair_prop_t new_pair_prop(mc_snapshot_t sn, mc_state_t sg, xbt_state_t st){
362   mc_pair_prop_t pair = NULL;
363   pair = xbt_new0(s_mc_pair_prop_t, 1);
364   pair->system_state = sn;
365   pair->automaton_state = st;
366   pair->graph_state = sg;
367   pair->propositions = xbt_dynar_new(sizeof(mc_prop_ato_t), NULL);
368   pair->fully_expanded = 0;
369   pair->interleave = 0;
370   mc_stats_pair->expanded_pairs++;
371   return pair;
372 }
373
374 int reached_prop(mc_pair_prop_t pair){
375
376   char* hash_reached = malloc(sizeof(char)*160);
377   unsigned int c= 0;
378
379   MC_SET_RAW_MEM;
380   char *hash = malloc(sizeof(char)*160);
381   xbt_sha((char *)&pair, hash);
382   xbt_dynar_foreach(reached_pairs_prop, c, hash_reached){
383     if(strcmp(hash, hash_reached) == 0){
384       MC_UNSET_RAW_MEM;
385       return 1;
386     }
387   }
388   
389   MC_UNSET_RAW_MEM;
390   return 0;
391 }
392
393 void set_pair_prop_reached(mc_pair_prop_t pair){
394
395   if(reached_prop(pair) == 0){
396     MC_SET_RAW_MEM;
397     char *hash = malloc(sizeof(char)*160) ;
398     xbt_sha((char *)&pair, hash);
399     xbt_dynar_push(reached_pairs_prop, &hash); 
400     MC_UNSET_RAW_MEM;
401   }
402
403 }
404
405 int invisible(mc_pair_prop_t p, mc_pair_prop_t np){
406   mc_prop_ato_t prop1;
407   mc_prop_ato_t prop2;
408   int i;
409   for(i=0;i<xbt_dynar_length(p->propositions); i++){
410     prop1 = xbt_dynar_get_as(p->propositions, i, mc_prop_ato_t);
411     prop2 = xbt_dynar_get_as(np->propositions, i, mc_prop_ato_t);
412     //XBT_DEBUG("test invisible : prop 1 = %s : %d / prop 2 = %s : %d", prop1->id, prop1->value, prop2->id, prop2->value);
413     if(prop1->value != prop2->value)
414           return 0;
415   }
416   return 1; 
417
418 }
419
420 void set_fully_expanded(mc_pair_prop_t pair){
421   pair->fully_expanded = 1;
422 }
423
424 void MC_dpor2_init(xbt_automaton_t a)
425 {
426   mc_pair_prop_t initial_pair = NULL;
427   mc_state_t initial_graph_state = NULL;
428   mc_snapshot_t initial_system_state = NULL;
429   xbt_state_t initial_automaton_state = NULL;
430  
431
432   MC_SET_RAW_MEM;
433   initial_graph_state = MC_state_new();
434   MC_UNSET_RAW_MEM;
435
436   /* Wait for requests (schedules processes) */
437   MC_wait_for_requests();
438
439   unsigned int cursor = 0;
440   unsigned int cursor2 = 0;
441   xbt_state_t automaton_state = NULL;
442   int res;
443   xbt_transition_t transition_succ;
444
445   xbt_dynar_foreach(a->states, cursor, automaton_state){
446     if(automaton_state->type == -1){
447       xbt_dynar_foreach(automaton_state->out, cursor2, transition_succ){
448         res = MC_automaton_evaluate_label(a, transition_succ->label);
449         if((res == 1) || (res == 2)){
450           initial_automaton_state = transition_succ->dst;
451           break;
452         }
453       }
454     }
455
456     if(xbt_fifo_size(mc_snapshot_stack) > 0)
457       break;
458   }
459
460   if(xbt_fifo_size(mc_snapshot_stack) == 0){
461     cursor = 0;
462     xbt_dynar_foreach(a->states, cursor, automaton_state){
463       if(automaton_state->type == -1){
464         initial_automaton_state = automaton_state;
465         break;
466       }
467     }
468   }
469
470   reached_pairs_prop = xbt_dynar_new(sizeof(char *), NULL); 
471   visible_transitions = xbt_dynar_new(sizeof(s_smx_req_t), NULL);
472   enabled_processes = xbt_dynar_new(sizeof(smx_process_t), NULL);
473
474   MC_SET_RAW_MEM;
475   initial_system_state = xbt_new0(s_mc_snapshot_t, 1);
476   MC_take_snapshot(initial_system_state);
477   initial_pair = new_pair_prop(initial_system_state, initial_graph_state, initial_automaton_state);
478   cursor = 0;
479   xbt_propositional_symbol_t ps;
480   xbt_dynar_foreach(a->propositional_symbols, cursor, ps){
481     int (*f)() = ps->function;
482     int val = (*f)();
483     mc_prop_ato_t pa = new_proposition(ps->pred, val);
484     xbt_dynar_push(initial_pair->propositions, &pa);
485   } 
486   xbt_fifo_unshift(mc_snapshot_stack, initial_pair);
487   MC_UNSET_RAW_MEM;
488
489
490   XBT_DEBUG("**************************************************");
491   XBT_DEBUG("Initial pair");
492
493   MC_dpor2(a, 0);
494     
495 }
496
497
498 void MC_dpor2(xbt_automaton_t a, int search_cycle)
499 {
500   char *req_str;
501   int value;
502   smx_req_t req = NULL, prev_req = NULL;
503   mc_state_t next_graph_state = NULL;
504   mc_snapshot_t next_system_state = NULL;
505   xbt_state_t next_automaton_state = NULL;
506   xbt_transition_t transition_succ;
507   unsigned int cursor;
508   int res;
509   mc_pair_prop_t pair = NULL, next_pair = NULL, prev_pair = NULL;
510   smx_process_t process = NULL;
511   xbt_fifo_item_t item = NULL;
512   int d;
513
514
515   while (xbt_fifo_size(mc_snapshot_stack) > 0) {
516
517     /* Get current pair */
518     pair = (mc_pair_prop_t) 
519       xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_snapshot_stack));
520
521     XBT_DEBUG("**************************************************");
522     XBT_DEBUG("Exploration depth=%d (pair=%p)(%u interleave)",
523            xbt_fifo_size(mc_snapshot_stack), pair,
524               MC_state_interleave_size(pair->graph_state));
525
526     xbt_dynar_reset(enabled_processes);
527
528     MC_SET_RAW_MEM;
529     
530     xbt_swag_foreach(process, simix_global->process_list){
531       if(MC_process_is_enabled(process)){ 
532         xbt_dynar_push(enabled_processes, &process);
533         //XBT_DEBUG("Process : pid=%lu",process->pid);
534       }
535     }
536
537     XBT_DEBUG("Enabled processes before pop : %lu", xbt_dynar_length(enabled_processes));
538     
539     XBT_DEBUG("Processes already interleaved : %d", pair->interleave);
540     
541     if(xbt_dynar_length(enabled_processes) > 0){
542       for(d=0;d<pair->interleave;d++){
543         xbt_dynar_shift(enabled_processes, NULL);
544       }
545     }
546
547     XBT_DEBUG("Enabled processes after pop : %lu", xbt_dynar_length(enabled_processes));
548     
549     if(pair->fully_expanded == 0){
550       if(xbt_dynar_length(enabled_processes) > 0){
551         MC_state_interleave_process(pair->graph_state, xbt_dynar_get_as(enabled_processes, 0, smx_process_t));
552         //XBT_DEBUG("Interleave process");
553       }
554     }
555     
556     MC_UNSET_RAW_MEM;
557
558
559     /* Update statistics */
560     mc_stats_pair->visited_pairs++;
561     //sleep(1);
562
563     /*cursor = 0;
564     mc_prop_ato_t pato;
565     xbt_dynar_foreach(pair->propositions, cursor, pato){
566       XBT_DEBUG("%s : %d", pato->id, pato->value);
567       }*/
568
569     /* Test acceptance pair and acceptance cycle*/
570
571     if(pair->automaton_state->type == 1){
572       if(search_cycle == 0){
573         set_pair_prop_reached(pair);
574         XBT_DEBUG("Acceptance pair : graph=%p, automaton=%p(%s)", pair->graph_state, pair->automaton_state, pair->automaton_state->id);
575       }else{
576         if(reached_prop(pair) == 1){
577           XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
578           XBT_INFO("|             ACCEPTANCE CYCLE            |");
579           XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
580           XBT_INFO("Counter-example that violates formula :");
581           MC_show_snapshot_stack(mc_snapshot_stack);
582           MC_dump_snapshot_stack(mc_snapshot_stack);
583           MC_print_statistics_pairs(mc_stats_pair);
584           exit(0);
585         }
586       }
587     }
588
589     /* If there are processes to interleave and the maximum depth has not been reached
590        then perform one step of the exploration algorithm */
591     if (xbt_fifo_size(mc_snapshot_stack) < MAX_DEPTH &&
592         (req = MC_state_get_request(pair->graph_state, &value))) {
593
594       /* Debug information */
595       if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
596         req_str = MC_request_to_string(req, value);
597         XBT_DEBUG("Execute: %s", req_str);
598         xbt_free(req_str);
599       }
600
601       MC_state_set_executed_request(pair->graph_state, req, value);
602       //mc_stats_pairs->executed_transitions++;
603
604       /* Answer the request */
605       SIMIX_request_pre(req, value); /* After this call req is no longer usefull */
606
607       /* Wait for requests (schedules processes) */
608       MC_wait_for_requests();
609
610       /* Create the new expanded state */
611       MC_SET_RAW_MEM;
612
613       pair->interleave++;
614       //XBT_DEBUG("Process interleaved in pair %p : %u", pair, MC_state_interleave_size(pair->graph_state));
615       //xbt_dynar_pop(enabled_processes, NULL);
616
617       next_graph_state = MC_state_new();
618
619       next_system_state = xbt_new0(s_mc_snapshot_t, 1);
620       MC_take_snapshot(next_system_state);
621       MC_UNSET_RAW_MEM;
622
623       cursor = 0;
624       xbt_dynar_foreach(pair->automaton_state->out, cursor, transition_succ){
625         res = MC_automaton_evaluate_label(a, transition_succ->label);   
626         if((res == 1) || (res == 2)){ // enabled transition in automaton
627           next_automaton_state = transition_succ->dst;
628           break;
629         }
630       }
631
632       if(next_automaton_state == NULL){
633         next_automaton_state = pair->automaton_state;
634       }
635
636       MC_SET_RAW_MEM;
637       
638       next_pair = new_pair_prop(next_system_state, next_graph_state, next_automaton_state);
639       cursor = 0;
640       xbt_propositional_symbol_t ps;
641       xbt_dynar_foreach(a->propositional_symbols, cursor, ps){
642         int (*f)() = ps->function;
643         int val = (*f)();
644         mc_prop_ato_t pa = new_proposition(ps->pred, val);
645         xbt_dynar_push(next_pair->propositions, &pa);
646         //XBT_DEBUG("%s : %d", pa->id, pa->value); 
647       } 
648       xbt_fifo_unshift(mc_snapshot_stack, next_pair);
649       
650       cursor = 0;
651       if((invisible(pair, next_pair) == 0) && (pair->fully_expanded == 0)){
652         set_fully_expanded(pair);
653         if(xbt_dynar_length(enabled_processes) > 1){ // Si 1 seul process activé, déjà exécuté juste avant donc état complètement étudié
654           xbt_dynar_foreach(enabled_processes, cursor, process){
655             MC_state_interleave_process(pair->graph_state, process);
656           }
657         }
658         XBT_DEBUG("Pair %p fully expanded (%u interleave)", pair, MC_state_interleave_size(pair->graph_state));
659       }
660
661       MC_UNSET_RAW_MEM;
662
663      
664       /* Let's loop again */
665
666       /* The interleave set is empty or the maximum depth is reached, let's back-track */
667     } else {
668       XBT_DEBUG("There are no more processes to interleave.");
669
670       /* Trash the current state, no longer needed */
671       MC_SET_RAW_MEM;
672       xbt_fifo_shift(mc_snapshot_stack);
673       //MC_state_delete(state);
674       MC_UNSET_RAW_MEM;
675
676       /* Check for deadlocks */
677       if(MC_deadlock_check()){
678         MC_show_deadlock(NULL);
679         return;
680       }
681
682       MC_SET_RAW_MEM;
683       /* Traverse the stack backwards until a state with a non empty interleave
684          set is found, deleting all the states that have it empty in the way.
685          For each deleted state, check if the request that has generated it 
686          (from it's predecesor state), depends on any other previous request 
687          executed before it. If it does then add it to the interleave set of the
688          state that executed that previous request. */
689       while ((pair = xbt_fifo_shift(mc_snapshot_stack)) != NULL) {
690         req = MC_state_get_internal_request(pair->graph_state);
691         xbt_fifo_foreach(mc_snapshot_stack, item, prev_pair, mc_pair_prop_t) {
692           if(MC_request_depend(req, MC_state_get_internal_request(prev_pair->graph_state))){
693             if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
694               XBT_DEBUG("Dependent Transitions:");
695               prev_req = MC_state_get_executed_request(prev_pair->graph_state, &value);
696               req_str = MC_request_to_string(prev_req, value);
697               XBT_DEBUG("%s (pair=%p)", req_str, prev_pair);
698               xbt_free(req_str);
699               prev_req = MC_state_get_executed_request(pair->graph_state, &value);
700               req_str = MC_request_to_string(prev_req, value);
701               XBT_DEBUG("%s (pair=%p)", req_str, pair);
702               xbt_free(req_str);              
703             }
704
705             if(prev_pair->fully_expanded == 0){
706               if(!MC_state_process_is_done(prev_pair->graph_state, req->issuer)){
707                 MC_state_interleave_process(prev_pair->graph_state, req->issuer);
708                 XBT_DEBUG("Process %p (%lu) interleaved in pair %p", req->issuer, req->issuer->pid, prev_pair);
709               }else{
710                 XBT_DEBUG("Process %p (%lu) is in done set", req->issuer, req->issuer->pid);
711               }
712             }
713       
714             break;
715           }
716         }
717
718         
719         if (MC_state_interleave_size(pair->graph_state) > 0) {
720           /* We found a back-tracking point, let's loop */
721           MC_restore_snapshot(pair->system_state);
722           xbt_fifo_unshift(mc_snapshot_stack, pair);
723           XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_snapshot_stack));
724           MC_UNSET_RAW_MEM;
725           break;
726         } else {
727           //MC_state_delete(state);
728         }
729       }
730       MC_UNSET_RAW_MEM;
731     }
732   }
733   MC_UNSET_RAW_MEM;
734   return;
735 }