1 /* Free a block of memory allocated by `mmalloc'.
2 Copyright 1990, 1991, 1992 Free Software Foundation
4 Written May 1989 by Mike Haertel.
5 Heavily modified Mar 1992 by Fred Fish. (fnf@cygnus.com)
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with the GNU C Library; see the file COPYING.LIB. If
19 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
22 The author may be reached (Email) at the address mike@ai.mit.edu,
23 or (US mail) as Mike Haertel c/o Free Software Foundation. */
25 #include "mmprivate.h"
27 /* Return memory to the heap.
28 Like `mfree' but don't call a mfree_hook if there is one. */
31 __mmalloc_free (struct mdesc *mdp, void *ptr)
34 size_t block;//, blocks; unused variable?
36 struct list *prev, *next;
40 type = mdp -> heapinfo[block].busy.type;
44 /* Get as many statistics as early as we can. */
45 mdp -> heapstats.chunks_used--;
46 mdp -> heapstats.bytes_used -=
47 mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
48 mdp -> heapstats.bytes_free +=
49 mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
51 /* Find the free cluster previous to this one in the free list.
52 Start searching at the last block referenced; this may benefit
53 programs with locality of allocation. */
59 i = mdp -> heapinfo[i].free.prev;
66 i = mdp -> heapinfo[i].free.next;
68 while ((i != 0) && (i < block));
69 i = mdp -> heapinfo[i].free.prev;
72 /* Determine how to link this block into the free list. */
73 if (block == i + mdp -> heapinfo[i].free.size)
75 /* Coalesce this block with its predecessor. */
76 mdp -> heapinfo[i].free.size +=
77 mdp -> heapinfo[block].busy.info.size;
82 /* Really link this block back into the free list. */
83 mdp -> heapinfo[block].free.size =
84 mdp -> heapinfo[block].busy.info.size;
85 mdp -> heapinfo[block].free.next = mdp -> heapinfo[i].free.next;
86 mdp -> heapinfo[block].free.prev = i;
87 mdp -> heapinfo[i].free.next = block;
88 mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
89 mdp -> heapstats.chunks_free++;
92 /* Now that the block is linked in, see if we can coalesce it
93 with its successor (by deleting its successor from the list
94 and adding in its size). */
95 if (block + mdp -> heapinfo[block].free.size ==
96 mdp -> heapinfo[block].free.next)
98 mdp -> heapinfo[block].free.size
99 += mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.size;
100 mdp -> heapinfo[block].free.next
101 = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.next;
102 mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
103 mdp -> heapstats.chunks_free--;
106 /* Now see if we can return stuff to the system. */
107 /* blocks = mdp -> heapinfo[block].free.size;
108 if (blocks >= FINAL_FREE_BLOCKS && block + blocks == mdp -> heaplimit
109 && mdp -> morecore (mdp, 0) == ADDRESS (block + blocks))
111 register size_t bytes = blocks * BLOCKSIZE;
112 mdp -> heaplimit -= blocks;
113 mdp -> morecore (mdp, -bytes);
114 mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
115 = mdp -> heapinfo[block].free.next;
116 mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
117 = mdp -> heapinfo[block].free.prev;
118 block = mdp -> heapinfo[block].free.prev;
119 mdp -> heapstats.chunks_free--;
120 mdp -> heapstats.bytes_free -= bytes;
123 /* Set the next search to begin at this block. */
124 mdp -> heapindex = block;
128 /* Do some of the statistics. */
129 mdp -> heapstats.chunks_used--;
130 mdp -> heapstats.bytes_used -= 1 << type;
131 mdp -> heapstats.chunks_free++;
132 mdp -> heapstats.bytes_free += 1 << type;
134 /* Get the address of the first free fragment in this block. */
135 prev = (struct list *)
136 ((char*) ADDRESS(block) +
137 ( mdp -> heapinfo[block].busy.info.frag.first << type));
139 if (mdp -> heapinfo[block].busy.info.frag.nfree ==
140 (BLOCKSIZE >> type) - 1)
142 /* If all fragments of this block are free, remove them
143 from the fragment list and free the whole block. */
145 for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
149 prev -> prev -> next = next;
152 next -> prev = prev -> prev;
154 mdp -> heapinfo[block].busy.type = 0;
155 mdp -> heapinfo[block].busy.info.size = 1;
157 /* Keep the statistics accurate. */
158 mdp -> heapstats.chunks_used++;
159 mdp -> heapstats.bytes_used += BLOCKSIZE;
160 mdp -> heapstats.chunks_free -= BLOCKSIZE >> type;
161 mdp -> heapstats.bytes_free -= BLOCKSIZE;
163 mfree ((void*) mdp, (void*) ADDRESS(block));
165 else if (mdp -> heapinfo[block].busy.info.frag.nfree != 0)
167 /* If some fragments of this block are free, link this
168 fragment into the fragment list after the first free
169 fragment of this block. */
170 next = (struct list *) ptr;
171 next -> next = prev -> next;
174 if (next -> next != NULL)
176 next -> next -> prev = next;
178 ++mdp -> heapinfo[block].busy.info.frag.nfree;
182 /* No fragments of this block are free, so link this
183 fragment into the fragment list and announce that
184 it is the first free fragment of this block. */
185 prev = (struct list *) ptr;
186 mdp -> heapinfo[block].busy.info.frag.nfree = 1;
187 mdp -> heapinfo[block].busy.info.frag.first =
188 RESIDUAL (ptr, BLOCKSIZE) >> type;
189 prev -> next = mdp -> fraghead[type].next;
190 prev -> prev = &mdp -> fraghead[type];
191 prev -> prev -> next = prev;
192 if (prev -> next != NULL)
194 prev -> next -> prev = prev;
201 /* Return memory to the heap. */
204 mfree (void *md, void *ptr)
207 register struct alignlist *l;
211 mdp = MD_TO_MDP (md);
212 for (l = mdp -> aligned_blocks; l != NULL; l = l -> next)
214 if (l -> aligned == ptr)
216 l -> aligned = NULL; /* Mark the slot in the list as free. */
221 if (mdp -> mfree_hook != NULL)
223 (*mdp -> mfree_hook) (mdp, ptr);
227 __mmalloc_free (mdp, ptr);
233 /* Useless prototype to make gcc happy */
234 void free(void* ptr);
237 /* When using this package, provide a version of malloc/realloc/free built
238 on top of it, so that if we use the default sbrk() region we will not
239 collide with another malloc package trying to do the same thing, if
240 the application contains any "hidden" calls to malloc/realloc/free (such
241 as inside a system library). */
246 mfree ((void*) NULL, ptr);