Logo AND Algorithmique Numérique Distribuée

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