Logo ROOT  
Reference Guide
mmalloc.c
Go to the documentation of this file.
1/* @(#)root/clib:$Id$ */
2/* Author: */
3
4/* Memory allocator `malloc'.
5 Copyright 1990, 1991, 1992 Free Software Foundation
6
7 Written May 1989 by Mike Haertel.
8 Heavily modified Mar 1992 by Fred Fish for mmap'd version.
9
10The GNU C Library is free software; you can redistribute it and/or
11modify it under the terms of the GNU Library General Public License as
12published by the Free Software Foundation; either version 2 of the
13License, or (at your option) any later version.
14
15The GNU C Library is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18Library General Public License for more details.
19
20You should have received a copy of the GNU Library General Public
21License along with the GNU C Library; see the file COPYING.LIB. If
22not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23Boston, MA 02111-1307, USA.
24
25 The author may be reached (Email) at the address mike@ai.mit.edu,
26 or (US mail) as Mike Haertel c/o Free Software Foundation. */
27
28#include <string.h> /* Prototypes for memcpy, memmove, memset, etc */
29
30#include "mmprivate.h"
31
32#include <stddef.h>
33
34/* Prototypes for local functions */
35
36static int initialize PARAMS ((struct mdesc *));
37static PTR morecore PARAMS ((struct mdesc *, size_t));
38static PTR align PARAMS ((struct mdesc *, size_t));
39
40/* Aligned allocation. */
41
42static PTR align(struct mdesc *mdp, size_t size)
43{
44 PTR result;
45 unsigned long int adj;
46
47 result = mdp -> morecore (mdp, size);
48 adj = RESIDUAL (result, BLOCKSIZE);
49 if (adj != 0)
50 {
51 adj = BLOCKSIZE - adj;
52 mdp -> morecore (mdp, adj);
53 result = (char *) result + adj;
54 }
55 return (result);
56}
57
58/* Set everything up and remember that we have. */
59
60static int initialize(struct mdesc *mdp)
61{
62 mdp -> heapsize = HEAP / BLOCKSIZE;
63 mdp -> heapinfo = (mmalloc_info *)
64 align (mdp, mdp -> heapsize * sizeof (mmalloc_info));
65 if (mdp -> heapinfo == NULL)
66 {
67 return (0);
68 }
69 memset ((PTR)mdp -> heapinfo, 0, mdp -> heapsize * sizeof (mmalloc_info));
70 mdp -> heapinfo[0].free.size = 0;
71 mdp -> heapinfo[0].free.next = mdp -> heapinfo[0].free.prev = 0;
72 mdp -> heapindex = 0;
73 mdp -> heapbase = (char *) mdp -> heapinfo;
74 mdp -> flags |= MMALLOC_INITIALIZED;
75 return (1);
76}
77
78/* Get neatly aligned memory, initializing or
79 growing the heap info table as necessary. */
80
81static PTR morecore(struct mdesc *mdp, size_t size)
82{
83 PTR result;
84 mmalloc_info *newinfo, *oldinfo;
85 size_t newsize;
86
87 result = align (mdp, size);
88 if (result == NULL)
89 {
90 return (NULL);
91 }
92
93 /* Check if we need to grow the info table. */
94 if ((size_t) BLOCK ((char *) result + size) > mdp -> heapsize)
95 {
96 newsize = mdp -> heapsize;
97 while ((size_t) BLOCK ((char *) result + size) > newsize)
98 {
99 newsize *= 2;
100 }
101 newinfo = (mmalloc_info *) align (mdp, newsize * sizeof (mmalloc_info));
102 if (newinfo == NULL)
103 {
104 mdp -> morecore (mdp, -(ptrdiff_t)size);
105 return (NULL);
106 }
107 memset ((PTR) newinfo, 0, newsize * sizeof (mmalloc_info));
108 memcpy ((PTR) newinfo, (PTR) mdp -> heapinfo,
109 mdp -> heapsize * sizeof (mmalloc_info));
110 oldinfo = mdp -> heapinfo;
111 newinfo[BLOCK (oldinfo)].busy.type = 0;
112 newinfo[BLOCK (oldinfo)].busy.info.size
113 = BLOCKIFY (mdp -> heapsize * sizeof (mmalloc_info));
114 mdp -> heapinfo = newinfo;
115 __mmalloc_free (mdp, (PTR)oldinfo);
116 mdp -> heapsize = newsize;
117 }
118
119 mdp -> heaplimit = BLOCK ((char *) result + size);
120 return (result);
121}
122
123/* Allocate memory from the heap. */
124
125PTR mmalloc(PTR md, size_t size)
126{
127 struct mdesc *mdp;
128 PTR result;
129 size_t block, blocks, lastblocks, start;
130 register size_t i;
131 struct mmlist *next;
132 register size_t log;
133
134 if (size == 0)
135 {
136 return (NULL);
137 }
138
139 mdp = MD_TO_MDP (md);
140
141 if (mdp -> mmalloc_hook != NULL)
142 {
143 return ((*mdp -> mmalloc_hook) (md, size));
144 }
145
146 if (!(mdp -> flags & MMALLOC_INITIALIZED))
147 {
148 if (!initialize (mdp))
149 {
150 return (NULL);
151 }
152 }
153
154 if (size < sizeof (struct mmlist))
155 {
156 size = sizeof (struct mmlist);
157 }
158
159 /* Determine the allocation policy based on the request size. */
160 if (size <= BLOCKSIZE / 2)
161 {
162 /* Small allocation to receive a fragment of a block.
163 Determine the logarithm to base two of the fragment size. */
164 log = 1;
165 --size;
166 while ((size /= 2) != 0)
167 {
168 ++log;
169 }
170
171 /* Look in the fragment lists for a
172 free fragment of the desired size. */
173 next = mdp -> fraghead[log].next;
174 if (next != NULL)
175 {
176 /* There are free fragments of this size.
177 Pop a fragment out of the fragment list and return it.
178 Update the block's nfree and first counters. */
179 result = (PTR) next;
180 next -> prev -> next = next -> next;
181 if (next -> next != NULL)
182 {
183 next -> next -> prev = next -> prev;
184 }
185 block = BLOCK (result);
186 if (--mdp -> heapinfo[block].busy.info.frag.nfree != 0)
187 {
188 mdp -> heapinfo[block].busy.info.frag.first =
189 RESIDUAL (next -> next, BLOCKSIZE) >> log;
190 }
191
192 /* Update the statistics. */
193 mdp -> heapstats.chunks_used++;
194 mdp -> heapstats.bytes_used += 1 << log;
195 mdp -> heapstats.chunks_free--;
196 mdp -> heapstats.bytes_free -= 1 << log;
197 }
198 else
199 {
200 /* No free fragments of the desired size, so get a new block
201 and break it into fragments, returning the first. */
202 result = mmalloc (md, BLOCKSIZE);
203 if (result == NULL)
204 {
205 return (NULL);
206 }
207
208 /* Link all fragments but the first into the free list. */
209 for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i)
210 {
211 next = (struct mmlist *) ((char *) result + (i << log));
212 next -> next = mdp -> fraghead[log].next;
213 next -> prev = &mdp -> fraghead[log];
214 next -> prev -> next = next;
215 if (next -> next != NULL)
216 {
217 next -> next -> prev = next;
218 }
219 }
220
221 /* Initialize the nfree and first counters for this block. */
222 block = BLOCK (result);
223 mdp -> heapinfo[block].busy.type = log;
224 mdp -> heapinfo[block].busy.info.frag.nfree = i - 1;
225 mdp -> heapinfo[block].busy.info.frag.first = i - 1;
226
227 mdp -> heapstats.chunks_free += (BLOCKSIZE >> log) - 1;
228 mdp -> heapstats.bytes_free += BLOCKSIZE - (1 << log);
229 mdp -> heapstats.bytes_used -= BLOCKSIZE - (1 << log);
230 }
231 }
232 else
233 {
234 /* Large allocation to receive one or more blocks.
235 Search the free list in a circle starting at the last place visited.
236 If we loop completely around without finding a large enough
237 space we will have to get more memory from the system. */
238 blocks = BLOCKIFY(size);
239 start = block = MALLOC_SEARCH_START;
240 while (mdp -> heapinfo[block].free.size < blocks)
241 {
242 block = mdp -> heapinfo[block].free.next;
243 if (block == start)
244 {
245 /* Need to get more from the system. Check to see if
246 the new core will be contiguous with the final free
247 block; if so we don't need to get as much. */
248 block = mdp -> heapinfo[0].free.prev;
249 lastblocks = mdp -> heapinfo[block].free.size;
250 if (mdp -> heaplimit != 0 &&
251 block + lastblocks == mdp -> heaplimit &&
252 mdp -> morecore (mdp, 0) == ADDRESS(block + lastblocks) &&
253 (morecore (mdp, (blocks - lastblocks) * BLOCKSIZE)) != NULL)
254 {
255 /* Which block we are extending (the `final free
256 block' referred to above) might have changed, if
257 it got combined with a freed info table. */
258 block = mdp -> heapinfo[0].free.prev;
259
260 mdp -> heapinfo[block].free.size += (blocks - lastblocks);
261 mdp -> heapstats.bytes_free +=
262 (blocks - lastblocks) * BLOCKSIZE;
263 continue;
264 }
265 result = morecore(mdp, blocks * BLOCKSIZE);
266 if (result == NULL)
267 {
268 return (NULL);
269 }
270 block = BLOCK (result);
271 mdp -> heapinfo[block].busy.type = 0;
272 mdp -> heapinfo[block].busy.info.size = blocks;
273 mdp -> heapstats.chunks_used++;
274 mdp -> heapstats.bytes_used += blocks * BLOCKSIZE;
275 return (result);
276 }
277 }
278
279 /* At this point we have found a suitable free list entry.
280 Figure out how to remove what we need from the list. */
281 result = ADDRESS(block);
282 if (mdp -> heapinfo[block].free.size > blocks)
283 {
284 /* The block we found has a bit left over,
285 so relink the tail end back into the free list. */
286 mdp -> heapinfo[block + blocks].free.size
287 = mdp -> heapinfo[block].free.size - blocks;
288 mdp -> heapinfo[block + blocks].free.next
289 = mdp -> heapinfo[block].free.next;
290 mdp -> heapinfo[block + blocks].free.prev
291 = mdp -> heapinfo[block].free.prev;
292 mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
293 = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
294 = mdp -> heapindex = block + blocks;
295 }
296 else
297 {
298 /* The block exactly matches our requirements,
299 so just remove it from the list. */
300 mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
301 = mdp -> heapinfo[block].free.prev;
302 mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
303 = mdp -> heapindex = mdp -> heapinfo[block].free.next;
304 mdp -> heapstats.chunks_free--;
305 }
306
307 mdp -> heapinfo[block].busy.type = 0;
308 mdp -> heapinfo[block].busy.info.size = blocks;
309 mdp -> heapstats.chunks_used++;
310 mdp -> heapstats.bytes_used += blocks * BLOCKSIZE;
311 mdp -> heapstats.bytes_free -= blocks * BLOCKSIZE;
312 }
313
314 return (result);
315}
316
317/* When using this package, provide a version of malloc/realloc/free built
318 on top of it, so that if we use the default sbrk() region we will not
319 collide with another malloc package trying to do the same thing, if
320 the application contains any "hidden" calls to malloc/realloc/free (such
321 as inside a system library). */
322
323#ifndef NO_SBRK_MALLOC
324
325PTR
327 size_t size;
328{
329 return (mmalloc ((PTR) NULL, size));
330}
331
332#endif
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
void initialize()
start
Definition Rotated.cxx:223
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
#define PARAMS(protos)
#define NULL
Definition ZInflate.c:15
#define free
Definition civetweb.c:1578
#define malloc
Definition civetweb.c:1575
void __mmalloc_free(struct mdesc *mdp, PTR ptr)
Definition mfree.c:34
PTR mmalloc(PTR md, size_t size)
Definition mmalloc.c:125
static int initialize(struct mdesc *mdp)
Definition mmalloc.c:60
static PTR align(struct mdesc *mdp, size_t size)
Definition mmalloc.c:42
static PTR morecore(struct mdesc *mdp, size_t size)
Definition mmalloc.c:81
#define PTR
Definition mmalloc.h:29
#define MD_TO_MDP(md)
Definition mmprivate.h:375
#define RESIDUAL(addr, bsize)
Definition mmprivate.h:85
#define HEAP
Definition mmprivate.h:90
#define BLOCKIFY(SIZE)
Definition mmprivate.h:82
#define ADDRESS(B)
Definition mmprivate.h:108
#define BLOCK(A)
Definition mmprivate.h:106
#define MMALLOC_INITIALIZED
Definition mmprivate.h:322
#define MALLOC_SEARCH_START
Definition mmprivate.h:102
#define BLOCKSIZE
Definition mmprivate.h:81
struct mmlist * prev
Definition mmprivate.h:155
struct mmlist * next
Definition mmprivate.h:154