Logo AND Algorithmique Numérique Distribuée

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