Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
b2bc6496cafb4555668a8b1830141e2ddde9c12b
[simgrid.git] / src / xbt / mmalloc / mfree.c
1 /* Free a block of memory allocated by `mmalloc'.
2    Copyright 1990, 1991, 1992 Free Software Foundation
3
4    Written May 1989 by Mike Haertel.
5    Heavily modified Mar 1992 by Fred Fish.  (fnf@cygnus.com) */
6
7 /* Copyright (c) 2010. The SimGrid Team.
8  * All rights reserved.                                                     */
9
10 /* This program is free software; you can redistribute it and/or modify it
11  * under the terms of the license (GNU LGPL) which comes with this package. */
12
13 #include "mmprivate.h"
14
15 /* Return memory to the heap.
16    Like `mfree' but don't call a mfree_hook if there is one.  */
17
18 void
19 __mmalloc_free (struct mdesc *mdp, void *ptr)
20 {
21   int type;
22   size_t block;//, blocks; unused variable?
23   register size_t i;
24   struct list *prev, *next;
25
26   block = BLOCK (ptr);
27
28   type = mdp -> heapinfo[block].busy.type;
29   switch (type)
30     {
31     case 0:
32       /* Get as many statistics as early as we can.  */
33       mdp -> heapstats.chunks_used--;
34       mdp -> heapstats.bytes_used -=
35           mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
36       mdp -> heapstats.bytes_free +=
37           mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
38
39       /* Find the free cluster previous to this one in the free list.
40          Start searching at the last block referenced; this may benefit
41          programs with locality of allocation.  */
42       i = mdp -> heapindex;
43       if (i > block)
44         {
45           while (i > block)
46             {
47               i = mdp -> heapinfo[i].free.prev;
48             }
49         }
50       else
51         {
52           do
53             {
54               i = mdp -> heapinfo[i].free.next;
55             }
56           while ((i != 0) && (i < block));
57           i = mdp -> heapinfo[i].free.prev;
58         }
59
60       /* Determine how to link this block into the free list.  */
61       if (block == i + mdp -> heapinfo[i].free.size)
62         {
63           /* Coalesce this block with its predecessor.  */
64           mdp -> heapinfo[i].free.size +=
65             mdp -> heapinfo[block].busy.info.size;
66           block = i;
67         }
68       else
69         {
70           /* Really link this block back into the free list.  */
71           mdp -> heapinfo[block].free.size =
72             mdp -> heapinfo[block].busy.info.size;
73           mdp -> heapinfo[block].free.next = mdp -> heapinfo[i].free.next;
74           mdp -> heapinfo[block].free.prev = i;
75           mdp -> heapinfo[i].free.next = block;
76           mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
77           mdp -> heapstats.chunks_free++;
78         }
79
80       /* Now that the block is linked in, see if we can coalesce it
81          with its successor (by deleting its successor from the list
82          and adding in its size).  */
83       if (block + mdp -> heapinfo[block].free.size ==
84           mdp -> heapinfo[block].free.next)
85         {
86           mdp -> heapinfo[block].free.size
87             += mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.size;
88           mdp -> heapinfo[block].free.next
89             = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.next;
90           mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
91           mdp -> heapstats.chunks_free--;
92         }
93
94       /* Now see if we can return stuff to the system.  */
95   /*    blocks = mdp -> heapinfo[block].free.size;
96       if (blocks >= FINAL_FREE_BLOCKS && block + blocks == mdp -> heaplimit
97           && mdp -> morecore (mdp, 0) == ADDRESS (block + blocks))
98         {
99           register size_t bytes = blocks * BLOCKSIZE;
100           mdp -> heaplimit -= blocks;
101           mdp -> morecore (mdp, -bytes);
102           mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
103             = mdp -> heapinfo[block].free.next;
104           mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
105             = mdp -> heapinfo[block].free.prev;
106           block = mdp -> heapinfo[block].free.prev;
107           mdp -> heapstats.chunks_free--;
108           mdp -> heapstats.bytes_free -= bytes;
109         }*/
110
111       /* Set the next search to begin at this block.  */
112       mdp -> heapindex = block;
113       break;
114
115     default:
116       /* Do some of the statistics.  */
117       mdp -> heapstats.chunks_used--;
118       mdp -> heapstats.bytes_used -= 1 << type;
119       mdp -> heapstats.chunks_free++;
120       mdp -> heapstats.bytes_free += 1 << type;
121
122       /* Get the address of the first free fragment in this block.  */
123       prev = (struct list *)
124         ((char*) ADDRESS(block) +
125          ( mdp -> heapinfo[block].busy.info.frag.first << type));
126
127       if (mdp -> heapinfo[block].busy.info.frag.nfree ==
128           (BLOCKSIZE >> type) - 1)
129         {
130           /* If all fragments of this block are free, remove them
131              from the fragment list and free the whole block.  */
132           next = prev;
133           for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
134             {
135               next = next -> next;
136             }
137           prev -> prev -> next = next;
138           if (next != NULL)
139             {
140               next -> prev = prev -> prev;
141             }
142           mdp -> heapinfo[block].busy.type = 0;
143           mdp -> heapinfo[block].busy.info.size = 1;
144
145           /* Keep the statistics accurate.  */
146           mdp -> heapstats.chunks_used++;
147           mdp -> heapstats.bytes_used += BLOCKSIZE;
148           mdp -> heapstats.chunks_free -= BLOCKSIZE >> type;
149           mdp -> heapstats.bytes_free -= BLOCKSIZE;
150
151           mfree ((void*) mdp, (void*) ADDRESS(block));
152         }
153       else if (mdp -> heapinfo[block].busy.info.frag.nfree != 0)
154         {
155           /* If some fragments of this block are free, link this
156              fragment into the fragment list after the first free
157              fragment of this block. */
158           next = (struct list *) ptr;
159           next -> next = prev -> next;
160           next -> prev = prev;
161           prev -> next = next;
162           if (next -> next != NULL)
163             {
164               next -> next -> prev = next;
165             }
166           ++mdp -> heapinfo[block].busy.info.frag.nfree;
167         }
168       else
169         {
170           /* No fragments of this block are free, so link this
171              fragment into the fragment list and announce that
172              it is the first free fragment of this block. */
173           prev = (struct list *) ptr;
174           mdp -> heapinfo[block].busy.info.frag.nfree = 1;
175           mdp -> heapinfo[block].busy.info.frag.first =
176             RESIDUAL (ptr, BLOCKSIZE) >> type;
177           prev -> next = mdp -> fraghead[type].next;
178           prev -> prev = &mdp -> fraghead[type];
179           prev -> prev -> next = prev;
180           if (prev -> next != NULL)
181             {
182               prev -> next -> prev = prev;
183             }
184         }
185       break;
186     }
187 }
188
189 /* Return memory to the heap.  */
190
191 void
192 mfree (void *md, void *ptr)
193 {
194   struct mdesc *mdp;
195   register struct alignlist *l;
196
197   if (ptr != NULL)
198     {
199       mdp = MD_TO_MDP (md);
200       for (l = mdp -> aligned_blocks; l != NULL; l = l -> next)
201         {
202           if (l -> aligned == ptr)
203             {
204               l -> aligned = NULL;  /* Mark the slot in the list as free. */
205               ptr = l -> exact;
206               break;
207             }
208         }      
209       if (mdp -> mfree_hook != NULL)
210         {
211           (*mdp -> mfree_hook) (mdp, ptr);
212         }
213       else
214         {
215           __mmalloc_free (mdp, ptr);
216         }
217     }
218 }
219
220
221 /* Useless prototype to make gcc happy */
222 void free(void* ptr);
223
224
225 /* When using this package, provide a version of malloc/realloc/free built
226    on top of it, so that if we use the default sbrk() region we will not
227    collide with another malloc package trying to do the same thing, if
228    the application contains any "hidden" calls to malloc/realloc/free (such
229    as inside a system library).
230    FIXME: disabled for now */
231
232 //void free (void* ptr) {
233 //  mfree ((void*) NULL, ptr);
234 //}