X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/6d215aa449fe86894819be267aa2ae30cb5b151c..c5071b3b404fbbfc84172a08fb4086bc5ce97fc9:/src/xbt/mmalloc/mmalloc.c diff --git a/src/xbt/mmalloc/mmalloc.c b/src/xbt/mmalloc/mmalloc.c index 37f8c6b933..42845de359 100644 --- a/src/xbt/mmalloc/mmalloc.c +++ b/src/xbt/mmalloc/mmalloc.c @@ -32,7 +32,7 @@ static void *align(struct mdesc *mdp, size_t size) result = mmorecore(mdp, size); /* if this reservation does not fill up the last block of our resa, - * complete the reservation by also asking for the full lastest block. + * complete the reservation by also asking for the full latest block. * * Also, the returned block is aligned to the end of block (but I've * no fucking idea of why, actually -- http://abstrusegoose.com/432 -- @@ -51,6 +51,9 @@ static void *align(struct mdesc *mdp, size_t size) * properly, we need to make the align function publicly visible, too */ static void initialize(xbt_mheap_t mdp) { + int i; + malloc_info mi; /* to compute the offset of the swag hook */ + mdp->heapsize = HEAP / BLOCKSIZE; mdp->heapinfo = (malloc_info *) align(mdp, mdp->heapsize * sizeof(malloc_info)); @@ -62,12 +65,20 @@ static void initialize(xbt_mheap_t mdp) mdp->heapindex = 0; mdp->heapbase = (void *) mdp->heapinfo; mdp->flags |= MMALLOC_INITIALIZED; + + for (i=0;ifraghead[i]), + xbt_swag_offset(mi, freehook)); + } } +#define update_hook(a,offset) do { if (a) { a = ((char*)a +(offset));} }while(0) + /* Get neatly aligned memory from the low level layers, and register it * into the heap info table as necessary. */ static void *register_morecore(struct mdesc *mdp, size_t size) { + int i; void *result; malloc_info *newinfo, *oldinfo; size_t newsize; @@ -87,6 +98,21 @@ static void *register_morecore(struct mdesc *mdp, size_t size) newinfo = (malloc_info *) align(mdp, newsize * sizeof(malloc_info)); memset(newinfo, 0, newsize * sizeof(malloc_info)); memcpy(newinfo, oldinfo, mdp->heapsize * sizeof(malloc_info)); + + /* Update the swag of busy blocks containing free fragments by applying the offset to all swag_hooks. Yeah. My hand is right in the fan and I still type */ + size_t offset=((char*)newinfo)-((char*)oldinfo); + + for (i=1/*first element of heapinfo describes the mdesc area*/; + iheaplimit; + i++) { + update_hook(newinfo[i].freehook.next,offset); + update_hook(newinfo[i].freehook.prev,offset); + } + // also update the starting points of the swag + for (i=0;ifraghead[i].head,offset); + update_hook(mdp->fraghead[i].tail,offset); + } mdp->heapinfo = newinfo; /* mark the space previously occupied by the block info as free by first marking it @@ -96,7 +122,8 @@ static void *register_morecore(struct mdesc *mdp, size_t size) newinfo[BLOCK(oldinfo)].busy_block.size = BLOCKIFY(mdp->heapsize * sizeof(malloc_info)); newinfo[BLOCK(oldinfo)].busy_block.busy_size = size; - newinfo[BLOCK(oldinfo)].busy_block.bt_size = 0;// FIXME setup the backtrace + newinfo[BLOCK(oldinfo)].busy_block.ignore = 0; + //newinfo[BLOCK(oldinfo)].busy_block.bt_size = 0;// FIXME setup the backtrace mfree(mdp, (void *) oldinfo); mdp->heapsize = newsize; } @@ -104,15 +131,23 @@ static void *register_morecore(struct mdesc *mdp, size_t size) mdp->heaplimit = BLOCK((char *) result + size); return (result); } +#undef update_hook /* Allocate memory from the heap. */ - -void *mmalloc(xbt_mheap_t mdp, size_t size) +void *mmalloc(xbt_mheap_t mdp, size_t size) { + void *res= mmalloc_no_memset(mdp,size); +// fprintf(stderr,"malloc(%zu)~>%p\n",size,res); + memset(res,0,size); + return res; +} +/* Spliting mmalloc this way is mandated by a trick in mrealloc, that gives + back the memory of big blocks to the system before reallocating them: we don't + want to loose the beginning of the area when this happens */ +void *mmalloc_no_memset(xbt_mheap_t mdp, size_t size) { void *result; size_t block, blocks, lastblocks, start; register size_t i; - struct list *next; register size_t log; int it; @@ -130,6 +165,8 @@ void *mmalloc(xbt_mheap_t mdp, size_t size) if (!(mdp->flags & MMALLOC_INITIALIZED)) initialize(mdp); + mmalloc_paranoia(mdp); + /* Determine the allocation policy based on the request size. */ if (size <= BLOCKSIZE / 2) { /* Small allocation to receive a fragment of a block. @@ -140,63 +177,67 @@ void *mmalloc(xbt_mheap_t mdp, size_t size) ++log; } - /* Look in the fragment lists for a - free fragment of the desired size. */ - next = mdp->fraghead[log].next; - if (next != NULL) { - /* There are free fragments of this size. - Pop a fragment out of the fragment list and return it. - Update the block's nfree and first counters. */ - int frag_nb; - result = (void *) next; - block = BLOCK(result); - - frag_nb = RESIDUAL(result, BLOCKSIZE) >> log; - mdp->heapinfo[block].busy_frag.frag_size[frag_nb] = requested_size; - xbt_backtrace_no_malloc(mdp->heapinfo[block].busy_frag.bt[frag_nb],XBT_BACKTRACE_SIZE); - - next->prev->next = next->next; - if (next->next != NULL) { - next->next->prev = next->prev; - } - if (--mdp->heapinfo[block].busy_frag.nfree != 0) { - mdp->heapinfo[block].busy_frag.first = - RESIDUAL(next->next, BLOCKSIZE) >> log; + /* Look in the fragment lists for a free fragment of the desired size. */ + if (xbt_swag_size(&mdp->fraghead[log])>0) { + /* There are free fragments of this size; Get one of them and prepare to return it. + Update the block's nfree and if no other free fragment, get out of the swag. */ + + /* search a fragment that I could return as a result */ + malloc_info *candidate_info = xbt_swag_getFirst(&mdp->fraghead[log]); + size_t candidate_block = (candidate_info - &(mdp->heapinfo[0])); + size_t candidate_frag; + for (candidate_frag=0;candidate_frag<(size_t) (BLOCKSIZE >> log);candidate_frag++) + if (candidate_info->busy_frag.frag_size[candidate_frag] == -1) + break; + xbt_assert(candidate_frag < (size_t) (BLOCKSIZE >> log), + "Block %zu was registered as containing free fragments of type %zu, but I can't find any",candidate_block,log); + + result = (void*) (((char*)ADDRESS(candidate_block)) + (candidate_frag << log)); + + /* Remove this fragment from the list of free guys */ + candidate_info->busy_frag.nfree--; + if (candidate_info->busy_frag.nfree == 0) { + xbt_swag_remove(candidate_info,&mdp->fraghead[log]); } + /* Update our metadata about this fragment */ + candidate_info->busy_frag.frag_size[candidate_frag] = requested_size; + candidate_info->busy_frag.ignore[candidate_frag] = 0; + //xbt_backtrace_no_malloc(candidate_info->busy_frag.bt[candidate_frag],XBT_BACKTRACE_SIZE); + //xbt_libunwind_backtrace(candidate_info->busy_frag.bt[candidate_frag],XBT_BACKTRACE_SIZE); + /* Update the statistics. */ mdp -> heapstats.chunks_used++; mdp -> heapstats.bytes_used += 1 << log; mdp -> heapstats.chunks_free--; mdp -> heapstats.bytes_free -= 1 << log; - + } else { /* No free fragments of the desired size, so get a new block and break it into fragments, returning the first. */ - //printf("(%s) No free fragment...",xbt_thread_self_name()); result = mmalloc(mdp, BLOCKSIZE); // does not return NULL - - /* Link all fragments but the first into the free list, and mark their requested size to 0. */ block = BLOCK(result); + + mdp->heapinfo[block].type = log; + /* Link all fragments but the first as free, and add the block to the swag of blocks containing free frags */ for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i) { - mdp->heapinfo[block].busy_frag.frag_size[i] = 0; - next = (struct list *) ((char *) result + (i << log)); - next->next = mdp->fraghead[log].next; - next->prev = &mdp->fraghead[log]; - next->prev->next = next; - if (next->next != NULL) { - next->next->prev = next; - } + mdp->heapinfo[block].busy_frag.frag_size[i] = -1; + mdp->heapinfo[block].busy_frag.ignore[i] = 0; } - mdp->heapinfo[block].busy_frag.frag_size[0] = requested_size; - xbt_backtrace_no_malloc(mdp->heapinfo[block].busy_frag.bt[0],XBT_BACKTRACE_SIZE); - - /* Initialize the nfree and first counters for this block. */ - mdp->heapinfo[block].type = log; mdp->heapinfo[block].busy_frag.nfree = i - 1; - mdp->heapinfo[block].busy_frag.first = i - 1; + mdp->heapinfo[block].freehook.prev = NULL; + mdp->heapinfo[block].freehook.next = NULL; + + xbt_swag_insert(&mdp->heapinfo[block], &(mdp->fraghead[log])); + /* mark the fragment returned as busy */ + mdp->heapinfo[block].busy_frag.frag_size[0] = requested_size; + mdp->heapinfo[block].busy_frag.ignore[0] = 0; + //xbt_backtrace_no_malloc(mdp->heapinfo[block].busy_frag.bt[0],XBT_BACKTRACE_SIZE); + //xbt_libunwind_backtrace(mdp->heapinfo[block].busy_frag.bt[0],XBT_BACKTRACE_SIZE); + + /* update stats */ mdp -> heapstats.chunks_free += (BLOCKSIZE >> log) - 1; mdp -> heapstats.bytes_free += BLOCKSIZE - (1 << log); mdp -> heapstats.bytes_used -= BLOCKSIZE - (1 << log); @@ -210,8 +251,8 @@ void *mmalloc(xbt_mheap_t mdp, size_t size) start = block = MALLOC_SEARCH_START; while (mdp->heapinfo[block].free_block.size < blocks) { if (mdp->heapinfo[block].type >=0) { // Don't trust xbt_die and friends in malloc-level library, you fool! - fprintf(stderr,"Internal error: found a free block not marked as such (block=%lu type=%lu). Please report this bug.\n",(unsigned long)block,(unsigned long)mdp->heapinfo[block].type); - abort(); + fprintf(stderr,"Internal error: found a free block not marked as such (block=%lu type=%lu). Please report this bug.\n",(unsigned long)block,(unsigned long)mdp->heapinfo[block].type); + abort(); } block = mdp->heapinfo[block].free_block.next; @@ -236,13 +277,18 @@ void *mmalloc(xbt_mheap_t mdp, size_t size) result = register_morecore(mdp, blocks * BLOCKSIZE); block = BLOCK(result); - for (it=0;itheapinfo[block+it].type = 0; + for (it=0;itheapinfo[block+it].type = 0; + mdp->heapinfo[block+it].busy_block.busy_size = 0; + mdp->heapinfo[block+it].busy_block.ignore = 0; + } mdp->heapinfo[block].busy_block.size = blocks; mdp->heapinfo[block].busy_block.busy_size = requested_size; - mdp->heapinfo[block].busy_block.bt_size=xbt_backtrace_no_malloc(mdp->heapinfo[block].busy_block.bt,XBT_BACKTRACE_SIZE); - mdp -> heapstats.chunks_used++; - mdp -> heapstats.bytes_used += blocks * BLOCKSIZE; + //mdp->heapinfo[block].busy_block.bt_size=xbt_backtrace_no_malloc(mdp->heapinfo[block].busy_block.bt,XBT_BACKTRACE_SIZE); + //mdp->heapinfo[block].busy_block.bt_size = xbt_libunwind_backtrace(mdp->heapinfo[block].busy_block.bt,XBT_BACKTRACE_SIZE); + mdp -> heapstats.chunks_used++; + mdp -> heapstats.bytes_used += blocks * BLOCKSIZE; + return result; } /* Need large block(s), but found some in the existing heap */ @@ -255,34 +301,39 @@ void *mmalloc(xbt_mheap_t mdp, size_t size) /* The block we found has a bit left over, so relink the tail end back into the free list. */ mdp->heapinfo[block + blocks].free_block.size - = mdp->heapinfo[block].free_block.size - blocks; + = mdp->heapinfo[block].free_block.size - blocks; mdp->heapinfo[block + blocks].free_block.next - = mdp->heapinfo[block].free_block.next; + = mdp->heapinfo[block].free_block.next; mdp->heapinfo[block + blocks].free_block.prev - = mdp->heapinfo[block].free_block.prev; + = mdp->heapinfo[block].free_block.prev; mdp->heapinfo[mdp->heapinfo[block].free_block.prev].free_block.next - = mdp->heapinfo[mdp->heapinfo[block].free_block.next].free_block.prev - = mdp->heapindex = block + blocks; + = mdp->heapinfo[mdp->heapinfo[block].free_block.next].free_block.prev + = mdp->heapindex = block + blocks; } else { /* The block exactly matches our requirements, so just remove it from the list. */ mdp->heapinfo[mdp->heapinfo[block].free_block.next].free_block.prev - = mdp->heapinfo[block].free_block.prev; + = mdp->heapinfo[block].free_block.prev; mdp->heapinfo[mdp->heapinfo[block].free_block.prev].free_block.next - = mdp->heapindex = mdp->heapinfo[block].free_block.next; + = mdp->heapindex = mdp->heapinfo[block].free_block.next; } - for (it=0;itheapinfo[block+it].type = 0; + mdp->heapinfo[block+it].busy_block.busy_size = 0; + mdp->heapinfo[block+it].busy_block.ignore = 0; + } mdp->heapinfo[block].busy_block.size = blocks; - mdp->heapinfo[block].busy_block.busy_size = requested_size; - //mdp->heapinfo[block].busy_block.bt_size = 0; - mdp->heapinfo[block].busy_block.bt_size = xbt_backtrace_no_malloc(mdp->heapinfo[block].busy_block.bt,XBT_BACKTRACE_SIZE); - + mdp->heapinfo[block].busy_block.busy_size = requested_size; + //mdp->heapinfo[block].busy_block.bt_size = xbt_backtrace_no_malloc(mdp->heapinfo[block].busy_block.bt,XBT_BACKTRACE_SIZE); + //mdp->heapinfo[block].busy_block.bt_size = xbt_libunwind_backtrace(mdp->heapinfo[block].busy_block.bt,XBT_BACKTRACE_SIZE); + mdp -> heapstats.chunks_used++; mdp -> heapstats.bytes_used += blocks * BLOCKSIZE; mdp -> heapstats.bytes_free -= blocks * BLOCKSIZE; + } //printf("(%s) Done mallocing. Result is %p\n",xbt_thread_self_name(),result);fflush(stdout); + return (result); }