Logo AND Algorithmique Numérique Distribuée

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