From 6c85989bc5420b3fbc6373025a469b41315f7813 Mon Sep 17 00:00:00 2001 From: Martin Quinson Date: Tue, 9 Oct 2012 00:28:30 +0200 Subject: [PATCH 1/1] Bug fix in mrealloc where the previous content could get lost When reallocating a large block, mrealloc tries to be cleaver and first frees the area before requesting it again to avoid a copy if there is some free adjacent memory. This trick obviously don't mix well with the mmalloc memseting the allocated memory to 0 before returning it. So, split the mmalloc in two, and use the non-memsetting one from mrealloc. --- include/xbt/mmalloc.h | 5 ++++- src/xbt/mmalloc/mmalloc.c | 16 +++++++++------- src/xbt/mmalloc/mrealloc.c | 8 +++++--- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/include/xbt/mmalloc.h b/include/xbt/mmalloc.h index 0c706ee990..99d0b5bb47 100644 --- a/include/xbt/mmalloc.h +++ b/include/xbt/mmalloc.h @@ -29,9 +29,12 @@ */ typedef struct mdesc *xbt_mheap_t; -/* Allocate SIZE bytes of memory. */ +/* Allocate SIZE bytes of memory (and memset it to 0). */ extern void *mmalloc(xbt_mheap_t md, size_t size); +/* Allocate SIZE bytes of memory (and don't mess with it) */ +void *mmalloc_no_memset(xbt_mheap_t mdp, size_t size); + /* Re-allocate the previously allocated block in void*, making the new block SIZE bytes long. */ extern void *mrealloc(xbt_mheap_t md, void *ptr, size_t size); diff --git a/src/xbt/mmalloc/mmalloc.c b/src/xbt/mmalloc/mmalloc.c index be68060138..7584c63335 100644 --- a/src/xbt/mmalloc/mmalloc.c +++ b/src/xbt/mmalloc/mmalloc.c @@ -106,8 +106,15 @@ static void *register_morecore(struct mdesc *mdp, size_t size) } /* 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); + 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; @@ -170,15 +177,12 @@ void *mmalloc(xbt_mheap_t mdp, size_t size) mdp -> heapstats.chunks_free--; mdp -> heapstats.bytes_free -= 1 << log; - memset(result, 0, requested_size); - } 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 - memset(result, 0, requested_size); /* Link all fragments but the first into the free list, and mark their requested size to 0. */ block = BLOCK(result); @@ -237,7 +241,6 @@ void *mmalloc(xbt_mheap_t mdp, size_t size) continue; } result = register_morecore(mdp, blocks * BLOCKSIZE); - memset(result, 0, requested_size); block = BLOCK(result); for (it=0;it heapstats.bytes_used += blocks * BLOCKSIZE; mdp -> heapstats.bytes_free -= blocks * BLOCKSIZE; - memset(result, 0, requested_size); } //printf("(%s) Done mallocing. Result is %p\n",xbt_thread_self_name(),result);fflush(stdout); return (result); diff --git a/src/xbt/mmalloc/mrealloc.c b/src/xbt/mmalloc/mrealloc.c index 23d0a1c202..c1078bdeaf 100644 --- a/src/xbt/mmalloc/mrealloc.c +++ b/src/xbt/mmalloc/mrealloc.c @@ -101,8 +101,9 @@ void *mrealloc(xbt_mheap_t mdp, void *ptr, size_t size) } else { /* Won't fit, so allocate a new region that will. - Free the old region first in case there is sufficient - adjacent free space to grow without moving. */ + Free the old region first in case there is sufficient adjacent free space to grow without moving. + This trick mandates using a specific version of mmalloc that does not memset the memory to 0 after + action for obvious reasons. */ blocks = mdp->heapinfo[block].busy_block.size; /* Prevent free from actually returning memory to the system. */ oldlimit = mdp->heaplimit; @@ -110,9 +111,10 @@ void *mrealloc(xbt_mheap_t mdp, void *ptr, size_t size) mfree(mdp, ptr); mdp->heaplimit = oldlimit; - result = mmalloc(mdp, requested_size); + result = mmalloc_no_memset(mdp, requested_size); if (ptr != result) memmove(result, ptr, blocks * BLOCKSIZE); + /* FIXME: we should memset the end of the recently area */ } break; -- 2.20.1