X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/bce048d821047a65f5044bb332515bba8ea90927..6edd98218de9a7958d1f1a4396a2d460eac2593a:/src/xbt/mmalloc/mm_diff.c diff --git a/src/xbt/mmalloc/mm_diff.c b/src/xbt/mmalloc/mm_diff.c index f3b0eed5c3..3935b9f88c 100644 --- a/src/xbt/mmalloc/mm_diff.c +++ b/src/xbt/mmalloc/mm_diff.c @@ -5,389 +5,712 @@ /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ +#include "xbt/ex_interface.h" /* internals of backtrace setup */ +#include "xbt/str.h" +#include "mc/mc.h" -int mmalloc_compare_heap(xbt_mheap_t mdp1, xbt_mheap_t mdp2, void *std_heap_addr){ +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mm_diff, xbt, + "Logging specific to mm_diff in mmalloc"); - if(mdp1 == NULL && mdp2 == NULL){ - XBT_DEBUG("Malloc descriptors null"); - return 0; - } +extern char *xbt_binary_name; - /* Heapstats */ +xbt_dynar_t mmalloc_ignore; - int errors = mmalloc_compare_mdesc(mdp1, mdp2, std_heap_addr); +typedef struct s_heap_area_pair{ + int block1; + int fragment1; + int block2; + int fragment2; +}s_heap_area_pair_t, *heap_area_pair_t; - return (errors > 0); +static void heap_area_pair_free(heap_area_pair_t pair); +static void heap_area_pair_free_voidp(void *d); +static int add_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2); +static int is_new_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2); -} +static int compare_area(void *area1, void* area2, size_t size, xbt_dynar_t previous, int check_ignore); +static void match_equals(xbt_dynar_t list); -int mmalloc_compare_mdesc(struct mdesc *mdp1, struct mdesc *mdp2, void *std_heap_addr){ +static int in_mmalloc_ignore(int block, int fragment); +static size_t heap_comparison_ignore(void *address); - int errors = 0; +void mmalloc_backtrace_block_display(void* heapinfo, int block){ - if(mdp1->headersize != mdp2->headersize){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different size of the file header for the mapped files"); - errors++; - }else{ - return 1; - } - } + xbt_ex_t e; - if(mdp1->refcount != mdp2->refcount){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different number of processes that attached the heap"); - errors++; - }else{ - return 1; - } + if (((malloc_info *)heapinfo)[block].busy_block.bt_size == 0) { + XBT_DEBUG("No backtrace available for that block, sorry."); + return; } - if(strcmp(mdp1->magic, mdp2->magic) != 0){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different magic number"); - errors++; - }else{ - return 1; - } - } + memcpy(&e.bt,&(((malloc_info *)heapinfo)[block].busy_block.bt),sizeof(void*)*XBT_BACKTRACE_SIZE); + e.used = ((malloc_info *)heapinfo)[block].busy_block.bt_size; - if(mdp1->flags != mdp2->flags){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different flags"); - errors++; - }else{ - return 1; - } - } + xbt_ex_setup_backtrace(&e); + if (e.used == 0) { + XBT_DEBUG("(backtrace not set)"); + } else if (e.bt_strings == NULL) { + XBT_DEBUG("(backtrace not ready to be computed. %s)",xbt_binary_name?"Dunno why":"xbt_binary_name not setup yet"); + } else { + int i; - if(mdp1->heapsize != mdp2->heapsize){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different number of info entries"); - errors++; - }else{ - return 1; + XBT_DEBUG("Backtrace of where the block %d was malloced (%d frames):", block ,e.used); + for (i = 0; i < e.used; i++) /* no need to display "xbt_backtrace_display" */{ + XBT_DEBUG("%d ---> %s",i, e.bt_strings[i] + 4); } } - //XBT_DEBUG("Heap size : %zu", mdp1->heapsize); +} - if(mdp1->heapbase != mdp2->heapbase){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different first block of the heap"); - errors++; - }else{ - return 1; - } - } +void mmalloc_backtrace_fragment_display(void* heapinfo, int block, int frag){ + xbt_ex_t e; - if(mdp1->heapindex != mdp2->heapindex){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different index for the heap table : %zu - %zu", mdp1->heapindex, mdp2->heapindex); - errors++; - }else{ - return 1; - } - } + memcpy(&e.bt,&(((malloc_info *)heapinfo)[block].busy_frag.bt[frag]),sizeof(void*)*XBT_BACKTRACE_SIZE); + e.used = XBT_BACKTRACE_SIZE; - //XBT_DEBUG("Heap index : %zu", mdp1->heapindex); + xbt_ex_setup_backtrace(&e); + if (e.used == 0) { + XBT_DEBUG("(backtrace not set)"); + } else if (e.bt_strings == NULL) { + XBT_DEBUG("(backtrace not ready to be computed. %s)",xbt_binary_name?"Dunno why":"xbt_binary_name not setup yet"); + } else { + int i; - if(mdp1->base != mdp2->base){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different base address of the memory region"); - errors++; - }else{ - return 1; + XBT_DEBUG("Backtrace of where the fragment %d in block %d was malloced (%d frames):", frag, block ,e.used); + for (i = 0; i < e.used; i++) /* no need to display "xbt_backtrace_display" */{ + XBT_DEBUG("%d ---> %s",i, e.bt_strings[i] + 4); } } - if(mdp1->breakval != mdp2->breakval){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different current location in the memory region"); - errors++; - }else{ - return 1; - } - } +} - if(mdp1->top != mdp2->top){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different end of the current location in the memory region"); - errors++; - }else{ - return 1; - } - } +void *s_heap, *heapbase1, *heapbase2; +malloc_info *heapinfo1, *heapinfo2; +size_t heaplimit, heapsize1, heapsize2; - if(mdp1->heaplimit != mdp2->heaplimit){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different limit of valid info table indices"); - errors++; - }else{ - return 1; - } - } +int ignore_done; - if(mdp1->fd != mdp2->fd){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different file descriptor for the file to which this malloc heap is mapped"); - errors++; - }else{ - return 1; - } +int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2){ + + if(heap1 == NULL && heap1 == NULL){ + XBT_DEBUG("Malloc descriptors null"); + return 0; } - if(mdp1->version != mdp2->version){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different version of the mmalloc package"); - errors++; - }else{ - return 1; - } + if(heap1->heaplimit != heap2->heaplimit){ + XBT_DEBUG("Different limit of valid info table indices"); + return 1; } + /* Heap information */ + heaplimit = ((struct mdesc *)heap1)->heaplimit; - size_t block_free1, block_free2 , next_block_free, first_block_free, block_free ; - size_t i, j; - void *addr_block1, *addr_block2; - size_t frag_size; + s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize(); + heapbase1 = (char *)heap1 + BLOCKSIZE; + heapbase2 = (char *)heap2 + BLOCKSIZE; - /* Search index of the first free block */ + heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)heap1->heapinfo - (char *)s_heap))); + heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)heap2->heapinfo - (char *)s_heap))); - block_free1 = mdp1->heapindex; - block_free2 = mdp2->heapindex; + heapsize1 = heap1->heapsize; + heapsize2 = heap2->heapsize; - while(mdp1->heapinfo[block_free1].free_block.prev != 0){ - block_free1 = mdp1->heapinfo[block_free1].free_block.prev; - } + /* Start comparison */ + size_t i1, i2, j1, j2, k, current_block, current_fragment; + void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2; - while(mdp2->heapinfo[block_free2].free_block.prev != 0){ - block_free2 = mdp1->heapinfo[block_free2].free_block.prev; - } + xbt_dynar_t previous = xbt_dynar_new(sizeof(heap_area_pair_t), heap_area_pair_free_voidp); - if(block_free1 != block_free2){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different first free block"); - errors++; - }else{ - return 1; + int equal, res_compare; + + ignore_done = 0; + + /* Init equal information */ + i1 = 1; + + while(i1<=heaplimit){ + if(heapinfo1[i1].type == 0){ + heapinfo1[i1].busy_block.equal_to = -1; } + if(heapinfo1[i1].type > 0){ + for(j1=0; j1 < MAX_FRAGMENT_PER_BLOCK; j1++){ + heapinfo1[i1].busy_frag.equal_to[j1] = -1; + } + } + i1++; } - first_block_free = block_free1; + i2 = 1; - if(mdp1->heapinfo[first_block_free].free_block.size != mdp2->heapinfo[first_block_free].free_block.size){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different size (in blocks) of the first free cluster"); - errors++; - }else{ - return 1; + while(i2<=heaplimit){ + if(heapinfo2[i2].type == 0){ + heapinfo2[i2].busy_block.equal_to = -1; } + if(heapinfo2[i2].type > 0){ + for(j2=0; j2 < MAX_FRAGMENT_PER_BLOCK; j2++){ + heapinfo2[i2].busy_frag.equal_to[j2] = -1; + } + } + i2++; } - /* Check busy blocks (circular checking)*/ + /* Check busy blocks*/ - i = first_block_free + mdp1->heapinfo[first_block_free].free_block.size; + i1 = 1; - if(mdp1->heapinfo[first_block_free].free_block.next != mdp2->heapinfo[first_block_free].free_block.next){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different next block free"); - errors++; - }else{ - return 1; + while(i1 <= heaplimit){ + + current_block = i1; + + if(heapinfo1[i1].type == -1){ /* Free block */ + i1++; + continue; } - } - block_free = first_block_free; - next_block_free = mdp1->heapinfo[first_block_free].free_block.next; + addr_block1 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)heapbase1)); - if(next_block_free == 0) - next_block_free = mdp1->heaplimit; + if(heapinfo1[i1].type == 0){ /* Large block */ + + if(heapinfo1[i1].busy_block.busy_size == 0){ + i1++; + continue; + } + + i2 = 1; + equal = 0; + + /* Try first to associate to same block in the other heap */ + if(heapinfo2[current_block].type == heapinfo1[current_block].type){ + + if(heapinfo1[current_block].busy_block.busy_size == heapinfo2[current_block].busy_block.busy_size){ + + addr_block2 = ((void*) (((ADDR2UINT(current_block)) - 1) * BLOCKSIZE + (char*)heapbase2)); + + add_heap_area_pair(previous, current_block, -1, current_block, -1); + + if(ignore_done < xbt_dynar_length(mmalloc_ignore)){ + if(in_mmalloc_ignore((int)current_block, -1)) + res_compare = compare_area(addr_block1, addr_block2, heapinfo1[current_block].busy_block.busy_size, previous, 1); + else + res_compare = compare_area(addr_block1, addr_block2, heapinfo1[current_block].busy_block.busy_size, previous, 0); + }else{ + res_compare = compare_area(addr_block1, addr_block2, heapinfo1[current_block].busy_block.busy_size, previous, 0); + } + + if(res_compare == 0){ + for(k=1; k < heapinfo2[current_block].busy_block.size; k++) + heapinfo2[current_block+k].busy_block.equal_to = 1 ; + for(k=1; k < heapinfo1[current_block].busy_block.size; k++) + heapinfo1[current_block+k].busy_block.equal_to = 1 ; + equal = 1; + match_equals(previous); + i1 = i1 + heapinfo1[i1].busy_block.size; + } + + xbt_dynar_reset(previous); + + } + + } + + while(i2 <= heaplimit && !equal){ + + if(i2 == current_block){ + i2++; + continue; + } + + if(heapinfo2[i2].type != 0){ + i2++; + continue; + } - while(i != first_block_free){ + if(heapinfo2[i2].busy_block.equal_to == 1){ + i2++; + continue; + } + + if(heapinfo1[i1].busy_block.size != heapinfo2[i2].busy_block.size){ + i2++; + continue; + } + + if(heapinfo1[i1].busy_block.busy_size != heapinfo2[i2].busy_block.busy_size){ + i2++; + continue; + } - while(iheapinfo[i].type != mdp2->heapinfo[i].type){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different type of busy block"); - errors++; + /* Comparison */ + add_heap_area_pair(previous, i1, -1, i2, -1); + + if(ignore_done < xbt_dynar_length(mmalloc_ignore)){ + if(in_mmalloc_ignore((int)i1, -1)) + res_compare = compare_area(addr_block1, addr_block2, heapinfo1[i1].busy_block.busy_size, previous, 1); + else + res_compare = compare_area(addr_block1, addr_block2, heapinfo1[i1].busy_block.busy_size, previous, 0); }else{ - return 1; + res_compare = compare_area(addr_block1, addr_block2, heapinfo1[i1].busy_block.busy_size, previous, 0); + } + + if(!res_compare){ + for(k=1; k < heapinfo2[i2].busy_block.size; k++) + heapinfo2[i2+k].busy_block.equal_to = 1; + for(k=1; k < heapinfo1[i1].busy_block.size; k++) + heapinfo1[i1+k].busy_block.equal_to = 1; + equal = 1; + match_equals(previous); } - }else{ - addr_block1 = (char *)mdp1 + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE); - addr_block2 = (char *)mdp2 + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE); + xbt_dynar_reset(previous); - switch(mdp1->heapinfo[i].type){ //FIXME deal with type<0 == free - case 0 : - if(mdp1->heapinfo[i].busy_block.size != mdp2->heapinfo[i].busy_block.size){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different size of a large cluster"); - errors++; + i2++; + + } + + if(!equal) + i1++; + + }else{ /* Fragmented block */ + + for(j1=0; j1 < (size_t) (BLOCKSIZE >> heapinfo1[i1].type); j1++){ + + current_fragment = j1; + + if(heapinfo1[i1].busy_frag.frag_size[j1] == 0) /* Free fragment */ + continue; + + addr_frag1 = (void*) ((char *)addr_block1 + (j1 << heapinfo1[i1].type)); + + i2 = 1; + equal = 0; + + /* Try first to associate to same fragment in the other heap */ + if(heapinfo2[current_block].type == heapinfo1[current_block].type){ + + if(heapinfo1[current_block].busy_frag.frag_size[current_fragment] == heapinfo2[current_block].busy_frag.frag_size[current_fragment]){ + + addr_block2 = ((void*) (((ADDR2UINT(current_block)) - 1) * BLOCKSIZE + (char*)heapbase2)); + addr_frag2 = (void*) ((char *)addr_block2 + (current_fragment << heapinfo2[current_block].type)); + + add_heap_area_pair(previous, current_block, current_fragment, current_block, current_fragment); + + if(ignore_done < xbt_dynar_length(mmalloc_ignore)){ + if(in_mmalloc_ignore((int)current_block, (int)current_fragment)) + res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[current_block].busy_frag.frag_size[current_fragment], previous, 1); + else + res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[current_block].busy_frag.frag_size[current_fragment], previous, 0); }else{ - return 1; + res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[current_block].busy_frag.frag_size[current_fragment], previous, 0); } - }else{ - if(memcmp(addr_block1, addr_block2, (mdp1->heapinfo[i].busy_block.size * BLOCKSIZE)) != 0){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different data in block %zu (size = %zu) (addr_block1 = %p (current = %p) - addr_block2 = %p)", i, mdp1->heapinfo[i].busy_block.size, addr_block1, (char *)std_heap_addr + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE), addr_block2); - errors++; - }else{ - return 1; - } + + if(res_compare == 0){ + equal = 1; + match_equals(previous); } + + xbt_dynar_reset(previous); + } - i = i+mdp1->heapinfo[i].busy_block.size; - - break; - default : - if(mdp1->heapinfo[i].busy_frag.nfree != mdp2->heapinfo[i].busy_frag.nfree){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different free fragments in the fragmented block %zu", i); - errors++; + + } + + + while(i2 <= heaplimit && !equal){ + + if(heapinfo2[i2].type <= 0){ + i2++; + continue; + } + + for(j2=0; j2 < (size_t) (BLOCKSIZE >> heapinfo2[i2].type); j2++){ + + if(heapinfo2[i2].type == heapinfo1[i1].type && i2 == current_block && j2 == current_fragment) + continue; + + if(heapinfo2[i2].busy_frag.equal_to[j2] == 1) + continue; + + if(heapinfo1[i1].busy_frag.frag_size[j1] != heapinfo2[i2].busy_frag.frag_size[j2]) /* Different size_used */ + continue; + + addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)heapbase2)); + addr_frag2 = (void*) ((char *)addr_block2 + (j2 << heapinfo2[i2].type)); + + /* Comparison */ + add_heap_area_pair(previous, i1, j1, i2, j2); + + if(ignore_done < xbt_dynar_length(mmalloc_ignore)){ + if(in_mmalloc_ignore((int)i1, (int)j1)) + res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[i1].busy_frag.frag_size[j1], previous, 1); + else + res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[i1].busy_frag.frag_size[j1], previous, 0); }else{ - return 1; + res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[i1].busy_frag.frag_size[j1], previous, 0); } - }else{ - if(mdp1->heapinfo[i].busy_frag.first != mdp2->heapinfo[i].busy_frag.first){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different first free fragments in the block %zu", i); - errors++; - }else{ - return 1; - } - }else{ - frag_size = pow(2,mdp1->heapinfo[i].type); - for(j=0 ; j< (BLOCKSIZE/frag_size); j++){ - if(memcmp((char *)addr_block1 + (j * frag_size), (char *)addr_block2 + (j * frag_size), frag_size) != 0){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different data in fragment %zu (addr_frag1 = %p - addr_frag2 = %p) of block %zu", j + 1, (char *)addr_block1 + (j * frag_size), (char *)addr_block2 + (j * frag_size), i); - errors++; - }else{ - return 1; - } - } - } + + if(!res_compare){ + equal = 1; + match_equals(previous); + xbt_dynar_reset(previous); + break; } + + xbt_dynar_reset(previous); + } - i++; + i2++; - break; } } + + i1++; + } - if( i != first_block_free){ + } - if(mdp1->heapinfo[block_free].free_block.next != mdp2->heapinfo[block_free].free_block.next){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different next block free"); - errors++; - }else{ - return 1; + /* All blocks/fragments are equal to another block/fragment ? */ + size_t i = 1, j = 0; + int nb_diff1 = 0, nb_diff2 = 0; + + while(i 0){ + if(heapinfo1[i].busy_block.equal_to == -1){ + if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){ + addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1)); + XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i, addr_block1, heapinfo1[i].busy_block.busy_size); + mmalloc_backtrace_block_display((void*)heapinfo1, i); + } + nb_diff1++; + } + } + } + if(heapinfo1[i].type > 0){ + for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo1[i].type); j++){ + if(heapinfo1[i].busy_frag.frag_size[j] > 0){ + if(heapinfo1[i].busy_frag.equal_to[j] == -1){ + if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){ + addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1)); + addr_frag1 = (void*) ((char *)addr_block1 + (j << heapinfo1[i].type)); + XBT_DEBUG("Block %zu, Fragment %zu (%p) not found (size used = %d)", i, j, addr_frag1, heapinfo1[i].busy_frag.frag_size[j]); + mmalloc_backtrace_fragment_display((void*)heapinfo1, i, j); + } + nb_diff1++; + } + } + } + } + + i++; + } + + XBT_DEBUG("Different blocks or fragments in heap1 : %d\n", nb_diff1); + + i = 1; + + while(i 0){ + if(heapinfo2[i].busy_block.equal_to == -1){ + if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){ + addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2)); + XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i, addr_block2, heapinfo2[i].busy_block.busy_size); + mmalloc_backtrace_block_display((void*)heapinfo2, i); + } + nb_diff2++; + } + } + } + if(heapinfo2[i].type > 0){ + for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo2[i].type); j++){ + if(heapinfo2[i].busy_frag.frag_size[j] > 0){ + if(heapinfo2[i].busy_frag.equal_to[j] == -1){ + if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){ + addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2)); + addr_frag2 = (void*) ((char *)addr_block2 + (j << heapinfo2[i].type)); + XBT_DEBUG( "Block %zu, Fragment %zu (%p) not found (size used = %d)", i, j, addr_frag2, heapinfo2[i].busy_frag.frag_size[j]); + mmalloc_backtrace_fragment_display((void*)heapinfo2, i, j); + } + nb_diff2++; + } + } + } + } + i++; + } + + XBT_DEBUG("Different blocks or fragments in heap2 : %d\n", nb_diff2); + + xbt_dynar_free(&previous); + + return ((nb_diff1 > 0) || (nb_diff2 > 0)); + +} + +static int in_mmalloc_ignore(int block, int fragment){ + + unsigned int cursor = 0; + int start = 0; + int end = xbt_dynar_length(mmalloc_ignore) - 1; + mc_ignore_region_t region; + + while(start <= end){ + cursor = (start + end) / 2; + region = (mc_ignore_region_t)xbt_dynar_get_as(mmalloc_ignore, cursor, mc_ignore_region_t); + if(region->block == block){ + if(region->fragment == fragment) + return 1; + if(region->fragment < fragment) + start = cursor + 1; + if(region->fragment > fragment) + end = cursor - 1; + } + if(region->block < block) + start = cursor + 1; + if(region->block > block) + end = cursor - 1; + } + + return 0; +} + +static size_t heap_comparison_ignore(void *address){ + unsigned int cursor = 0; + int start = 0; + int end = xbt_dynar_length(mmalloc_ignore) - 1; + mc_ignore_region_t region; + + while(start <= end){ + cursor = (start + end) / 2; + region = (mc_ignore_region_t)xbt_dynar_get_as(mmalloc_ignore, cursor, mc_ignore_region_t); + if(region->address == address) + return region->size; + if(region->address < address) + start = cursor + 1; + if(region->address > address) + end = cursor - 1; + } + + return 0; +} + + +static int compare_area(void *area1, void* area2, size_t size, xbt_dynar_t previous, int check_ignore){ + + size_t i = 0, pointer_align = 0, ignore1 = 0, ignore2 = 0; + void *address_pointed1, *address_pointed2, *addr_block_pointed1, *addr_block_pointed2, *addr_frag_pointed1, *addr_frag_pointed2; + size_t block_pointed1, block_pointed2, frag_pointed1, frag_pointed2; + int res_compare; + void *current_area1, *current_area2; + + while(iheapbase + ((((char *)area1) + i) - (char *)heapbase1); + if((ignore1 = heap_comparison_ignore(current_area1)) > 0){ + current_area2 = (char*)((xbt_mheap_t)s_heap)->heapbase + ((((char *)area2) + i) - (char *)heapbase2); + if((ignore2 = heap_comparison_ignore(current_area2)) == ignore1){ + i = i + ignore2; + ignore_done++; + continue; } } - block_free = mdp1->heapinfo[block_free].free_block.next; - next_block_free = mdp1->heapinfo[block_free].free_block.next; + } + + if(memcmp(((char *)area1) + i, ((char *)area2) + i, 1) != 0){ + + /* Check pointer difference */ + pointer_align = (i / sizeof(void*)) * sizeof(void*); + address_pointed1 = *((void **)((char *)area1 + pointer_align)); + address_pointed2 = *((void **)((char *)area2 + pointer_align)); + + /* Get pointed blocks number */ + block_pointed1 = ((char*)address_pointed1 - (char*)((xbt_mheap_t)s_heap)->heapbase) / BLOCKSIZE + 1; + block_pointed2 = ((char*)address_pointed2 - (char*)((xbt_mheap_t)s_heap)->heapbase) / BLOCKSIZE + 1; + + /* Check if valid blocks number */ + 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) + return 1; + + if(heapinfo1[block_pointed1].type == heapinfo2[block_pointed2].type){ /* Same type of block (large or fragmented) */ - i = block_free + mdp1->heapinfo[block_free].free_block.size; + addr_block_pointed1 = ((void*) (((ADDR2UINT(block_pointed1)) - 1) * BLOCKSIZE + (char*)heapbase1)); + addr_block_pointed2 = ((void*) (((ADDR2UINT(block_pointed2)) - 1) * BLOCKSIZE + (char*)heapbase2)); + + if(heapinfo1[block_pointed1].type == 0){ /* Large block */ - if((next_block_free == 0) && (i != mdp1->heaplimit)){ + if(heapinfo1[block_pointed1].busy_block.size != heapinfo2[block_pointed2].busy_block.size){ + return 1; + } + + if(heapinfo1[block_pointed1].busy_block.busy_size != heapinfo2[block_pointed2].busy_block.busy_size){ + return 1; + } - while(i < mdp1->heaplimit){ + if(add_heap_area_pair(previous, block_pointed1, -1, block_pointed2, -1)){ - if(mdp1->heapinfo[i].type != mdp2->heapinfo[i].type){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different type of busy block"); - errors++; + if(ignore_done < xbt_dynar_length(mmalloc_ignore)){ + if(in_mmalloc_ignore(block_pointed1, -1)) + res_compare = compare_area(addr_block_pointed1, addr_block_pointed2, heapinfo1[block_pointed1].busy_block.busy_size, previous, 1); + else + res_compare = compare_area(addr_block_pointed1, addr_block_pointed2, heapinfo1[block_pointed1].busy_block.busy_size, previous, 0); }else{ + res_compare = compare_area(addr_block_pointed1, addr_block_pointed2, heapinfo1[block_pointed1].busy_block.busy_size, previous, 0); + } + + if(res_compare) return 1; + + } + + }else{ /* Fragmented block */ + + /* Get pointed fragments number */ + frag_pointed1 = ((uintptr_t) (ADDR2UINT (address_pointed1) % (BLOCKSIZE))) >> heapinfo1[block_pointed1].type; + frag_pointed2 = ((uintptr_t) (ADDR2UINT (address_pointed2) % (BLOCKSIZE))) >> heapinfo2[block_pointed2].type; + + if(heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1] != heapinfo2[block_pointed2].busy_frag.frag_size[frag_pointed2]) /* Different size_used */ + return 1; + + addr_frag_pointed1 = (void*) ((char *)addr_block_pointed1 + (frag_pointed1 << heapinfo1[block_pointed1].type)); + addr_frag_pointed2 = (void*) ((char *)addr_block_pointed2 + (frag_pointed2 << heapinfo2[block_pointed2].type)); + + if(add_heap_area_pair(previous, block_pointed1, frag_pointed1, block_pointed2, frag_pointed2)){ + + if(ignore_done < xbt_dynar_length(mmalloc_ignore)){ + if(in_mmalloc_ignore(block_pointed1, frag_pointed1)) + res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 1); + else + res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 0); + }else{ + res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 0); } - }else{ - addr_block1 = (char *)mdp1 + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE); - addr_block2 = (char *)mdp2 + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE); - - switch(mdp1->heapinfo[i].type){ - case 0 : - if(mdp1->heapinfo[i].busy_block.size != mdp2->heapinfo[i].busy_block.size){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different size of a large cluster"); - errors++; - }else{ - return 1; - } - }else{ - if(memcmp(addr_block1, addr_block2, (mdp1->heapinfo[i].busy_block.size * BLOCKSIZE)) != 0){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different data in block %zu (addr_block1 = %p (current = %p) - addr_block2 = %p)", i, addr_block1, (char *)std_heap_addr + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE), addr_block2); - errors++; - }else{ - return 1; - } - } - } - - i = i+mdp1->heapinfo[i].busy_block.size; + if(res_compare) + return 1; + + } + + } + + }else{ - break; - default : - if(mdp1->heapinfo[i].busy_frag.nfree != mdp2->heapinfo[i].busy_frag.nfree){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different free fragments in the fragmented block %zu", i); - errors++; - }else{ - return 1; - } - }else{ - if(mdp1->heapinfo[i].busy_frag.first != mdp2->heapinfo[i].busy_frag.first){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different first free fragments in the block %zu", i); - errors++; - }else{ - return 1; - } - }else{ - frag_size = pow(2,mdp1->heapinfo[i].type); - for(j=0 ; j< (BLOCKSIZE/frag_size); j++){ - if(memcmp((char *)addr_block1 + (j * frag_size), (char *)addr_block2 + (j * frag_size), frag_size) != 0){ - if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){ - XBT_DEBUG("Different data in fragment %zu (addr_frag1 = %p - addr_frag2 = %p) of block %zu", j + 1, (char *)addr_block1 + (j * frag_size), (char *)addr_block2 + (j * frag_size), i); - errors++; - }else{ - return 1; - } - } - } - } - } - - i++; + if((heapinfo1[block_pointed1].type > 0) && (heapinfo2[block_pointed2].type > 0)){ + + addr_block_pointed1 = ((void*) (((ADDR2UINT(block_pointed1)) - 1) * BLOCKSIZE + (char*)heapbase1)); + addr_block_pointed2 = ((void*) (((ADDR2UINT(block_pointed2)) - 1) * BLOCKSIZE + (char*)heapbase2)); + + frag_pointed1 = ((uintptr_t) (ADDR2UINT (address_pointed1) % (BLOCKSIZE))) >> heapinfo1[block_pointed1].type; + frag_pointed2 = ((uintptr_t) (ADDR2UINT (address_pointed2) % (BLOCKSIZE))) >> heapinfo2[block_pointed2].type; - break; + if(heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1] != heapinfo2[block_pointed2].busy_frag.frag_size[frag_pointed2]) /* Different size_used */ + return 1; + + addr_frag_pointed1 = (void*) ((char *)addr_block_pointed1 + (frag_pointed1 << heapinfo1[block_pointed1].type)); + addr_frag_pointed2 = (void*) ((char *)addr_block_pointed2 + (frag_pointed2 << heapinfo2[block_pointed2].type)); + + if(add_heap_area_pair(previous, block_pointed1, frag_pointed1, block_pointed2, frag_pointed2)){ + + if(ignore_done < xbt_dynar_length(mmalloc_ignore)){ + if(in_mmalloc_ignore(block_pointed1, frag_pointed1)) + res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 1); + else + res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 0); + }else{ + res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 0); } + + if(res_compare) + return 1; + } + + }else{ + return 1; } } + i = pointer_align + sizeof(void *); + + }else{ + + i++; + } } - return (errors>0); + return 0; + + +} + +static void heap_area_pair_free(heap_area_pair_t pair){ + if (pair){ + free(pair); + pair = NULL; + } } +static void heap_area_pair_free_voidp(void *d) +{ + heap_area_pair_free((heap_area_pair_t) * (void **) d); +} -void mmalloc_display_info_heap(xbt_mheap_t h){ +static int add_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2){ + if(is_new_heap_area_pair(list, block1, fragment1, block2, fragment2)){ + heap_area_pair_t pair = NULL; + pair = xbt_new0(s_heap_area_pair_t, 1); + pair->block1 = block1; + pair->fragment1 = fragment1; + pair->block2 = block2; + pair->fragment2 = fragment2; + + xbt_dynar_push(list, &pair); + + return 1; + } + + return 0; } + +static int is_new_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2){ + + unsigned int cursor = 0; + heap_area_pair_t current_pair; + + xbt_dynar_foreach(list, cursor, current_pair){ + if(current_pair->block1 == block1 && current_pair->block2 == block2 && current_pair->fragment1 == fragment1 && current_pair->fragment2 == fragment2) + return 0; + } + + return 1; +} + +static void match_equals(xbt_dynar_t list){ + unsigned int cursor = 0; + heap_area_pair_t current_pair; + xbt_dynar_foreach(list, cursor, current_pair){ + if(current_pair->fragment1 != -1){ + heapinfo1[current_pair->block1].busy_frag.equal_to[current_pair->fragment1] = 1; + heapinfo2[current_pair->block2].busy_frag.equal_to[current_pair->fragment2] = 1; + }else{ + heapinfo1[current_pair->block1].busy_block.equal_to = 1; + heapinfo2[current_pair->block2].busy_block.equal_to = 1; + } + } + +}