Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid
[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 {
24   struct mdesc *mdp;
25   void *result;
26   int type;
27   size_t block, blocks, oldlimit;
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
40   if ((char *) ptr < (char *) mdp->heapbase || BLOCK(ptr) > mdp->heapsize) {
41     printf
42         ("FIXME. Ouch, this pointer is not mine. I will malloc it instead of reallocing it. (please report this bug)\n");
43     result = mmalloc(md, size);
44     abort();
45     return result;
46   }
47
48   if (mdp->mrealloc_hook != NULL) {
49     return mdp->mrealloc_hook(md, ptr, size);
50   }
51
52   block = BLOCK(ptr);
53
54   type = mdp->heapinfo[block].busy.type;
55   switch (type) {
56   case 0:
57     /* Maybe reallocate a large block to a small fragment.  */
58     if (size <= BLOCKSIZE / 2) {
59       //printf("(%s) alloc large block...",xbt_thread_self_name());
60       result = mmalloc(md, size);
61       if (result != NULL) {
62         memcpy(result, ptr, size);
63         mfree(md, ptr);
64         return (result);
65       }
66     }
67
68     /* The new size is a large allocation as well;
69        see if we can hold it in place. */
70     blocks = BLOCKIFY(size);
71     if (blocks < mdp->heapinfo[block].busy.info.block.size) {
72       /* The new size is smaller; return excess memory to the free list. */
73       //printf("(%s) return excess memory...",xbt_thread_self_name());
74       mdp->heapinfo[block + blocks].busy.type = 0;
75       mdp->heapinfo[block + blocks].busy.info.block.size
76           = mdp->heapinfo[block].busy.info.block.size - blocks;
77       mdp->heapinfo[block].busy.info.block.size = blocks;
78       mdp->heapinfo[block].busy.info.block.busy_size = size;
79       mfree(md, ADDRESS(block + blocks));
80       result = ptr;
81     } else if (blocks == mdp->heapinfo[block].busy.info.block.size) {
82       /* No size change necessary.  */
83       result = ptr;
84     } else {
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.block.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         mmalloc(md, blocks * BLOCKSIZE);
97         return (NULL);
98       }
99       if (ptr != result)
100         memmove(result, ptr, blocks * BLOCKSIZE);
101     }
102     break;
103
104   default:
105     /* Old size is a fragment; type is logarithm
106        to base two of the fragment size.  */
107     if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type)) {
108       /* The new size is the same kind of fragment.  */
109       //printf("(%s) new size is same kind of fragment...",xbt_thread_self_name());
110       result = ptr;
111     } else {
112       /* The new size is different; allocate a new space,
113          and copy the lesser of the new size and the old. */
114       //printf("(%s) new size is different...",xbt_thread_self_name());
115
116       result = mmalloc(md, size);
117       if (result == NULL)
118         return (NULL);
119
120       memcpy(result, ptr, MIN(size, (size_t) 1 << type));
121       mfree(md, ptr);
122     }
123     break;
124   }
125   //printf("(%s) Done reallocing: %p\n",xbt_thread_self_name(),result);fflush(stdout);
126   return (result);
127 }