diff options
Diffstat (limited to 'libc/stdlib/malloc')
-rw-r--r-- | libc/stdlib/malloc/realloc.c | 99 |
1 files changed, 54 insertions, 45 deletions
diff --git a/libc/stdlib/malloc/realloc.c b/libc/stdlib/malloc/realloc.c index 7188bc897..31639d7fe 100644 --- a/libc/stdlib/malloc/realloc.c +++ b/libc/stdlib/malloc/realloc.c @@ -21,60 +21,69 @@ void * realloc (void *mem, size_t new_size) { - if (! mem) - return malloc (new_size); - else + size_t size; + char *base_mem; + + /* Check for special cases. */ + if (! new_size) { - char *base_mem = MALLOC_BASE (mem); - size_t size = MALLOC_SIZE (mem); + free (mem); + return 0; + } + else if (! mem) + return malloc (new_size); - /* Include extra space to record the size of the allocated block. - Also make sure that we're dealing in a multiple of the heap - allocation unit (SIZE is already guaranteed to be so).*/ - new_size = HEAP_ADJUST_SIZE (new_size + MALLOC_HEADER_SIZE); + /* Normal realloc. */ - MALLOC_DEBUG ("realloc: 0x%lx, %d (base = 0x%lx, total_size = %d)\n", - (long)mem, new_size, (long)base_mem, size); + base_mem = MALLOC_BASE (mem); + size = MALLOC_SIZE (mem); - if (new_size > size) - /* Grow the block. */ - { - size_t extra = new_size - size; + /* Include extra space to record the size of the allocated block. + Also make sure that we're dealing in a multiple of the heap + allocation unit (SIZE is already guaranteed to be so).*/ + new_size = HEAP_ADJUST_SIZE (new_size + MALLOC_HEADER_SIZE); + + MALLOC_DEBUG ("realloc: 0x%lx, %d (base = 0x%lx, total_size = %d)\n", + (long)mem, new_size, (long)base_mem, size); + + if (new_size > size) + /* Grow the block. */ + { + size_t extra = new_size - size; - __malloc_lock (); - extra = __heap_alloc_at (&__malloc_heap, base_mem + size, extra); - __malloc_unlock (); + __malloc_lock (); + extra = __heap_alloc_at (&__malloc_heap, base_mem + size, extra); + __malloc_unlock (); - if (extra) - /* Record the changed size. */ - MALLOC_SET_SIZE (mem, new_size); - else - /* Our attempts to extend MEM in place failed, just - allocate-and-copy. */ + if (extra) + /* Record the changed size. */ + MALLOC_SET_SIZE (mem, new_size); + else + /* Our attempts to extend MEM in place failed, just + allocate-and-copy. */ + { + void *new_mem = malloc (new_size - MALLOC_HEADER_SIZE); + if (new_mem) { - void *new_mem = malloc (new_size - MALLOC_HEADER_SIZE); - if (new_mem) - { - memcpy (new_mem, mem, size - MALLOC_HEADER_SIZE); - free (mem); - } - mem = new_mem; + memcpy (new_mem, mem, size - MALLOC_HEADER_SIZE); + free (mem); } + mem = new_mem; } - else if (new_size + MALLOC_REALLOC_MIN_FREE_SIZE <= size) - /* Shrink the block. */ - { - __malloc_lock (); - __heap_free (&__malloc_heap, base_mem + new_size, size - new_size); - __malloc_unlock (); - MALLOC_SET_SIZE (mem, new_size); - } + } + else if (new_size + MALLOC_REALLOC_MIN_FREE_SIZE <= size) + /* Shrink the block. */ + { + __malloc_lock (); + __heap_free (&__malloc_heap, base_mem + new_size, size - new_size); + __malloc_unlock (); + MALLOC_SET_SIZE (mem, new_size); + } - if (mem) - MALLOC_DEBUG (" realloc: returning 0x%lx" - " (base:0x%lx, total_size:%d)\n", - (long)mem, (long)MALLOC_BASE(mem), (long)MALLOC_SIZE(mem)); + if (mem) + MALLOC_DEBUG (" realloc: returning 0x%lx" + " (base:0x%lx, total_size:%d)\n", + (long)mem, (long)MALLOC_BASE(mem), (long)MALLOC_SIZE(mem)); - return mem; - } + return mem; } |