OSDN Git Service

hidden_def/hidden_proto: convert all users (I hope) termios split, add some missing...
[uclinux-h8/uClibc.git] / libc / stdlib / malloc / realloc.c
1 /*
2  * libc/stdlib/malloc/realloc.c -- realloc function
3  *
4  *  Copyright (C) 2002  NEC Corporation
5  *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
6  *
7  * This file is subject to the terms and conditions of the GNU Lesser
8  * General Public License.  See the file COPYING.LIB in the main
9  * directory of this archive for more details.
10  * 
11  * Written by Miles Bader <miles@gnu.org>
12  */
13
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17
18 libc_hidden_proto(memcpy)
19
20 #include "malloc.h"
21 #include "heap.h"
22
23
24 void *
25 realloc (void *mem, size_t new_size)
26 {
27   size_t size;
28   char *base_mem;
29
30   /* Check for special cases.  */
31   if (! mem)
32     return malloc (new_size);
33   if (! new_size)
34     {
35       free (mem);
36       return malloc (new_size);
37     }
38
39   /* Normal realloc.  */
40
41   base_mem = MALLOC_BASE (mem);
42   size = MALLOC_SIZE (mem);
43
44   /* Include extra space to record the size of the allocated block.
45      Also make sure that we're dealing in a multiple of the heap
46      allocation unit (SIZE is already guaranteed to be so).*/
47   new_size = HEAP_ADJUST_SIZE (new_size + MALLOC_HEADER_SIZE);
48
49   MALLOC_DEBUG (1, "realloc: 0x%lx, %d (base = 0x%lx, total_size = %d)",
50                 (long)mem, new_size, (long)base_mem, size);
51
52   if (new_size > size)
53     /* Grow the block.  */
54     {
55       size_t extra = new_size - size;
56
57       __heap_lock (&__malloc_heap);
58       extra = __heap_alloc_at (&__malloc_heap, base_mem + size, extra);
59       __heap_unlock (&__malloc_heap);
60
61       if (extra)
62         /* Record the changed size.  */
63         MALLOC_SET_SIZE (base_mem, size + extra);
64       else
65         /* Our attempts to extend MEM in place failed, just
66            allocate-and-copy.  */
67         {
68           void *new_mem = malloc (new_size - MALLOC_HEADER_SIZE);
69           if (new_mem)
70             {
71               memcpy (new_mem, mem, size - MALLOC_HEADER_SIZE);
72               free (mem);
73             }
74           mem = new_mem;
75         }
76     }
77   else if (new_size + MALLOC_REALLOC_MIN_FREE_SIZE <= size)
78     /* Shrink the block.  */
79     {
80       __heap_lock (&__malloc_heap);
81       __heap_free (&__malloc_heap, base_mem + new_size, size - new_size);
82       __heap_unlock (&__malloc_heap);
83       MALLOC_SET_SIZE (base_mem, new_size);
84     }
85
86   if (mem)
87     MALLOC_DEBUG (-1, "realloc: returning 0x%lx (base:0x%lx, total_size:%d)",
88                   (long)mem, (long)MALLOC_BASE(mem), (long)MALLOC_SIZE(mem));
89   else
90     MALLOC_DEBUG (-1, "realloc: returning 0");
91
92   return mem;
93 }