Logo AND Algorithmique Numérique Distribuée

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