Logo AND Algorithmique Numérique Distribuée

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