Logo AND Algorithmique Numérique Distribuée

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