Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
model-checker : use separate configuration flags for comm determinism and send determ...
[simgrid.git] / src / mc / mc_global.c
1 /* Copyright (c) 2008-2013. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include <sys/wait.h>
10 #include <sys/time.h>
11 #include <libgen.h>
12
13 #include "simgrid/sg_config.h"
14 #include "../surf/surf_private.h"
15 #include "../simix/smx_private.h"
16 #include "../xbt/mmalloc/mmprivate.h"
17 #include "xbt/fifo.h"
18 #include "mc_private.h"
19 #include "xbt/automaton.h"
20 #include "xbt/dict.h"
21
22 XBT_LOG_NEW_CATEGORY(mc, "All MC categories");
23 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_global, mc,
24                                 "Logging specific to MC (global)");
25
26 /* Configuration support */
27 e_mc_reduce_t mc_reduce_kind=e_mc_reduce_unset;
28
29 int _sg_do_model_check = 0;
30 int _sg_mc_checkpoint=0;
31 char* _sg_mc_property_file=NULL;
32 int _sg_mc_timeout=0;
33 int _sg_mc_hash=0;
34 int _sg_mc_max_depth=1000;
35 int _sg_mc_visited=0;
36 char *_sg_mc_dot_output_file = NULL;
37 int _sg_mc_comms_determinism=0;
38 int _sg_mc_send_determinism=0;
39
40 int user_max_depth_reached = 0;
41
42 void _mc_cfg_cb_reduce(const char *name, int pos) {
43   if (_sg_cfg_init_status && !_sg_do_model_check) {
44     xbt_die("You are specifying a reduction strategy after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
45   }
46   char *val= xbt_cfg_get_string(_sg_cfg_set, name);
47   if (!strcasecmp(val,"none")) {
48     mc_reduce_kind = e_mc_reduce_none;
49   } else if (!strcasecmp(val,"dpor")) {
50     mc_reduce_kind = e_mc_reduce_dpor;
51   } else {
52     xbt_die("configuration option %s can only take 'none' or 'dpor' as a value",name);
53   }
54 }
55
56 void _mc_cfg_cb_checkpoint(const char *name, int pos) {
57   if (_sg_cfg_init_status && !_sg_do_model_check) {
58     xbt_die("You are specifying a checkpointing value after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
59   }
60   _sg_mc_checkpoint = xbt_cfg_get_int(_sg_cfg_set, name);
61 }
62 void _mc_cfg_cb_property(const char *name, int pos) {
63   if (_sg_cfg_init_status && !_sg_do_model_check) {
64     xbt_die("You are specifying a property after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
65   }
66   _sg_mc_property_file= xbt_cfg_get_string(_sg_cfg_set, name);
67 }
68
69 void _mc_cfg_cb_timeout(const char *name, int pos) {
70   if (_sg_cfg_init_status && !_sg_do_model_check) {
71     xbt_die("You are specifying a value to enable/disable timeout for wait requests after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
72   }
73   _sg_mc_timeout= xbt_cfg_get_boolean(_sg_cfg_set, name);
74 }
75
76 void _mc_cfg_cb_hash(const char *name, int pos) {
77   if (_sg_cfg_init_status && !_sg_do_model_check) {
78     xbt_die("You are specifying a value to enable/disable the use of global hash to speedup state comparaison, but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
79   }
80   _sg_mc_hash= xbt_cfg_get_boolean(_sg_cfg_set, name);
81 }
82
83 void _mc_cfg_cb_max_depth(const char *name, int pos) {
84   if (_sg_cfg_init_status && !_sg_do_model_check) {
85     xbt_die("You are specifying a max depth value after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
86   }
87   _sg_mc_max_depth= xbt_cfg_get_int(_sg_cfg_set, name);
88 }
89
90 void _mc_cfg_cb_visited(const char *name, int pos) {
91   if (_sg_cfg_init_status && !_sg_do_model_check) {
92     xbt_die("You are specifying a number of stored visited states after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
93   }
94   _sg_mc_visited= xbt_cfg_get_int(_sg_cfg_set, name);
95 }
96
97 void _mc_cfg_cb_dot_output(const char *name, int pos) {
98   if (_sg_cfg_init_status && !_sg_do_model_check) {
99     xbt_die("You are specifying a file name for a dot output of graph state after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
100   }
101   _sg_mc_dot_output_file= xbt_cfg_get_string(_sg_cfg_set, name);
102 }
103
104 void _mc_cfg_cb_comms_determinism(const char *name, int pos) {
105   if (_sg_cfg_init_status && !_sg_do_model_check) {
106     xbt_die("You are specifying a value to enable/disable the detection of determinism in the communications schemes after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
107   }
108   _sg_mc_comms_determinism= xbt_cfg_get_boolean(_sg_cfg_set, name);
109 }
110
111 void _mc_cfg_cb_send_determinism(const char *name, int pos) {
112   if (_sg_cfg_init_status && !_sg_do_model_check) {
113     xbt_die("You are specifying a value to enable/disable the detection of send-determinism in the communications schemes after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
114   }
115   _sg_mc_send_determinism= xbt_cfg_get_boolean(_sg_cfg_set, name);
116 }
117
118 /* MC global data structures */
119 mc_state_t mc_current_state = NULL;
120 char mc_replay_mode = FALSE;
121 double *mc_time = NULL;
122 __thread mc_comparison_times_t mc_comp_times = NULL;
123 __thread double mc_snapshot_comparison_time;
124 mc_stats_t mc_stats = NULL;
125
126 /* Safety */
127 xbt_fifo_t mc_stack_safety = NULL;
128 mc_global_t initial_state_safety = NULL;
129
130 /* Liveness */
131 xbt_fifo_t mc_stack_liveness = NULL;
132 mc_global_t initial_state_liveness = NULL;
133 int compare;
134
135 xbt_automaton_t _mc_property_automaton = NULL;
136
137 /* Variables */
138 mc_object_info_t mc_libsimgrid_info = NULL;
139 mc_object_info_t mc_binary_info = NULL;
140
141 /* Ignore mechanism */
142 extern xbt_dynar_t mc_heap_comparison_ignore;
143 extern xbt_dynar_t stacks_areas;
144
145 /* Dot output */
146 FILE *dot_output = NULL;
147 const char* colors[13];
148
149
150 /*******************************  DWARF Information *******************************/
151 /**********************************************************************************/
152
153 /************************** Free functions *************************/
154
155 static void dw_location_free(dw_location_t l){
156   if(l){
157     if(l->type == e_dw_loclist)
158       xbt_dynar_free(&(l->location.loclist));
159     else if(l->type == e_dw_compose)
160       xbt_dynar_free(&(l->location.compose));
161     else if(l->type == e_dw_arithmetic)
162       xbt_free(l->location.arithmetic);
163   
164     xbt_free(l);
165   }
166 }
167
168 static void dw_location_entry_free(dw_location_entry_t e){
169   dw_location_free(e->location);
170   xbt_free(e);
171 }
172
173 void dw_type_free(dw_type_t t){
174   xbt_free(t->name);
175   xbt_free(t->dw_type_id);
176   xbt_dynar_free(&(t->members));
177   xbt_free(t);
178 }
179
180 static void dw_type_free_voidp(void *t){
181   dw_type_free((dw_type_t) * (void **) t);
182 }
183
184 void dw_variable_free(dw_variable_t v){
185   if(v){
186     xbt_free(v->name);
187     xbt_free(v->type_origin);
188     if(!v->global)
189       dw_location_free(v->location);
190     xbt_free(v);
191   }
192 }
193
194 void dw_variable_free_voidp(void *t){
195   dw_variable_free((dw_variable_t) * (void **) t);
196 }
197
198 // ***** object_info
199
200 mc_object_info_t MC_new_object_info(void) {
201   mc_object_info_t res = xbt_new0(s_mc_object_info_t, 1);
202   res->local_variables = xbt_dict_new_homogeneous(NULL);
203   res->global_variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
204   res->types = xbt_dict_new_homogeneous(NULL);
205   res->types_by_name = xbt_dict_new_homogeneous(NULL);
206   return res;
207 }
208
209
210 void MC_free_object_info(mc_object_info_t* info) {
211   xbt_free(&(*info)->file_name);
212   xbt_dict_free(&(*info)->local_variables);
213   xbt_dynar_free(&(*info)->global_variables);
214   xbt_dict_free(&(*info)->types);
215   xbt_dict_free(&(*info)->types_by_name);
216   xbt_free(info);
217   xbt_dynar_free(&(*info)->functions_index);
218   *info = NULL;
219 }
220
221 // ***** Helpers
222
223 void* MC_object_base_address(mc_object_info_t info) {
224   void* result = info->start_exec;
225   if(info->start_rw!=NULL && result > (void*) info->start_rw) result = info->start_rw;
226   if(info->start_ro!=NULL && result > (void*) info->start_ro) result = info->start_ro;
227   return result;
228 }
229
230 // ***** Functions index
231
232 static int MC_compare_frame_index_items(mc_function_index_item_t a, mc_function_index_item_t b) {
233   if(a->low_pc < b->low_pc)
234     return -1;
235   else if(a->low_pc == b->low_pc)
236     return 0;
237   else
238     return 1;
239 }
240
241 static void MC_make_functions_index(mc_object_info_t info) {
242   xbt_dynar_t index = xbt_dynar_new(sizeof(s_mc_function_index_item_t), NULL);
243
244   // Populate the array:
245   dw_frame_t frame = NULL;
246   xbt_dict_cursor_t cursor = NULL;
247   const char* name = NULL;
248   xbt_dict_foreach(info->local_variables, cursor, name, frame) {
249     if(frame->low_pc==NULL)
250       continue;
251     s_mc_function_index_item_t entry;
252     entry.low_pc = frame->low_pc;
253     entry.high_pc = frame->high_pc;
254     entry.function = frame;
255     xbt_dynar_push(index, &entry);
256   }
257
258   mc_function_index_item_t base = (mc_function_index_item_t) xbt_dynar_get_ptr(index, 0);
259
260   // Sort the array by low_pc:
261   qsort(base,
262     xbt_dynar_length(index),
263     sizeof(s_mc_function_index_item_t),
264     (int (*)(const void *, const void *))MC_compare_frame_index_items);
265
266   info->functions_index = index;
267 }
268
269 mc_object_info_t MC_ip_find_object_info(void* ip) {
270   mc_object_info_t infos[2] = { mc_binary_info, mc_libsimgrid_info };
271   size_t n = 2;
272   size_t i;
273   for(i=0; i!=n; ++i) {
274     if(ip >= (void*)infos[i]->start_exec && ip <= (void*)infos[i]->end_exec) {
275       return infos[i];
276     }
277   }
278   return NULL;
279 }
280
281 static dw_frame_t MC_find_function_by_ip_and_object(void* ip, mc_object_info_t info) {
282   xbt_dynar_t dynar = info->functions_index;
283   mc_function_index_item_t base = (mc_function_index_item_t) xbt_dynar_get_ptr(dynar, 0);
284   int i = 0;
285   int j = xbt_dynar_length(dynar) - 1;
286   while(j>=i) {
287     int k = i + ((j-i)/2);
288     if(ip < base[k].low_pc) {
289       j = k-1;
290     } else if(ip > base[k].high_pc) {
291       i = k+1;
292     } else {
293       return base[k].function;
294     }
295   }
296   return NULL;
297 }
298
299 dw_frame_t MC_find_function_by_ip(void* ip) {
300   mc_object_info_t info = MC_ip_find_object_info(ip);
301   if(info==NULL)
302     return NULL;
303   else
304     return MC_find_function_by_ip_and_object(ip, info);
305 }
306
307 static void MC_post_process_variables(mc_object_info_t info) {
308   unsigned cursor = 0;
309   dw_variable_t variable = NULL;
310   xbt_dynar_foreach(info->global_variables, cursor, variable) {
311     if(variable->type_origin) {
312       variable->type = xbt_dict_get_or_null(info->types, variable->type_origin);
313     }
314   }
315 }
316
317 static void MC_post_process_functions(mc_object_info_t info) {
318   xbt_dict_cursor_t cursor = NULL;
319   char* key = NULL;
320   dw_frame_t function = NULL;
321   xbt_dict_foreach(info->local_variables, cursor, key, function) {
322     unsigned cursor2 = 0;
323     dw_variable_t variable = NULL;
324     xbt_dynar_foreach(function->variables, cursor2, variable) {
325       if(variable->type_origin) {
326         variable->type = xbt_dict_get_or_null(info->types, variable->type_origin);
327       }
328     }
329   }
330 }
331
332 /** \brief Finds informations about a given shared object/executable */
333 mc_object_info_t MC_find_object_info(memory_map_t maps, char* name, int executable) {
334   mc_object_info_t result = MC_new_object_info();
335   if(executable)
336     result->flags |= MC_OBJECT_INFO_EXECUTABLE;
337   result->file_name = xbt_strdup(name);
338   MC_find_object_address(maps, result);
339   MC_dwarf_get_variables(result);
340   MC_post_process_types(result);
341   MC_post_process_variables(result);
342   MC_post_process_functions(result);
343   MC_make_functions_index(result);
344   return result;
345 }
346
347 /*************************************************************************/
348
349 static dw_location_t MC_dwarf_get_location(xbt_dict_t location_list, char *expr){
350
351   dw_location_t loc = xbt_new0(s_dw_location_t, 1);
352
353   if(location_list != NULL){
354     
355     char *key = bprintf("%d", (int)strtoul(expr, NULL, 16));
356     loc->type = e_dw_loclist;
357     loc->location.loclist =  (xbt_dynar_t)xbt_dict_get_or_null(location_list, key);
358     if(loc->location.loclist == NULL)
359       XBT_INFO("Key not found in loclist");
360     xbt_free(key);
361     return loc;
362
363   }else{
364
365     int cursor = 0;
366     char *tok = NULL, *tok2 = NULL; 
367     
368     xbt_dynar_t tokens1 = xbt_str_split(expr, ";");
369     xbt_dynar_t tokens2;
370
371     loc->type = e_dw_compose;
372     loc->location.compose = xbt_dynar_new(sizeof(dw_location_t), NULL);
373
374     while(cursor < xbt_dynar_length(tokens1)){
375
376       tok = xbt_dynar_get_as(tokens1, cursor, char*);
377       tokens2 = xbt_str_split(tok, " ");
378       tok2 = xbt_dynar_get_as(tokens2, 0, char*);
379       
380       if(strncmp(tok2, "DW_OP_reg", 9) == 0){
381         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
382         new_element->type = e_dw_register;
383         new_element->location.reg = atoi(strtok(tok2, "DW_OP_reg"));
384         xbt_dynar_push(loc->location.compose, &new_element);     
385       }else if(strcmp(tok2, "DW_OP_fbreg:") == 0){
386         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
387         new_element->type = e_dw_fbregister_op;
388         new_element->location.fbreg_op = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
389         xbt_dynar_push(loc->location.compose, &new_element);
390       }else if(strncmp(tok2, "DW_OP_breg", 10) == 0){
391         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
392         new_element->type = e_dw_bregister_op;
393         new_element->location.breg_op.reg = atoi(strtok(tok2, "DW_OP_breg"));
394         new_element->location.breg_op.offset = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
395         xbt_dynar_push(loc->location.compose, &new_element);
396       }else if(strncmp(tok2, "DW_OP_lit", 9) == 0){
397         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
398         new_element->type = e_dw_lit;
399         new_element->location.lit = atoi(strtok(tok2, "DW_OP_lit"));
400         xbt_dynar_push(loc->location.compose, &new_element);
401       }else if(strcmp(tok2, "DW_OP_piece:") == 0){
402         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
403         new_element->type = e_dw_piece;
404         new_element->location.piece = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
405         xbt_dynar_push(loc->location.compose, &new_element);
406       }else if(strcmp(tok2, "DW_OP_plus_uconst:") == 0){
407         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
408         new_element->type = e_dw_plus_uconst;
409         new_element->location.plus_uconst = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char *));
410         xbt_dynar_push(loc->location.compose, &new_element);
411       }else if(strcmp(tok, "DW_OP_abs") == 0 || 
412                strcmp(tok, "DW_OP_and") == 0 ||
413                strcmp(tok, "DW_OP_div") == 0 ||
414                strcmp(tok, "DW_OP_minus") == 0 ||
415                strcmp(tok, "DW_OP_mod") == 0 ||
416                strcmp(tok, "DW_OP_mul") == 0 ||
417                strcmp(tok, "DW_OP_neg") == 0 ||
418                strcmp(tok, "DW_OP_not") == 0 ||
419                strcmp(tok, "DW_OP_or") == 0 ||
420                strcmp(tok, "DW_OP_plus") == 0){               
421         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
422         new_element->type = e_dw_arithmetic;
423         new_element->location.arithmetic = strdup(strtok(tok2, "DW_OP_"));
424         xbt_dynar_push(loc->location.compose, &new_element);
425       }else if(strcmp(tok, "DW_OP_stack_value") == 0){
426       }else if(strcmp(tok2, "DW_OP_deref_size:") == 0){
427         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
428         new_element->type = e_dw_deref;
429         new_element->location.deref_size = (unsigned int short) atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
430         xbt_dynar_push(loc->location.compose, &new_element);
431       }else if(strcmp(tok, "DW_OP_deref") == 0){
432         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
433         new_element->type = e_dw_deref;
434         new_element->location.deref_size = sizeof(void *);
435         xbt_dynar_push(loc->location.compose, &new_element);
436       }else if(strcmp(tok2, "DW_OP_constu:") == 0){
437         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
438         new_element->type = e_dw_uconstant;
439         new_element->location.uconstant.bytes = 1;
440         new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
441         xbt_dynar_push(loc->location.compose, &new_element);
442       }else if(strcmp(tok2, "DW_OP_consts:") == 0){
443         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
444         new_element->type = e_dw_sconstant;
445         new_element->location.sconstant.bytes = 1;
446         new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
447         xbt_dynar_push(loc->location.compose, &new_element);
448       }else if(strcmp(tok2, "DW_OP_const1u:") == 0 ||
449                strcmp(tok2, "DW_OP_const2u:") == 0 ||
450                strcmp(tok2, "DW_OP_const4u:") == 0 ||
451                strcmp(tok2, "DW_OP_const8u:") == 0){
452         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
453         new_element->type = e_dw_uconstant;
454         new_element->location.uconstant.bytes = tok2[11] - '0';
455         new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
456         xbt_dynar_push(loc->location.compose, &new_element);
457       }else if(strcmp(tok, "DW_OP_const1s") == 0 ||
458                strcmp(tok, "DW_OP_const2s") == 0 ||
459                strcmp(tok, "DW_OP_const4s") == 0 ||
460                strcmp(tok, "DW_OP_const8s") == 0){
461         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
462         new_element->type = e_dw_sconstant;
463         new_element->location.sconstant.bytes = tok2[11] - '0';
464         new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
465         xbt_dynar_push(loc->location.compose, &new_element);
466       }else{
467         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
468         new_element->type = e_dw_unsupported;
469         xbt_dynar_push(loc->location.compose, &new_element);
470       }
471
472       cursor++;
473       xbt_dynar_free(&tokens2);
474
475     }
476     
477     xbt_dynar_free(&tokens1);
478
479     return loc;
480     
481   }
482
483 }
484
485
486 /** \brief Finds a frame (DW_TAG_subprogram) from an DWARF offset in the rangd of this subprogram
487  *
488  * The offset can be an offset of a child DW_TAG_variable.
489  */
490 static dw_frame_t MC_dwarf_get_frame_by_offset(xbt_dict_t all_variables, unsigned long int offset){
491
492   xbt_dict_cursor_t cursor = NULL;
493   char *name;
494   dw_frame_t res;
495
496   xbt_dict_foreach(all_variables, cursor, name, res) {
497     if(offset >= res->start && offset < res->end){
498       xbt_dict_cursor_free(&cursor);
499       return res;
500     }
501   }
502
503   xbt_dict_cursor_free(&cursor);
504   return NULL;
505   
506 }
507
508 static dw_variable_t MC_dwarf_get_variable_by_name(dw_frame_t frame, char *var){
509
510   unsigned int cursor = 0;
511   dw_variable_t current_var;
512
513   xbt_dynar_foreach(frame->variables, cursor, current_var){
514     if(strcmp(var, current_var->name) == 0)
515       return current_var;
516   }
517
518   return NULL;
519 }
520
521 static int MC_dwarf_get_variable_index(xbt_dynar_t variables, char* var, void *address){
522
523   if(xbt_dynar_is_empty(variables))
524     return 0;
525
526   unsigned int cursor = 0;
527   int start = 0;
528   int end = xbt_dynar_length(variables) - 1;
529   dw_variable_t var_test = NULL;
530
531   while(start <= end){
532     cursor = (start + end) / 2;
533     var_test = (dw_variable_t)xbt_dynar_get_as(variables, cursor, dw_variable_t);
534     if(strcmp(var_test->name, var) < 0){
535       start = cursor + 1;
536     }else if(strcmp(var_test->name, var) > 0){
537       end = cursor - 1;
538     }else{
539       if(address){ /* global variable */
540         if(var_test->address == address)
541           return -1;
542         if(var_test->address > address)
543           end = cursor - 1;
544         else
545           start = cursor + 1;
546       }else{ /* local variable */
547         return -1;
548       }
549     }
550   }
551
552   if(strcmp(var_test->name, var) == 0){
553     if(address && var_test->address < address)
554       return cursor+1;
555     else
556       return cursor;
557   }else if(strcmp(var_test->name, var) < 0)
558     return cursor+1;
559   else
560     return cursor;
561
562 }
563
564 void MC_dwarf_register_global_variable(mc_object_info_t info, dw_variable_t variable) {
565   int index = MC_dwarf_get_variable_index(info->global_variables, variable->name, variable->address);
566   if (index != -1)
567     xbt_dynar_insert_at(info->global_variables, index, &variable);
568   // TODO, else ?
569 }
570
571 void MC_dwarf_register_non_global_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable) {
572   xbt_assert(frame, "Frame is NULL");
573   int index = MC_dwarf_get_variable_index(frame->variables, variable->name, NULL);
574   if (index != -1)
575     xbt_dynar_insert_at(frame->variables, index, &variable);
576   // TODO, else ?
577 }
578
579 void MC_dwarf_register_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable) {
580   if(variable->global)
581     MC_dwarf_register_global_variable(info, variable);
582   else if(frame==NULL)
583     xbt_die("No frame for this local variable");
584   else
585     MC_dwarf_register_non_global_variable(info, frame, variable);
586 }
587
588
589 /*******************************  Ignore mechanism *******************************/
590 /*********************************************************************************/
591
592 xbt_dynar_t mc_checkpoint_ignore;
593
594 typedef struct s_mc_stack_ignore_variable{
595   char *var_name;
596   char *frame;
597 }s_mc_stack_ignore_variable_t, *mc_stack_ignore_variable_t;
598
599 /**************************** Free functions ******************************/
600
601 static void stack_ignore_variable_free(mc_stack_ignore_variable_t v){
602   xbt_free(v->var_name);
603   xbt_free(v->frame);
604   xbt_free(v);
605 }
606
607 static void stack_ignore_variable_free_voidp(void *v){
608   stack_ignore_variable_free((mc_stack_ignore_variable_t) * (void **) v);
609 }
610
611 void heap_ignore_region_free(mc_heap_ignore_region_t r){
612   xbt_free(r);
613 }
614
615 void heap_ignore_region_free_voidp(void *r){
616   heap_ignore_region_free((mc_heap_ignore_region_t) * (void **) r);
617 }
618
619 static void checkpoint_ignore_region_free(mc_checkpoint_ignore_region_t r){
620   xbt_free(r);
621 }
622
623 static void checkpoint_ignore_region_free_voidp(void *r){
624   checkpoint_ignore_region_free((mc_checkpoint_ignore_region_t) * (void **) r);
625 }
626
627 /***********************************************************************/
628
629 void MC_ignore_heap(void *address, size_t size){
630
631   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
632
633   MC_SET_RAW_MEM;
634
635   mc_heap_ignore_region_t region = NULL;
636   region = xbt_new0(s_mc_heap_ignore_region_t, 1);
637   region->address = address;
638   region->size = size;
639   
640   region->block = ((char*)address - (char*)((xbt_mheap_t)std_heap)->heapbase) / BLOCKSIZE + 1;
641   
642   if(((xbt_mheap_t)std_heap)->heapinfo[region->block].type == 0){
643     region->fragment = -1;
644     ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_block.ignore++;
645   }else{
646     region->fragment = ((uintptr_t) (ADDR2UINT (address) % (BLOCKSIZE))) >> ((xbt_mheap_t)std_heap)->heapinfo[region->block].type;
647     ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_frag.ignore[region->fragment]++;
648   }
649   
650   if(mc_heap_comparison_ignore == NULL){
651     mc_heap_comparison_ignore = xbt_dynar_new(sizeof(mc_heap_ignore_region_t), heap_ignore_region_free_voidp);
652     xbt_dynar_push(mc_heap_comparison_ignore, &region);
653     if(!raw_mem_set)
654       MC_UNSET_RAW_MEM;
655     return;
656   }
657
658   unsigned int cursor = 0;
659   mc_heap_ignore_region_t current_region = NULL;
660   int start = 0;
661   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
662   
663   while(start <= end){
664     cursor = (start + end) / 2;
665     current_region = (mc_heap_ignore_region_t)xbt_dynar_get_as(mc_heap_comparison_ignore, cursor, mc_heap_ignore_region_t);
666     if(current_region->address == address){
667       heap_ignore_region_free(region);
668       if(!raw_mem_set)
669         MC_UNSET_RAW_MEM;
670       return;
671     }else if(current_region->address < address){
672       start = cursor + 1;
673     }else{
674       end = cursor - 1;
675     }   
676   }
677
678   if(current_region->address < address)
679     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor + 1, &region);
680   else
681     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor, &region);
682
683   if(!raw_mem_set)
684     MC_UNSET_RAW_MEM;
685 }
686
687 void MC_remove_ignore_heap(void *address, size_t size){
688
689   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
690
691   MC_SET_RAW_MEM;
692
693   unsigned int cursor = 0;
694   int start = 0;
695   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
696   mc_heap_ignore_region_t region;
697   int ignore_found = 0;
698
699   while(start <= end){
700     cursor = (start + end) / 2;
701     region = (mc_heap_ignore_region_t)xbt_dynar_get_as(mc_heap_comparison_ignore, cursor, mc_heap_ignore_region_t);
702     if(region->address == address){
703       ignore_found = 1;
704       break;
705     }else if(region->address < address){
706       start = cursor + 1;
707     }else{
708       if((char * )region->address <= ((char *)address + size)){
709         ignore_found = 1;
710         break;
711       }else{
712         end = cursor - 1;   
713       }
714     }
715   }
716   
717   if(ignore_found == 1){
718     xbt_dynar_remove_at(mc_heap_comparison_ignore, cursor, NULL);
719     MC_remove_ignore_heap(address, size);
720   }
721
722   if(!raw_mem_set)
723     MC_UNSET_RAW_MEM;
724
725 }
726
727 void MC_ignore_global_variable(const char *name){
728
729   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
730
731   MC_SET_RAW_MEM;
732
733   xbt_assert(mc_libsimgrid_info, "MC subsystem not initialized");
734
735     unsigned int cursor = 0;
736     dw_variable_t current_var;
737     int start = 0;
738     int end = xbt_dynar_length(mc_libsimgrid_info->global_variables) - 1;
739
740     while(start <= end){
741       cursor = (start + end) /2;
742       current_var = (dw_variable_t)xbt_dynar_get_as(mc_libsimgrid_info->global_variables, cursor, dw_variable_t);
743       if(strcmp(current_var->name, name) == 0){
744         xbt_dynar_remove_at(mc_libsimgrid_info->global_variables, cursor, NULL);
745         start = 0;
746         end = xbt_dynar_length(mc_libsimgrid_info->global_variables) - 1;
747       }else if(strcmp(current_var->name, name) < 0){
748         start = cursor + 1;
749       }else{
750         end = cursor - 1;
751       } 
752     }
753
754   if(!raw_mem_set)
755     MC_UNSET_RAW_MEM;
756 }
757
758 void MC_ignore_local_variable(const char *var_name, const char *frame_name){
759   
760   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
761
762   MC_SET_RAW_MEM;
763
764     unsigned int cursor = 0;
765     dw_variable_t current_var;
766     int start, end;
767     if(strcmp(frame_name, "*") == 0){ /* Remove variable in all frames */
768       xbt_dict_cursor_t dict_cursor;
769       char *current_frame_name;
770       dw_frame_t frame;
771       xbt_dict_foreach(mc_libsimgrid_info->local_variables, dict_cursor, current_frame_name, frame){
772         start = 0;
773         end = xbt_dynar_length(frame->variables) - 1;
774         while(start <= end){
775           cursor = (start + end) / 2;
776           current_var = (dw_variable_t)xbt_dynar_get_as(frame->variables, cursor, dw_variable_t); 
777           if(strcmp(current_var->name, var_name) == 0){
778             xbt_dynar_remove_at(frame->variables, cursor, NULL);
779             start = 0;
780             end = xbt_dynar_length(frame->variables) - 1;
781           }else if(strcmp(current_var->name, var_name) < 0){
782             start = cursor + 1;
783           }else{
784             end = cursor - 1;
785           } 
786         }
787       }
788        xbt_dict_foreach(mc_binary_info->local_variables, dict_cursor, current_frame_name, frame){
789         start = 0;
790         end = xbt_dynar_length(frame->variables) - 1;
791         while(start <= end){
792           cursor = (start + end) / 2;
793           current_var = (dw_variable_t)xbt_dynar_get_as(frame->variables, cursor, dw_variable_t); 
794           if(strcmp(current_var->name, var_name) == 0){
795             xbt_dynar_remove_at(frame->variables, cursor, NULL);
796             start = 0;
797             end = xbt_dynar_length(frame->variables) - 1;
798           }else if(strcmp(current_var->name, var_name) < 0){
799             start = cursor + 1;
800           }else{
801             end = cursor - 1;
802           } 
803         }
804       }
805     }else{
806       xbt_dynar_t variables_list = ((dw_frame_t)xbt_dict_get_or_null(
807                                       mc_libsimgrid_info->local_variables, frame_name))->variables;
808       start = 0;
809       end = xbt_dynar_length(variables_list) - 1;
810       while(start <= end){
811         cursor = (start + end) / 2;
812         current_var = (dw_variable_t)xbt_dynar_get_as(variables_list, cursor, dw_variable_t);
813         if(strcmp(current_var->name, var_name) == 0){
814           xbt_dynar_remove_at(variables_list, cursor, NULL);
815           start = 0;
816           end = xbt_dynar_length(variables_list) - 1;
817         }else if(strcmp(current_var->name, var_name) < 0){
818           start = cursor + 1;
819         }else{
820           end = cursor - 1;
821         } 
822       }
823     } 
824
825   if(!raw_mem_set)
826     MC_UNSET_RAW_MEM;
827
828 }
829
830 void MC_new_stack_area(void *stack, char *name, void* context, size_t size){
831
832   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
833
834   MC_SET_RAW_MEM;
835
836   if(stacks_areas == NULL)
837     stacks_areas = xbt_dynar_new(sizeof(stack_region_t), NULL);
838   
839   stack_region_t region = NULL;
840   region = xbt_new0(s_stack_region_t, 1);
841   region->address = stack;
842   region->process_name = strdup(name);
843   region->context = context;
844   region->size = size;
845   region->block = ((char*)stack - (char*)((xbt_mheap_t)std_heap)->heapbase) / BLOCKSIZE + 1;
846   xbt_dynar_push(stacks_areas, &region);
847
848   if(!raw_mem_set)
849     MC_UNSET_RAW_MEM;
850 }
851
852 void MC_ignore(void *addr, size_t size){
853
854   int raw_mem_set= (mmalloc_get_current_heap() == raw_heap);
855
856   MC_SET_RAW_MEM;
857
858   if(mc_checkpoint_ignore == NULL)
859     mc_checkpoint_ignore = xbt_dynar_new(sizeof(mc_checkpoint_ignore_region_t), checkpoint_ignore_region_free_voidp);
860
861   mc_checkpoint_ignore_region_t region = xbt_new0(s_mc_checkpoint_ignore_region_t, 1);
862   region->addr = addr;
863   region->size = size;
864
865   if(xbt_dynar_is_empty(mc_checkpoint_ignore)){
866     xbt_dynar_push(mc_checkpoint_ignore, &region);
867   }else{
868      
869     unsigned int cursor = 0;
870     int start = 0;
871     int end = xbt_dynar_length(mc_checkpoint_ignore) -1;
872     mc_checkpoint_ignore_region_t current_region = NULL;
873
874     while(start <= end){
875       cursor = (start + end) / 2;
876       current_region = (mc_checkpoint_ignore_region_t)xbt_dynar_get_as(mc_checkpoint_ignore, cursor, mc_checkpoint_ignore_region_t);
877       if(current_region->addr == addr){
878         if(current_region->size == size){
879           checkpoint_ignore_region_free(region);
880           if(!raw_mem_set)
881             MC_UNSET_RAW_MEM;
882           return;
883         }else if(current_region->size < size){
884           start = cursor + 1;
885         }else{
886           end = cursor - 1;
887         }
888       }else if(current_region->addr < addr){
889           start = cursor + 1;
890       }else{
891         end = cursor - 1;
892       }
893     }
894
895      if(current_region->addr == addr){
896        if(current_region->size < size){
897         xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, &region);
898       }else{
899         xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, &region);
900       }
901     }else if(current_region->addr < addr){
902        xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, &region);
903     }else{
904        xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, &region);
905     }
906   }
907
908   if(!raw_mem_set)
909     MC_UNSET_RAW_MEM;
910 }
911
912 /*******************************  Initialisation of MC *******************************/
913 /*********************************************************************************/
914
915 static void MC_post_process_object_info(mc_object_info_t info) {
916   mc_object_info_t other_info = info == mc_binary_info ? mc_libsimgrid_info : mc_binary_info;
917   xbt_dict_cursor_t cursor = NULL;
918   char* key = NULL;
919   dw_type_t type = NULL;
920   xbt_dict_foreach(info->types, cursor, key, type){
921     if(type->name && type->byte_size == 0) {
922       type->other_object_same_type = xbt_dict_get_or_null(other_info->types_by_name, type->name);
923     }
924   }
925 }
926
927 static void MC_init_debug_info(void) {
928   XBT_INFO("Get debug information ...");
929
930   memory_map_t maps = MC_get_memory_map();
931
932   /* Get local variables for state equality detection */
933   mc_binary_info = MC_find_object_info(maps, xbt_binary_name, 1);
934   mc_libsimgrid_info = MC_find_object_info(maps, libsimgrid_path, 0);
935
936   // Use information of the other objects:
937   MC_post_process_object_info(mc_binary_info);
938   MC_post_process_object_info(mc_libsimgrid_info);
939
940   MC_free_memory_map(maps);
941   XBT_INFO("Get debug information done !");
942 }
943
944 void MC_init(){
945
946   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
947
948   compare = 0;
949
950   /* Initialize the data structures that must be persistent across every
951      iteration of the model-checker (in RAW memory) */
952
953   MC_SET_RAW_MEM;
954
955   MC_init_memory_map_info();
956   MC_init_debug_info();
957
958    /* Init parmap */
959   parmap = xbt_parmap_mc_new(xbt_os_get_numcores(), XBT_PARMAP_DEFAULT);
960
961   MC_UNSET_RAW_MEM;
962
963    /* Ignore some variables from xbt/ex.h used by exception e for stacks comparison */
964   MC_ignore_local_variable("e", "*");
965   MC_ignore_local_variable("__ex_cleanup", "*");
966   MC_ignore_local_variable("__ex_mctx_en", "*");
967   MC_ignore_local_variable("__ex_mctx_me", "*");
968   MC_ignore_local_variable("__xbt_ex_ctx_ptr", "*");
969   MC_ignore_local_variable("_log_ev", "*");
970   MC_ignore_local_variable("_throw_ctx", "*");
971   MC_ignore_local_variable("ctx", "*");
972
973   MC_ignore_local_variable("next_context", "smx_ctx_sysv_suspend_serial");
974   MC_ignore_local_variable("i", "smx_ctx_sysv_suspend_serial");
975
976   /* Ignore local variable about time used for tracing */
977   MC_ignore_local_variable("start_time", "*"); 
978
979   MC_ignore_global_variable("mc_comp_times");
980   MC_ignore_global_variable("mc_snapshot_comparison_time"); 
981   MC_ignore_global_variable("mc_time");
982   MC_ignore_global_variable("smpi_current_rank");
983   MC_ignore_global_variable("counter"); /* Static variable used for tracing */
984   MC_ignore_global_variable("maestro_stack_start");
985   MC_ignore_global_variable("maestro_stack_end");
986   MC_ignore_global_variable("smx_total_comms");
987
988   MC_ignore_heap(&(simix_global->process_to_run), sizeof(simix_global->process_to_run));
989   MC_ignore_heap(&(simix_global->process_that_ran), sizeof(simix_global->process_that_ran));
990   MC_ignore_heap(simix_global->process_to_run, sizeof(*(simix_global->process_to_run)));
991   MC_ignore_heap(simix_global->process_that_ran, sizeof(*(simix_global->process_that_ran)));
992   
993   smx_process_t process;
994   xbt_swag_foreach(process, simix_global->process_list){
995     MC_ignore_heap(&(process->process_hookup), sizeof(process->process_hookup));
996   }
997
998   if(raw_mem_set)
999     MC_SET_RAW_MEM;
1000
1001 }
1002
1003 static void MC_init_dot_output(){ /* FIXME : more colors */
1004
1005   colors[0] = "blue";
1006   colors[1] = "red";
1007   colors[2] = "green3";
1008   colors[3] = "goldenrod";
1009   colors[4] = "brown";
1010   colors[5] = "purple";
1011   colors[6] = "magenta";
1012   colors[7] = "turquoise4";
1013   colors[8] = "gray25";
1014   colors[9] = "forestgreen";
1015   colors[10] = "hotpink";
1016   colors[11] = "lightblue";
1017   colors[12] = "tan";
1018
1019   dot_output = fopen(_sg_mc_dot_output_file, "w");
1020   
1021   if(dot_output == NULL){
1022     perror("Error open dot output file");
1023     xbt_abort();
1024   }
1025
1026   fprintf(dot_output, "digraph graphname{\n fixedsize=true; rankdir=TB; ranksep=.25; edge [fontsize=12]; node [fontsize=10, shape=circle,width=.5 ]; graph [resolution=20, fontsize=10];\n");
1027
1028 }
1029
1030 /*******************************  Core of MC *******************************/
1031 /**************************************************************************/
1032
1033 void MC_do_the_modelcheck_for_real() {
1034
1035   MC_SET_RAW_MEM;
1036   mc_comp_times = xbt_new0(s_mc_comparison_times_t, 1);
1037   MC_UNSET_RAW_MEM;
1038   
1039   if (!_sg_mc_property_file || _sg_mc_property_file[0]=='\0') {
1040     if (mc_reduce_kind==e_mc_reduce_unset)
1041       mc_reduce_kind=e_mc_reduce_dpor;
1042
1043     XBT_INFO("Check a safety property");
1044     MC_modelcheck_safety();
1045
1046   } else  {
1047
1048     if (mc_reduce_kind==e_mc_reduce_unset)
1049       mc_reduce_kind=e_mc_reduce_none;
1050
1051     XBT_INFO("Check the liveness property %s",_sg_mc_property_file);
1052     MC_automaton_load(_sg_mc_property_file);
1053     MC_modelcheck_liveness();
1054   }
1055 }
1056
1057 void MC_modelcheck_safety(void)
1058 {
1059   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1060
1061   /* Check if MC is already initialized */
1062   if (initial_state_safety)
1063     return;
1064
1065   mc_time = xbt_new0(double, simix_process_maxpid);
1066
1067   /* mc_time refers to clock for each process -> ignore it for heap comparison */  
1068   MC_ignore_heap(mc_time, simix_process_maxpid * sizeof(double));
1069
1070   /* Initialize the data structures that must be persistent across every
1071      iteration of the model-checker (in RAW memory) */
1072   
1073   MC_SET_RAW_MEM;
1074
1075   /* Initialize statistics */
1076   mc_stats = xbt_new0(s_mc_stats_t, 1);
1077   mc_stats->state_size = 1;
1078
1079   /* Create exploration stack */
1080   mc_stack_safety = xbt_fifo_new();
1081
1082   if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0'))
1083     MC_init_dot_output();
1084
1085   MC_UNSET_RAW_MEM;
1086
1087   if(_sg_mc_visited > 0){
1088     MC_init();
1089   }else{
1090     MC_SET_RAW_MEM;
1091     MC_init_memory_map_info();
1092     MC_init_debug_info();
1093     MC_UNSET_RAW_MEM;
1094   }
1095
1096   MC_dpor_init();
1097
1098   MC_SET_RAW_MEM;
1099   /* Save the initial state */
1100   initial_state_safety = xbt_new0(s_mc_global_t, 1);
1101   initial_state_safety->snapshot = MC_take_snapshot(0);
1102   initial_state_safety->initial_communications_pattern_done = 0;
1103   initial_state_safety->comm_deterministic = 1;
1104   initial_state_safety->send_deterministic = 1;
1105   MC_UNSET_RAW_MEM;
1106
1107   MC_dpor();
1108
1109   if(raw_mem_set)
1110     MC_SET_RAW_MEM;
1111
1112   xbt_abort();
1113   //MC_exit();
1114 }
1115
1116 void MC_modelcheck_liveness(){
1117
1118   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1119
1120   MC_init();
1121
1122   mc_time = xbt_new0(double, simix_process_maxpid);
1123
1124   /* mc_time refers to clock for each process -> ignore it for heap comparison */  
1125   MC_ignore_heap(mc_time, simix_process_maxpid * sizeof(double));
1126  
1127   MC_SET_RAW_MEM;
1128  
1129   /* Initialize statistics */
1130   mc_stats = xbt_new0(s_mc_stats_t, 1);
1131   mc_stats->state_size = 1;
1132
1133   /* Create exploration stack */
1134   mc_stack_liveness = xbt_fifo_new();
1135
1136   /* Create the initial state */
1137   initial_state_liveness = xbt_new0(s_mc_global_t, 1);
1138
1139   if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0'))
1140     MC_init_dot_output();
1141   
1142   MC_UNSET_RAW_MEM;
1143
1144   MC_ddfs_init();
1145
1146   /* We're done */
1147   MC_print_statistics(mc_stats);
1148   xbt_free(mc_time);
1149
1150   if(raw_mem_set)
1151     MC_SET_RAW_MEM;
1152
1153 }
1154
1155
1156 void MC_exit(void)
1157 {
1158   xbt_free(mc_time);
1159
1160   MC_memory_exit();
1161   //xbt_abort();
1162 }
1163
1164 int SIMIX_pre_mc_random(smx_simcall_t simcall, int min, int max){
1165
1166   return simcall->mc_value;
1167 }
1168
1169
1170 int MC_random(int min, int max)
1171 {
1172   /*FIXME: return mc_current_state->executed_transition->random.value;*/
1173   return simcall_mc_random(min, max);
1174 }
1175
1176 /**
1177  * \brief Schedules all the process that are ready to run
1178  */
1179 void MC_wait_for_requests(void)
1180 {
1181   smx_process_t process;
1182   smx_simcall_t req;
1183   unsigned int iter;
1184
1185   while (!xbt_dynar_is_empty(simix_global->process_to_run)) {
1186     SIMIX_process_runall();
1187     xbt_dynar_foreach(simix_global->process_that_ran, iter, process) {
1188       req = &process->simcall;
1189       if (req->call != SIMCALL_NONE && !MC_request_is_visible(req))
1190         SIMIX_simcall_pre(req, 0);
1191     }
1192   }
1193 }
1194
1195 int MC_deadlock_check()
1196 {
1197   int deadlock = FALSE;
1198   smx_process_t process;
1199   if(xbt_swag_size(simix_global->process_list)){
1200     deadlock = TRUE;
1201     xbt_swag_foreach(process, simix_global->process_list){
1202       if(process->simcall.call != SIMCALL_NONE
1203          && MC_request_is_enabled(&process->simcall)){
1204         deadlock = FALSE;
1205         break;
1206       }
1207     }
1208   }
1209   return deadlock;
1210 }
1211
1212 /**
1213  * \brief Re-executes from the state at position start all the transitions indicated by
1214  *        a given model-checker stack.
1215  * \param stack The stack with the transitions to execute.
1216  * \param start Start index to begin the re-execution.
1217  */
1218 void MC_replay(xbt_fifo_t stack, int start)
1219 {
1220   int raw_mem = (mmalloc_get_current_heap() == raw_heap);
1221
1222   int value, i = 1, count = 1;
1223   char *req_str;
1224   smx_simcall_t req = NULL, saved_req = NULL;
1225   xbt_fifo_item_t item, start_item;
1226   mc_state_t state;
1227   smx_process_t process = NULL;
1228   int comm_pattern = 0;
1229
1230   XBT_DEBUG("**** Begin Replay ****");
1231
1232   if(start == -1){
1233     /* Restore the initial state */
1234     MC_restore_snapshot(initial_state_safety->snapshot);
1235     /* At the moment of taking the snapshot the raw heap was set, so restoring
1236      * it will set it back again, we have to unset it to continue  */
1237     MC_UNSET_RAW_MEM;
1238   }
1239
1240   start_item = xbt_fifo_get_last_item(stack);
1241   if(start != -1){
1242     while (i != start){
1243       start_item = xbt_fifo_get_prev_item(start_item);
1244       i++;
1245     }
1246   }
1247
1248   MC_SET_RAW_MEM;
1249   xbt_dict_reset(first_enabled_state);
1250   xbt_swag_foreach(process, simix_global->process_list){
1251     if(MC_process_is_enabled(process)){
1252       char *key = bprintf("%lu", process->pid);
1253       char *data = bprintf("%d", count);
1254       xbt_dict_set(first_enabled_state, key, data, NULL);
1255       xbt_free(key);
1256     }
1257   }
1258   if(_sg_mc_comms_determinism || _sg_mc_send_determinism)
1259     xbt_dynar_reset(communications_pattern);
1260   MC_UNSET_RAW_MEM;
1261   
1262
1263   /* Traverse the stack from the state at position start and re-execute the transitions */
1264   for (item = start_item;
1265        item != xbt_fifo_get_first_item(stack);
1266        item = xbt_fifo_get_prev_item(item)) {
1267
1268     state = (mc_state_t) xbt_fifo_get_item_content(item);
1269     saved_req = MC_state_get_executed_request(state, &value);
1270    
1271     MC_SET_RAW_MEM;
1272     char *key = bprintf("%lu", saved_req->issuer->pid);
1273     xbt_dict_remove(first_enabled_state, key); 
1274     xbt_free(key);
1275     MC_UNSET_RAW_MEM;
1276    
1277     if(saved_req){
1278       /* because we got a copy of the executed request, we have to fetch the  
1279          real one, pointed by the request field of the issuer process */
1280       req = &saved_req->issuer->simcall;
1281
1282       /* Debug information */
1283       if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
1284         req_str = MC_request_to_string(req, value);
1285         XBT_DEBUG("Replay: %s (%p)", req_str, state);
1286         xbt_free(req_str);
1287       }
1288     }
1289
1290     if(_sg_mc_comms_determinism || _sg_mc_send_determinism){
1291       if(req->call == SIMCALL_COMM_ISEND)
1292         comm_pattern = 1;
1293       else if(req->call == SIMCALL_COMM_IRECV)
1294       comm_pattern = 2;
1295     }
1296
1297     SIMIX_simcall_pre(req, value);
1298
1299     if(_sg_mc_comms_determinism || _sg_mc_send_determinism){
1300       MC_SET_RAW_MEM;
1301       if(comm_pattern != 0){
1302         get_comm_pattern(communications_pattern, req, comm_pattern);
1303       }
1304       MC_UNSET_RAW_MEM;
1305       comm_pattern = 0;
1306     }
1307     
1308     MC_wait_for_requests();
1309
1310     count++;
1311
1312     MC_SET_RAW_MEM;
1313     /* Insert in dict all enabled processes */
1314     xbt_swag_foreach(process, simix_global->process_list){
1315       if(MC_process_is_enabled(process) /*&& !MC_state_process_is_done(state, process)*/){
1316         char *key = bprintf("%lu", process->pid);
1317         if(xbt_dict_get_or_null(first_enabled_state, key) == NULL){
1318           char *data = bprintf("%d", count);
1319           xbt_dict_set(first_enabled_state, key, data, NULL);
1320         }
1321         xbt_free(key);
1322       }
1323     }
1324     MC_UNSET_RAW_MEM;
1325          
1326     /* Update statistics */
1327     mc_stats->visited_states++;
1328     mc_stats->executed_transitions++;
1329
1330   }
1331
1332   XBT_DEBUG("**** End Replay ****");
1333
1334   if(raw_mem)
1335     MC_SET_RAW_MEM;
1336   else
1337     MC_UNSET_RAW_MEM;
1338   
1339
1340 }
1341
1342 void MC_replay_liveness(xbt_fifo_t stack, int all_stack)
1343 {
1344
1345   initial_state_liveness->raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1346
1347   int value;
1348   char *req_str;
1349   smx_simcall_t req = NULL, saved_req = NULL;
1350   xbt_fifo_item_t item;
1351   mc_state_t state;
1352   mc_pair_t pair;
1353   int depth = 1;
1354
1355   XBT_DEBUG("**** Begin Replay ****");
1356
1357   /* Restore the initial state */
1358   MC_restore_snapshot(initial_state_liveness->snapshot);
1359
1360   /* At the moment of taking the snapshot the raw heap was set, so restoring
1361    * it will set it back again, we have to unset it to continue  */
1362   if(!initial_state_liveness->raw_mem_set)
1363     MC_UNSET_RAW_MEM;
1364
1365   if(all_stack){
1366
1367     item = xbt_fifo_get_last_item(stack);
1368
1369     while(depth <= xbt_fifo_size(stack)){
1370
1371       pair = (mc_pair_t) xbt_fifo_get_item_content(item);
1372       state = (mc_state_t) pair->graph_state;
1373
1374       if(pair->requests > 0){
1375    
1376         saved_req = MC_state_get_executed_request(state, &value);
1377         //XBT_DEBUG("SavedReq->call %u", saved_req->call);
1378       
1379         if(saved_req != NULL){
1380           /* because we got a copy of the executed request, we have to fetch the  
1381              real one, pointed by the request field of the issuer process */
1382           req = &saved_req->issuer->simcall;
1383           //XBT_DEBUG("Req->call %u", req->call);
1384   
1385           /* Debug information */
1386           if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
1387             req_str = MC_request_to_string(req, value);
1388             XBT_DEBUG("Replay (depth = %d) : %s (%p)", depth, req_str, state);
1389             xbt_free(req_str);
1390           }
1391   
1392         }
1393  
1394         SIMIX_simcall_pre(req, value);
1395         MC_wait_for_requests();
1396       }
1397
1398       depth++;
1399     
1400       /* Update statistics */
1401       mc_stats->visited_pairs++;
1402       mc_stats->executed_transitions++;
1403
1404       item = xbt_fifo_get_prev_item(item);
1405     }
1406
1407   }else{
1408
1409     /* Traverse the stack from the initial state and re-execute the transitions */
1410     for (item = xbt_fifo_get_last_item(stack);
1411          item != xbt_fifo_get_first_item(stack);
1412          item = xbt_fifo_get_prev_item(item)) {
1413
1414       pair = (mc_pair_t) xbt_fifo_get_item_content(item);
1415       state = (mc_state_t) pair->graph_state;
1416
1417       if(pair->requests > 0){
1418    
1419         saved_req = MC_state_get_executed_request(state, &value);
1420         //XBT_DEBUG("SavedReq->call %u", saved_req->call);
1421       
1422         if(saved_req != NULL){
1423           /* because we got a copy of the executed request, we have to fetch the  
1424              real one, pointed by the request field of the issuer process */
1425           req = &saved_req->issuer->simcall;
1426           //XBT_DEBUG("Req->call %u", req->call);
1427   
1428           /* Debug information */
1429           if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
1430             req_str = MC_request_to_string(req, value);
1431             XBT_DEBUG("Replay (depth = %d) : %s (%p)", depth, req_str, state);
1432             xbt_free(req_str);
1433           }
1434   
1435         }
1436  
1437         SIMIX_simcall_pre(req, value);
1438         MC_wait_for_requests();
1439       }
1440
1441       depth++;
1442     
1443       /* Update statistics */
1444       mc_stats->visited_pairs++;
1445       mc_stats->executed_transitions++;
1446     }
1447   }  
1448
1449   XBT_DEBUG("**** End Replay ****");
1450
1451   if(initial_state_liveness->raw_mem_set)
1452     MC_SET_RAW_MEM;
1453   else
1454     MC_UNSET_RAW_MEM;
1455   
1456 }
1457
1458 /**
1459  * \brief Dumps the contents of a model-checker's stack and shows the actual
1460  *        execution trace
1461  * \param stack The stack to dump
1462  */
1463 void MC_dump_stack_safety(xbt_fifo_t stack)
1464 {
1465   
1466   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1467
1468   MC_show_stack_safety(stack);
1469
1470   if(!_sg_mc_checkpoint){
1471
1472     mc_state_t state;
1473
1474     MC_SET_RAW_MEM;
1475     while ((state = (mc_state_t) xbt_fifo_pop(stack)) != NULL)
1476       MC_state_delete(state);
1477     MC_UNSET_RAW_MEM;
1478
1479   }
1480
1481   if(raw_mem_set)
1482     MC_SET_RAW_MEM;
1483   else
1484     MC_UNSET_RAW_MEM;
1485   
1486 }
1487
1488
1489 void MC_show_stack_safety(xbt_fifo_t stack)
1490 {
1491
1492   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1493
1494   MC_SET_RAW_MEM;
1495
1496   int value;
1497   mc_state_t state;
1498   xbt_fifo_item_t item;
1499   smx_simcall_t req;
1500   char *req_str = NULL;
1501   
1502   for (item = xbt_fifo_get_last_item(stack);
1503        (item ? (state = (mc_state_t) (xbt_fifo_get_item_content(item)))
1504         : (NULL)); item = xbt_fifo_get_prev_item(item)) {
1505     req = MC_state_get_executed_request(state, &value);
1506     if(req){
1507       req_str = MC_request_to_string(req, value);
1508       XBT_INFO("%s", req_str);
1509       xbt_free(req_str);
1510     }
1511   }
1512
1513   if(!raw_mem_set)
1514     MC_UNSET_RAW_MEM;
1515 }
1516
1517 void MC_show_deadlock(smx_simcall_t req)
1518 {
1519   /*char *req_str = NULL;*/
1520   XBT_INFO("**************************");
1521   XBT_INFO("*** DEAD-LOCK DETECTED ***");
1522   XBT_INFO("**************************");
1523   XBT_INFO("Locked request:");
1524   /*req_str = MC_request_to_string(req);
1525     XBT_INFO("%s", req_str);
1526     xbt_free(req_str);*/
1527   XBT_INFO("Counter-example execution trace:");
1528   MC_dump_stack_safety(mc_stack_safety);
1529   MC_print_statistics(mc_stats);
1530 }
1531
1532
1533 void MC_show_stack_liveness(xbt_fifo_t stack){
1534   int value;
1535   mc_pair_t pair;
1536   xbt_fifo_item_t item;
1537   smx_simcall_t req;
1538   char *req_str = NULL;
1539   
1540   for (item = xbt_fifo_get_last_item(stack);
1541        (item ? (pair = (mc_pair_t) (xbt_fifo_get_item_content(item)))
1542         : (NULL)); item = xbt_fifo_get_prev_item(item)) {
1543     req = MC_state_get_executed_request(pair->graph_state, &value);
1544     if(req){
1545       if(pair->requests>0){
1546         req_str = MC_request_to_string(req, value);
1547         XBT_INFO("%s", req_str);
1548         xbt_free(req_str);
1549       }else{
1550         XBT_INFO("End of system requests but evolution in Büchi automaton");
1551       }
1552     }
1553   }
1554 }
1555
1556 void MC_dump_stack_liveness(xbt_fifo_t stack){
1557
1558   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1559
1560   mc_pair_t pair;
1561
1562   MC_SET_RAW_MEM;
1563   while ((pair = (mc_pair_t) xbt_fifo_pop(stack)) != NULL)
1564     MC_pair_delete(pair);
1565   MC_UNSET_RAW_MEM;
1566
1567   if(raw_mem_set)
1568     MC_SET_RAW_MEM;
1569
1570 }
1571
1572
1573 void MC_print_statistics(mc_stats_t stats)
1574 {
1575   if(stats->expanded_pairs == 0){
1576     XBT_INFO("Expanded states = %lu", stats->expanded_states);
1577     XBT_INFO("Visited states = %lu", stats->visited_states);
1578   }else{
1579     XBT_INFO("Expanded pairs = %lu", stats->expanded_pairs);
1580     XBT_INFO("Visited pairs = %lu", stats->visited_pairs);
1581   }
1582   XBT_INFO("Executed transitions = %lu", stats->executed_transitions);
1583   MC_SET_RAW_MEM;
1584   if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0')){
1585     fprintf(dot_output, "}\n");
1586     fclose(dot_output);
1587   }
1588   if(initial_state_safety != NULL){
1589     if(_sg_mc_comms_determinism)
1590       XBT_INFO("Communication-deterministic : %s", !initial_state_safety->comm_deterministic ? "No" : "Yes");
1591     if (_sg_mc_send_determinism)
1592       XBT_INFO("Send-deterministic : %s", !initial_state_safety->send_deterministic ? "No" : "Yes");
1593   }
1594   MC_UNSET_RAW_MEM;
1595 }
1596
1597 void MC_assert(int prop)
1598 {
1599   if (MC_is_active() && !prop){
1600     XBT_INFO("**************************");
1601     XBT_INFO("*** PROPERTY NOT VALID ***");
1602     XBT_INFO("**************************");
1603     XBT_INFO("Counter-example execution trace:");
1604     MC_dump_stack_safety(mc_stack_safety);
1605     MC_print_statistics(mc_stats);
1606     xbt_abort();
1607   }
1608 }
1609
1610 void MC_cut(void){
1611   user_max_depth_reached = 1;
1612 }
1613
1614 void MC_process_clock_add(smx_process_t process, double amount)
1615 {
1616   mc_time[process->pid] += amount;
1617 }
1618
1619 double MC_process_clock_get(smx_process_t process)
1620 {
1621   if(mc_time){
1622     if(process != NULL)
1623       return mc_time[process->pid];
1624     else 
1625       return -1;
1626   }else{
1627     return 0;
1628   }
1629 }
1630
1631 void MC_automaton_load(const char *file){
1632
1633   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1634
1635   MC_SET_RAW_MEM;
1636
1637   if (_mc_property_automaton == NULL)
1638     _mc_property_automaton = xbt_automaton_new();
1639   
1640   xbt_automaton_load(_mc_property_automaton,file);
1641
1642   MC_UNSET_RAW_MEM;
1643
1644   if(raw_mem_set)
1645     MC_SET_RAW_MEM;
1646
1647 }
1648
1649 void MC_automaton_new_propositional_symbol(const char* id, void* fct) {
1650
1651   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1652
1653   MC_SET_RAW_MEM;
1654
1655   if (_mc_property_automaton == NULL)
1656     _mc_property_automaton = xbt_automaton_new();
1657
1658   xbt_automaton_propositional_symbol_new(_mc_property_automaton,id,fct);
1659
1660   MC_UNSET_RAW_MEM;
1661
1662   if(raw_mem_set)
1663     MC_SET_RAW_MEM;
1664   
1665 }
1666
1667
1668