X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/c0bf08270464302ec402873aed75a459b08e0a8c..fd50a7a8ea7d090e171e0ce78f03f01529720a34:/src/xbt/mmalloc/mmalloc.c diff --git a/src/xbt/mmalloc/mmalloc.c b/src/xbt/mmalloc/mmalloc.c index b0934baf5d..7d8f8ef083 100644 --- a/src/xbt/mmalloc/mmalloc.c +++ b/src/xbt/mmalloc/mmalloc.c @@ -22,35 +22,32 @@ static void* align (struct mdesc *mdp, size_t size); /* Aligned allocation. */ -static void* -align (struct mdesc *mdp, size_t size) -{ +static void* align (struct mdesc *mdp, size_t size) { void* result; unsigned long int adj; result = mdp -> morecore (mdp, size); adj = RESIDUAL (result, BLOCKSIZE); if (adj != 0) - { - adj = BLOCKSIZE - adj; - mdp -> morecore (mdp, adj); - result = (char*) result + adj; - } + { + adj = BLOCKSIZE - adj; + mdp -> morecore (mdp, adj); + result = (char*) result + adj; + } return (result); } /* Set everything up and remember that we have. */ -static int -initialize (struct mdesc *mdp) +static int initialize (struct mdesc *mdp) { mdp -> heapsize = HEAP / BLOCKSIZE; mdp -> heapinfo = (malloc_info *) - align (mdp, mdp -> heapsize * sizeof (malloc_info)); + align (mdp, mdp -> heapsize * sizeof (malloc_info)); if (mdp -> heapinfo == NULL) - { - return (0); - } + { + return (0); + } memset ((void*)mdp -> heapinfo, 0, mdp -> heapsize * sizeof (malloc_info)); mdp -> heapinfo[0].free.size = 0; mdp -> heapinfo[0].free.next = mdp -> heapinfo[0].free.prev = 0; @@ -63,8 +60,7 @@ initialize (struct mdesc *mdp) /* Get neatly aligned memory, initializing or growing the heap info table as necessary. */ -static void* -morecore (struct mdesc *mdp, size_t size) +static void* morecore (struct mdesc *mdp, size_t size) { void* result; malloc_info *newinfo, *oldinfo; @@ -72,35 +68,35 @@ morecore (struct mdesc *mdp, size_t size) result = align (mdp, size); if (result == NULL) - { - return (NULL); - } + { + return (NULL); + } /* Check if we need to grow the info table. */ if ((size_t) BLOCK ((char*) result + size) > mdp -> heapsize) + { + newsize = mdp -> heapsize; + while ((size_t) BLOCK ((char*) result + size) > newsize) + { + newsize *= 2; + } + newinfo = (malloc_info *) align (mdp, newsize * sizeof (malloc_info)); + if (newinfo == NULL) { - newsize = mdp -> heapsize; - while ((size_t) BLOCK ((char*) result + size) > newsize) - { - newsize *= 2; - } - newinfo = (malloc_info *) align (mdp, newsize * sizeof (malloc_info)); - if (newinfo == NULL) - { - mdp -> morecore (mdp, -size); - return (NULL); - } - memset ((void*) newinfo, 0, newsize * sizeof (malloc_info)); - memcpy ((void*) newinfo, (void*) mdp -> heapinfo, - mdp -> heapsize * sizeof (malloc_info)); - oldinfo = mdp -> heapinfo; - newinfo[BLOCK (oldinfo)].busy.type = 0; - newinfo[BLOCK (oldinfo)].busy.info.size - = BLOCKIFY (mdp -> heapsize * sizeof (malloc_info)); - mdp -> heapinfo = newinfo; - __mmalloc_free (mdp, (void*)oldinfo); - mdp -> heapsize = newsize; + mdp -> morecore (mdp, -size); + return (NULL); } + memset ((void*) newinfo, 0, newsize * sizeof (malloc_info)); + memcpy ((void*) newinfo, (void*) mdp -> heapinfo, + mdp -> heapsize * sizeof (malloc_info)); + oldinfo = mdp -> heapinfo; + newinfo[BLOCK (oldinfo)].busy.type = 0; + newinfo[BLOCK (oldinfo)].busy.info.size + = BLOCKIFY (mdp -> heapsize * sizeof (malloc_info)); + mdp -> heapinfo = newinfo; + __mmalloc_free (mdp, (void*)oldinfo); + mdp -> heapsize = newsize; + } mdp -> heaplimit = BLOCK ((char*) result + size); return (result); @@ -108,11 +104,7 @@ morecore (struct mdesc *mdp, size_t size) /* Allocate memory from the heap. */ -void* -mmalloc (md, size) - void* md; - size_t size; -{ +void* mmalloc (void *md, size_t size) { struct mdesc *mdp; void* result; size_t block, blocks, lastblocks, start; @@ -120,199 +112,196 @@ mmalloc (md, size) struct list *next; register size_t log; + /* Work even if the user was stupid enough to ask a 0-byte block, ie return a valid block that can be realloced or freed + * glibc malloc does not use this trick but return a constant pointer, but my hack is quicker to implement ;) + */ if (size == 0) - { - return (NULL); - } + size=1; mdp = MD_TO_MDP (md); - - if (mdp -> mmalloc_hook != NULL) - { - return ((*mdp -> mmalloc_hook) (md, size)); - } + LOCK(mdp); +// printf("(%s) Mallocing %d bytes on %p (default: %p)...",xbt_thread_self_name(),size,mdp,__mmalloc_default_mdp);fflush(stdout); - if (!(mdp -> flags & MMALLOC_INITIALIZED)) - { - if (!initialize (mdp)) - { - return (NULL); - } - } - if (size < sizeof (struct list)) - { - size = sizeof (struct list); + if (mdp -> mmalloc_hook != NULL) { + void * res = ((*mdp -> mmalloc_hook) (md, size)); + UNLOCK(mdp); + return res; + } + + if (!(mdp -> flags & MMALLOC_INITIALIZED)) { + if (!initialize (mdp)) { + UNLOCK(mdp); + return (NULL); } + } + + if (size < sizeof (struct list)) { + size = sizeof (struct list); + } /* Determine the allocation policy based on the request size. */ if (size <= BLOCKSIZE / 2) - { - /* Small allocation to receive a fragment of a block. + { + /* Small allocation to receive a fragment of a block. Determine the logarithm to base two of the fragment size. */ - log = 1; - --size; - while ((size /= 2) != 0) - { - ++log; - } - - /* Look in the fragment lists for a + log = 1; + --size; + while ((size /= 2) != 0) + { + ++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. + 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. */ - result = (void*) next; - next -> prev -> next = next -> next; - if (next -> next != NULL) - { - next -> next -> prev = next -> prev; - } - block = BLOCK (result); - if (--mdp -> heapinfo[block].busy.info.frag.nfree != 0) - { - mdp -> heapinfo[block].busy.info.frag.first = - RESIDUAL (next -> next, BLOCKSIZE) >> log; - } - - /* 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 + result = (void*) next; + next -> prev -> next = next -> next; + if (next -> next != NULL) + { + next -> next -> prev = next -> prev; + } + block = BLOCK (result); + if (--mdp -> heapinfo[block].busy.info.frag.nfree != 0) + { + mdp -> heapinfo[block].busy.info.frag.first = + RESIDUAL (next -> next, BLOCKSIZE) >> log; + } + + /* 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. */ - result = mmalloc (md, BLOCKSIZE); - if (result == NULL) - { - return (NULL); - } - - /* Link all fragments but the first into the free list. */ - for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i) - { - 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; - } - } - - /* Initialize the nfree and first counters for this block. */ - block = BLOCK (result); - mdp -> heapinfo[block].busy.type = log; - mdp -> heapinfo[block].busy.info.frag.nfree = i - 1; - mdp -> heapinfo[block].busy.info.frag.first = i - 1; - - mdp -> heapstats.chunks_free += (BLOCKSIZE >> log) - 1; - mdp -> heapstats.bytes_free += BLOCKSIZE - (1 << log); - mdp -> heapstats.bytes_used -= BLOCKSIZE - (1 << log); - } + UNLOCK(mdp); + //printf("(%s) No free fragment...",xbt_thread_self_name()); + result = mmalloc (md, BLOCKSIZE); + //printf("(%s) Fragment: %p...",xbt_thread_self_name(),result); + LOCK(mdp); + if (result == NULL) + { + UNLOCK(mdp); + return (NULL); + } + + /* Link all fragments but the first into the free list. */ + for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i) + { + 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; + } + } + + /* Initialize the nfree and first counters for this block. */ + block = BLOCK (result); + mdp -> heapinfo[block].busy.type = log; + mdp -> heapinfo[block].busy.info.frag.nfree = i - 1; + mdp -> heapinfo[block].busy.info.frag.first = i - 1; + + mdp -> heapstats.chunks_free += (BLOCKSIZE >> log) - 1; + mdp -> heapstats.bytes_free += BLOCKSIZE - (1 << log); + mdp -> heapstats.bytes_used -= BLOCKSIZE - (1 << log); } + } else - { - /* Large allocation to receive one or more blocks. + { + /* Large allocation to receive one or more blocks. Search the free list in a circle starting at the last place visited. If we loop completely around without finding a large enough space we will have to get more memory from the system. */ - blocks = BLOCKIFY(size); - start = block = MALLOC_SEARCH_START; - while (mdp -> heapinfo[block].free.size < blocks) - { - block = mdp -> heapinfo[block].free.next; - if (block == start) - { - /* Need to get more from the system. Check to see if + blocks = BLOCKIFY(size); + start = block = MALLOC_SEARCH_START; + while (mdp -> heapinfo[block].free.size < blocks) + { + block = mdp -> heapinfo[block].free.next; + if (block == start) + { + /* Need to get more from the system. Check to see if the new core will be contiguous with the final free block; if so we don't need to get as much. */ - block = mdp -> heapinfo[0].free.prev; - lastblocks = mdp -> heapinfo[block].free.size; - if (mdp -> heaplimit != 0 && - block + lastblocks == mdp -> heaplimit && - mdp -> morecore (mdp, 0) == ADDRESS(block + lastblocks) && - (morecore (mdp, (blocks - lastblocks) * BLOCKSIZE)) != NULL) - { - /* Which block we are extending (the `final free + block = mdp -> heapinfo[0].free.prev; + lastblocks = mdp -> heapinfo[block].free.size; + if (mdp -> heaplimit != 0 && + block + lastblocks == mdp -> heaplimit && + mdp -> morecore (mdp, 0) == ADDRESS(block + lastblocks) && + (morecore (mdp, (blocks - lastblocks) * BLOCKSIZE)) != NULL) + { + /* Which block we are extending (the `final free block' referred to above) might have changed, if it got combined with a freed info table. */ - block = mdp -> heapinfo[0].free.prev; - - mdp -> heapinfo[block].free.size += (blocks - lastblocks); - mdp -> heapstats.bytes_free += - (blocks - lastblocks) * BLOCKSIZE; - continue; - } - result = morecore(mdp, blocks * BLOCKSIZE); - if (result == NULL) - { - return (NULL); - } - block = BLOCK (result); - mdp -> heapinfo[block].busy.type = 0; - mdp -> heapinfo[block].busy.info.size = blocks; - mdp -> heapstats.chunks_used++; - mdp -> heapstats.bytes_used += blocks * BLOCKSIZE; - return (result); - } - } - - /* At this point we have found a suitable free list entry. + block = mdp -> heapinfo[0].free.prev; + + mdp -> heapinfo[block].free.size += (blocks - lastblocks); + mdp -> heapstats.bytes_free += + (blocks - lastblocks) * BLOCKSIZE; + continue; + } + result = morecore(mdp, blocks * BLOCKSIZE); + if (result == NULL) + { + UNLOCK(mdp); + return (NULL); + } + block = BLOCK (result); + mdp -> heapinfo[block].busy.type = 0; + mdp -> heapinfo[block].busy.info.size = blocks; + mdp -> heapstats.chunks_used++; + mdp -> heapstats.bytes_used += blocks * BLOCKSIZE; + UNLOCK(mdp); + return (result); + } + } + + /* At this point we have found a suitable free list entry. Figure out how to remove what we need from the list. */ - result = ADDRESS(block); - if (mdp -> heapinfo[block].free.size > blocks) - { - /* The block we found has a bit left over, + result = ADDRESS(block); + if (mdp -> heapinfo[block].free.size > blocks) + { + /* The block we found has a bit left over, so relink the tail end back into the free list. */ - mdp -> heapinfo[block + blocks].free.size - = mdp -> heapinfo[block].free.size - blocks; - mdp -> heapinfo[block + blocks].free.next - = mdp -> heapinfo[block].free.next; - mdp -> heapinfo[block + blocks].free.prev - = mdp -> heapinfo[block].free.prev; - mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next - = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev - = mdp -> heapindex = block + blocks; - } - else - { - /* The block exactly matches our requirements, + mdp -> heapinfo[block + blocks].free.size + = mdp -> heapinfo[block].free.size - blocks; + mdp -> heapinfo[block + blocks].free.next + = mdp -> heapinfo[block].free.next; + mdp -> heapinfo[block + blocks].free.prev + = mdp -> heapinfo[block].free.prev; + mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next + = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.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.next].free.prev - = mdp -> heapinfo[block].free.prev; - mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next - = mdp -> heapindex = mdp -> heapinfo[block].free.next; - mdp -> heapstats.chunks_free--; - } - - mdp -> heapinfo[block].busy.type = 0; - mdp -> heapinfo[block].busy.info.size = blocks; - mdp -> heapstats.chunks_used++; - mdp -> heapstats.bytes_used += blocks * BLOCKSIZE; - mdp -> heapstats.bytes_free -= blocks * BLOCKSIZE; + mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev + = mdp -> heapinfo[block].free.prev; + mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next + = mdp -> heapindex = mdp -> heapinfo[block].free.next; + mdp -> heapstats.chunks_free--; } - return (result); -} - -/* When using this package, provide a version of malloc/realloc/free built - on top of it, so that if we use the default sbrk() region we will not - collide with another malloc package trying to do the same thing, if - the application contains any "hidden" calls to malloc/realloc/free (such - as inside a system library). */ - -void* -malloc (size_t size) -{ - void* result; - result = mmalloc (NULL, size); + mdp -> heapinfo[block].busy.type = 0; + mdp -> heapinfo[block].busy.info.size = blocks; + 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); + UNLOCK(mdp); return (result); }