Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
1b788ec394e368b91e3071c35cdb1ecdb6318cb3
[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* mrealloc (void *md, void *ptr, size_t size) {
23   struct mdesc *mdp;
24   void* result;
25   int type;
26   size_t block, blocks, oldlimit;
27
28
29   if (size == 0) {
30     mfree (md, ptr);
31     return (mmalloc (md, 0));
32   } else if (ptr == NULL) {
33     return (mmalloc (md, size));
34   }
35
36   mdp = MD_TO_MDP (md);
37
38   printf("(%s)realloc %p to %d...",xbt_thread_self_name(),ptr,(int)size);
39   if ((char*)ptr < (char*)mdp->heapbase || BLOCK(ptr) > mdp->heapsize ) {
40
41     printf("FIXME. Ouch, this pointer is not mine. I will malloc it instead of reallocing it.\n");
42     result = mmalloc(md,size);
43     abort();
44     return result;
45   }
46
47   LOCK(mdp);
48   if (mdp -> mrealloc_hook != NULL)
49   {
50     UNLOCK(mdp);
51     return ((*mdp -> mrealloc_hook) (md, ptr, size));
52   }
53
54   block = BLOCK (ptr);
55
56   type = mdp -> heapinfo[block].busy.type;
57   switch (type)
58   {
59   case 0:
60     /* Maybe reallocate a large block to a small fragment.  */
61     if (size <= BLOCKSIZE / 2)
62     {
63       UNLOCK(mdp);
64       printf("(%s) alloc large block...",xbt_thread_self_name());
65       result = mmalloc (md, size);
66       if (result != NULL)
67       {
68         memcpy (result, ptr, size);
69         mfree (md, ptr);
70         return (result);
71       }
72     }
73
74     /* The new size is a large allocation as well;
75          see if we can hold it in place. */
76     LOCK(mdp);
77     blocks = BLOCKIFY (size);
78     if (blocks < mdp -> heapinfo[block].busy.info.size)
79     {
80       /* The new size is smaller; return excess memory to the free list. */
81       printf("(%s) return excess memory...",xbt_thread_self_name());
82       mdp -> heapinfo[block + blocks].busy.type = 0;
83       mdp -> heapinfo[block + blocks].busy.info.size
84       = mdp -> heapinfo[block].busy.info.size - blocks;
85       mdp -> heapinfo[block].busy.info.size = blocks;
86       mfree (md, ADDRESS (block + blocks));
87       result = ptr;
88     }
89     else if (blocks == mdp -> heapinfo[block].busy.info.size)
90     {
91       /* No size change necessary.  */
92       result = ptr;
93     }
94     else
95     {
96       /* Won't fit, so allocate a new region that will.
97              Free the old region first in case there is sufficient
98              adjacent free space to grow without moving. */
99       blocks = mdp -> heapinfo[block].busy.info.size;
100       /* Prevent free from actually returning memory to the system.  */
101       oldlimit = mdp -> heaplimit;
102       mdp -> heaplimit = 0;
103       mfree (md, ptr);
104       mdp -> heaplimit = oldlimit;
105       UNLOCK(mdp);
106       result = mmalloc (md, size);
107       if (result == NULL) {
108         mmalloc (md, blocks * BLOCKSIZE);
109         return (NULL);
110       }
111       if (ptr != result)
112         memmove (result, ptr, blocks * BLOCKSIZE);
113       LOCK(mdp);
114     }
115     break;
116
117   default:
118     /* Old size is a fragment; type is logarithm
119          to base two of the fragment size.  */
120     if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type)) {
121       /* The new size is the same kind of fragment.  */
122       printf("(%s) new size is same kind of fragment...",xbt_thread_self_name());
123       result = ptr;
124     } else {
125       /* The new size is different; allocate a new space,
126              and copy the lesser of the new size and the old. */
127       printf("(%s) new size is different...",xbt_thread_self_name());
128
129       UNLOCK(mdp);
130       result = mmalloc (md, size);
131       if (result == NULL)
132         return (NULL);
133
134       memcpy (result, ptr, MIN (size, (size_t) 1 << type));
135       mfree (md, ptr);
136     }
137     break;
138   }
139   printf("(%s) Done reallocing: %p\n",xbt_thread_self_name(),result);fflush(stdout);
140   return (result);
141 }