1 | /* DO NOT EDIT THIS FILE -- it is automagically generated. -*- C -*- */
|
---|
2 |
|
---|
3 | #define _MALLOC_INTERNAL
|
---|
4 |
|
---|
5 | /* The malloc headers and source files from the C library follow here. */
|
---|
6 |
|
---|
7 | /* Declarations for `malloc' and friends.
|
---|
8 | Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
|
---|
9 | Written May 1989 by Mike Haertel.
|
---|
10 |
|
---|
11 | This library is free software; you can redistribute it and/or
|
---|
12 | modify it under the terms of the GNU Library General Public License as
|
---|
13 | published by the Free Software Foundation; either version 2 of the
|
---|
14 | License, or (at your option) any later version.
|
---|
15 |
|
---|
16 | This library is distributed in the hope that it will be useful,
|
---|
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
19 | Library General Public License for more details.
|
---|
20 |
|
---|
21 | You should have received a copy of the GNU Library General Public
|
---|
22 | License along with this library; see the file COPYING.LIB. If
|
---|
23 | not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
---|
24 | Cambridge, MA 02139, USA.
|
---|
25 |
|
---|
26 | The author may be reached (Email) at the address [email protected],
|
---|
27 | or (US mail) as Mike Haertel c/o Free Software Foundation. */
|
---|
28 |
|
---|
29 | #ifndef _MALLOC_H
|
---|
30 |
|
---|
31 | #define _MALLOC_H 1
|
---|
32 |
|
---|
33 | #ifdef _MALLOC_INTERNAL
|
---|
34 |
|
---|
35 | #ifdef HAVE_CONFIG_H
|
---|
36 | #include <sysfuncs.h>
|
---|
37 | #endif
|
---|
38 |
|
---|
39 | #if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG)
|
---|
40 | #include <string.h>
|
---|
41 | #else
|
---|
42 | #ifndef memset
|
---|
43 | #define memset(s, zero, n) bzero ((s), (n))
|
---|
44 | #endif
|
---|
45 | #ifndef memcpy
|
---|
46 | #define memcpy(d, s, n) bcopy ((s), (d), (n))
|
---|
47 | #endif
|
---|
48 | #endif
|
---|
49 |
|
---|
50 | #if defined(__GNU_LIBRARY__) || __STDC__
|
---|
51 | #include <limits.h>
|
---|
52 | #else
|
---|
53 | #define CHAR_BIT 8
|
---|
54 | #endif
|
---|
55 |
|
---|
56 | #ifdef HAVE_UNISTD_H
|
---|
57 | #include <unistd.h>
|
---|
58 | #endif
|
---|
59 |
|
---|
60 | #endif /* _MALLOC_INTERNAL. */
|
---|
61 |
|
---|
62 |
|
---|
63 | #ifdef __cplusplus
|
---|
64 | extern "C"
|
---|
65 | {
|
---|
66 | #endif
|
---|
67 |
|
---|
68 | #if defined (__cplusplus) || __STDC__
|
---|
69 | #undef __P
|
---|
70 | #define __P(args) args
|
---|
71 | #undef __ptr_t
|
---|
72 | #define __ptr_t void *
|
---|
73 | #else /* Not C++ or ANSI C. */
|
---|
74 | #undef __P
|
---|
75 | #define __P(args) ()
|
---|
76 | #undef const
|
---|
77 | #define const
|
---|
78 | #undef __ptr_t
|
---|
79 | #define __ptr_t char *
|
---|
80 | #endif /* C++ or ANSI C. */
|
---|
81 |
|
---|
82 | #if __STDC__
|
---|
83 | #include <stddef.h>
|
---|
84 | #else
|
---|
85 | #undef size_t
|
---|
86 | #define size_t unsigned int
|
---|
87 | #undef ptrdiff_t
|
---|
88 | #define ptrdiff_t int
|
---|
89 | #endif
|
---|
90 |
|
---|
91 | #ifndef NULL
|
---|
92 | #define NULL 0
|
---|
93 | #endif
|
---|
94 |
|
---|
95 |
|
---|
96 | /* Allocate SIZE bytes of memory. */
|
---|
97 | extern __ptr_t malloc __P ((size_t __size));
|
---|
98 | /* Re-allocate the previously allocated block
|
---|
99 | in __ptr_t, making the new block SIZE bytes long. */
|
---|
100 | extern __ptr_t realloc __P ((__ptr_t __ptr, size_t __size));
|
---|
101 | /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
|
---|
102 | extern __ptr_t calloc __P ((size_t __nmemb, size_t __size));
|
---|
103 | /* Free a block allocated by `malloc', `realloc' or `calloc'. */
|
---|
104 | extern void free __P ((__ptr_t __ptr));
|
---|
105 |
|
---|
106 | /* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
|
---|
107 | extern __ptr_t memalign __P ((size_t __alignment, size_t __size));
|
---|
108 |
|
---|
109 | /* Allocate SIZE bytes on a page boundary. */
|
---|
110 | extern __ptr_t valloc __P ((size_t __size));
|
---|
111 |
|
---|
112 |
|
---|
113 | #ifdef _MALLOC_INTERNAL
|
---|
114 |
|
---|
115 | /* The allocator divides the heap into blocks of fixed size; large
|
---|
116 | requests receive one or more whole blocks, and small requests
|
---|
117 | receive a fragment of a block. Fragment sizes are powers of two,
|
---|
118 | and all fragments of a block are the same size. When all the
|
---|
119 | fragments in a block have been freed, the block itself is freed. */
|
---|
120 | #define INT_BIT (CHAR_BIT * sizeof(int))
|
---|
121 | #define BLOCKLOG (INT_BIT > 16 ? 12 : 9)
|
---|
122 | #define BLOCKSIZE (1 << BLOCKLOG)
|
---|
123 | #define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
|
---|
124 |
|
---|
125 | /* Determine the amount of memory spanned by the initial heap table
|
---|
126 | (not an absolute limit). */
|
---|
127 | #define HEAP (INT_BIT > 16 ? 4194304 : 65536)
|
---|
128 |
|
---|
129 | /* Number of contiguous free blocks allowed to build up at the end of
|
---|
130 | memory before they will be returned to the system. */
|
---|
131 | #define FINAL_FREE_BLOCKS 8
|
---|
132 |
|
---|
133 | /* Data structure giving per-block information. */
|
---|
134 | typedef union
|
---|
135 | {
|
---|
136 | /* Heap information for a busy block. */
|
---|
137 | struct
|
---|
138 | {
|
---|
139 | /* Zero for a large block, or positive giving the
|
---|
140 | logarithm to the base two of the fragment size. */
|
---|
141 | int type;
|
---|
142 | union
|
---|
143 | {
|
---|
144 | struct
|
---|
145 | {
|
---|
146 | size_t nfree; /* Free fragments in a fragmented block. */
|
---|
147 | size_t first; /* First free fragment of the block. */
|
---|
148 | } frag;
|
---|
149 | /* Size (in blocks) of a large cluster. */
|
---|
150 | size_t size;
|
---|
151 | } info;
|
---|
152 | } busy;
|
---|
153 | /* Heap information for a free block
|
---|
154 | (that may be the first of a free cluster). */
|
---|
155 | struct
|
---|
156 | {
|
---|
157 | size_t size; /* Size (in blocks) of a free cluster. */
|
---|
158 | size_t next; /* Index of next free cluster. */
|
---|
159 | size_t prev; /* Index of previous free cluster. */
|
---|
160 | } free;
|
---|
161 | } malloc_info;
|
---|
162 |
|
---|
163 | /* Pointer to first block of the heap. */
|
---|
164 | extern char *_heapbase;
|
---|
165 |
|
---|
166 | /* Table indexed by block number giving per-block information. */
|
---|
167 | extern malloc_info *_heapinfo;
|
---|
168 |
|
---|
169 | /* Address to block number and vice versa. */
|
---|
170 | #define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
|
---|
171 | #define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))
|
---|
172 |
|
---|
173 | /* Current search index for the heap table. */
|
---|
174 | extern size_t _heapindex;
|
---|
175 |
|
---|
176 | /* Limit of valid info table indices. */
|
---|
177 | extern size_t _heaplimit;
|
---|
178 |
|
---|
179 | /* Doubly linked lists of free fragments. */
|
---|
180 | struct list
|
---|
181 | {
|
---|
182 | struct list *next;
|
---|
183 | struct list *prev;
|
---|
184 | };
|
---|
185 |
|
---|
186 | /* Free list headers for each fragment size. */
|
---|
187 | extern struct list _fraghead[];
|
---|
188 |
|
---|
189 | /* List of blocks allocated with `memalign' (or `valloc'). */
|
---|
190 | struct alignlist
|
---|
191 | {
|
---|
192 | struct alignlist *next;
|
---|
193 | __ptr_t aligned; /* The address that memaligned returned. */
|
---|
194 | __ptr_t exact; /* The address that malloc returned. */
|
---|
195 | };
|
---|
196 | extern struct alignlist *_aligned_blocks;
|
---|
197 |
|
---|
198 | /* Instrumentation. */
|
---|
199 | extern size_t _chunks_used;
|
---|
200 | extern size_t _bytes_used;
|
---|
201 | extern size_t _chunks_free;
|
---|
202 | extern size_t _bytes_free;
|
---|
203 |
|
---|
204 | /* Internal version of `free' used in `morecore' (malloc.c). */
|
---|
205 | extern void _free_internal __P ((__ptr_t __ptr));
|
---|
206 |
|
---|
207 | #endif /* _MALLOC_INTERNAL. */
|
---|
208 |
|
---|
209 | /* Underlying allocation function; successive calls should
|
---|
210 | return contiguous pieces of memory. */
|
---|
211 | extern __ptr_t (*__morecore) __P ((ptrdiff_t __size));
|
---|
212 |
|
---|
213 | /* Default value of `__morecore'. */
|
---|
214 | extern __ptr_t __default_morecore __P ((ptrdiff_t __size));
|
---|
215 |
|
---|
216 | /* If not NULL, this function is called after each time
|
---|
217 | `__morecore' is called to increase the data size. */
|
---|
218 | extern void (*__after_morecore_hook) __P ((void));
|
---|
219 |
|
---|
220 | /* Nonzero if `malloc' has been called and done its initialization. */
|
---|
221 | extern int __malloc_initialized;
|
---|
222 |
|
---|
223 | /* Hooks for debugging versions. */
|
---|
224 | extern void (*__free_hook) __P ((__ptr_t __ptr));
|
---|
225 | extern __ptr_t (*__malloc_hook) __P ((size_t __size));
|
---|
226 | extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
|
---|
227 |
|
---|
228 | /* Return values for `mprobe': these are the kinds of inconsistencies that
|
---|
229 | `mcheck' enables detection of. */
|
---|
230 | enum mcheck_status
|
---|
231 | {
|
---|
232 | MCHECK_DISABLED = -1, /* Consistency checking is not turned on. */
|
---|
233 | MCHECK_OK, /* Block is fine. */
|
---|
234 | MCHECK_FREE, /* Block freed twice. */
|
---|
235 | MCHECK_HEAD, /* Memory before the block was clobbered. */
|
---|
236 | MCHECK_TAIL /* Memory after the block was clobbered. */
|
---|
237 | };
|
---|
238 |
|
---|
239 | /* Activate a standard collection of debugging hooks. This must be called
|
---|
240 | before `malloc' is ever called. ABORTFUNC is called with an error code
|
---|
241 | (see enum above) when an inconsistency is detected. If ABORTFUNC is
|
---|
242 | null, the standard function prints on stderr and then calls `abort'. */
|
---|
243 | extern int mcheck __P ((void (*__abortfunc) __P ((enum mcheck_status))));
|
---|
244 |
|
---|
245 | /* Check for aberrations in a particular malloc'd block. You must have
|
---|
246 | called `mcheck' already. These are the same checks that `mcheck' does
|
---|
247 | when you free or reallocate a block. */
|
---|
248 | extern enum mcheck_status mprobe __P ((__ptr_t __ptr));
|
---|
249 |
|
---|
250 | /* Activate a standard collection of tracing hooks. */
|
---|
251 | extern void mtrace __P ((void));
|
---|
252 |
|
---|
253 | /* Statistics available to the user. */
|
---|
254 | struct mstats
|
---|
255 | {
|
---|
256 | size_t bytes_total; /* Total size of the heap. */
|
---|
257 | size_t chunks_used; /* Chunks allocated by the user. */
|
---|
258 | size_t bytes_used; /* Byte total of user-allocated chunks. */
|
---|
259 | size_t chunks_free; /* Chunks in the free list. */
|
---|
260 | size_t bytes_free; /* Byte total of chunks in the free list. */
|
---|
261 | };
|
---|
262 |
|
---|
263 | /* Pick up the current statistics. */
|
---|
264 | extern struct mstats mstats __P ((void));
|
---|
265 |
|
---|
266 | /* Call WARNFUN with a warning message when memory usage is high. */
|
---|
267 | extern void memory_warnings __P ((__ptr_t __start,
|
---|
268 | void (*__warnfun) __P ((const char *))));
|
---|
269 |
|
---|
270 |
|
---|
271 | /* Relocating allocator. */
|
---|
272 |
|
---|
273 | /* Allocate SIZE bytes, and store the address in *HANDLEPTR. */
|
---|
274 | extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, size_t __size));
|
---|
275 |
|
---|
276 | /* Free the storage allocated in HANDLEPTR. */
|
---|
277 | extern void r_alloc_free __P ((__ptr_t *__handleptr));
|
---|
278 |
|
---|
279 | /* Adjust the block at HANDLEPTR to be SIZE bytes long. */
|
---|
280 | extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, size_t __size));
|
---|
281 |
|
---|
282 |
|
---|
283 | #ifdef __cplusplus
|
---|
284 | }
|
---|
285 | #endif
|
---|
286 |
|
---|
287 | #endif /* malloc.h */
|
---|
288 | /* Allocate memory on a page boundary.
|
---|
289 | Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
|
---|
290 |
|
---|
291 | This library is free software; you can redistribute it and/or
|
---|
292 | modify it under the terms of the GNU Library General Public License as
|
---|
293 | published by the Free Software Foundation; either version 2 of the
|
---|
294 | License, or (at your option) any later version.
|
---|
295 |
|
---|
296 | This library is distributed in the hope that it will be useful,
|
---|
297 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
298 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
299 | Library General Public License for more details.
|
---|
300 |
|
---|
301 | You should have received a copy of the GNU Library General Public
|
---|
302 | License along with this library; see the file COPYING.LIB. If
|
---|
303 | not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
---|
304 | Cambridge, MA 02139, USA.
|
---|
305 |
|
---|
306 | The author may be reached (Email) at the address [email protected],
|
---|
307 | or (US mail) as Mike Haertel c/o Free Software Foundation. */
|
---|
308 |
|
---|
309 | #if defined (__GNU_LIBRARY__) || defined (_LIBC)
|
---|
310 | #include <stddef.h>
|
---|
311 | #include <sys/cdefs.h>
|
---|
312 | extern size_t __getpagesize __P ((void));
|
---|
313 | #else
|
---|
314 | #include "getpagesize.h"
|
---|
315 | #define __getpagesize() getpagesize()
|
---|
316 | #endif
|
---|
317 |
|
---|
318 | #ifndef _MALLOC_INTERNAL
|
---|
319 | #define _MALLOC_INTERNAL
|
---|
320 | #include <malloc.h>
|
---|
321 | #endif
|
---|
322 |
|
---|
323 | static size_t pagesize;
|
---|
324 |
|
---|
325 | __ptr_t
|
---|
326 | valloc (size)
|
---|
327 | size_t size;
|
---|
328 | {
|
---|
329 | if (pagesize == 0)
|
---|
330 | pagesize = __getpagesize ();
|
---|
331 |
|
---|
332 | return memalign (pagesize, size);
|
---|
333 | }
|
---|
334 | /* Memory allocator `malloc'.
|
---|
335 | Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation
|
---|
336 | Written May 1989 by Mike Haertel.
|
---|
337 |
|
---|
338 | This library is free software; you can redistribute it and/or
|
---|
339 | modify it under the terms of the GNU Library General Public License as
|
---|
340 | published by the Free Software Foundation; either version 2 of the
|
---|
341 | License, or (at your option) any later version.
|
---|
342 |
|
---|
343 | This library is distributed in the hope that it will be useful,
|
---|
344 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
345 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
346 | Library General Public License for more details.
|
---|
347 |
|
---|
348 | You should have received a copy of the GNU Library General Public
|
---|
349 | License along with this library; see the file COPYING.LIB. If
|
---|
350 | not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
---|
351 | Cambridge, MA 02139, USA.
|
---|
352 |
|
---|
353 | The author may be reached (Email) at the address [email protected],
|
---|
354 | or (US mail) as Mike Haertel c/o Free Software Foundation. */
|
---|
355 |
|
---|
356 | #ifndef _MALLOC_INTERNAL
|
---|
357 | #define _MALLOC_INTERNAL
|
---|
358 | #include <malloc.h>
|
---|
359 | #endif
|
---|
360 |
|
---|
361 | /* How to really get more memory. */
|
---|
362 | __ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore;
|
---|
363 |
|
---|
364 | /* Debugging hook for `malloc'. */
|
---|
365 | __ptr_t (*__malloc_hook) __P ((size_t __size));
|
---|
366 |
|
---|
367 | /* Pointer to the base of the first block. */
|
---|
368 | char *_heapbase;
|
---|
369 |
|
---|
370 | /* Block information table. Allocated with align/__free (not malloc/free). */
|
---|
371 | malloc_info *_heapinfo;
|
---|
372 |
|
---|
373 | /* Number of info entries. */
|
---|
374 | static size_t heapsize;
|
---|
375 |
|
---|
376 | /* Search index in the info table. */
|
---|
377 | size_t _heapindex;
|
---|
378 |
|
---|
379 | /* Limit of valid info table indices. */
|
---|
380 | size_t _heaplimit;
|
---|
381 |
|
---|
382 | /* Free lists for each fragment size. */
|
---|
383 | struct list _fraghead[BLOCKLOG];
|
---|
384 |
|
---|
385 | /* Instrumentation. */
|
---|
386 | size_t _chunks_used;
|
---|
387 | size_t _bytes_used;
|
---|
388 | size_t _chunks_free;
|
---|
389 | size_t _bytes_free;
|
---|
390 |
|
---|
391 | /* Are you experienced? */
|
---|
392 | int __malloc_initialized;
|
---|
393 |
|
---|
394 | void (*__after_morecore_hook) __P ((void));
|
---|
395 |
|
---|
396 | /* Aligned allocation. */
|
---|
397 | static __ptr_t align __P ((size_t));
|
---|
398 | static __ptr_t
|
---|
399 | align (size)
|
---|
400 | size_t size;
|
---|
401 | {
|
---|
402 | __ptr_t result;
|
---|
403 | mg_u_long adj;
|
---|
404 |
|
---|
405 | result = (*__morecore) (size);
|
---|
406 | adj = (mg_u_long) ((mg_u_long) ((char *) result -
|
---|
407 | (char *) NULL)) % BLOCKSIZE;
|
---|
408 | if (adj != 0)
|
---|
409 | {
|
---|
410 | adj = BLOCKSIZE - adj;
|
---|
411 | (void) (*__morecore) (adj);
|
---|
412 | result = (char *) result + adj;
|
---|
413 | }
|
---|
414 |
|
---|
415 | if (__after_morecore_hook)
|
---|
416 | (*__after_morecore_hook) ();
|
---|
417 |
|
---|
418 | return result;
|
---|
419 | }
|
---|
420 |
|
---|
421 | /* Set everything up and remember that we have. */
|
---|
422 | static int initialize __P ((void));
|
---|
423 | static int
|
---|
424 | initialize ()
|
---|
425 | {
|
---|
426 | heapsize = HEAP / BLOCKSIZE;
|
---|
427 | _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info));
|
---|
428 | if (_heapinfo == NULL)
|
---|
429 | return 0;
|
---|
430 | memset (_heapinfo, 0, heapsize * sizeof (malloc_info));
|
---|
431 | _heapinfo[0].free.size = 0;
|
---|
432 | _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
|
---|
433 | _heapindex = 0;
|
---|
434 | _heapbase = (char *) _heapinfo;
|
---|
435 |
|
---|
436 | /* Account for the _heapinfo block itself in the statistics. */
|
---|
437 | _bytes_used = heapsize * sizeof (malloc_info);
|
---|
438 | _chunks_used = 1;
|
---|
439 |
|
---|
440 | __malloc_initialized = 1;
|
---|
441 | return 1;
|
---|
442 | }
|
---|
443 |
|
---|
444 | /* Get neatly aligned memory, initializing or
|
---|
445 | growing the heap info table as necessary. */
|
---|
446 | static __ptr_t morecore __P ((size_t));
|
---|
447 | static __ptr_t
|
---|
448 | morecore (size)
|
---|
449 | size_t size;
|
---|
450 | {
|
---|
451 | __ptr_t result;
|
---|
452 | malloc_info *newinfo, *oldinfo;
|
---|
453 | size_t newsize;
|
---|
454 |
|
---|
455 | result = align (size);
|
---|
456 | if (result == NULL)
|
---|
457 | return NULL;
|
---|
458 |
|
---|
459 | /* Check if we need to grow the info table. */
|
---|
460 | if ((size_t) BLOCK ((char *) result + size) > heapsize)
|
---|
461 | {
|
---|
462 | newsize = heapsize;
|
---|
463 | while ((size_t) BLOCK ((char *) result + size) > newsize)
|
---|
464 | newsize *= 2;
|
---|
465 | newinfo = (malloc_info *) align (newsize * sizeof (malloc_info));
|
---|
466 | if (newinfo == NULL)
|
---|
467 | {
|
---|
468 | (*__morecore) (-size);
|
---|
469 | return NULL;
|
---|
470 | }
|
---|
471 | memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info));
|
---|
472 | memset (&newinfo[heapsize], 0,
|
---|
473 | (newsize - heapsize) * sizeof (malloc_info));
|
---|
474 | oldinfo = _heapinfo;
|
---|
475 | newinfo[BLOCK (oldinfo)].busy.type = 0;
|
---|
476 | newinfo[BLOCK (oldinfo)].busy.info.size
|
---|
477 | = BLOCKIFY (heapsize * sizeof (malloc_info));
|
---|
478 | _heapinfo = newinfo;
|
---|
479 | /* Account for the _heapinfo block itself in the statistics. */
|
---|
480 | _bytes_used += newsize * sizeof (malloc_info);
|
---|
481 | ++_chunks_used;
|
---|
482 | _free_internal (oldinfo);
|
---|
483 | heapsize = newsize;
|
---|
484 | }
|
---|
485 |
|
---|
486 | _heaplimit = BLOCK ((char *) result + size);
|
---|
487 | return result;
|
---|
488 | }
|
---|
489 |
|
---|
490 | /* Allocate memory from the heap. */
|
---|
491 | __ptr_t
|
---|
492 | malloc (size)
|
---|
493 | size_t size;
|
---|
494 | {
|
---|
495 | __ptr_t result;
|
---|
496 | size_t block, blocks, lastblocks, start;
|
---|
497 | register size_t i;
|
---|
498 | struct list *next;
|
---|
499 |
|
---|
500 | /* ANSI C allows `malloc (0)' to either return NULL, or to return a
|
---|
501 | valid address you can realloc and free (though not dereference).
|
---|
502 |
|
---|
503 | It turns out that some extant code (sunrpc, at least Ultrix's version)
|
---|
504 | expects `malloc (0)' to return non-NULL and breaks otherwise.
|
---|
505 | Be compatible. */
|
---|
506 |
|
---|
507 | #if 0
|
---|
508 | if (size == 0)
|
---|
509 | return NULL;
|
---|
510 | #endif
|
---|
511 |
|
---|
512 | if (__malloc_hook != NULL)
|
---|
513 | return (*__malloc_hook) (size);
|
---|
514 |
|
---|
515 | if (!__malloc_initialized)
|
---|
516 | if (!initialize ())
|
---|
517 | return NULL;
|
---|
518 |
|
---|
519 | if (size < sizeof (struct list))
|
---|
520 | size = sizeof (struct list);
|
---|
521 |
|
---|
522 | #ifdef SUNOS_LOCALTIME_BUG
|
---|
523 | if (size < 16)
|
---|
524 | size = 16;
|
---|
525 | #endif
|
---|
526 |
|
---|
527 | /* Determine the allocation policy based on the request size. */
|
---|
528 | if (size <= BLOCKSIZE / 2)
|
---|
529 | {
|
---|
530 | /* Small allocation to receive a fragment of a block.
|
---|
531 | Determine the logarithm to base two of the fragment size. */
|
---|
532 | register size_t log = 1;
|
---|
533 | --size;
|
---|
534 | while ((size /= 2) != 0)
|
---|
535 | ++log;
|
---|
536 |
|
---|
537 | /* Look in the fragment lists for a
|
---|
538 | free fragment of the desired size. */
|
---|
539 | next = _fraghead[log].next;
|
---|
540 | if (next != NULL)
|
---|
541 | {
|
---|
542 | /* There are free fragments of this size.
|
---|
543 | Pop a fragment out of the fragment list and return it.
|
---|
544 | Update the block's nfree and first counters. */
|
---|
545 | result = (__ptr_t) next;
|
---|
546 | next->prev->next = next->next;
|
---|
547 | if (next->next != NULL)
|
---|
548 | next->next->prev = next->prev;
|
---|
549 | block = BLOCK (result);
|
---|
550 | if (--_heapinfo[block].busy.info.frag.nfree != 0)
|
---|
551 | _heapinfo[block].busy.info.frag.first = (mg_u_long)
|
---|
552 | ((mg_u_long) ((char *) next->next - (char *) NULL)
|
---|
553 | % BLOCKSIZE) >> log;
|
---|
554 |
|
---|
555 | /* Update the statistics. */
|
---|
556 | ++_chunks_used;
|
---|
557 | _bytes_used += 1 << log;
|
---|
558 | --_chunks_free;
|
---|
559 | _bytes_free -= 1 << log;
|
---|
560 | }
|
---|
561 | else
|
---|
562 | {
|
---|
563 | /* No free fragments of the desired size, so get a new block
|
---|
564 | and break it into fragments, returning the first. */
|
---|
565 | result = malloc (BLOCKSIZE);
|
---|
566 | if (result == NULL)
|
---|
567 | return NULL;
|
---|
568 |
|
---|
569 | /* Link all fragments but the first into the free list. */
|
---|
570 | for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i)
|
---|
571 | {
|
---|
572 | next = (struct list *) ((char *) result + (i << log));
|
---|
573 | next->next = _fraghead[log].next;
|
---|
574 | next->prev = &_fraghead[log];
|
---|
575 | next->prev->next = next;
|
---|
576 | if (next->next != NULL)
|
---|
577 | next->next->prev = next;
|
---|
578 | }
|
---|
579 |
|
---|
580 | /* Initialize the nfree and first counters for this block. */
|
---|
581 | block = BLOCK (result);
|
---|
582 | _heapinfo[block].busy.type = log;
|
---|
583 | _heapinfo[block].busy.info.frag.nfree = i - 1;
|
---|
584 | _heapinfo[block].busy.info.frag.first = i - 1;
|
---|
585 |
|
---|
586 | _chunks_free += (BLOCKSIZE >> log) - 1;
|
---|
587 | _bytes_free += BLOCKSIZE - (1 << log);
|
---|
588 | _bytes_used -= BLOCKSIZE - (1 << log);
|
---|
589 | }
|
---|
590 | }
|
---|
591 | else
|
---|
592 | {
|
---|
593 | /* Large allocation to receive one or more blocks.
|
---|
594 | Search the free list in a circle starting at the last place visited.
|
---|
595 | If we loop completely around without finding a large enough
|
---|
596 | space we will have to get more memory from the system. */
|
---|
597 | blocks = BLOCKIFY (size);
|
---|
598 | start = block = _heapindex;
|
---|
599 | while (_heapinfo[block].free.size < blocks)
|
---|
600 | {
|
---|
601 | block = _heapinfo[block].free.next;
|
---|
602 | if (block == start)
|
---|
603 | {
|
---|
604 | /* Need to get more from the system. Check to see if
|
---|
605 | the new core will be contiguous with the final free
|
---|
606 | block; if so we don't need to get as much. */
|
---|
607 | block = _heapinfo[0].free.prev;
|
---|
608 | lastblocks = _heapinfo[block].free.size;
|
---|
609 | if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
|
---|
610 | (*__morecore) (0) == ADDRESS (block + lastblocks) &&
|
---|
611 | (morecore ((blocks - lastblocks) * BLOCKSIZE)) != NULL)
|
---|
612 | {
|
---|
613 | /* Which block we are extending (the `final free
|
---|
614 | block' referred to above) might have changed, if
|
---|
615 | it got combined with a freed info table. */
|
---|
616 | block = _heapinfo[0].free.prev;
|
---|
617 | _heapinfo[block].free.size += (blocks - lastblocks);
|
---|
618 | _bytes_free += (blocks - lastblocks) * BLOCKSIZE;
|
---|
619 | continue;
|
---|
620 | }
|
---|
621 | result = morecore (blocks * BLOCKSIZE);
|
---|
622 | if (result == NULL)
|
---|
623 | return NULL;
|
---|
624 | block = BLOCK (result);
|
---|
625 | _heapinfo[block].busy.type = 0;
|
---|
626 | _heapinfo[block].busy.info.size = blocks;
|
---|
627 | ++_chunks_used;
|
---|
628 | _bytes_used += blocks * BLOCKSIZE;
|
---|
629 | return result;
|
---|
630 | }
|
---|
631 | }
|
---|
632 |
|
---|
633 | /* At this point we have found a suitable free list entry.
|
---|
634 | Figure out how to remove what we need from the list. */
|
---|
635 | result = ADDRESS (block);
|
---|
636 | if (_heapinfo[block].free.size > blocks)
|
---|
637 | {
|
---|
638 | /* The block we found has a bit left over,
|
---|
639 | so relink the tail end back into the free list. */
|
---|
640 | _heapinfo[block + blocks].free.size
|
---|
641 | = _heapinfo[block].free.size - blocks;
|
---|
642 | _heapinfo[block + blocks].free.next
|
---|
643 | = _heapinfo[block].free.next;
|
---|
644 | _heapinfo[block + blocks].free.prev
|
---|
645 | = _heapinfo[block].free.prev;
|
---|
646 | _heapinfo[_heapinfo[block].free.prev].free.next
|
---|
647 | = _heapinfo[_heapinfo[block].free.next].free.prev
|
---|
648 | = _heapindex = block + blocks;
|
---|
649 | }
|
---|
650 | else
|
---|
651 | {
|
---|
652 | /* The block exactly matches our requirements,
|
---|
653 | so just remove it from the list. */
|
---|
654 | _heapinfo[_heapinfo[block].free.next].free.prev
|
---|
655 | = _heapinfo[block].free.prev;
|
---|
656 | _heapinfo[_heapinfo[block].free.prev].free.next
|
---|
657 | = _heapindex = _heapinfo[block].free.next;
|
---|
658 | --_chunks_free;
|
---|
659 | }
|
---|
660 |
|
---|
661 | _heapinfo[block].busy.type = 0;
|
---|
662 | _heapinfo[block].busy.info.size = blocks;
|
---|
663 | ++_chunks_used;
|
---|
664 | _bytes_used += blocks * BLOCKSIZE;
|
---|
665 | _bytes_free -= blocks * BLOCKSIZE;
|
---|
666 | }
|
---|
667 |
|
---|
668 | return result;
|
---|
669 | }
|
---|
670 | |
---|
671 |
|
---|
672 | #ifndef _LIBC
|
---|
673 |
|
---|
674 | /* On some ANSI C systems, some libc functions call _malloc, _free
|
---|
675 | and _realloc. Make them use the GNU functions. */
|
---|
676 |
|
---|
677 | __ptr_t
|
---|
678 | _malloc (size)
|
---|
679 | size_t size;
|
---|
680 | {
|
---|
681 | return malloc (size);
|
---|
682 | }
|
---|
683 |
|
---|
684 | void
|
---|
685 | _free (ptr)
|
---|
686 | __ptr_t ptr;
|
---|
687 | {
|
---|
688 | free (ptr);
|
---|
689 | }
|
---|
690 |
|
---|
691 | __ptr_t
|
---|
692 | _realloc (ptr, size)
|
---|
693 | __ptr_t ptr;
|
---|
694 | size_t size;
|
---|
695 | {
|
---|
696 | return realloc (ptr, size);
|
---|
697 | }
|
---|
698 |
|
---|
699 | #endif
|
---|
700 | /* Free a block of memory allocated by `malloc'.
|
---|
701 | Copyright 1990, 1991, 1992 Free Software Foundation
|
---|
702 | Written May 1989 by Mike Haertel.
|
---|
703 |
|
---|
704 | This library is free software; you can redistribute it and/or
|
---|
705 | modify it under the terms of the GNU Library General Public License as
|
---|
706 | published by the Free Software Foundation; either version 2 of the
|
---|
707 | License, or (at your option) any later version.
|
---|
708 |
|
---|
709 | This library is distributed in the hope that it will be useful,
|
---|
710 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
711 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
712 | Library General Public License for more details.
|
---|
713 |
|
---|
714 | You should have received a copy of the GNU Library General Public
|
---|
715 | License along with this library; see the file COPYING.LIB. If
|
---|
716 | not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
---|
717 | Cambridge, MA 02139, USA.
|
---|
718 |
|
---|
719 | The author may be reached (Email) at the address [email protected],
|
---|
720 | or (US mail) as Mike Haertel c/o Free Software Foundation. */
|
---|
721 |
|
---|
722 | #ifndef _MALLOC_INTERNAL
|
---|
723 | #define _MALLOC_INTERNAL
|
---|
724 | #include <malloc.h>
|
---|
725 | #endif
|
---|
726 |
|
---|
727 | /* Debugging hook for free. */
|
---|
728 | void (*__free_hook) __P ((__ptr_t __ptr));
|
---|
729 |
|
---|
730 | /* List of blocks allocated by memalign. */
|
---|
731 | struct alignlist *_aligned_blocks = NULL;
|
---|
732 |
|
---|
733 | /* Return memory to the heap.
|
---|
734 | Like `free' but don't call a __free_hook if there is one. */
|
---|
735 | void
|
---|
736 | _free_internal (ptr)
|
---|
737 | __ptr_t ptr;
|
---|
738 | {
|
---|
739 | int type;
|
---|
740 | size_t block, blocks;
|
---|
741 | register size_t i;
|
---|
742 | struct list *prev, *next;
|
---|
743 |
|
---|
744 | block = BLOCK (ptr);
|
---|
745 |
|
---|
746 | type = _heapinfo[block].busy.type;
|
---|
747 | switch (type)
|
---|
748 | {
|
---|
749 | case 0:
|
---|
750 | /* Get as many statistics as early as we can. */
|
---|
751 | --_chunks_used;
|
---|
752 | _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
|
---|
753 | _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
|
---|
754 |
|
---|
755 | /* Find the free cluster previous to this one in the free list.
|
---|
756 | Start searching at the last block referenced; this may benefit
|
---|
757 | programs with locality of allocation. */
|
---|
758 | i = _heapindex;
|
---|
759 | if (i > block)
|
---|
760 | while (i > block)
|
---|
761 | i = _heapinfo[i].free.prev;
|
---|
762 | else
|
---|
763 | {
|
---|
764 | do
|
---|
765 | i = _heapinfo[i].free.next;
|
---|
766 | while (i > 0 && i < block);
|
---|
767 | i = _heapinfo[i].free.prev;
|
---|
768 | }
|
---|
769 |
|
---|
770 | /* Determine how to link this block into the free list. */
|
---|
771 | if (block == i + _heapinfo[i].free.size)
|
---|
772 | {
|
---|
773 | /* Coalesce this block with its predecessor. */
|
---|
774 | _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
|
---|
775 | block = i;
|
---|
776 | }
|
---|
777 | else
|
---|
778 | {
|
---|
779 | /* Really link this block back into the free list. */
|
---|
780 | _heapinfo[block].free.size = _heapinfo[block].busy.info.size;
|
---|
781 | _heapinfo[block].free.next = _heapinfo[i].free.next;
|
---|
782 | _heapinfo[block].free.prev = i;
|
---|
783 | _heapinfo[i].free.next = block;
|
---|
784 | _heapinfo[_heapinfo[block].free.next].free.prev = block;
|
---|
785 | ++_chunks_free;
|
---|
786 | }
|
---|
787 |
|
---|
788 | /* Now that the block is linked in, see if we can coalesce it
|
---|
789 | with its successor (by deleting its successor from the list
|
---|
790 | and adding in its size). */
|
---|
791 | if (block + _heapinfo[block].free.size == _heapinfo[block].free.next)
|
---|
792 | {
|
---|
793 | _heapinfo[block].free.size
|
---|
794 | += _heapinfo[_heapinfo[block].free.next].free.size;
|
---|
795 | _heapinfo[block].free.next
|
---|
796 | = _heapinfo[_heapinfo[block].free.next].free.next;
|
---|
797 | _heapinfo[_heapinfo[block].free.next].free.prev = block;
|
---|
798 | --_chunks_free;
|
---|
799 | }
|
---|
800 |
|
---|
801 | /* Now see if we can return stuff to the system. */
|
---|
802 | blocks = _heapinfo[block].free.size;
|
---|
803 | if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
|
---|
804 | && (*__morecore) (0) == ADDRESS (block + blocks))
|
---|
805 | {
|
---|
806 | register size_t bytes = blocks * BLOCKSIZE;
|
---|
807 | _heaplimit -= blocks;
|
---|
808 | (*__morecore) (-bytes);
|
---|
809 | _heapinfo[_heapinfo[block].free.prev].free.next
|
---|
810 | = _heapinfo[block].free.next;
|
---|
811 | _heapinfo[_heapinfo[block].free.next].free.prev
|
---|
812 | = _heapinfo[block].free.prev;
|
---|
813 | block = _heapinfo[block].free.prev;
|
---|
814 | --_chunks_free;
|
---|
815 | _bytes_free -= bytes;
|
---|
816 | }
|
---|
817 |
|
---|
818 | /* Set the next search to begin at this block. */
|
---|
819 | _heapindex = block;
|
---|
820 | break;
|
---|
821 |
|
---|
822 | default:
|
---|
823 | /* Do some of the statistics. */
|
---|
824 | --_chunks_used;
|
---|
825 | _bytes_used -= 1 << type;
|
---|
826 | ++_chunks_free;
|
---|
827 | _bytes_free += 1 << type;
|
---|
828 |
|
---|
829 | /* Get the address of the first free fragment in this block. */
|
---|
830 | prev = (struct list *) ((char *) ADDRESS (block) +
|
---|
831 | (_heapinfo[block].busy.info.frag.first << type));
|
---|
832 |
|
---|
833 | if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)
|
---|
834 | {
|
---|
835 | /* If all fragments of this block are free, remove them
|
---|
836 | from the fragment list and free the whole block. */
|
---|
837 | next = prev;
|
---|
838 | for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
|
---|
839 | next = next->next;
|
---|
840 | prev->prev->next = next;
|
---|
841 | if (next != NULL)
|
---|
842 | next->prev = prev->prev;
|
---|
843 | _heapinfo[block].busy.type = 0;
|
---|
844 | _heapinfo[block].busy.info.size = 1;
|
---|
845 |
|
---|
846 | /* Keep the statistics accurate. */
|
---|
847 | ++_chunks_used;
|
---|
848 | _bytes_used += BLOCKSIZE;
|
---|
849 | _chunks_free -= BLOCKSIZE >> type;
|
---|
850 | _bytes_free -= BLOCKSIZE;
|
---|
851 |
|
---|
852 | free (ADDRESS (block));
|
---|
853 | }
|
---|
854 | else if (_heapinfo[block].busy.info.frag.nfree != 0)
|
---|
855 | {
|
---|
856 | /* If some fragments of this block are free, link this
|
---|
857 | fragment into the fragment list after the first free
|
---|
858 | fragment of this block. */
|
---|
859 | next = (struct list *) ptr;
|
---|
860 | next->next = prev->next;
|
---|
861 | next->prev = prev;
|
---|
862 | prev->next = next;
|
---|
863 | if (next->next != NULL)
|
---|
864 | next->next->prev = next;
|
---|
865 | ++_heapinfo[block].busy.info.frag.nfree;
|
---|
866 | }
|
---|
867 | else
|
---|
868 | {
|
---|
869 | /* No fragments of this block are free, so link this
|
---|
870 | fragment into the fragment list and announce that
|
---|
871 | it is the first free fragment of this block. */
|
---|
872 | prev = (struct list *) ptr;
|
---|
873 | _heapinfo[block].busy.info.frag.nfree = 1;
|
---|
874 | _heapinfo[block].busy.info.frag.first = (mg_u_long)
|
---|
875 | ((mg_u_long) ((char *) ptr - (char *) NULL)
|
---|
876 | % BLOCKSIZE >> type);
|
---|
877 | prev->next = _fraghead[type].next;
|
---|
878 | prev->prev = &_fraghead[type];
|
---|
879 | prev->prev->next = prev;
|
---|
880 | if (prev->next != NULL)
|
---|
881 | prev->next->prev = prev;
|
---|
882 | }
|
---|
883 | break;
|
---|
884 | }
|
---|
885 | }
|
---|
886 |
|
---|
887 | /* Return memory to the heap. */
|
---|
888 | void
|
---|
889 | free (ptr)
|
---|
890 | __ptr_t ptr;
|
---|
891 | {
|
---|
892 | register struct alignlist *l;
|
---|
893 |
|
---|
894 | if (ptr == NULL)
|
---|
895 | return;
|
---|
896 |
|
---|
897 | for (l = _aligned_blocks; l != NULL; l = l->next)
|
---|
898 | if (l->aligned == ptr)
|
---|
899 | {
|
---|
900 | l->aligned = NULL; /* Mark the slot in the list as free. */
|
---|
901 | ptr = l->exact;
|
---|
902 | break;
|
---|
903 | }
|
---|
904 |
|
---|
905 | if (__free_hook != NULL)
|
---|
906 | (*__free_hook) (ptr);
|
---|
907 | else
|
---|
908 | _free_internal (ptr);
|
---|
909 | }
|
---|
910 | /* Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
|
---|
911 | This file is part of the GNU C Library.
|
---|
912 |
|
---|
913 | The GNU C Library is free software; you can redistribute it and/or
|
---|
914 | modify it under the terms of the GNU Library General Public License as
|
---|
915 | published by the Free Software Foundation; either version 2 of the
|
---|
916 | License, or (at your option) any later version.
|
---|
917 |
|
---|
918 | The GNU C Library is distributed in the hope that it will be useful,
|
---|
919 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
920 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
921 | Library General Public License for more details.
|
---|
922 |
|
---|
923 | You should have received a copy of the GNU Library General Public
|
---|
924 | License along with the GNU C Library; see the file COPYING.LIB. If
|
---|
925 | not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
---|
926 | Cambridge, MA 02139, USA. */
|
---|
927 |
|
---|
928 | #ifndef _MALLOC_INTERNAL
|
---|
929 | #define _MALLOC_INTERNAL
|
---|
930 | #include <malloc.h>
|
---|
931 | #endif
|
---|
932 |
|
---|
933 | #ifdef _LIBC
|
---|
934 |
|
---|
935 | #include <ansidecl.h>
|
---|
936 | #include <gnu-stabs.h>
|
---|
937 |
|
---|
938 | #undef cfree
|
---|
939 |
|
---|
940 | function_alias(cfree, free, void, (ptr),
|
---|
941 | DEFUN(cfree, (ptr), PTR ptr))
|
---|
942 |
|
---|
943 | #else
|
---|
944 |
|
---|
945 | void
|
---|
946 | cfree (ptr)
|
---|
947 | __ptr_t ptr;
|
---|
948 | {
|
---|
949 | free (ptr);
|
---|
950 | }
|
---|
951 |
|
---|
952 | #endif
|
---|
953 | /* Change the size of a block allocated by `malloc'.
|
---|
954 | Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
|
---|
955 | Written May 1989 by Mike Haertel.
|
---|
956 |
|
---|
957 | This library is free software; you can redistribute it and/or
|
---|
958 | modify it under the terms of the GNU Library General Public License as
|
---|
959 | published by the Free Software Foundation; either version 2 of the
|
---|
960 | License, or (at your option) any later version.
|
---|
961 |
|
---|
962 | This library is distributed in the hope that it will be useful,
|
---|
963 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
964 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
965 | Library General Public License for more details.
|
---|
966 |
|
---|
967 | You should have received a copy of the GNU Library General Public
|
---|
968 | License along with this library; see the file COPYING.LIB. If
|
---|
969 | not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
---|
970 | Cambridge, MA 02139, USA.
|
---|
971 |
|
---|
972 | The author may be reached (Email) at the address [email protected],
|
---|
973 | or (US mail) as Mike Haertel c/o Free Software Foundation. */
|
---|
974 |
|
---|
975 | #ifndef _MALLOC_INTERNAL
|
---|
976 | #define _MALLOC_INTERNAL
|
---|
977 | #include <malloc.h>
|
---|
978 | #endif
|
---|
979 |
|
---|
980 | #if (defined (MEMMOVE_MISSING) || \
|
---|
981 | !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG))
|
---|
982 |
|
---|
983 | /* Snarfed directly from Emacs src/dispnew.c:
|
---|
984 | XXX Should use system bcopy if it handles overlap. */
|
---|
985 | #ifndef emacs
|
---|
986 |
|
---|
987 | /* Like bcopy except never gets confused by overlap. */
|
---|
988 |
|
---|
989 | static void
|
---|
990 | safe_bcopy (from, to, size)
|
---|
991 | char *from, *to;
|
---|
992 | int size;
|
---|
993 | {
|
---|
994 | if (size <= 0 || from == to)
|
---|
995 | return;
|
---|
996 |
|
---|
997 | /* If the source and destination don't overlap, then bcopy can
|
---|
998 | handle it. If they do overlap, but the destination is lower in
|
---|
999 | memory than the source, we'll assume bcopy can handle that. */
|
---|
1000 | if (to < from || from + size <= to)
|
---|
1001 | bcopy (from, to, size);
|
---|
1002 |
|
---|
1003 | /* Otherwise, we'll copy from the end. */
|
---|
1004 | else
|
---|
1005 | {
|
---|
1006 | register char *endf = from + size;
|
---|
1007 | register char *endt = to + size;
|
---|
1008 |
|
---|
1009 | /* If TO - FROM is large, then we should break the copy into
|
---|
1010 | nonoverlapping chunks of TO - FROM bytes each. However, if
|
---|
1011 | TO - FROM is small, then the bcopy function call overhead
|
---|
1012 | makes this not worth it. The crossover point could be about
|
---|
1013 | anywhere. Since I don't think the obvious copy loop is too
|
---|
1014 | bad, I'm trying to err in its favor. */
|
---|
1015 | if (to - from < 64)
|
---|
1016 | {
|
---|
1017 | do
|
---|
1018 | *--endt = *--endf;
|
---|
1019 | while (endf != from);
|
---|
1020 | }
|
---|
1021 | else
|
---|
1022 | {
|
---|
1023 | for (;;)
|
---|
1024 | {
|
---|
1025 | endt -= (to - from);
|
---|
1026 | endf -= (to - from);
|
---|
1027 |
|
---|
1028 | if (endt < to)
|
---|
1029 | break;
|
---|
1030 |
|
---|
1031 | bcopy (endf, endt, to - from);
|
---|
1032 | }
|
---|
1033 |
|
---|
1034 | /* If SIZE wasn't a multiple of TO - FROM, there will be a
|
---|
1035 | little left over. The amount left over is
|
---|
1036 | (endt + (to - from)) - to, which is endt - from. */
|
---|
1037 | bcopy (from, to, endt - from);
|
---|
1038 | }
|
---|
1039 | }
|
---|
1040 | }
|
---|
1041 | #endif /* Not emacs. */
|
---|
1042 |
|
---|
1043 | #define memmove(to, from, size) safe_bcopy ((from), (to), (size))
|
---|
1044 |
|
---|
1045 | #endif
|
---|
1046 |
|
---|
1047 |
|
---|
1048 | #define min(A, B) ((A) < (B) ? (A) : (B))
|
---|
1049 |
|
---|
1050 | /* Debugging hook for realloc. */
|
---|
1051 | __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
|
---|
1052 |
|
---|
1053 | /* Resize the given region to the new size, returning a pointer
|
---|
1054 | to the (possibly moved) region. This is optimized for speed;
|
---|
1055 | some benchmarks seem to indicate that greater compactness is
|
---|
1056 | achieved by unconditionally allocating and copying to a
|
---|
1057 | new region. This module has incestuous knowledge of the
|
---|
1058 | internals of both free and malloc. */
|
---|
1059 | __ptr_t
|
---|
1060 | realloc (ptr, size)
|
---|
1061 | __ptr_t ptr;
|
---|
1062 | size_t size;
|
---|
1063 | {
|
---|
1064 | __ptr_t result;
|
---|
1065 | int type;
|
---|
1066 | size_t block, blocks, oldlimit;
|
---|
1067 |
|
---|
1068 | if (size == 0)
|
---|
1069 | {
|
---|
1070 | free (ptr);
|
---|
1071 | return malloc (0);
|
---|
1072 | }
|
---|
1073 | else if (ptr == NULL)
|
---|
1074 | return malloc (size);
|
---|
1075 |
|
---|
1076 | if (__realloc_hook != NULL)
|
---|
1077 | return (*__realloc_hook) (ptr, size);
|
---|
1078 |
|
---|
1079 | block = BLOCK (ptr);
|
---|
1080 |
|
---|
1081 | type = _heapinfo[block].busy.type;
|
---|
1082 | switch (type)
|
---|
1083 | {
|
---|
1084 | case 0:
|
---|
1085 | /* Maybe reallocate a large block to a small fragment. */
|
---|
1086 | if (size <= BLOCKSIZE / 2)
|
---|
1087 | {
|
---|
1088 | result = malloc (size);
|
---|
1089 | if (result != NULL)
|
---|
1090 | {
|
---|
1091 | memcpy (result, ptr, size);
|
---|
1092 | _free_internal (ptr);
|
---|
1093 | return result;
|
---|
1094 | }
|
---|
1095 | }
|
---|
1096 |
|
---|
1097 | /* The new size is a large allocation as well;
|
---|
1098 | see if we can hold it in place. */
|
---|
1099 | blocks = BLOCKIFY (size);
|
---|
1100 | if (blocks < _heapinfo[block].busy.info.size)
|
---|
1101 | {
|
---|
1102 | /* The new size is smaller; return
|
---|
1103 | excess memory to the free list. */
|
---|
1104 | _heapinfo[block + blocks].busy.type = 0;
|
---|
1105 | _heapinfo[block + blocks].busy.info.size
|
---|
1106 | = _heapinfo[block].busy.info.size - blocks;
|
---|
1107 | _heapinfo[block].busy.info.size = blocks;
|
---|
1108 | /* We have just created a new chunk by splitting a chunk in two.
|
---|
1109 | Now we will free this chunk; increment the statistics counter
|
---|
1110 | so it doesn't become wrong when _free_internal decrements it. */
|
---|
1111 | ++_chunks_used;
|
---|
1112 | _free_internal (ADDRESS (block + blocks));
|
---|
1113 | result = ptr;
|
---|
1114 | }
|
---|
1115 | else if (blocks == _heapinfo[block].busy.info.size)
|
---|
1116 | /* No size change necessary. */
|
---|
1117 | result = ptr;
|
---|
1118 | else
|
---|
1119 | {
|
---|
1120 | /* Won't fit, so allocate a new region that will.
|
---|
1121 | Free the old region first in case there is sufficient
|
---|
1122 | adjacent free space to grow without moving. */
|
---|
1123 | blocks = _heapinfo[block].busy.info.size;
|
---|
1124 | /* Prevent free from actually returning memory to the system. */
|
---|
1125 | oldlimit = _heaplimit;
|
---|
1126 | _heaplimit = 0;
|
---|
1127 | _free_internal (ptr);
|
---|
1128 | _heaplimit = oldlimit;
|
---|
1129 | result = malloc (size);
|
---|
1130 | if (result == NULL)
|
---|
1131 | {
|
---|
1132 | /* Now we're really in trouble. We have to unfree
|
---|
1133 | the thing we just freed. Unfortunately it might
|
---|
1134 | have been coalesced with its neighbors. */
|
---|
1135 | if (_heapindex == block)
|
---|
1136 | (void) malloc (blocks * BLOCKSIZE);
|
---|
1137 | else
|
---|
1138 | {
|
---|
1139 | __ptr_t previous = malloc ((block - _heapindex) * BLOCKSIZE);
|
---|
1140 | (void) malloc (blocks * BLOCKSIZE);
|
---|
1141 | _free_internal (previous);
|
---|
1142 | }
|
---|
1143 | return NULL;
|
---|
1144 | }
|
---|
1145 | if (ptr != result)
|
---|
1146 | memmove (result, ptr, blocks * BLOCKSIZE);
|
---|
1147 | }
|
---|
1148 | break;
|
---|
1149 |
|
---|
1150 | default:
|
---|
1151 | /* Old size is a fragment; type is logarithm
|
---|
1152 | to base two of the fragment size. */
|
---|
1153 | if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))
|
---|
1154 | /* The new size is the same kind of fragment. */
|
---|
1155 | result = ptr;
|
---|
1156 | else
|
---|
1157 | {
|
---|
1158 | /* The new size is different; allocate a new space,
|
---|
1159 | and copy the lesser of the new size and the old. */
|
---|
1160 | result = malloc (size);
|
---|
1161 | if (result == NULL)
|
---|
1162 | return NULL;
|
---|
1163 | memcpy (result, ptr, min (size, (size_t) 1 << type));
|
---|
1164 | free (ptr);
|
---|
1165 | }
|
---|
1166 | break;
|
---|
1167 | }
|
---|
1168 |
|
---|
1169 | return result;
|
---|
1170 | }
|
---|
1171 | /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
|
---|
1172 |
|
---|
1173 | This library is free software; you can redistribute it and/or
|
---|
1174 | modify it under the terms of the GNU Library General Public License as
|
---|
1175 | published by the Free Software Foundation; either version 2 of the
|
---|
1176 | License, or (at your option) any later version.
|
---|
1177 |
|
---|
1178 | This library is distributed in the hope that it will be useful,
|
---|
1179 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
1180 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
1181 | Library General Public License for more details.
|
---|
1182 |
|
---|
1183 | You should have received a copy of the GNU Library General Public
|
---|
1184 | License along with this library; see the file COPYING.LIB. If
|
---|
1185 | not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
---|
1186 | Cambridge, MA 02139, USA.
|
---|
1187 |
|
---|
1188 | The author may be reached (Email) at the address [email protected],
|
---|
1189 | or (US mail) as Mike Haertel c/o Free Software Foundation. */
|
---|
1190 |
|
---|
1191 | #ifndef _MALLOC_INTERNAL
|
---|
1192 | #define _MALLOC_INTERNAL
|
---|
1193 | #include <malloc.h>
|
---|
1194 | #endif
|
---|
1195 |
|
---|
1196 | /* Allocate an array of NMEMB elements each SIZE bytes long.
|
---|
1197 | The entire array is initialized to zeros. */
|
---|
1198 | __ptr_t
|
---|
1199 | calloc (nmemb, size)
|
---|
1200 | register size_t nmemb;
|
---|
1201 | register size_t size;
|
---|
1202 | {
|
---|
1203 | register __ptr_t result = malloc (nmemb * size);
|
---|
1204 |
|
---|
1205 | if (result != NULL)
|
---|
1206 | (void) memset (result, 0, nmemb * size);
|
---|
1207 |
|
---|
1208 | return result;
|
---|
1209 | }
|
---|
1210 | /* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
|
---|
1211 | This file is part of the GNU C Library.
|
---|
1212 |
|
---|
1213 | The GNU C Library is free software; you can redistribute it and/or modify
|
---|
1214 | it under the terms of the GNU General Public License as published by
|
---|
1215 | the Free Software Foundation; either version 2, or (at your option)
|
---|
1216 | any later version.
|
---|
1217 |
|
---|
1218 | The GNU C Library is distributed in the hope that it will be useful,
|
---|
1219 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
1220 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
1221 | GNU General Public License for more details.
|
---|
1222 |
|
---|
1223 | You should have received a copy of the GNU General Public License
|
---|
1224 | along with the GNU C Library; see the file COPYING. If not, write to
|
---|
1225 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
---|
1226 |
|
---|
1227 | #ifndef _MALLOC_INTERNAL
|
---|
1228 | #define _MALLOC_INTERNAL
|
---|
1229 | #include <malloc.h>
|
---|
1230 | #endif
|
---|
1231 |
|
---|
1232 | #ifndef __GNU_LIBRARY__
|
---|
1233 | #define __sbrk sbrk
|
---|
1234 | #endif
|
---|
1235 |
|
---|
1236 | #ifdef __GNU_LIBRARY__
|
---|
1237 | /* It is best not to declare this and cast its result on foreign operating
|
---|
1238 | systems with potentially hostile include files. */
|
---|
1239 | extern __ptr_t __sbrk __P ((int increment));
|
---|
1240 | #endif
|
---|
1241 |
|
---|
1242 | #ifndef NULL
|
---|
1243 | #define NULL 0
|
---|
1244 | #endif
|
---|
1245 |
|
---|
1246 | /* Allocate INCREMENT more bytes of data space,
|
---|
1247 | and return the start of data space, or NULL on errors.
|
---|
1248 | If INCREMENT is negative, shrink data space. */
|
---|
1249 | __ptr_t
|
---|
1250 | __default_morecore (increment)
|
---|
1251 | ptrdiff_t increment;
|
---|
1252 | {
|
---|
1253 | __ptr_t result = (__ptr_t) __sbrk ((int) increment);
|
---|
1254 | if (result == (__ptr_t) -1)
|
---|
1255 | return NULL;
|
---|
1256 | return result;
|
---|
1257 | }
|
---|
1258 | /* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
|
---|
1259 |
|
---|
1260 | This library is free software; you can redistribute it and/or
|
---|
1261 | modify it under the terms of the GNU Library General Public License as
|
---|
1262 | published by the Free Software Foundation; either version 2 of the
|
---|
1263 | License, or (at your option) any later version.
|
---|
1264 |
|
---|
1265 | This library is distributed in the hope that it will be useful,
|
---|
1266 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
1267 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
1268 | Library General Public License for more details.
|
---|
1269 |
|
---|
1270 | You should have received a copy of the GNU Library General Public
|
---|
1271 | License along with this library; see the file COPYING.LIB. If
|
---|
1272 | not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
---|
1273 | Cambridge, MA 02139, USA. */
|
---|
1274 |
|
---|
1275 | #ifndef _MALLOC_INTERNAL
|
---|
1276 | #define _MALLOC_INTERNAL
|
---|
1277 | #include <malloc.h>
|
---|
1278 | #endif
|
---|
1279 |
|
---|
1280 | __ptr_t
|
---|
1281 | memalign (alignment, size)
|
---|
1282 | size_t alignment;
|
---|
1283 | size_t size;
|
---|
1284 | {
|
---|
1285 | __ptr_t result;
|
---|
1286 | mg_u_long int adj;
|
---|
1287 |
|
---|
1288 | size = ((size + alignment - 1) / alignment) * alignment;
|
---|
1289 |
|
---|
1290 | result = malloc (size);
|
---|
1291 | if (result == NULL)
|
---|
1292 | return NULL;
|
---|
1293 | adj = (mg_u_long) ((mg_u_long) ((char *) result -
|
---|
1294 | (char *) NULL)) % alignment;
|
---|
1295 | if (adj != 0)
|
---|
1296 | {
|
---|
1297 | struct alignlist *l;
|
---|
1298 | for (l = _aligned_blocks; l != NULL; l = l->next)
|
---|
1299 | if (l->aligned == NULL)
|
---|
1300 | /* This slot is free. Use it. */
|
---|
1301 | break;
|
---|
1302 | if (l == NULL)
|
---|
1303 | {
|
---|
1304 | l = (struct alignlist *) malloc (sizeof (struct alignlist));
|
---|
1305 | if (l == NULL)
|
---|
1306 | {
|
---|
1307 | free (result);
|
---|
1308 | return NULL;
|
---|
1309 | }
|
---|
1310 | l->next = _aligned_blocks;
|
---|
1311 | _aligned_blocks = l;
|
---|
1312 | }
|
---|
1313 | l->exact = result;
|
---|
1314 | result = l->aligned = (char *) result + alignment - adj;
|
---|
1315 | }
|
---|
1316 |
|
---|
1317 | return result;
|
---|
1318 | }
|
---|