Logo AND Algorithmique Numérique Distribuée

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