Logo AND Algorithmique Numérique Distribuée

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