Logo AND Algorithmique Numérique Distribuée

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