Logo AND Algorithmique Numérique Distribuée

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