Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
ccd837c969672b1ca5d30f9f693ef1bd056c3e94
[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 /* Copyright (c) 2010. The SimGrid Team.
6  * All rights reserved.                                                     */
7
8 /* This program is free software; you can redistribute it and/or modify it
9  * under the terms of the license (GNU LGPL) which comes with this package. */
10
11 #include <string.h>     /* Prototypes for memcpy, memmove, memset, etc */
12
13 #include "mmprivate.h"
14
15 /* Resize the given region to the new size, returning a pointer
16    to the (possibly moved) region.  This is optimized for speed;
17    some benchmarks seem to indicate that greater compactness is
18    achieved by unconditionally allocating and copying to a
19    new region.  This module has incestuous knowledge of the
20    internals of both mfree and mmalloc. */
21
22 void*
23 mrealloc (void *md, void *ptr, size_t size)
24 {
25   struct mdesc *mdp;
26   void* result;
27   int type;
28   size_t block, blocks, oldlimit;
29
30   if (size == 0)
31     {
32       mfree (md, ptr);
33       return (mmalloc (md, 0));
34     }
35   else if (ptr == NULL)
36     {
37       return (mmalloc (md, size));
38     }
39
40   mdp = MD_TO_MDP (md);
41
42   if (mdp -> mrealloc_hook != NULL)
43     {
44       return ((*mdp -> mrealloc_hook) (md, ptr, size));
45     }
46
47   block = BLOCK (ptr);
48
49   type = mdp -> heapinfo[block].busy.type;
50   switch (type)
51     {
52     case 0:
53       /* Maybe reallocate a large block to a small fragment.  */
54       if (size <= BLOCKSIZE / 2)
55         {
56           result = mmalloc (md, size);
57           if (result != NULL)
58             {
59               memcpy (result, ptr, size);
60               mfree (md, ptr);
61               return (result);
62             }
63         }
64
65       /* The new size is a large allocation as well;
66          see if we can hold it in place. */
67       blocks = BLOCKIFY (size);
68       if (blocks < mdp -> heapinfo[block].busy.info.size)
69         {
70           /* The new size is smaller; return excess memory to the free list. */
71           mdp -> heapinfo[block + blocks].busy.type = 0;
72           mdp -> heapinfo[block + blocks].busy.info.size
73             = mdp -> heapinfo[block].busy.info.size - blocks;
74           mdp -> heapinfo[block].busy.info.size = blocks;
75           mfree (md, ADDRESS (block + blocks));
76           result = ptr;
77         }
78       else if (blocks == mdp -> heapinfo[block].busy.info.size)
79         {
80           /* No size change necessary.  */
81           result = ptr;
82         }
83       else
84         {
85           /* Won't fit, so allocate a new region that will.
86              Free the old region first in case there is sufficient
87              adjacent free space to grow without moving. */
88           blocks = mdp -> heapinfo[block].busy.info.size;
89           /* Prevent free from actually returning memory to the system.  */
90           oldlimit = mdp -> heaplimit;
91           mdp -> heaplimit = 0;
92           mfree (md, ptr);
93           mdp -> heaplimit = oldlimit;
94           result = mmalloc (md, size);
95           if (result == NULL)
96             {
97               mmalloc (md, blocks * BLOCKSIZE);
98               return (NULL);
99             }
100           if (ptr != result)
101             {
102               memmove (result, ptr, blocks * BLOCKSIZE);
103             }
104         }
105       break;
106
107     default:
108       /* Old size is a fragment; type is logarithm
109          to base two of the fragment size.  */
110       if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))
111         {
112           /* The new size is the same kind of fragment.  */
113           result = ptr;
114         }
115       else
116         {
117           /* The new size is different; allocate a new space,
118              and copy the lesser of the new size and the old. */
119           result = mmalloc (md, size);
120           if (result == NULL)
121             {
122               return (NULL);
123             }
124           memcpy (result, ptr, MIN (size, (size_t) 1 << type));
125           mfree (md, ptr);
126         }
127       break;
128     }
129
130   return (result);
131 }
132
133 /* Useless prototype to make gcc happy */
134 void *realloc (void *ptr, size_t size);
135
136 /* When using this package, provide a version of malloc/realloc/free built
137    on top of it, so that if we use the default sbrk() region we will not
138    collide with another malloc package trying to do the same thing, if
139    the application contains any "hidden" calls to malloc/realloc/free (such
140    as inside a system library).
141    FIXME: disabled for now */
142
143 //void * realloc (void *ptr, size_t size) {
144 //  void* result;
145
146 //  result = mrealloc (NULL, ptr, size);
147 //  return (result);
148 //}