Logo AND Algorithmique Numérique Distribuée

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