Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
change mmalloc.h into a public header
[simgrid.git] / src / xbt / mmalloc / mrealloc.c
1 /* Change the size of a block allocated by `mmalloc'.
2    Copyright 1990, 1991 Free Software Foundation
3                   Written May 1989 by Mike Haertel.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB.  If
17 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19
20    The author may be reached (Email) at the address mike@ai.mit.edu,
21    or (US mail) as Mike Haertel c/o Free Software Foundation. */
22
23 #include <string.h>     /* Prototypes for memcpy, memmove, memset, etc */
24
25 #include "mmprivate.h"
26
27 /* Resize the given region to the new size, returning a pointer
28    to the (possibly moved) region.  This is optimized for speed;
29    some benchmarks seem to indicate that greater compactness is
30    achieved by unconditionally allocating and copying to a
31    new region.  This module has incestuous knowledge of the
32    internals of both mfree and mmalloc. */
33
34 void*
35 mrealloc (void *md, void *ptr, size_t size)
36 {
37   struct mdesc *mdp;
38   void* result;
39   int type;
40   size_t block, blocks, oldlimit;
41
42   if (size == 0)
43     {
44       mfree (md, ptr);
45       return (mmalloc (md, 0));
46     }
47   else if (ptr == NULL)
48     {
49       return (mmalloc (md, size));
50     }
51
52   mdp = MD_TO_MDP (md);
53
54   if (mdp -> mrealloc_hook != NULL)
55     {
56       return ((*mdp -> mrealloc_hook) (md, ptr, size));
57     }
58
59   block = BLOCK (ptr);
60
61   type = mdp -> heapinfo[block].busy.type;
62   switch (type)
63     {
64     case 0:
65       /* Maybe reallocate a large block to a small fragment.  */
66       if (size <= BLOCKSIZE / 2)
67         {
68           result = mmalloc (md, size);
69           if (result != NULL)
70             {
71               memcpy (result, ptr, size);
72               mfree (md, ptr);
73               return (result);
74             }
75         }
76
77       /* The new size is a large allocation as well;
78          see if we can hold it in place. */
79       blocks = BLOCKIFY (size);
80       if (blocks < mdp -> heapinfo[block].busy.info.size)
81         {
82           /* The new size is smaller; return excess memory to the free list. */
83           mdp -> heapinfo[block + blocks].busy.type = 0;
84           mdp -> heapinfo[block + blocks].busy.info.size
85             = mdp -> heapinfo[block].busy.info.size - blocks;
86           mdp -> heapinfo[block].busy.info.size = blocks;
87           mfree (md, ADDRESS (block + blocks));
88           result = ptr;
89         }
90       else if (blocks == mdp -> heapinfo[block].busy.info.size)
91         {
92           /* No size change necessary.  */
93           result = ptr;
94         }
95       else
96         {
97           /* Won't fit, so allocate a new region that will.
98              Free the old region first in case there is sufficient
99              adjacent free space to grow without moving. */
100           blocks = mdp -> heapinfo[block].busy.info.size;
101           /* Prevent free from actually returning memory to the system.  */
102           oldlimit = mdp -> heaplimit;
103           mdp -> heaplimit = 0;
104           mfree (md, ptr);
105           mdp -> heaplimit = oldlimit;
106           result = mmalloc (md, size);
107           if (result == NULL)
108             {
109               mmalloc (md, blocks * BLOCKSIZE);
110               return (NULL);
111             }
112           if (ptr != result)
113             {
114               memmove (result, ptr, blocks * BLOCKSIZE);
115             }
116         }
117       break;
118
119     default:
120       /* Old size is a fragment; type is logarithm
121          to base two of the fragment size.  */
122       if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))
123         {
124           /* The new size is the same kind of fragment.  */
125           result = ptr;
126         }
127       else
128         {
129           /* The new size is different; allocate a new space,
130              and copy the lesser of the new size and the old. */
131           result = mmalloc (md, size);
132           if (result == NULL)
133             {
134               return (NULL);
135             }
136           memcpy (result, ptr, MIN (size, (size_t) 1 << type));
137           mfree (md, ptr);
138         }
139       break;
140     }
141
142   return (result);
143 }
144
145 /* Useless prototype to make gcc happy */
146 void *realloc (void *ptr, size_t size);
147
148 /* When using this package, provide a version of malloc/realloc/free built
149    on top of it, so that if we use the default sbrk() region we will not
150    collide with another malloc package trying to do the same thing, if
151    the application contains any "hidden" calls to malloc/realloc/free (such
152    as inside a system library). */
153
154 void *
155 realloc (void *ptr, size_t size)
156 {
157   void* result;
158
159   result = mrealloc (NULL, ptr, size);
160   return (result);
161 }