Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
9b0e907eafc1f39ec20572472e7646af6245ebed
[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 #include <stdlib.h> /* abort */
13
14 #include "mmprivate.h"
15
16 /* Resize the given region to the new size, returning a pointer
17    to the (possibly moved) region.  This is optimized for speed;
18    some benchmarks seem to indicate that greater compactness is
19    achieved by unconditionally allocating and copying to a
20    new region.  This module has incestuous knowledge of the
21    internals of both mfree and mmalloc. */
22
23 void *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     mfree(md, ptr);
32     return (mmalloc(md, 0));
33   } else if (ptr == NULL) {
34     return (mmalloc(md, size));
35   }
36
37   mdp = MD_TO_MDP(md);
38
39   //printf("(%s)realloc %p to %d...",xbt_thread_self_name(),ptr,(int)size);
40
41   if ((char *) ptr < (char *) mdp->heapbase || BLOCK(ptr) > mdp->heapsize) {
42     printf
43         ("FIXME. Ouch, this pointer is not mine, refusing to proceed (another solution would be to malloc it instead of reallocing it, see source code)\n");
44     result = mmalloc(md, size);
45     abort();
46     return result;
47   }
48
49   block = BLOCK(ptr);
50
51   type = mdp->heapinfo[block].busy.type;
52   switch (type) {
53   case 0:
54     /* Maybe reallocate a large block to a small fragment.  */
55     if (size <= BLOCKSIZE / 2) {
56       //printf("(%s) alloc large block...",xbt_thread_self_name());
57       result = mmalloc(md, size);
58       if (result != NULL) {
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.block.size) {
69       /* The new size is smaller; return excess memory to the free list. */
70       //printf("(%s) return excess memory...",xbt_thread_self_name());
71       mdp->heapinfo[block + blocks].busy.type = 0;
72       mdp->heapinfo[block + blocks].busy.info.block.size
73           = mdp->heapinfo[block].busy.info.block.size - blocks;
74       mdp->heapinfo[block].busy.info.block.size = blocks;
75       mdp->heapinfo[block].busy.info.block.busy_size = size;
76       mfree(md, ADDRESS(block + blocks));
77       result = ptr;
78     } else if (blocks == mdp->heapinfo[block].busy.info.block.size) {
79       /* No size change necessary.  */
80       result = ptr;
81     } else {
82       /* Won't fit, so allocate a new region that will.
83          Free the old region first in case there is sufficient
84          adjacent free space to grow without moving. */
85       blocks = mdp->heapinfo[block].busy.info.block.size;
86       /* Prevent free from actually returning memory to the system.  */
87       oldlimit = mdp->heaplimit;
88       mdp->heaplimit = 0;
89       mfree(md, ptr);
90       mdp->heaplimit = oldlimit;
91       result = mmalloc(md, size);
92       if (result == NULL) {
93         mmalloc(md, blocks * BLOCKSIZE);
94         return (NULL);
95       }
96       if (ptr != result)
97         memmove(result, ptr, blocks * BLOCKSIZE);
98     }
99     break;
100
101   default:
102     /* Old size is a fragment; type is logarithm
103        to base two of the fragment size.  */
104     if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type)) {
105       /* The new size is the same kind of fragment.  */
106       //printf("(%s) new size is same kind of fragment...",xbt_thread_self_name());
107       result = ptr;
108     } else {
109       /* The new size is different; allocate a new space,
110          and copy the lesser of the new size and the old. */
111       //printf("(%s) new size is different...",xbt_thread_self_name());
112
113       result = mmalloc(md, size);
114       if (result == NULL)
115         return (NULL);
116
117       memcpy(result, ptr, MIN(size, (size_t) 1 << type));
118       mfree(md, ptr);
119     }
120     break;
121   }
122   //printf("(%s) Done reallocing: %p\n",xbt_thread_self_name(),result);fflush(stdout);
123   return (result);
124 }