Logo AND Algorithmique Numérique Distribuée

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