Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Include ELF file name in object_info_t
[simgrid.git] / src / mc / mc_compare.c
1 /* Copyright (c) 2012-2013. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "mc_private.h"
8
9 #include "xbt/mmalloc.h"
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_compare, mc,
12                                 "Logging specific to mc_compare");
13
14 typedef struct s_pointers_pair{
15   void *p1;
16   void *p2;
17 }s_pointers_pair_t, *pointers_pair_t;
18
19 __thread xbt_dynar_t compared_pointers;
20
21 /************************** Free functions ****************************/
22 /********************************************************************/
23
24 static void stack_region_free(stack_region_t s){
25   if(s){
26     xbt_free(s->process_name);
27     xbt_free(s);
28   }
29 }
30
31 static void stack_region_free_voidp(void *s){
32   stack_region_free((stack_region_t) * (void **) s);
33 }
34
35 static void pointers_pair_free(pointers_pair_t p){
36   xbt_free(p);
37 }
38
39 static void pointers_pair_free_voidp(void *p){
40   pointers_pair_free((pointers_pair_t) * (void **)p);
41 }
42
43 /************************** Snapshot comparison *******************************/
44 /******************************************************************************/
45
46 static int already_compared_pointers(void *p1, void *p2){
47
48   if(xbt_dynar_is_empty(compared_pointers))
49     return -1;
50
51   unsigned int cursor = 0;
52   int start = 0;
53   int end = xbt_dynar_length(compared_pointers) - 1;
54   pointers_pair_t pair;
55
56   while(start <= end){
57     cursor = (start + end) / 2;
58     pair = (pointers_pair_t)xbt_dynar_get_as(compared_pointers, cursor, pointers_pair_t);
59     if(pair->p1 == p1){
60       if(pair->p2 == p2)
61         return 0;
62       else if(pair->p2 < p2)
63         start = cursor + 1;
64       else
65         end = cursor - 1;
66     }else if(pair->p1 < p1){
67       start = cursor + 1;
68     }else{
69       end = cursor - 1 ;
70     }
71   }
72
73   return -1;
74
75 }
76
77 static void add_compared_pointers(void *p1, void *p2){
78
79   pointers_pair_t new_pair = xbt_new0(s_pointers_pair_t, 1);
80   new_pair->p1 = p1;
81   new_pair->p2 = p2;
82   
83   if(xbt_dynar_is_empty(compared_pointers)){
84     xbt_dynar_push(compared_pointers, &new_pair);
85     return;
86   }
87
88   unsigned int cursor = 0;
89   int start = 0;
90   int end = xbt_dynar_length(compared_pointers) - 1;
91   pointers_pair_t pair = NULL;
92
93   while(start <= end){
94     cursor = (start + end) / 2;
95     pair = (pointers_pair_t)xbt_dynar_get_as(compared_pointers, cursor, pointers_pair_t);
96     if(pair->p1 == p1){
97       if(pair->p2 == p2){
98         pointers_pair_free(new_pair);
99         return;
100       }else if(pair->p2 < p2)
101         start = cursor + 1;
102       else
103         end = cursor - 1;
104     }else if(pair->p1 < p1){
105       start = cursor + 1;
106     }else{
107       end = cursor - 1 ;
108     }
109   }
110
111   if(pair->p1 == p1){
112     if(pair->p2 < p2)
113       xbt_dynar_insert_at(compared_pointers, cursor + 1, &new_pair);
114     else
115       xbt_dynar_insert_at(compared_pointers, cursor, &new_pair); 
116   }else{
117     if(pair->p1 < p1)
118       xbt_dynar_insert_at(compared_pointers, cursor + 1, &new_pair);
119     else
120       xbt_dynar_insert_at(compared_pointers, cursor, &new_pair);   
121   }
122
123 }
124
125 static int compare_areas_with_type(void *area1, void *area2, xbt_dict_t types, xbt_dict_t other_types, char *type_id, int region_size, int region_type, void *start_data, int pointer_level){
126
127   dw_type_t type = xbt_dict_get_or_null(types, type_id);;
128   unsigned int cursor = 0;
129   dw_type_t member, subtype, subsubtype;
130   int elm_size, i, res, switch_types = 0;
131   void *addr_pointed1, *addr_pointed2;
132
133   switch(type->type){
134   case e_dw_base_type:
135   case e_dw_enumeration_type:
136   case e_dw_union_type:
137     return (memcmp(area1, area2, type->size) != 0);
138     break;
139   case e_dw_typedef:
140   case e_dw_volatile_type:
141     return compare_areas_with_type(area1, area2, types, other_types, type->dw_type_id, region_size, region_type, start_data, pointer_level);
142     break;
143   case e_dw_const_type: /* Const variable cannot be modified */
144     return -1;
145     break;
146   case e_dw_array_type:
147     subtype = xbt_dict_get_or_null(types, type->dw_type_id);
148     switch(subtype->type){
149     case e_dw_base_type:
150     case e_dw_enumeration_type:
151     case e_dw_pointer_type:
152     case e_dw_structure_type:
153     case e_dw_union_type:
154       if(subtype->size == 0){ /*declaration of the type, need the complete description */
155         subtype = xbt_dict_get_or_null(types, get_type_description(types, subtype->name));
156         if(subtype == NULL){
157           subtype = xbt_dict_get_or_null(other_types, get_type_description(other_types, subtype->name));
158           switch_types = 1;
159         }
160       }
161       elm_size = subtype->size;
162       break;
163     case e_dw_typedef:
164     case e_dw_volatile_type:
165       subsubtype = xbt_dict_get_or_null(types, subtype->dw_type_id);
166       if(subsubtype->size == 0){ /*declaration of the type, need the complete description */
167         subsubtype = xbt_dict_get_or_null(types, get_type_description(types, subsubtype->name));
168         if(subsubtype == NULL){
169           subsubtype = xbt_dict_get_or_null(other_types, get_type_description(other_types, subsubtype->name));
170           switch_types = 1;
171         }
172       }
173       elm_size = subsubtype->size;
174       break;
175     default : 
176       return 0;
177       break;
178     }
179     for(i=0; i<type->size; i++){
180       if(switch_types)
181         res = compare_areas_with_type((char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), other_types, types, type->dw_type_id, region_size, region_type, start_data, pointer_level);
182       else
183         res = compare_areas_with_type((char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), types, other_types, type->dw_type_id, region_size, region_type, start_data, pointer_level);
184       if(res == 1)
185         return res;
186     }
187     break;
188   case e_dw_pointer_type: 
189     if(type->dw_type_id && ((dw_type_t)xbt_dict_get_or_null(types, type->dw_type_id))->type == e_dw_subroutine_type){
190       addr_pointed1 = *((void **)(area1)); 
191       addr_pointed2 = *((void **)(area2));
192       return (addr_pointed1 != addr_pointed2);
193     }else{
194       addr_pointed1 = *((void **)(area1)); 
195       addr_pointed2 = *((void **)(area2));
196       
197       if(addr_pointed1 == NULL && addr_pointed2 == NULL)
198         return 0;
199       if(already_compared_pointers(addr_pointed1, addr_pointed2) != -1)
200         return 0;
201       add_compared_pointers(addr_pointed1, addr_pointed2);
202
203       pointer_level++;
204       
205       if(addr_pointed1 > std_heap && (char *)addr_pointed1 < (char*) std_heap + STD_HEAP_SIZE && addr_pointed2 > std_heap && (char *)addr_pointed2 < (char*) std_heap + STD_HEAP_SIZE){
206         return compare_heap_area(addr_pointed1, addr_pointed2, NULL, types, other_types, type->dw_type_id, pointer_level); 
207       }else if(addr_pointed1 > start_data && (char*)addr_pointed1 <= (char *)start_data + region_size && addr_pointed2 > start_data && (char*)addr_pointed2 <= (char *)start_data + region_size){
208         if(type->dw_type_id == NULL)
209           return  (addr_pointed1 != addr_pointed2);
210         else
211           return  compare_areas_with_type(addr_pointed1, addr_pointed2, types, other_types, type->dw_type_id, region_size, region_type, start_data, pointer_level); 
212       }else{
213         return (addr_pointed1 != addr_pointed2);
214       }
215     }
216     break;
217   case e_dw_structure_type:
218     xbt_dynar_foreach(type->members, cursor, member){
219       res = compare_areas_with_type((char *)area1 + member->offset, (char *)area2 + member->offset, types, other_types, member->dw_type_id, region_size, region_type, start_data, pointer_level);
220       if(res == 1)
221         return res;
222     }
223     break;
224   case e_dw_subroutine_type:
225     return -1;
226     break;
227   default:
228     XBT_VERB("Unknown case : %d", type->type);
229     break;
230   }
231   
232   return 0;
233 }
234
235 static int compare_global_variables(int region_type, mc_mem_region_t r1, mc_mem_region_t r2){
236
237   if(!compared_pointers){
238     compared_pointers = xbt_dynar_new(sizeof(pointers_pair_t), pointers_pair_free_voidp);
239     MC_ignore_global_variable("compared_pointers");
240   }else{
241     xbt_dynar_reset(compared_pointers);
242   }
243
244   xbt_dynar_t variables;
245   xbt_dict_t types, other_types;
246   int res;
247   unsigned int cursor = 0;
248   dw_variable_t current_var;
249   size_t offset;
250   void *start_data;
251
252   mc_object_info_t object_info = NULL;
253   mc_object_info_t other_object_info = NULL;
254   if(region_type == 2){
255     object_info = mc_binary_info;
256     other_object_info = mc_libsimgrid_info;
257     start_data = start_data_binary;
258   }else{
259     object_info = mc_libsimgrid_info;
260     other_object_info = mc_binary_info;
261     start_data = start_data_libsimgrid;
262   }
263   variables = object_info->global_variables;
264   types = object_info->types;
265   other_types = other_object_info->types;
266
267   xbt_dynar_foreach(variables, cursor, current_var){
268
269     if(region_type == 2)
270       offset = (char *)current_var->address.address - (char *)start_data_binary;
271     else
272       offset = (char *)current_var->address.address - (char *)start_data_libsimgrid;
273
274     res = compare_areas_with_type((char *)r1->data + offset, (char *)r2->data + offset, types, other_types, current_var->type_origin, r1->size, region_type, start_data, 0);
275     if(res == 1){
276       XBT_VERB("Global variable %s (%p - %p) is different between snapshots", current_var->name, (char *)r1->data + offset, (char *)r2->data + offset);
277       xbt_dynar_free(&compared_pointers);
278       compared_pointers = NULL;
279       return 1;
280     }
281
282   }
283
284   xbt_dynar_free(&compared_pointers);
285   compared_pointers = NULL;
286
287   return 0;
288
289 }
290
291 static int compare_local_variables(mc_snapshot_stack_t stack1, mc_snapshot_stack_t stack2, void *heap1, void *heap2){
292
293   if(!compared_pointers){
294     compared_pointers = xbt_dynar_new(sizeof(pointers_pair_t), pointers_pair_free_voidp);
295     MC_ignore_global_variable("compared_pointers");
296   }else{
297     xbt_dynar_reset(compared_pointers);
298   }
299
300   if(xbt_dynar_length(stack1->local_variables) != xbt_dynar_length(stack2->local_variables)){
301     XBT_VERB("Different number of local variables");
302     xbt_dynar_free(&compared_pointers);
303     compared_pointers = NULL;
304     return 1;
305   }else{
306     unsigned int cursor = 0;
307     local_variable_t current_var1, current_var2;
308     int offset1, offset2, res;
309     while(cursor < xbt_dynar_length(stack1->local_variables)){
310       current_var1 = (local_variable_t)xbt_dynar_get_as(stack1->local_variables, cursor, local_variable_t);
311       current_var2 = (local_variable_t)xbt_dynar_get_as(stack2->local_variables, cursor, local_variable_t);
312       if(strcmp(current_var1->name, current_var2->name) != 0 || strcmp(current_var1->frame, current_var2->frame) != 0 || current_var1->ip != current_var2->ip){
313         xbt_dynar_free(&compared_pointers);
314         XBT_VERB("Different name of variable (%s - %s) or frame (%s - %s) or ip (%lu - %lu)", current_var1->name, current_var2->name, current_var1->frame, current_var2->frame, current_var1->ip, current_var2->ip);
315         return 1;
316       }
317       offset1 = (char *)current_var1->address - (char *)std_heap;
318       offset2 = (char *)current_var2->address - (char *)std_heap;
319       if(current_var1->region == 1)
320         res = compare_areas_with_type( (char *)heap1 + offset1, (char *)heap2 + offset2, mc_libsimgrid_info->types, mc_binary_info->types, current_var1->type, 0, 1, start_data_libsimgrid, 0);
321       else
322         res = compare_areas_with_type( (char *)heap1 + offset1, (char *)heap2 + offset2, mc_binary_info->types, mc_libsimgrid_info->types, current_var1->type, 0, 2, start_data_binary, 0);
323       if(res == 1){
324         XBT_VERB("Local variable %s (%p - %p) in frame %s  is different between snapshots", current_var1->name,(char *)heap1 + offset1, (char *)heap2 + offset2, current_var1->frame);
325         xbt_dynar_free(&compared_pointers);
326         compared_pointers = NULL;
327         return res;
328       }
329       cursor++;
330     }
331     xbt_dynar_free(&compared_pointers);
332     compared_pointers = NULL;
333     return 0;
334   }
335 }
336
337 int snapshot_compare(void *state1, void *state2){
338
339   mc_snapshot_t s1, s2;
340   int num1, num2;
341   
342   if(_sg_mc_property_file && _sg_mc_property_file[0] != '\0'){ /* Liveness MC */
343     s1 = ((mc_visited_pair_t)state1)->graph_state->system_state;
344     s2 = ((mc_visited_pair_t)state2)->graph_state->system_state;
345     num1 = ((mc_visited_pair_t)state1)->num;
346     num2 =  ((mc_visited_pair_t)state2)->num;
347     /* Firstly compare automaton state */
348     /*if(xbt_automaton_state_compare(((mc_pair_t)state1)->automaton_state, ((mc_pair_t)state2)->automaton_state) != 0)
349       return 1;
350     if(xbt_automaton_propositional_symbols_compare_value(((mc_pair_t)state1)->atomic_propositions, ((mc_pair_t)state2)->atomic_propositions) != 0)
351     return 1;*/
352   }else{ /* Safety MC */
353     s1 = ((mc_visited_state_t)state1)->system_state;
354     s2 = ((mc_visited_state_t)state2)->system_state;
355     num1 = ((mc_visited_state_t)state1)->num;
356     num2 = ((mc_visited_state_t)state2)->num;
357   }
358
359   int errors = 0;
360   int res_init;
361
362   xbt_os_timer_t global_timer = xbt_os_timer_new();
363   xbt_os_timer_t timer = xbt_os_timer_new();
364
365   xbt_os_walltimer_start(global_timer);
366
367   #ifdef MC_DEBUG
368     xbt_os_walltimer_start(timer);
369   #endif
370
371   /* Compare size of stacks */
372   int i = 0;
373   size_t size_used1, size_used2;
374   int is_diff = 0;
375   while(i < xbt_dynar_length(s1->stacks)){
376     size_used1 = s1->stack_sizes[i];
377     size_used2 = s2->stack_sizes[i];
378     if(size_used1 != size_used2){
379     #ifdef MC_DEBUG
380       if(is_diff == 0){
381         xbt_os_walltimer_stop(timer);
382         mc_comp_times->stacks_sizes_comparison_time = xbt_os_timer_elapsed(timer);
383       }
384       XBT_DEBUG("(%d - %d) Different size used in stacks : %zu - %zu", num1, num2, size_used1, size_used2);
385       errors++;
386       is_diff = 1;
387     #else
388       #ifdef MC_VERBOSE
389       XBT_VERB("(%d - %d) Different size used in stacks : %zu - %zu", num1, num2, size_used1, size_used2);
390       #endif
391
392       xbt_os_walltimer_stop(timer);
393       xbt_os_timer_free(timer);
394       xbt_os_walltimer_stop(global_timer);
395       mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer);
396       xbt_os_timer_free(global_timer);
397
398       return 1;
399     #endif  
400     }
401     i++;
402   }
403
404   #ifdef MC_DEBUG
405     if(is_diff == 0)
406       xbt_os_walltimer_stop(timer);
407     xbt_os_walltimer_start(timer);
408   #endif
409
410   /* Compare hash of global variables */
411   if(s1->hash_global != NULL && s2->hash_global != NULL){
412     if(strcmp(s1->hash_global, s2->hash_global) != 0){
413       #ifdef MC_DEBUG
414         xbt_os_walltimer_stop(timer);
415         mc_comp_times->hash_global_variables_comparison_time = xbt_os_timer_elapsed(timer);
416         XBT_DEBUG("Different hash of global variables : %s - %s", s1->hash_global, s2->hash_global); 
417         errors++; 
418       #else
419         #ifdef MC_VERBOSE
420           XBT_VERB("Different hash of global variables : %s - %s", s1->hash_global, s2->hash_global); 
421         #endif
422
423         xbt_os_walltimer_stop(timer);
424         xbt_os_timer_free(timer);
425         xbt_os_walltimer_stop(global_timer);
426         mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer);
427         xbt_os_timer_free(global_timer);
428
429         return 1;
430       #endif
431     }
432   }
433
434   #ifdef MC_DEBUG
435     xbt_os_walltimer_start(timer);
436   #endif
437
438   /* Compare hash of local variables */
439   if(s1->hash_local != NULL && s2->hash_local != NULL){
440     if(strcmp(s1->hash_local, s2->hash_local) != 0){
441       #ifdef MC_DEBUG
442         xbt_os_walltimer_stop(timer);
443         mc_comp_times->hash_local_variables_comparison_time = xbt_os_timer_elapsed(timer);
444         XBT_DEBUG("Different hash of local variables : %s - %s", s1->hash_local, s2->hash_local); 
445         errors++; 
446       #else
447         #ifdef MC_VERBOSE
448           XBT_VERB("Different hash of local variables : %s - %s", s1->hash_local, s2->hash_local); 
449         #endif
450
451         xbt_os_walltimer_stop(timer);
452         xbt_os_timer_free(timer);
453         xbt_os_walltimer_stop(global_timer);
454         mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer);
455         xbt_os_timer_free(global_timer);
456
457         return 1;
458       #endif
459     }
460   }
461
462   #ifdef MC_DEBUG
463     xbt_os_walltimer_start(timer);
464   #endif
465
466   /* Init heap information used in heap comparison algorithm */
467   res_init = init_heap_information((xbt_mheap_t)s1->regions[0]->data, (xbt_mheap_t)s2->regions[0]->data, s1->to_ignore, s2->to_ignore);
468   if(res_init == -1){
469      #ifdef MC_DEBUG
470     XBT_DEBUG("(%d - %d) Different heap information", num1, num2); 
471         errors++; 
472       #else
473         #ifdef MC_VERBOSE
474         XBT_VERB("(%d - %d) Different heap information", num1, num2); 
475         #endif
476
477         xbt_os_walltimer_stop(global_timer);
478         mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer);
479         xbt_os_timer_free(global_timer);
480
481         return 1;
482       #endif
483   }
484
485   #ifdef MC_DEBUG
486     xbt_os_walltimer_start(timer);
487   #endif
488
489   /* Stacks comparison */
490   unsigned int  cursor = 0;
491   int diff_local = 0;
492   is_diff = 0;
493   mc_snapshot_stack_t stack1, stack2;
494     
495   while(cursor < xbt_dynar_length(s1->stacks)){
496     stack1 = (mc_snapshot_stack_t)xbt_dynar_get_as(s1->stacks, cursor, mc_snapshot_stack_t);
497     stack2 = (mc_snapshot_stack_t)xbt_dynar_get_as(s2->stacks, cursor, mc_snapshot_stack_t);
498     diff_local = compare_local_variables(stack1, stack2, s1->regions[0]->data, s2->regions[0]->data);
499     if(diff_local > 0){
500       #ifdef MC_DEBUG
501         if(is_diff == 0){
502           xbt_os_walltimer_stop(timer);
503           mc_comp_times->stacks_comparison_time = xbt_os_timer_elapsed(timer);
504         }
505         XBT_DEBUG("(%d - %d) Different local variables between stacks %d", num1, num2, cursor + 1);
506         errors++;
507         is_diff = 1;
508       #else
509         
510         #ifdef MC_VERBOSE
511         XBT_VERB("(%d - %d) Different local variables between stacks %d", num1, num2, cursor + 1);
512         #endif
513           
514         reset_heap_information();
515         xbt_os_walltimer_stop(timer);
516         xbt_os_timer_free(timer);
517         xbt_os_walltimer_stop(global_timer);
518         mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer);
519         xbt_os_timer_free(global_timer);
520  
521         return 1;
522       #endif
523     }
524     cursor++;
525   }
526
527   #ifdef MC_DEBUG
528     if(is_diff == 0)
529       xbt_os_walltimer_stop(timer);
530     xbt_os_walltimer_start(timer);
531   #endif
532
533   /* Compare binary global variables */
534   is_diff = compare_global_variables(2, s1->regions[2], s2->regions[2]);
535   if(is_diff != 0){
536     #ifdef MC_DEBUG
537       xbt_os_walltimer_stop(timer);
538       mc_comp_times->binary_global_variables_comparison_time = xbt_os_timer_elapsed(timer);
539       XBT_DEBUG("(%d - %d) Different global variables in binary", num1, num2);
540       errors++;
541     #else
542       #ifdef MC_VERBOSE
543       XBT_VERB("(%d - %d) Different global variables in binary", num1, num2);
544       #endif
545
546       reset_heap_information();
547       xbt_os_walltimer_stop(timer);
548       xbt_os_timer_free(timer);
549       xbt_os_walltimer_stop(global_timer);
550       mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer);
551       xbt_os_timer_free(global_timer);
552
553       return 1;
554     #endif
555   }
556
557   #ifdef MC_DEBUG
558     if(is_diff == 0)
559       xbt_os_walltimer_stop(timer);
560     xbt_os_walltimer_start(timer);
561   #endif
562
563   /* Compare libsimgrid global variables */
564   is_diff = compare_global_variables(1, s1->regions[1], s2->regions[1]);
565   if(is_diff != 0){
566     #ifdef MC_DEBUG
567       xbt_os_walltimer_stop(timer);
568       mc_comp_times->libsimgrid_global_variables_comparison_time = xbt_os_timer_elapsed(timer);
569       XBT_DEBUG("(%d - %d) Different global variables in libsimgrid", num1, num2);
570       errors++;
571     #else
572       #ifdef MC_VERBOSE
573       XBT_VERB("(%d - %d) Different global variables in libsimgrid", num1, num2);
574       #endif
575         
576       reset_heap_information();
577       xbt_os_walltimer_stop(timer);
578       xbt_os_timer_free(timer);
579       xbt_os_walltimer_stop(global_timer);
580       mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer);
581       xbt_os_timer_free(global_timer);
582
583       return 1;
584     #endif
585   }
586
587   #ifdef MC_DEBUG
588     xbt_os_walltimer_start(timer);
589   #endif
590
591   /* Compare heap */
592     if(mmalloc_compare_heap((xbt_mheap_t)s1->regions[0]->data,
593                             (xbt_mheap_t)s2->regions[0]->data,
594                             mc_libsimgrid_info->types,
595                             mc_binary_info->types) > 0){
596
597     #ifdef MC_DEBUG
598       xbt_os_walltimer_stop(timer);
599       mc_comp_times->heap_comparison_time = xbt_os_timer_elapsed(timer); 
600       XBT_DEBUG("(%d - %d) Different heap (mmalloc_compare)", num1, num2);
601       errors++;
602     #else
603  
604       #ifdef MC_VERBOSE
605       XBT_VERB("(%d - %d) Different heap (mmalloc_compare)", num1, num2);
606       #endif
607        
608       reset_heap_information();
609       xbt_os_walltimer_stop(timer);
610       xbt_os_timer_free(timer);
611       xbt_os_walltimer_stop(global_timer);
612       mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer);
613       xbt_os_timer_free(global_timer);
614
615       return 1;
616     #endif
617   }else{
618     #ifdef MC_DEBUG
619       xbt_os_walltimer_stop(timer);
620     #endif
621   }
622
623   reset_heap_information();
624   
625   xbt_os_walltimer_stop(timer);
626   xbt_os_timer_free(timer);
627
628   #ifdef MC_VERBOSE
629     xbt_os_walltimer_stop(global_timer);
630     mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer);
631   #endif
632
633   xbt_os_timer_free(global_timer);
634
635   #ifdef MC_DEBUG
636     print_comparison_times();
637   #endif
638
639   return errors > 0;
640   
641 }
642
643 /***************************** Statistics *****************************/
644 /*******************************************************************/
645
646 void print_comparison_times(){
647   XBT_DEBUG("*** Comparison times ***");
648   XBT_DEBUG("- Nb processes : %f", mc_comp_times->nb_processes_comparison_time);
649   XBT_DEBUG("- Nb bytes used : %f", mc_comp_times->bytes_used_comparison_time);
650   XBT_DEBUG("- Stacks sizes : %f", mc_comp_times->stacks_sizes_comparison_time);
651   XBT_DEBUG("- Binary global variables : %f", mc_comp_times->binary_global_variables_comparison_time);
652   XBT_DEBUG("- Libsimgrid global variables : %f", mc_comp_times->libsimgrid_global_variables_comparison_time);
653   XBT_DEBUG("- Heap : %f", mc_comp_times->heap_comparison_time);
654   XBT_DEBUG("- Stacks : %f", mc_comp_times->stacks_comparison_time);
655 }
656
657 /**************************** MC snapshot compare simcall **************************/
658 /***********************************************************************************/
659
660 int SIMIX_pre_mc_compare_snapshots(smx_simcall_t simcall,
661                                    mc_snapshot_t s1, mc_snapshot_t s2){
662   return snapshot_compare(s1, s2);
663 }
664
665 int MC_compare_snapshots(void *s1, void *s2){
666   
667   MC_ignore_local_variable("self", "simcall_BODY_mc_snapshot");
668   return simcall_mc_compare_snapshots(s1, s2);
669
670 }