diff options
Diffstat (limited to 'libc/stdlib')
| -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;  } | 
