Logo AND Algorithmique Numérique Distribuée

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