Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
model-checker : simplify algorithm for the verification of liveness properties
[simgrid.git] / src / xbt / mmalloc / mm_diff.c
1 /* mm_diff - Memory snapshooting and comparison                             */
2
3 /* Copyright (c) 2008-2012. The SimGrid Team. All rights reserved.          */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "xbt/ex_interface.h" /* internals of backtrace setup */
9 #include "xbt/str.h"
10 #include "mc/mc.h"
11 #include "xbt/mmalloc.h"
12
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mm_diff, xbt,
14                                 "Logging specific to mm_diff in mmalloc");
15
16 xbt_dynar_t mc_heap_comparison_ignore;
17 xbt_dynar_t stacks_areas;
18 void *maestro_stack_start, *maestro_stack_end;
19
20 static void heap_area_pair_free(heap_area_pair_t pair);
21 static void heap_area_pair_free_voidp(void *d);
22 static int add_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2);
23 static int is_new_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2);
24 static heap_area_t new_heap_area(int block, int fragment);
25
26 static size_t heap_comparison_ignore_size(xbt_dynar_t list, void *address);
27 static void add_heap_equality(xbt_dynar_t equals, void *a1, void *a2);
28 static void remove_heap_equality(xbt_dynar_t equals, int address, void *a);
29
30 static int is_stack(void *address);
31 static int is_block_stack(int block);
32 static int equal_blocks(int b1, int b2);
33 static int equal_fragments(int b1, int f1, int b2, int f2);
34
35 void mmalloc_backtrace_block_display(void* heapinfo, int block){
36
37   /* xbt_ex_t e; */
38
39   /* if (((malloc_info *)heapinfo)[block].busy_block.bt_size == 0) { */
40   /*   fprintf(stderr, "No backtrace available for that block, sorry.\n"); */
41   /*   return; */
42   /* } */
43
44   /* memcpy(&e.bt,&(((malloc_info *)heapinfo)[block].busy_block.bt),sizeof(void*)*XBT_BACKTRACE_SIZE); */
45   /* e.used = ((malloc_info *)heapinfo)[block].busy_block.bt_size; */
46
47   /* xbt_ex_setup_backtrace(&e); */
48   /* if (e.used == 0) { */
49   /*   fprintf(stderr, "(backtrace not set)\n"); */
50   /* } else if (e.bt_strings == NULL) { */
51   /*   fprintf(stderr, "(backtrace not ready to be computed. %s)\n",xbt_binary_name?"Dunno why":"xbt_binary_name not setup yet"); */
52   /* } else { */
53   /*   int i; */
54
55   /*   fprintf(stderr, "Backtrace of where the block %d was malloced (%d frames):\n", block ,e.used); */
56   /*   for (i = 0; i < e.used; i++)       /\* no need to display "xbt_backtrace_display" *\/{ */
57   /*     fprintf(stderr, "%d ---> %s\n",i, e.bt_strings[i] + 4); */
58   /*   } */
59   /* } */
60 }
61
62 void mmalloc_backtrace_fragment_display(void* heapinfo, int block, int frag){
63
64   /* xbt_ex_t e; */
65
66   /* memcpy(&e.bt,&(((malloc_info *)heapinfo)[block].busy_frag.bt[frag]),sizeof(void*)*XBT_BACKTRACE_SIZE); */
67   /* e.used = XBT_BACKTRACE_SIZE; */
68
69   /* xbt_ex_setup_backtrace(&e); */
70   /* if (e.used == 0) { */
71   /*   fprintf(stderr, "(backtrace not set)\n"); */
72   /* } else if (e.bt_strings == NULL) { */
73   /*   fprintf(stderr, "(backtrace not ready to be computed. %s)\n",xbt_binary_name?"Dunno why":"xbt_binary_name not setup yet"); */
74   /* } else { */
75   /*   int i; */
76
77   /*   fprintf(stderr, "Backtrace of where the fragment %d in block %d was malloced (%d frames):\n", frag, block ,e.used); */
78   /*   for (i = 0; i < e.used; i++)       /\* no need to display "xbt_backtrace_display" *\/{ */
79   /*     fprintf(stderr, "%d ---> %s\n",i, e.bt_strings[i] + 4); */
80   /*   } */
81   /* } */
82
83 }
84
85 void mmalloc_backtrace_display(void *addr){
86
87   /* size_t block, frag_nb; */
88   /* int type; */
89   
90   /* xbt_mheap_t heap = __mmalloc_current_heap ?: (xbt_mheap_t) mmalloc_preinit(); */
91
92   /* block = (((char*) (addr) - (char*) heap -> heapbase) / BLOCKSIZE + 1); */
93
94   /* type = heap->heapinfo[block].type; */
95
96   /* switch(type){ */
97   /* case -1 : /\* Free block *\/ */
98   /*   fprintf(stderr, "Asked to display the backtrace of a block that is free. I'm puzzled\n"); */
99   /*   xbt_abort(); */
100   /*   break;  */
101   /* case 0: /\* Large block *\/ */
102   /*   mmalloc_backtrace_block_display(heap->heapinfo, block); */
103   /*   break; */
104   /* default: /\* Fragmented block *\/ */
105   /*   frag_nb = RESIDUAL(addr, BLOCKSIZE) >> type; */
106   /*   if(heap->heapinfo[block].busy_frag.frag_size[frag_nb] == -1){ */
107   /*     fprintf(stderr , "Asked to display the backtrace of a fragment that is free. I'm puzzled\n"); */
108   /*     xbt_abort(); */
109   /*   } */
110   /*   mmalloc_backtrace_fragment_display(heap->heapinfo, block, frag_nb); */
111   /*   break; */
112   /* } */
113 }
114
115
116 void *s_heap = NULL, *heapbase1 = NULL, *heapbase2 = NULL;
117 malloc_info *heapinfo1 = NULL, *heapinfo2 = NULL;
118 size_t heaplimit = 0, heapsize1 = 0, heapsize2 = 0;
119 xbt_dynar_t to_ignore1 = NULL, to_ignore2 = NULL;
120
121 void init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t i1, xbt_dynar_t i2){
122
123   heaplimit = ((struct mdesc *)heap1)->heaplimit;
124
125   s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize();
126
127   heapbase1 = (char *)heap1 + BLOCKSIZE;
128   heapbase2 = (char *)heap2 + BLOCKSIZE;
129
130   heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)((struct mdesc *)heap1)->heapinfo - (char *)s_heap)));
131   heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)((struct mdesc *)heap2)->heapinfo - (char *)s_heap)));
132
133   heapsize1 = heap1->heapsize;
134   heapsize2 = heap2->heapsize;
135
136   to_ignore1 = i1;
137   to_ignore2 = i2;
138
139   if(MC_is_active()){
140     MC_ignore_data_bss(&heaplimit, sizeof(heaplimit));
141     MC_ignore_data_bss(&s_heap, sizeof(s_heap));
142     MC_ignore_data_bss(&heapbase1, sizeof(heapbase1));
143     MC_ignore_data_bss(&heapbase2, sizeof(heapbase2));
144     MC_ignore_data_bss(&heapinfo1, sizeof(heapinfo1));
145     MC_ignore_data_bss(&heapinfo2, sizeof(heapinfo2));
146     MC_ignore_data_bss(&heapsize1, sizeof(heapsize1));
147     MC_ignore_data_bss(&heapsize2, sizeof(heapsize2));
148     MC_ignore_data_bss(&to_ignore1, sizeof(to_ignore1));
149     MC_ignore_data_bss(&to_ignore2, sizeof(to_ignore2));
150   }
151 }
152
153 int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2){
154
155   if(heap1 == NULL && heap1 == NULL){
156     XBT_DEBUG("Malloc descriptors null");
157     return 0;
158   }
159
160   if(heap1->heaplimit != heap2->heaplimit){
161     XBT_DEBUG("Different limit of valid info table indices");
162     return 1;
163   }
164
165   /* Start comparison */
166   size_t i1, i2, j1, j2, k;
167   size_t current_block = -1;    /* avoid "maybe uninitialized" warning */
168   size_t current_fragment;
169   void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2;
170   int nb_diff1 = 0, nb_diff2 = 0;
171
172   xbt_dynar_t previous = xbt_dynar_new(sizeof(heap_area_pair_t), heap_area_pair_free_voidp);
173
174   int equal, res_compare = 0;
175
176   /* Check busy blocks*/
177
178   i1 = 1;
179
180   while(i1 <= heaplimit){
181
182     current_block = i1;
183
184     if(heapinfo1[i1].type == -1){ /* Free block */
185       i1++;
186       continue;
187     }
188
189     addr_block1 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
190
191     if(heapinfo1[i1].type == 0){  /* Large block */
192       
193       if(is_stack(addr_block1)){
194         for(k=0; k < heapinfo1[i1].busy_block.size; k++)
195           heapinfo1[i1+k].busy_block.equal_to = new_heap_area(i1, -1);
196         for(k=0; k < heapinfo2[i1].busy_block.size; k++)
197           heapinfo2[i1+k].busy_block.equal_to = new_heap_area(i1, -1);
198         i1 = i1 + heapinfo1[current_block].busy_block.size;
199         continue;
200       }
201
202       if(heapinfo1[i1].busy_block.equal_to != NULL){
203         i1++;
204         continue;
205       }
206     
207       i2 = 1;
208       equal = 0;
209       res_compare = 0;
210   
211       /* Try first to associate to same block in the other heap */
212       if(heapinfo2[current_block].type == heapinfo1[current_block].type){
213
214         if(heapinfo2[current_block].busy_block.equal_to == NULL){  
215         
216           addr_block2 = ((void*) (((ADDR2UINT(current_block)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
217         
218           res_compare = compare_area(addr_block1, addr_block2, NULL);
219         
220           if(res_compare == 0){
221             for(k=1; k < heapinfo2[current_block].busy_block.size; k++)
222               heapinfo2[current_block+k].busy_block.equal_to = new_heap_area(i1, -1);
223             for(k=1; k < heapinfo1[current_block].busy_block.size; k++)
224               heapinfo1[current_block+k].busy_block.equal_to = new_heap_area(i1, -1);
225             equal = 1;
226             i1 = i1 + heapinfo1[current_block].busy_block.size;
227           }
228         
229           xbt_dynar_reset(previous);
230         
231         }
232         
233       }
234
235       while(i2 <= heaplimit && !equal){
236
237         addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));        
238            
239         if(i2 == current_block){
240           i2++;
241           continue;
242         }
243
244         if(heapinfo2[i2].type != 0){
245           i2++;
246           continue;
247         }
248
249         if(heapinfo2[i2].busy_block.equal_to != NULL){         
250           i2++;
251           continue;
252         }
253           
254         res_compare = compare_area(addr_block1, addr_block2, NULL);
255         
256         if(res_compare == 0){
257           for(k=1; k < heapinfo2[i2].busy_block.size; k++)
258             heapinfo2[i2+k].busy_block.equal_to = new_heap_area(i1, -1);
259           for(k=1; k < heapinfo1[i1].busy_block.size; k++)
260             heapinfo1[i1+k].busy_block.equal_to = new_heap_area(i2, -1);
261           equal = 1;
262           i1 = i1 + heapinfo1[i1].busy_block.size;
263         }
264
265         xbt_dynar_reset(previous);
266
267         i2++;
268
269       }
270
271       if(!equal){
272         /*XBT_DEBUG("Block %zu not found (size_used = %zu, addr = %p)", i1, heapinfo1[i1].busy_block.busy_size, addr_block1);
273         i1 = heaplimit + 1;
274         nb_diff1++;*/
275         i1++;
276       }
277       
278     }else{ /* Fragmented block */
279
280       for(j1=0; j1 < (size_t) (BLOCKSIZE >> heapinfo1[i1].type); j1++){
281
282         current_fragment = j1;
283
284         if(heapinfo1[i1].busy_frag.frag_size[j1] == -1) /* Free fragment */
285           continue;
286
287         if(heapinfo1[i1].busy_frag.equal_to[j1] != NULL)
288           continue;
289
290         addr_frag1 = (void*) ((char *)addr_block1 + (j1 << heapinfo1[i1].type));
291
292         i2 = 1;
293         equal = 0;
294         
295         /* Try first to associate to same fragment in the other heap */
296         if(heapinfo2[current_block].type == heapinfo1[current_block].type){
297
298           if(heapinfo2[current_block].busy_frag.equal_to[current_fragment] == NULL){  
299           
300             addr_block2 = ((void*) (((ADDR2UINT(current_block)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
301             addr_frag2 = (void*) ((char *)addr_block2 + (current_fragment << ((xbt_mheap_t)s_heap)->heapinfo[current_block].type));
302
303             res_compare = compare_area(addr_frag1, addr_frag2, NULL);
304
305             if(res_compare == 0)
306               equal = 1;
307         
308             xbt_dynar_reset(previous);
309
310           }
311
312         }
313
314         while(i2 <= heaplimit && !equal){
315
316           
317           if(heapinfo2[i2].type <= 0){
318             i2++;
319             continue;
320           }
321
322           for(j2=0; j2 < (size_t) (BLOCKSIZE >> heapinfo2[i2].type); j2++){
323
324             if(i2 == current_block && j2 == current_fragment)
325               continue;
326
327             if(heapinfo2[i2].busy_frag.equal_to[j2] != NULL)                
328               continue;            
329                           
330             addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
331             addr_frag2 = (void*) ((char *)addr_block2 + (j2 << ((xbt_mheap_t)s_heap)->heapinfo[i2].type));
332
333             res_compare = compare_area(addr_frag1, addr_frag2, NULL);
334             
335             if(res_compare == 0){
336               equal = 1;
337               xbt_dynar_reset(previous);
338               break;
339             }
340
341             xbt_dynar_reset(previous);
342
343           }
344
345           i2++;
346
347         }
348
349         /*if(heapinfo1[i1].busy_frag.equal_to[j1] == NULL){
350           fprintf(stderr,"Block %zu, fragment %zu not found (size_used = %zd, address = %p, ignore %d)\n", i1, j1, heapinfo1[i1].busy_frag.frag_size[j1], addr_frag1, heapinfo1[i1].busy_frag.ignore[j1]);
351           i2 = heaplimit + 1;
352           i1 = heaplimit + 1;
353           nb_diff1++;
354           break;
355           }*/
356
357       }
358
359       i1++;
360       
361     }
362
363   }
364
365   /* All blocks/fragments are equal to another block/fragment ? */
366   size_t i = 1, j = 0;
367   void *real_addr_frag1 = NULL, *real_addr_block1 = NULL, *real_addr_block2 = NULL, *real_addr_frag2 = NULL;
368  
369   while(i<=heaplimit){
370     if(heapinfo1[i].type == 0){
371       if(current_block == heaplimit){
372         if(heapinfo1[i].busy_block.busy_size > 0){
373           if(heapinfo1[i].busy_block.equal_to == NULL){
374             if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){
375               addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1));
376               XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i, addr_block1, heapinfo1[i].busy_block.busy_size);
377               //mmalloc_backtrace_block_display((void*)heapinfo1, i);
378             }
379             nb_diff1++;
380           }
381         }
382       }
383     }
384     if(heapinfo1[i].type > 0){
385       addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1));
386       real_addr_block1 =  ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)((struct mdesc *)s_heap)->heapbase));
387       for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo1[i].type); j++){
388         if(current_block == heaplimit){
389           if(heapinfo1[i].busy_frag.frag_size[j] > 0){
390             if(heapinfo1[i].busy_frag.equal_to[j] == NULL){
391               if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){
392                 addr_frag1 = (void*) ((char *)addr_block1 + (j << heapinfo1[i].type));
393                 real_addr_frag1 = (void*) ((char *)real_addr_block1 + (j << ((struct mdesc *)s_heap)->heapinfo[i].type));
394                 XBT_DEBUG("Block %zu, Fragment %zu (%p - %p) not found (size used = %zd)", i, j, addr_frag1, real_addr_frag1, heapinfo1[i].busy_frag.frag_size[j]);
395                 //mmalloc_backtrace_fragment_display((void*)heapinfo1, i, j);
396               }
397               nb_diff1++;
398             }
399           }
400         }
401       }
402     }
403     i++; 
404   }
405
406   if(current_block == heaplimit)
407     XBT_DEBUG("Number of blocks/fragments not found in heap1 : %d", nb_diff1);
408
409   i = 1;
410
411   while(i<=heaplimit){
412     if(heapinfo2[i].type == 0){
413       if(current_block == heaplimit){
414         if(heapinfo2[i].busy_block.busy_size > 0){
415           if(heapinfo2[i].busy_block.equal_to == NULL){
416             if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){
417               addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2));
418               XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i, addr_block2, heapinfo2[i].busy_block.busy_size);
419               //mmalloc_backtrace_block_display((void*)heapinfo2, i);
420             }
421             nb_diff2++;
422           }
423         }
424       }
425     }
426     if(heapinfo2[i].type > 0){
427       addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2));
428       real_addr_block2 =  ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)((struct mdesc *)s_heap)->heapbase));
429       for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo2[i].type); j++){
430         if(current_block == heaplimit){
431           if(heapinfo2[i].busy_frag.frag_size[j] > 0){
432             if(heapinfo2[i].busy_frag.equal_to[j] == NULL){
433               if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){
434                 addr_frag2 = (void*) ((char *)addr_block2 + (j << heapinfo2[i].type));
435                 real_addr_frag2 = (void*) ((char *)real_addr_block2 + (j << ((struct mdesc *)s_heap)->heapinfo[i].type));
436                 XBT_DEBUG( "Block %zu, Fragment %zu (%p - %p) not found (size used = %zd)", i, j, addr_frag2, real_addr_frag2, heapinfo2[i].busy_frag.frag_size[j]);
437                 //mmalloc_backtrace_fragment_display((void*)heapinfo2, i, j);
438               }
439               nb_diff2++;
440             }
441           }
442         }
443       }
444     }
445     i++; 
446   }
447
448   if(current_block == heaplimit)
449     XBT_DEBUG("Number of blocks/fragments not found in heap2 : %d", nb_diff2);
450
451   xbt_dynar_free(&previous);
452   real_addr_frag1 = NULL, real_addr_block1 = NULL, real_addr_block2 = NULL, real_addr_frag2 = NULL;
453
454   return ((nb_diff1 > 0) || (nb_diff2 > 0));
455 }
456
457 void reset_heap_information(){
458
459   size_t i = 0, j;
460
461   while(i<=heaplimit){
462     if(heapinfo1[i].type == 0){
463       xbt_free(heapinfo1[i].busy_block.equal_to);
464       heapinfo1[i].busy_block.equal_to = NULL;
465     }
466     if(heapinfo1[i].type > 0){
467       for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo1[i].type); j++){
468         xbt_free(heapinfo1[i].busy_frag.equal_to[j]);
469         heapinfo1[i].busy_frag.equal_to[j] = NULL;
470       }
471     }
472     i++; 
473   }
474
475   i = 0;
476
477   while(i<=heaplimit){
478     if(heapinfo2[i].type == 0){
479       xbt_free(heapinfo2[i].busy_block.equal_to);
480       heapinfo2[i].busy_block.equal_to = NULL;
481     }
482     if(heapinfo2[i].type > 0){
483       for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo2[i].type); j++){
484         xbt_free(heapinfo2[i].busy_frag.equal_to[j]);
485         heapinfo2[i].busy_frag.equal_to[j] = NULL;
486       }
487     }
488     i++; 
489   }
490
491   s_heap = NULL, heapbase1 = NULL, heapbase2 = NULL;
492   heapinfo1 = NULL, heapinfo2 = NULL;
493   heaplimit = 0, heapsize1 = 0, heapsize2 = 0;
494   to_ignore1 = NULL, to_ignore2 = NULL;
495
496 }
497
498 static heap_area_t new_heap_area(int block, int fragment){
499   heap_area_t area = NULL;
500   area = xbt_new0(s_heap_area_t, 1);
501   area->block = block;
502   area->fragment = fragment;
503   return area;
504 }
505
506
507 static size_t heap_comparison_ignore_size(xbt_dynar_t ignore_list, void *address){
508
509   unsigned int cursor = 0;
510   int start = 0;
511   int end = xbt_dynar_length(ignore_list) - 1;
512   mc_heap_ignore_region_t region;
513
514   while(start <= end){
515     cursor = (start + end) / 2;
516     region = (mc_heap_ignore_region_t)xbt_dynar_get_as(ignore_list, cursor, mc_heap_ignore_region_t);
517     if(region->address == address)
518       return region->size;
519     if(region->address < address)
520       start = cursor + 1;
521     if(region->address > address)
522       end = cursor - 1;   
523   }
524
525   return 0;
526 }
527
528
529 int compare_area(void *area1, void* area2, xbt_dynar_t previous){
530
531   size_t i = 0, pointer_align = 0, ignore1 = 0, ignore2 = 0;
532   void *addr_pointed1, *addr_pointed2;
533   int res_compare;
534   ssize_t block1, frag1, block2, frag2;
535   ssize_t size;
536   int check_ignore = 0;
537
538   void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2;
539   void *area1_to_compare, *area2_to_compare;
540
541   int match_pairs = 0;
542
543   if(previous == NULL){
544     previous = xbt_dynar_new(sizeof(heap_area_pair_t), heap_area_pair_free_voidp);
545     match_pairs = 1;
546   }
547
548   block1 = ((char*)area1 - (char*)((xbt_mheap_t)s_heap)->heapbase) / BLOCKSIZE + 1;
549   block2 = ((char*)area2 - (char*)((xbt_mheap_t)s_heap)->heapbase) / BLOCKSIZE + 1;
550
551   if(is_block_stack((int)block1) && is_block_stack((int)block2)){
552     add_heap_area_pair(previous, block1, -1, block2, -1);
553     if(match_pairs){
554       match_equals(previous);
555       xbt_dynar_free(&previous);
556     }
557     return 0;
558   }
559
560   if(((char *)area1 < (char*)((xbt_mheap_t)s_heap)->heapbase)  || (block1 > heapsize1) || (block1 < 1) || ((char *)area2 < (char*)((xbt_mheap_t)s_heap)->heapbase) || (block2 > heapsize2) || (block2 < 1)){
561     if(match_pairs){
562       xbt_dynar_free(&previous);
563     }
564     return 1;
565   }
566
567   addr_block1 = ((void*) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE + (char*)heapbase1));
568   addr_block2 = ((void*) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE + (char*)heapbase2));
569   
570   if(heapinfo1[block1].type == heapinfo2[block2].type){
571     
572     if(heapinfo1[block1].type == -1){ /* Free block */
573       if(match_pairs){
574         match_equals(previous);
575         xbt_dynar_free(&previous);
576       }
577       return 0;
578
579     }else if(heapinfo1[block1].type == 0){ /* Complete block */
580
581       if(heapinfo1[block1].busy_block.equal_to != NULL && heapinfo2[block2].busy_block.equal_to != NULL){
582         if(equal_blocks(block1, block2)){
583           if(match_pairs){
584             match_equals(previous);
585             xbt_dynar_free(&previous);
586           }
587           return 0;
588         }
589       }
590
591       if(heapinfo1[block1].busy_block.size != heapinfo2[block2].busy_block.size){
592         if(match_pairs){
593           xbt_dynar_free(&previous);
594         }
595         return 1;
596       }
597
598       if(heapinfo1[block1].busy_block.busy_size != heapinfo2[block2].busy_block.busy_size){
599         if(match_pairs){
600           xbt_dynar_free(&previous);
601         }
602         return 1;
603       }
604
605       if(!add_heap_area_pair(previous, block1, -1, block2, -1)){
606         if(match_pairs){
607           match_equals(previous);
608           xbt_dynar_free(&previous);
609         }
610         return 0;
611       }
612  
613       size = heapinfo1[block1].busy_block.busy_size;
614
615       if(size <= 0){
616         if(match_pairs){
617           match_equals(previous);
618           xbt_dynar_free(&previous);
619         }
620         return 0;
621       }
622
623       frag1 = -1;
624       frag2 = -1;
625
626       area1_to_compare = addr_block1;
627       area2_to_compare = addr_block2;
628
629       if((heapinfo1[block1].busy_block.ignore > 0) && (heapinfo2[block2].busy_block.ignore == heapinfo1[block1].busy_block.ignore))
630         check_ignore = heapinfo1[block1].busy_block.ignore;
631       
632     }else{
633       frag1 = ((uintptr_t) (ADDR2UINT (area1) % (BLOCKSIZE))) >> heapinfo1[block1].type;
634       frag2 = ((uintptr_t) (ADDR2UINT (area2) % (BLOCKSIZE))) >> heapinfo2[block2].type;
635       
636       addr_frag1 = (void*) ((char *)addr_block1 + (frag1 << heapinfo1[block1].type));
637       addr_frag2 = (void*) ((char *)addr_block2 + (frag2 << heapinfo2[block2].type));
638       
639       area1_to_compare = addr_frag1;
640       area2_to_compare = addr_frag2;
641
642       if(heapinfo1[block1].busy_frag.equal_to[frag1] != NULL && heapinfo2[block2].busy_frag.equal_to[frag2] != NULL){
643         if(equal_fragments(block1, frag1, block2, frag2)){
644           if(match_pairs){
645             match_equals(previous);
646             xbt_dynar_free(&previous);
647           }
648           return 0;
649         }
650       }
651
652       if(heapinfo1[block1].busy_frag.frag_size[frag1] != heapinfo2[block2].busy_frag.frag_size[frag2]){
653         if(match_pairs){
654           xbt_dynar_free(&previous);
655         }
656         return 1;  
657       }
658       
659       if(!add_heap_area_pair(previous, block1, frag1, block2, frag2)){
660         if(match_pairs){
661           match_equals(previous);
662           xbt_dynar_free(&previous);
663         }
664         return 0;
665       }
666
667       size = heapinfo1[block1].busy_frag.frag_size[frag1];
668
669       if(size <= 0){
670         if(match_pairs){
671           match_equals(previous);
672           xbt_dynar_free(&previous);
673         }
674         return 0;
675       }
676       
677       if((heapinfo1[block1].busy_frag.ignore[frag1] > 0) && ( heapinfo2[block2].busy_frag.ignore[frag2] == heapinfo1[block1].busy_frag.ignore[frag1]))
678         check_ignore = heapinfo1[block1].busy_frag.ignore[frag1];
679       
680     }
681
682   }else if((heapinfo1[block1].type > 0) && (heapinfo2[block2].type > 0)){
683
684     frag1 = ((uintptr_t) (ADDR2UINT (area1) % (BLOCKSIZE))) >> heapinfo1[block1].type;
685     frag2 = ((uintptr_t) (ADDR2UINT (area2) % (BLOCKSIZE))) >> heapinfo2[block2].type;
686
687     if(heapinfo1[block1].busy_frag.equal_to[frag1] != NULL || heapinfo2[block2].busy_frag.equal_to[frag2] != NULL){
688       if(equal_fragments(block1, frag1, block2, frag2)){
689         if(match_pairs){
690           match_equals(previous);
691           xbt_dynar_free(&previous);
692         }
693         return 0;
694       }
695     }
696
697     if(heapinfo1[block1].busy_frag.frag_size[frag1] != heapinfo2[block2].busy_frag.frag_size[frag2]){
698       if(match_pairs){
699         xbt_dynar_free(&previous);
700       }
701       return 1;
702     }
703     
704     if(!add_heap_area_pair(previous, block1, frag1, block2, frag2)){
705       if(match_pairs){
706         match_equals(previous);
707         xbt_dynar_free(&previous);
708       }
709       return 0;
710     }
711
712     addr_frag1 = (void*) ((char *)addr_block1 + (frag1 << heapinfo1[block1].type));
713     addr_frag2 = (void*) ((char *)addr_block2 + (frag2 << heapinfo2[block2].type));
714
715     area1_to_compare = addr_frag1;
716     area2_to_compare = addr_frag2;
717       
718     size = heapinfo1[block1].busy_frag.frag_size[frag1];
719
720     if(size <= 0){
721       if(match_pairs){
722         match_equals(previous);
723         xbt_dynar_free(&previous);
724       }
725       return 0;
726     }
727
728     if((heapinfo1[block1].busy_frag.ignore[frag1] > 0) && (heapinfo2[block2].busy_frag.ignore[frag2] == heapinfo1[block1].busy_frag.ignore[frag1]))
729       check_ignore = heapinfo1[block1].busy_frag.ignore[frag1];   
730     
731   }else{
732     if(match_pairs){
733       xbt_dynar_free(&previous);
734     }
735     return 1;
736   }
737   
738   while(i<size){
739
740     if(check_ignore > 0){
741       if((ignore1 = heap_comparison_ignore_size(to_ignore1, (char *)area1 + i)) > 0){
742         if((ignore2 = heap_comparison_ignore_size(to_ignore2, (char *)area2 + i))  == ignore1){
743           i = i + ignore2;
744           check_ignore--;
745           continue;
746         }
747       }
748     }
749
750     if(memcmp(((char *)area1_to_compare) + i, ((char *)area2_to_compare) + i, 1) != 0){
751
752       pointer_align = (i / sizeof(void*)) * sizeof(void*);
753       addr_pointed1 = *((void **)((char *)area1_to_compare + pointer_align));
754       addr_pointed2 = *((void **)((char *)area2_to_compare + pointer_align));
755       
756       if(addr_pointed1 > maestro_stack_start && addr_pointed1 < maestro_stack_end && addr_pointed2 > maestro_stack_start && addr_pointed2 < maestro_stack_end){
757         i = pointer_align + sizeof(void *);
758         continue;
759       }else if((addr_pointed1 > s_heap) && ((char *)addr_pointed1 < (char *)s_heap + STD_HEAP_SIZE) 
760            && (addr_pointed2 > s_heap) && ((char *)addr_pointed2 < (char *)s_heap + STD_HEAP_SIZE)){
761         res_compare = compare_area(addr_pointed1, addr_pointed2, previous);
762         if(res_compare != 0){
763           if(match_pairs)
764             xbt_dynar_free(&previous);
765           return res_compare;
766         }
767         i = pointer_align + sizeof(void *);
768         continue;
769       }else{
770         if(match_pairs)
771           xbt_dynar_free(&previous);
772         return 1;
773       }
774       
775     }
776     
777     i++;
778
779   }
780
781   if(match_pairs){
782     match_equals(previous);
783     xbt_dynar_free(&previous);
784   }
785
786   return 0;
787   
788
789 }
790
791 static void heap_area_pair_free(heap_area_pair_t pair){
792   xbt_free(pair);
793   pair = NULL;
794 }
795
796 static void heap_area_pair_free_voidp(void *d)
797 {
798   heap_area_pair_free((heap_area_pair_t) * (void **) d);
799 }
800
801 static int add_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2){
802
803   if(is_new_heap_area_pair(list, block1, fragment1, block2, fragment2)){
804     heap_area_pair_t pair = NULL;
805     pair = xbt_new0(s_heap_area_pair_t, 1);
806     pair->block1 = block1;
807     pair->fragment1 = fragment1;
808     pair->block2 = block2;
809     pair->fragment2 = fragment2;
810     
811     xbt_dynar_push(list, &pair); 
812
813     return 1;
814   }
815
816   return 0;
817 }
818  
819 static int is_new_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2){
820   
821   unsigned int cursor = 0;
822   heap_area_pair_t current_pair;
823
824   xbt_dynar_foreach(list, cursor, current_pair){
825     if(current_pair->block1 == block1 && current_pair->block2 == block2 && current_pair->fragment1 == fragment1 && current_pair->fragment2 == fragment2)
826       return 0; 
827   }
828   
829   return 1;
830 }
831
832
833 void match_equals(xbt_dynar_t list){
834
835   unsigned int cursor = 0;
836   heap_area_pair_t current_pair;
837   heap_area_t previous_area;
838
839   xbt_dynar_foreach(list, cursor, current_pair){
840
841     if(current_pair->fragment1 != -1){
842       
843       if(heapinfo1[current_pair->block1].busy_frag.equal_to[current_pair->fragment1] != NULL){    
844         previous_area = heapinfo1[current_pair->block1].busy_frag.equal_to[current_pair->fragment1];
845         xbt_free(heapinfo2[previous_area->block].busy_frag.equal_to[previous_area->fragment]);
846         heapinfo2[previous_area->block].busy_frag.equal_to[previous_area->fragment] = NULL;
847         xbt_free(previous_area); 
848       }
849       if(heapinfo2[current_pair->block2].busy_frag.equal_to[current_pair->fragment2] != NULL){        
850         previous_area = heapinfo2[current_pair->block2].busy_frag.equal_to[current_pair->fragment2];
851         xbt_free(heapinfo1[previous_area->block].busy_frag.equal_to[previous_area->fragment]);
852         heapinfo1[previous_area->block].busy_frag.equal_to[previous_area->fragment] = NULL;
853         xbt_free(previous_area);
854       }
855
856       heapinfo1[current_pair->block1].busy_frag.equal_to[current_pair->fragment1] = new_heap_area(current_pair->block2, current_pair->fragment2);
857       heapinfo2[current_pair->block2].busy_frag.equal_to[current_pair->fragment2] = new_heap_area(current_pair->block1, current_pair->fragment1);
858
859     }else{
860
861       if(heapinfo1[current_pair->block1].busy_block.equal_to != NULL){
862         previous_area = heapinfo1[current_pair->block1].busy_block.equal_to;
863         xbt_free(heapinfo2[previous_area->block].busy_block.equal_to);
864         heapinfo2[previous_area->block].busy_block.equal_to = NULL; 
865         xbt_free(previous_area);
866       }
867       if(heapinfo2[current_pair->block2].busy_block.equal_to != NULL){
868         previous_area = heapinfo2[current_pair->block2].busy_block.equal_to;
869         xbt_free(heapinfo1[previous_area->block].busy_block.equal_to);
870         heapinfo1[previous_area->block].busy_block.equal_to = NULL;
871         xbt_free(previous_area);
872       }
873
874       heapinfo1[current_pair->block1].busy_block.equal_to = new_heap_area(current_pair->block2, current_pair->fragment2);
875       heapinfo2[current_pair->block2].busy_block.equal_to = new_heap_area(current_pair->block1, current_pair->fragment1);
876
877     }
878   }
879
880 }
881
882 #ifndef max
883 #define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
884 #endif
885
886 int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2){
887
888   if(heap1 == NULL && heap1 == NULL){
889     XBT_DEBUG("Malloc descriptors null");
890     return 0;
891   }
892
893   if(heap1->heaplimit != heap2->heaplimit){
894     XBT_DEBUG("Different limit of valid info table indices");
895     return 1;
896   }
897
898   /* Heap information */
899   heaplimit = ((struct mdesc *)heap1)->heaplimit;
900
901   s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize();
902
903   heapbase1 = (char *)heap1 + BLOCKSIZE;
904   heapbase2 = (char *)heap2 + BLOCKSIZE;
905
906   heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)heap1->heapinfo - (char *)s_heap)));
907   heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)heap2->heapinfo - (char *)s_heap)));
908
909   heapsize1 = heap1->heapsize;
910   heapsize2 = heap2->heapsize;
911
912   /* Start comparison */
913   size_t i, j, k;
914   void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2;
915
916   int distance = 0;
917
918   /* Check busy blocks*/
919
920   i = 1;
921
922   while(i <= heaplimit){
923
924     addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1));
925     addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2));
926
927     if(heapinfo1[i].type != heapinfo2[i].type){
928   
929       distance += BLOCKSIZE;
930       XBT_DEBUG("Different type of blocks (%zu) : %d - %d -> distance = %d", i, heapinfo1[i].type, heapinfo2[i].type, distance);
931       i++;
932     
933     }else{
934
935       if(heapinfo1[i].type == -1){ /* Free block */
936         i++;
937         continue;
938       }
939
940       if(heapinfo1[i].type == 0){ /* Large block */
941        
942         if(heapinfo1[i].busy_block.size != heapinfo2[i].busy_block.size){
943           distance += BLOCKSIZE * max(heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size);
944           i += max(heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size);
945           XBT_DEBUG("Different larger of cluster at block %zu : %zu - %zu -> distance = %d", i, heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size, distance);
946           continue;
947         }
948
949         /*if(heapinfo1[i].busy_block.busy_size != heapinfo2[i].busy_block.busy_size){
950           distance += max(heapinfo1[i].busy_block.busy_size, heapinfo2[i].busy_block.busy_size);
951           i += max(heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size);
952           XBT_DEBUG("Different size used oin large cluster at block %zu : %zu - %zu -> distance = %d", i, heapinfo1[i].busy_block.busy_size, heapinfo2[i].busy_block.busy_size, distance);
953           continue;
954           }*/
955
956         k = 0;
957
958         //while(k < (heapinfo1[i].busy_block.busy_size)){
959         while(k < heapinfo1[i].busy_block.size * BLOCKSIZE){
960           if(memcmp((char *)addr_block1 + k, (char *)addr_block2 + k, 1) != 0){
961             distance ++;
962           }
963           k++;
964         } 
965
966         i++;
967
968       }else { /* Fragmented block */
969
970         for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo1[i].type); j++){
971
972           addr_frag1 = (void*) ((char *)addr_block1 + (j << heapinfo1[i].type));
973           addr_frag2 = (void*) ((char *)addr_block2 + (j << heapinfo2[i].type));
974
975           if(heapinfo1[i].busy_frag.frag_size[j] == 0 && heapinfo2[i].busy_frag.frag_size[j] == 0){
976             continue;
977           }
978           
979           
980           /*if(heapinfo1[i].busy_frag.frag_size[j] != heapinfo2[i].busy_frag.frag_size[j]){
981             distance += max(heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j]);
982             XBT_DEBUG("Different size used in fragment %zu in block %zu : %d - %d -> distance = %d", j, i, heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j], distance); 
983             continue;
984             }*/
985    
986           k=0;
987
988           //while(k < max(heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j])){
989           while(k < (BLOCKSIZE / (BLOCKSIZE >> heapinfo1[i].type))){
990             if(memcmp((char *)addr_frag1 + k, (char *)addr_frag2 + k, 1) != 0){
991               distance ++;
992             }
993             k++;
994           }
995
996         }
997
998         i++;
999
1000       }
1001       
1002     }
1003
1004   }
1005
1006   return distance;
1007   
1008 }
1009
1010 static int is_stack(void *address){
1011   unsigned int cursor = 0;
1012   stack_region_t stack;
1013
1014   xbt_dynar_foreach(stacks_areas, cursor, stack){
1015     if(address == stack->address)
1016       return 1;
1017   }
1018
1019   return 0;
1020 }
1021
1022 static int is_block_stack(int block){
1023   unsigned int cursor = 0;
1024   stack_region_t stack;
1025
1026   xbt_dynar_foreach(stacks_areas, cursor, stack){
1027     if(block == stack->block)
1028       return 1;
1029   }
1030
1031   return 0;
1032 }
1033
1034 static void add_heap_equality(xbt_dynar_t equals, void *a1, void *a2){
1035   
1036   if(xbt_dynar_is_empty(equals)){
1037
1038     heap_equality_t he = xbt_new0(s_heap_equality_t, 1);
1039     he->address1 = a1;
1040     he->address2 = a2;
1041
1042     xbt_dynar_insert_at(equals, 0, &he);
1043   
1044   }else{
1045
1046     unsigned int cursor = 0;
1047     int start = 0;
1048     int end = xbt_dynar_length(equals) - 1;
1049     heap_equality_t current_equality = NULL;
1050
1051     while(start <= end){
1052       cursor = (start + end) / 2;
1053       current_equality = (heap_equality_t)xbt_dynar_get_as(equals, cursor, heap_equality_t);
1054       if(current_equality->address1 == a1){
1055         if(current_equality->address2 == a2)
1056           return;
1057         if(current_equality->address2 < a2)
1058           start = cursor + 1;
1059         if(current_equality->address2 > a2)
1060           end = cursor - 1;
1061       }
1062       if(current_equality->address1 < a1)
1063         start = cursor + 1;
1064       if(current_equality->address1 > a1)
1065         end = cursor - 1; 
1066     }
1067
1068     heap_equality_t he = xbt_new0(s_heap_equality_t, 1);
1069     he->address1 = a1;
1070     he->address2 = a2;
1071   
1072     if(current_equality->address1 < a1)
1073       xbt_dynar_insert_at(equals, cursor + 1 , &he);
1074     else
1075        xbt_dynar_insert_at(equals, cursor, &he); 
1076
1077   }
1078
1079 }
1080
1081 static void remove_heap_equality(xbt_dynar_t equals, int address, void *a){
1082   
1083   unsigned int cursor = 0;
1084   heap_equality_t current_equality;
1085   int found = 0;
1086
1087   if(address == 1){
1088
1089     int start = 0;
1090     int end = xbt_dynar_length(equals) - 1;
1091
1092
1093     while(start <= end && found == 0){
1094       cursor = (start + end) / 2;
1095       current_equality = (heap_equality_t)xbt_dynar_get_as(equals, cursor, heap_equality_t);
1096       if(current_equality->address1 == a)
1097         found = 1;
1098       if(current_equality->address1 < a)
1099         start = cursor + 1;
1100       if(current_equality->address1 > a)
1101         end = cursor - 1; 
1102     }
1103
1104     if(found == 1)
1105       xbt_dynar_remove_at(equals, cursor, NULL);
1106   
1107   }else{
1108
1109     xbt_dynar_foreach(equals, cursor, current_equality){
1110       if(current_equality->address2 == a){
1111         found = 1;
1112         break;
1113       }
1114     }
1115
1116     if(found == 1)
1117       xbt_dynar_remove_at(equals, cursor, NULL);
1118
1119   }
1120   
1121 }
1122
1123 int is_free_area(void *area, xbt_mheap_t heap){
1124
1125   void *sheap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize();
1126   malloc_info *heapinfo = (malloc_info *)((char *)heap + ((uintptr_t)((char *)heap->heapinfo - (char *)sheap)));
1127   size_t heapsize = heap->heapsize;
1128
1129   /* Get block number */ 
1130   size_t block = ((char*)area - (char*)((xbt_mheap_t)sheap)->heapbase) / BLOCKSIZE + 1;
1131   size_t fragment;
1132
1133   /* Check if valid block number */
1134   if((char *)area < (char*)((xbt_mheap_t)sheap)->heapbase || block > heapsize || block < 1)
1135     return 0;
1136
1137   if(heapinfo[block].type < 0)
1138     return 1;
1139
1140   if(heapinfo[block].type == 0)
1141     return 0;
1142
1143   if(heapinfo[block].type > 0){
1144     fragment = ((uintptr_t) (ADDR2UINT(area) % (BLOCKSIZE))) >> heapinfo[block].type;
1145     if(heapinfo[block].busy_frag.frag_size[fragment] == 0)
1146       return 1;  
1147   }
1148
1149   return 0;
1150  
1151 }
1152
1153 static int equal_blocks(int b1, int b2){
1154   if(heapinfo1[b1].busy_block.equal_to != NULL){
1155     if(heapinfo2[b2].busy_block.equal_to != NULL){
1156       if(((heap_area_t)(heapinfo1[b1].busy_block.equal_to))->block == b2 && ((heap_area_t)(heapinfo2[b2].busy_block.equal_to))->block == b1)
1157         return 1;
1158     }
1159   }
1160   return 0;
1161 }
1162
1163 static int equal_fragments(int b1, int f1, int b2, int f2){
1164   if(heapinfo1[b1].busy_frag.equal_to[f1] != NULL){
1165     if(heapinfo2[b2].busy_frag.equal_to[f2] != NULL){
1166       if(((heap_area_t)(heapinfo1[b1].busy_frag.equal_to[f1]))->block == b2 && ((heap_area_t)(heapinfo2[b2].busy_frag.equal_to[f2]))->block == b1 && ((heap_area_t)(heapinfo1[b1].busy_frag.equal_to[f1]))->fragment == f2 && ((heap_area_t)(heapinfo2[b2].busy_frag.equal_to[f2]))->fragment == f1)
1167         return 1;
1168     }
1169   }
1170   return 0;
1171 }