Add 2007 to copyright years.
[bpt/emacs.git] / src / gmalloc.c
CommitLineData
74ad5c7f
KH
1/* This file is no longer automatically generated from libc. */
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.
0b5538bd 8 Copyright (C) 1990, 1991, 1992, 1993, 1995, 1996, 1999, 2002, 2003, 2004,
aaef169d 9 2005, 2006 Free Software Foundation, Inc.
74ad5c7f
KH
10 Written May 1989 by Mike Haertel.
11
12This library is free software; you can redistribute it and/or
423a1f3c 13modify it under the terms of the GNU General Public License as
74ad5c7f
KH
14published by the Free Software Foundation; either version 2 of the
15License, or (at your option) any later version.
16
17This library is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
423a1f3c 20General Public License for more details.
74ad5c7f 21
423a1f3c
JB
22You should have received a copy of the GNU General Public
23License along with this library; see the file COPYING. If
3ef97fb6
LK
24not, write to the Free Software Foundation, Inc., 51 Franklin Street,
25Fifth Floor, Boston, MA 02110-1301, USA.
74ad5c7f
KH
26
27 The author may be reached (Email) at the address mike@ai.mit.edu,
28 or (US mail) as Mike Haertel c/o Free Software Foundation. */
29
30#ifndef _MALLOC_H
31
32#define _MALLOC_H 1
33
34#ifdef _MALLOC_INTERNAL
35
36#ifdef HAVE_CONFIG_H
37#include <config.h>
38#endif
39
b2e92d3e
RS
40#if ((defined __cplusplus || (defined (__STDC__) && __STDC__) \
41 || defined STDC_HEADERS || defined PROTOTYPES) \
42 && ! defined (BROKEN_PROTOTYPES))
0a27e8ed
RS
43#undef PP
44#define PP(args) args
74ad5c7f
KH
45#undef __ptr_t
46#define __ptr_t void *
47#else /* Not C++ or ANSI C. */
0a27e8ed
RS
48#undef PP
49#define PP(args) ()
74ad5c7f
KH
50#undef __ptr_t
51#define __ptr_t char *
52#endif /* C++ or ANSI C. */
53
54#if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG)
55#include <string.h>
56#else
57#ifndef memset
58#define memset(s, zero, n) bzero ((s), (n))
59#endif
60#ifndef memcpy
61#define memcpy(d, s, n) bcopy ((s), (d), (n))
62#endif
63#endif
64
ca9c0567 65#ifdef HAVE_LIMITS_H
74ad5c7f 66#include <limits.h>
ca9c0567 67#endif
74ad5c7f
KH
68#ifndef CHAR_BIT
69#define CHAR_BIT 8
70#endif
74ad5c7f
KH
71
72#ifdef HAVE_UNISTD_H
73#include <unistd.h>
74#endif
75
76#endif /* _MALLOC_INTERNAL. */
77
78
79#ifdef __cplusplus
80extern "C"
81{
82#endif
83
ca9c0567 84#ifdef STDC_HEADERS
74ad5c7f
KH
85#include <stddef.h>
86#define __malloc_size_t size_t
87#define __malloc_ptrdiff_t ptrdiff_t
88#else
eec2d1de
EZ
89#ifdef __GNUC__
90#include <stddef.h>
91#ifdef __SIZE_TYPE__
92#define __malloc_size_t __SIZE_TYPE__
93#endif
94#endif
95#ifndef __malloc_size_t
74ad5c7f 96#define __malloc_size_t unsigned int
eec2d1de 97#endif
74ad5c7f
KH
98#define __malloc_ptrdiff_t int
99#endif
100
101#ifndef NULL
102#define NULL 0
103#endif
104
ca9c0567
PE
105#ifndef FREE_RETURN_TYPE
106#define FREE_RETURN_TYPE void
107#endif
108
74ad5c7f
KH
109
110/* Allocate SIZE bytes of memory. */
0a27e8ed 111extern __ptr_t malloc PP ((__malloc_size_t __size));
74ad5c7f
KH
112/* Re-allocate the previously allocated block
113 in __ptr_t, making the new block SIZE bytes long. */
0a27e8ed 114extern __ptr_t realloc PP ((__ptr_t __ptr, __malloc_size_t __size));
74ad5c7f 115/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
0a27e8ed 116extern __ptr_t calloc PP ((__malloc_size_t __nmemb, __malloc_size_t __size));
74ad5c7f 117/* Free a block allocated by `malloc', `realloc' or `calloc'. */
ca9c0567 118extern FREE_RETURN_TYPE free PP ((__ptr_t __ptr));
74ad5c7f
KH
119
120/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
121#if ! (defined (_MALLOC_INTERNAL) && __DJGPP__ - 0 == 1) /* Avoid conflict. */
0a27e8ed
RS
122extern __ptr_t memalign PP ((__malloc_size_t __alignment,
123 __malloc_size_t __size));
74ad5c7f
KH
124#endif
125
126/* Allocate SIZE bytes on a page boundary. */
127#if ! (defined (_MALLOC_INTERNAL) && defined (GMALLOC_INHIBIT_VALLOC))
0a27e8ed 128extern __ptr_t valloc PP ((__malloc_size_t __size));
74ad5c7f
KH
129#endif
130
131
132#ifdef _MALLOC_INTERNAL
133
134/* The allocator divides the heap into blocks of fixed size; large
135 requests receive one or more whole blocks, and small requests
136 receive a fragment of a block. Fragment sizes are powers of two,
137 and all fragments of a block are the same size. When all the
138 fragments in a block have been freed, the block itself is freed. */
139#define INT_BIT (CHAR_BIT * sizeof(int))
140#define BLOCKLOG (INT_BIT > 16 ? 12 : 9)
141#define BLOCKSIZE (1 << BLOCKLOG)
142#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
143
144/* Determine the amount of memory spanned by the initial heap table
145 (not an absolute limit). */
146#define HEAP (INT_BIT > 16 ? 4194304 : 65536)
147
148/* Number of contiguous free blocks allowed to build up at the end of
149 memory before they will be returned to the system. */
150#define FINAL_FREE_BLOCKS 8
151
152/* Data structure giving per-block information. */
153typedef union
154 {
155 /* Heap information for a busy block. */
156 struct
157 {
158 /* Zero for a large (multiblock) object, or positive giving the
159 logarithm to the base two of the fragment size. */
160 int type;
161 union
162 {
163 struct
164 {
165 __malloc_size_t nfree; /* Free frags in a fragmented block. */
166 __malloc_size_t first; /* First free fragment of the block. */
167 } frag;
168 /* For a large object, in its first block, this has the number
169 of blocks in the object. In the other blocks, this has a
170 negative number which says how far back the first block is. */
171 __malloc_ptrdiff_t size;
172 } info;
173 } busy;
174 /* Heap information for a free block
175 (that may be the first of a free cluster). */
176 struct
177 {
178 __malloc_size_t size; /* Size (in blocks) of a free cluster. */
179 __malloc_size_t next; /* Index of next free cluster. */
180 __malloc_size_t prev; /* Index of previous free cluster. */
181 } free;
182 } malloc_info;
183
184/* Pointer to first block of the heap. */
185extern char *_heapbase;
186
187/* Table indexed by block number giving per-block information. */
188extern malloc_info *_heapinfo;
189
190/* Address to block number and vice versa. */
191#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
192#define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))
193
194/* Current search index for the heap table. */
195extern __malloc_size_t _heapindex;
196
197/* Limit of valid info table indices. */
198extern __malloc_size_t _heaplimit;
199
200/* Doubly linked lists of free fragments. */
201struct list
202 {
203 struct list *next;
204 struct list *prev;
205 };
206
207/* Free list headers for each fragment size. */
208extern struct list _fraghead[];
209
210/* List of blocks allocated with `memalign' (or `valloc'). */
211struct alignlist
212 {
213 struct alignlist *next;
214 __ptr_t aligned; /* The address that memaligned returned. */
215 __ptr_t exact; /* The address that malloc returned. */
216 };
217extern struct alignlist *_aligned_blocks;
218
219/* Instrumentation. */
220extern __malloc_size_t _chunks_used;
221extern __malloc_size_t _bytes_used;
222extern __malloc_size_t _chunks_free;
223extern __malloc_size_t _bytes_free;
224
225/* Internal versions of `malloc', `realloc', and `free'
226 used when these functions need to call each other.
227 They are the same but don't call the hooks. */
0a27e8ed
RS
228extern __ptr_t _malloc_internal PP ((__malloc_size_t __size));
229extern __ptr_t _realloc_internal PP ((__ptr_t __ptr, __malloc_size_t __size));
230extern void _free_internal PP ((__ptr_t __ptr));
74ad5c7f
KH
231
232#endif /* _MALLOC_INTERNAL. */
233
234/* Given an address in the middle of a malloc'd object,
235 return the address of the beginning of the object. */
0a27e8ed 236extern __ptr_t malloc_find_object_address PP ((__ptr_t __ptr));
74ad5c7f
KH
237
238/* Underlying allocation function; successive calls should
239 return contiguous pieces of memory. */
0a27e8ed 240extern __ptr_t (*__morecore) PP ((__malloc_ptrdiff_t __size));
74ad5c7f
KH
241
242/* Default value of `__morecore'. */
0a27e8ed 243extern __ptr_t __default_morecore PP ((__malloc_ptrdiff_t __size));
74ad5c7f
KH
244
245/* If not NULL, this function is called after each time
246 `__morecore' is called to increase the data size. */
0a27e8ed 247extern void (*__after_morecore_hook) PP ((void));
74ad5c7f
KH
248
249/* Number of extra blocks to get each time we ask for more core.
250 This reduces the frequency of calling `(*__morecore)'. */
251extern __malloc_size_t __malloc_extra_blocks;
252
253/* Nonzero if `malloc' has been called and done its initialization. */
254extern int __malloc_initialized;
255/* Function called to initialize malloc data structures. */
0a27e8ed 256extern int __malloc_initialize PP ((void));
74ad5c7f
KH
257
258/* Hooks for debugging versions. */
0a27e8ed
RS
259extern void (*__malloc_initialize_hook) PP ((void));
260extern void (*__free_hook) PP ((__ptr_t __ptr));
261extern __ptr_t (*__malloc_hook) PP ((__malloc_size_t __size));
262extern __ptr_t (*__realloc_hook) PP ((__ptr_t __ptr, __malloc_size_t __size));
263extern __ptr_t (*__memalign_hook) PP ((__malloc_size_t __size,
264 __malloc_size_t __alignment));
74ad5c7f
KH
265
266/* Return values for `mprobe': these are the kinds of inconsistencies that
267 `mcheck' enables detection of. */
268enum mcheck_status
269 {
270 MCHECK_DISABLED = -1, /* Consistency checking is not turned on. */
271 MCHECK_OK, /* Block is fine. */
272 MCHECK_FREE, /* Block freed twice. */
273 MCHECK_HEAD, /* Memory before the block was clobbered. */
274 MCHECK_TAIL /* Memory after the block was clobbered. */
275 };
276
277/* Activate a standard collection of debugging hooks. This must be called
278 before `malloc' is ever called. ABORTFUNC is called with an error code
279 (see enum above) when an inconsistency is detected. If ABORTFUNC is
280 null, the standard function prints on stderr and then calls `abort'. */
0a27e8ed 281extern int mcheck PP ((void (*__abortfunc) PP ((enum mcheck_status))));
74ad5c7f
KH
282
283/* Check for aberrations in a particular malloc'd block. You must have
284 called `mcheck' already. These are the same checks that `mcheck' does
285 when you free or reallocate a block. */
0a27e8ed 286extern enum mcheck_status mprobe PP ((__ptr_t __ptr));
74ad5c7f
KH
287
288/* Activate a standard collection of tracing hooks. */
0a27e8ed
RS
289extern void mtrace PP ((void));
290extern void muntrace PP ((void));
74ad5c7f
KH
291
292/* Statistics available to the user. */
293struct mstats
294 {
295 __malloc_size_t bytes_total; /* Total size of the heap. */
296 __malloc_size_t chunks_used; /* Chunks allocated by the user. */
297 __malloc_size_t bytes_used; /* Byte total of user-allocated chunks. */
298 __malloc_size_t chunks_free; /* Chunks in the free list. */
299 __malloc_size_t bytes_free; /* Byte total of chunks in the free list. */
300 };
301
302/* Pick up the current statistics. */
0a27e8ed 303extern struct mstats mstats PP ((void));
74ad5c7f
KH
304
305/* Call WARNFUN with a warning message when memory usage is high. */
0a27e8ed
RS
306extern void memory_warnings PP ((__ptr_t __start,
307 void (*__warnfun) PP ((const char *))));
74ad5c7f
KH
308
309
310/* Relocating allocator. */
311
312/* Allocate SIZE bytes, and store the address in *HANDLEPTR. */
0a27e8ed 313extern __ptr_t r_alloc PP ((__ptr_t *__handleptr, __malloc_size_t __size));
74ad5c7f
KH
314
315/* Free the storage allocated in HANDLEPTR. */
0a27e8ed 316extern void r_alloc_free PP ((__ptr_t *__handleptr));
74ad5c7f
KH
317
318/* Adjust the block at HANDLEPTR to be SIZE bytes long. */
0a27e8ed 319extern __ptr_t r_re_alloc PP ((__ptr_t *__handleptr, __malloc_size_t __size));
74ad5c7f
KH
320
321
322#ifdef __cplusplus
323}
324#endif
325
326#endif /* malloc.h */
327/* Memory allocator `malloc'.
328 Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
329 Written May 1989 by Mike Haertel.
330
331This library is free software; you can redistribute it and/or
423a1f3c 332modify it under the terms of the GNU General Public License as
74ad5c7f
KH
333published by the Free Software Foundation; either version 2 of the
334License, or (at your option) any later version.
335
336This library is distributed in the hope that it will be useful,
337but WITHOUT ANY WARRANTY; without even the implied warranty of
338MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
423a1f3c 339General Public License for more details.
74ad5c7f 340
423a1f3c
JB
341You should have received a copy of the GNU General Public
342License along with this library; see the file COPYING. If
3ef97fb6
LK
343not, write to the Free Software Foundation, Inc., 51 Franklin Street,
344Fifth Floor, Boston, MA 02110-1301, USA.
74ad5c7f
KH
345
346 The author may be reached (Email) at the address mike@ai.mit.edu,
347 or (US mail) as Mike Haertel c/o Free Software Foundation. */
348
349#ifndef _MALLOC_INTERNAL
350#define _MALLOC_INTERNAL
351#include <malloc.h>
352#endif
353#include <errno.h>
354
355/* How to really get more memory. */
ef6d1039
SM
356#if defined(CYGWIN)
357extern __ptr_t bss_sbrk PP ((ptrdiff_t __size));
358extern int bss_sbrk_did_unexec;
359#endif
0a27e8ed 360__ptr_t (*__morecore) PP ((ptrdiff_t __size)) = __default_morecore;
74ad5c7f
KH
361
362/* Debugging hook for `malloc'. */
0a27e8ed 363__ptr_t (*__malloc_hook) PP ((__malloc_size_t __size));
74ad5c7f
KH
364
365/* Pointer to the base of the first block. */
366char *_heapbase;
367
368/* Block information table. Allocated with align/__free (not malloc/free). */
369malloc_info *_heapinfo;
370
371/* Number of info entries. */
372static __malloc_size_t heapsize;
373
374/* Search index in the info table. */
375__malloc_size_t _heapindex;
376
377/* Limit of valid info table indices. */
378__malloc_size_t _heaplimit;
379
380/* Free lists for each fragment size. */
381struct list _fraghead[BLOCKLOG];
382
383/* Instrumentation. */
384__malloc_size_t _chunks_used;
385__malloc_size_t _bytes_used;
386__malloc_size_t _chunks_free;
387__malloc_size_t _bytes_free;
388
389/* Are you experienced? */
390int __malloc_initialized;
391
392__malloc_size_t __malloc_extra_blocks;
393
0a27e8ed
RS
394void (*__malloc_initialize_hook) PP ((void));
395void (*__after_morecore_hook) PP ((void));
74ad5c7f 396
5dcab13e
GM
397#if defined GC_MALLOC_CHECK && defined GC_PROTECT_MALLOC_STATE
398
399/* Some code for hunting a bug writing into _heapinfo.
400
401 Call this macro with argument PROT non-zero to protect internal
402 malloc state against writing to it, call it with a zero argument to
403 make it readable and writable.
404
405 Note that this only works if BLOCKSIZE == page size, which is
406 the case on the i386. */
407
408#include <sys/types.h>
409#include <sys/mman.h>
410
411static int state_protected_p;
412static __malloc_size_t last_state_size;
413static malloc_info *last_heapinfo;
414
415void
416protect_malloc_state (protect_p)
417 int protect_p;
418{
419 /* If _heapinfo has been relocated, make sure its old location
420 isn't left read-only; it will be reused by malloc. */
421 if (_heapinfo != last_heapinfo
422 && last_heapinfo
423 && state_protected_p)
424 mprotect (last_heapinfo, last_state_size, PROT_READ | PROT_WRITE);
425
426 last_state_size = _heaplimit * sizeof *_heapinfo;
427 last_heapinfo = _heapinfo;
177c0ea7 428
5dcab13e
GM
429 if (protect_p != state_protected_p)
430 {
431 state_protected_p = protect_p;
432 if (mprotect (_heapinfo, last_state_size,
433 protect_p ? PROT_READ : PROT_READ | PROT_WRITE) != 0)
434 abort ();
435 }
436}
437
438#define PROTECT_MALLOC_STATE(PROT) protect_malloc_state(PROT)
439
440#else
441#define PROTECT_MALLOC_STATE(PROT) /* empty */
442#endif
443
74ad5c7f
KH
444
445/* Aligned allocation. */
0a27e8ed 446static __ptr_t align PP ((__malloc_size_t));
74ad5c7f
KH
447static __ptr_t
448align (size)
449 __malloc_size_t size;
450{
451 __ptr_t result;
452 unsigned long int adj;
453
ceeb3d7d
EZ
454 /* align accepts an unsigned argument, but __morecore accepts a
455 signed one. This could lead to trouble if SIZE overflows a
456 signed int type accepted by __morecore. We just punt in that
457 case, since they are requesting a ludicrous amount anyway. */
458 if ((__malloc_ptrdiff_t)size < 0)
459 result = 0;
460 else
461 result = (*__morecore) (size);
74ad5c7f
KH
462 adj = (unsigned long int) ((unsigned long int) ((char *) result -
463 (char *) NULL)) % BLOCKSIZE;
464 if (adj != 0)
465 {
466 __ptr_t new;
467 adj = BLOCKSIZE - adj;
468 new = (*__morecore) (adj);
469 result = (char *) result + adj;
470 }
471
472 if (__after_morecore_hook)
473 (*__after_morecore_hook) ();
474
475 return result;
476}
477
478/* Get SIZE bytes, if we can get them starting at END.
479 Return the address of the space we got.
480 If we cannot get space at END, fail and return 0. */
0a27e8ed 481static __ptr_t get_contiguous_space PP ((__malloc_ptrdiff_t, __ptr_t));
74ad5c7f
KH
482static __ptr_t
483get_contiguous_space (size, position)
484 __malloc_ptrdiff_t size;
485 __ptr_t position;
486{
487 __ptr_t before;
488 __ptr_t after;
489
490 before = (*__morecore) (0);
491 /* If we can tell in advance that the break is at the wrong place,
492 fail now. */
493 if (before != position)
494 return 0;
495
496 /* Allocate SIZE bytes and get the address of them. */
497 after = (*__morecore) (size);
498 if (!after)
499 return 0;
500
501 /* It was not contiguous--reject it. */
502 if (after != position)
503 {
504 (*__morecore) (- size);
505 return 0;
506 }
507
508 return after;
509}
510
511
512/* This is called when `_heapinfo' and `heapsize' have just
513 been set to describe a new info table. Set up the table
514 to describe itself and account for it in the statistics. */
0a27e8ed 515static void register_heapinfo PP ((void));
74ad5c7f
KH
516#ifdef __GNUC__
517__inline__
518#endif
519static void
520register_heapinfo ()
521{
522 __malloc_size_t block, blocks;
523
524 block = BLOCK (_heapinfo);
525 blocks = BLOCKIFY (heapsize * sizeof (malloc_info));
526
527 /* Account for the _heapinfo block itself in the statistics. */
528 _bytes_used += blocks * BLOCKSIZE;
529 ++_chunks_used;
530
531 /* Describe the heapinfo block itself in the heapinfo. */
532 _heapinfo[block].busy.type = 0;
533 _heapinfo[block].busy.info.size = blocks;
534 /* Leave back-pointers for malloc_find_address. */
535 while (--blocks > 0)
536 _heapinfo[block + blocks].busy.info.size = -blocks;
537}
538
539/* Set everything up and remember that we have. */
540int
541__malloc_initialize ()
542{
543 if (__malloc_initialized)
544 return 0;
545
a3ba27da
GM
546#ifdef GC_MCHECK
547 mcheck (NULL);
548#endif
549
74ad5c7f
KH
550 if (__malloc_initialize_hook)
551 (*__malloc_initialize_hook) ();
552
553 heapsize = HEAP / BLOCKSIZE;
554 _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info));
555 if (_heapinfo == NULL)
556 return 0;
557 memset (_heapinfo, 0, heapsize * sizeof (malloc_info));
558 _heapinfo[0].free.size = 0;
559 _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
560 _heapindex = 0;
561 _heapbase = (char *) _heapinfo;
562 _heaplimit = BLOCK (_heapbase + heapsize * sizeof (malloc_info));
563
564 register_heapinfo ();
565
566 __malloc_initialized = 1;
5dcab13e 567 PROTECT_MALLOC_STATE (1);
74ad5c7f
KH
568 return 1;
569}
570
571static int morecore_recursing;
572
573/* Get neatly aligned memory, initializing or
574 growing the heap info table as necessary. */
0a27e8ed 575static __ptr_t morecore PP ((__malloc_size_t));
74ad5c7f
KH
576static __ptr_t
577morecore (size)
578 __malloc_size_t size;
579{
580 __ptr_t result;
581 malloc_info *newinfo, *oldinfo;
582 __malloc_size_t newsize;
583
584 if (morecore_recursing)
585 /* Avoid recursion. The caller will know how to handle a null return. */
586 return NULL;
587
588 result = align (size);
589 if (result == NULL)
590 return NULL;
591
5dcab13e
GM
592 PROTECT_MALLOC_STATE (0);
593
74ad5c7f
KH
594 /* Check if we need to grow the info table. */
595 if ((__malloc_size_t) BLOCK ((char *) result + size) > heapsize)
596 {
597 /* Calculate the new _heapinfo table size. We do not account for the
598 added blocks in the table itself, as we hope to place them in
599 existing free space, which is already covered by part of the
600 existing table. */
601 newsize = heapsize;
602 do
603 newsize *= 2;
604 while ((__malloc_size_t) BLOCK ((char *) result + size) > newsize);
605
606 /* We must not reuse existing core for the new info table when called
607 from realloc in the case of growing a large block, because the
608 block being grown is momentarily marked as free. In this case
609 _heaplimit is zero so we know not to reuse space for internal
610 allocation. */
611 if (_heaplimit != 0)
612 {
613 /* First try to allocate the new info table in core we already
614 have, in the usual way using realloc. If realloc cannot
615 extend it in place or relocate it to existing sufficient core,
616 we will get called again, and the code above will notice the
617 `morecore_recursing' flag and return null. */
618 int save = errno; /* Don't want to clobber errno with ENOMEM. */
619 morecore_recursing = 1;
620 newinfo = (malloc_info *) _realloc_internal
621 (_heapinfo, newsize * sizeof (malloc_info));
622 morecore_recursing = 0;
623 if (newinfo == NULL)
624 errno = save;
625 else
626 {
627 /* We found some space in core, and realloc has put the old
628 table's blocks on the free list. Now zero the new part
629 of the table and install the new table location. */
630 memset (&newinfo[heapsize], 0,
631 (newsize - heapsize) * sizeof (malloc_info));
632 _heapinfo = newinfo;
633 heapsize = newsize;
634 goto got_heap;
635 }
636 }
637
638 /* Allocate new space for the malloc info table. */
639 while (1)
640 {
641 newinfo = (malloc_info *) align (newsize * sizeof (malloc_info));
642
643 /* Did it fail? */
644 if (newinfo == NULL)
645 {
646 (*__morecore) (-size);
647 return NULL;
648 }
649
650 /* Is it big enough to record status for its own space?
651 If so, we win. */
652 if ((__malloc_size_t) BLOCK ((char *) newinfo
653 + newsize * sizeof (malloc_info))
654 < newsize)
655 break;
656
657 /* Must try again. First give back most of what we just got. */
658 (*__morecore) (- newsize * sizeof (malloc_info));
659 newsize *= 2;
660 }
661
662 /* Copy the old table to the beginning of the new,
663 and zero the rest of the new table. */
664 memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info));
665 memset (&newinfo[heapsize], 0,
666 (newsize - heapsize) * sizeof (malloc_info));
667 oldinfo = _heapinfo;
668 _heapinfo = newinfo;
669 heapsize = newsize;
670
671 register_heapinfo ();
672
673 /* Reset _heaplimit so _free_internal never decides
674 it can relocate or resize the info table. */
675 _heaplimit = 0;
676 _free_internal (oldinfo);
5dcab13e 677 PROTECT_MALLOC_STATE (0);
74ad5c7f
KH
678
679 /* The new heap limit includes the new table just allocated. */
680 _heaplimit = BLOCK ((char *) newinfo + heapsize * sizeof (malloc_info));
681 return result;
682 }
683
684 got_heap:
685 _heaplimit = BLOCK ((char *) result + size);
686 return result;
687}
688
689/* Allocate memory from the heap. */
690__ptr_t
691_malloc_internal (size)
692 __malloc_size_t size;
693{
694 __ptr_t result;
695 __malloc_size_t block, blocks, lastblocks, start;
696 register __malloc_size_t i;
697 struct list *next;
698
699 /* ANSI C allows `malloc (0)' to either return NULL, or to return a
700 valid address you can realloc and free (though not dereference).
701
702 It turns out that some extant code (sunrpc, at least Ultrix's version)
703 expects `malloc (0)' to return non-NULL and breaks otherwise.
704 Be compatible. */
705
706#if 0
707 if (size == 0)
708 return NULL;
709#endif
710
5dcab13e
GM
711 PROTECT_MALLOC_STATE (0);
712
74ad5c7f
KH
713 if (size < sizeof (struct list))
714 size = sizeof (struct list);
715
716#ifdef SUNOS_LOCALTIME_BUG
717 if (size < 16)
718 size = 16;
719#endif
720
721 /* Determine the allocation policy based on the request size. */
722 if (size <= BLOCKSIZE / 2)
723 {
724 /* Small allocation to receive a fragment of a block.
725 Determine the logarithm to base two of the fragment size. */
726 register __malloc_size_t log = 1;
727 --size;
728 while ((size /= 2) != 0)
729 ++log;
730
731 /* Look in the fragment lists for a
732 free fragment of the desired size. */
733 next = _fraghead[log].next;
734 if (next != NULL)
735 {
736 /* There are free fragments of this size.
737 Pop a fragment out of the fragment list and return it.
738 Update the block's nfree and first counters. */
739 result = (__ptr_t) next;
740 next->prev->next = next->next;
741 if (next->next != NULL)
742 next->next->prev = next->prev;
743 block = BLOCK (result);
744 if (--_heapinfo[block].busy.info.frag.nfree != 0)
745 _heapinfo[block].busy.info.frag.first = (unsigned long int)
746 ((unsigned long int) ((char *) next->next - (char *) NULL)
747 % BLOCKSIZE) >> log;
748
749 /* Update the statistics. */
750 ++_chunks_used;
751 _bytes_used += 1 << log;
752 --_chunks_free;
753 _bytes_free -= 1 << log;
754 }
755 else
756 {
757 /* No free fragments of the desired size, so get a new block
758 and break it into fragments, returning the first. */
8094989b
GM
759#ifdef GC_MALLOC_CHECK
760 result = _malloc_internal (BLOCKSIZE);
5dcab13e 761 PROTECT_MALLOC_STATE (0);
8094989b 762#else
74ad5c7f 763 result = malloc (BLOCKSIZE);
8094989b 764#endif
74ad5c7f 765 if (result == NULL)
5dcab13e
GM
766 {
767 PROTECT_MALLOC_STATE (1);
768 return NULL;
769 }
74ad5c7f
KH
770
771 /* Link all fragments but the first into the free list. */
772 next = (struct list *) ((char *) result + (1 << log));
773 next->next = NULL;
774 next->prev = &_fraghead[log];
775 _fraghead[log].next = next;
776
777 for (i = 2; i < (__malloc_size_t) (BLOCKSIZE >> log); ++i)
778 {
779 next = (struct list *) ((char *) result + (i << log));
780 next->next = _fraghead[log].next;
781 next->prev = &_fraghead[log];
782 next->prev->next = next;
783 next->next->prev = next;
784 }
785
786 /* Initialize the nfree and first counters for this block. */
787 block = BLOCK (result);
788 _heapinfo[block].busy.type = log;
789 _heapinfo[block].busy.info.frag.nfree = i - 1;
790 _heapinfo[block].busy.info.frag.first = i - 1;
791
792 _chunks_free += (BLOCKSIZE >> log) - 1;
793 _bytes_free += BLOCKSIZE - (1 << log);
794 _bytes_used -= BLOCKSIZE - (1 << log);
795 }
796 }
797 else
798 {
799 /* Large allocation to receive one or more blocks.
800 Search the free list in a circle starting at the last place visited.
801 If we loop completely around without finding a large enough
802 space we will have to get more memory from the system. */
803 blocks = BLOCKIFY (size);
804 start = block = _heapindex;
805 while (_heapinfo[block].free.size < blocks)
806 {
807 block = _heapinfo[block].free.next;
808 if (block == start)
809 {
810 /* Need to get more from the system. Get a little extra. */
811 __malloc_size_t wantblocks = blocks + __malloc_extra_blocks;
812 block = _heapinfo[0].free.prev;
813 lastblocks = _heapinfo[block].free.size;
814 /* Check to see if the new core will be contiguous with the
815 final free block; if so we don't need to get as much. */
816 if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
817 /* We can't do this if we will have to make the heap info
818 table bigger to accomodate the new space. */
819 block + wantblocks <= heapsize &&
820 get_contiguous_space ((wantblocks - lastblocks) * BLOCKSIZE,
821 ADDRESS (block + lastblocks)))
822 {
823 /* We got it contiguously. Which block we are extending
824 (the `final free block' referred to above) might have
825 changed, if it got combined with a freed info table. */
826 block = _heapinfo[0].free.prev;
827 _heapinfo[block].free.size += (wantblocks - lastblocks);
828 _bytes_free += (wantblocks - lastblocks) * BLOCKSIZE;
829 _heaplimit += wantblocks - lastblocks;
830 continue;
831 }
832 result = morecore (wantblocks * BLOCKSIZE);
833 if (result == NULL)
834 return NULL;
835 block = BLOCK (result);
836 /* Put the new block at the end of the free list. */
837 _heapinfo[block].free.size = wantblocks;
838 _heapinfo[block].free.prev = _heapinfo[0].free.prev;
839 _heapinfo[block].free.next = 0;
840 _heapinfo[0].free.prev = block;
841 _heapinfo[_heapinfo[block].free.prev].free.next = block;
842 ++_chunks_free;
843 /* Now loop to use some of that block for this allocation. */
844 }
845 }
846
847 /* At this point we have found a suitable free list entry.
848 Figure out how to remove what we need from the list. */
849 result = ADDRESS (block);
850 if (_heapinfo[block].free.size > blocks)
851 {
852 /* The block we found has a bit left over,
853 so relink the tail end back into the free list. */
854 _heapinfo[block + blocks].free.size
855 = _heapinfo[block].free.size - blocks;
856 _heapinfo[block + blocks].free.next
857 = _heapinfo[block].free.next;
858 _heapinfo[block + blocks].free.prev
859 = _heapinfo[block].free.prev;
860 _heapinfo[_heapinfo[block].free.prev].free.next
861 = _heapinfo[_heapinfo[block].free.next].free.prev
862 = _heapindex = block + blocks;
863 }
864 else
865 {
866 /* The block exactly matches our requirements,
867 so just remove it from the list. */
868 _heapinfo[_heapinfo[block].free.next].free.prev
869 = _heapinfo[block].free.prev;
870 _heapinfo[_heapinfo[block].free.prev].free.next
871 = _heapindex = _heapinfo[block].free.next;
872 --_chunks_free;
873 }
874
875 _heapinfo[block].busy.type = 0;
876 _heapinfo[block].busy.info.size = blocks;
877 ++_chunks_used;
878 _bytes_used += blocks * BLOCKSIZE;
879 _bytes_free -= blocks * BLOCKSIZE;
880
881 /* Mark all the blocks of the object just allocated except for the
882 first with a negative number so you can find the first block by
883 adding that adjustment. */
884 while (--blocks > 0)
885 _heapinfo[block + blocks].busy.info.size = -blocks;
886 }
887
5dcab13e 888 PROTECT_MALLOC_STATE (1);
74ad5c7f
KH
889 return result;
890}
891
892__ptr_t
893malloc (size)
894 __malloc_size_t size;
895{
896 if (!__malloc_initialized && !__malloc_initialize ())
897 return NULL;
898
899 return (__malloc_hook != NULL ? *__malloc_hook : _malloc_internal) (size);
900}
901\f
902#ifndef _LIBC
903
904/* On some ANSI C systems, some libc functions call _malloc, _free
905 and _realloc. Make them use the GNU functions. */
906
907__ptr_t
908_malloc (size)
909 __malloc_size_t size;
910{
911 return malloc (size);
912}
913
914void
915_free (ptr)
916 __ptr_t ptr;
917{
918 free (ptr);
919}
920
921__ptr_t
922_realloc (ptr, size)
923 __ptr_t ptr;
924 __malloc_size_t size;
925{
926 return realloc (ptr, size);
927}
928
929#endif
930/* Free a block of memory allocated by `malloc'.
931 Copyright 1990, 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
932 Written May 1989 by Mike Haertel.
933
934This library is free software; you can redistribute it and/or
423a1f3c 935modify it under the terms of the GNU General Public License as
74ad5c7f
KH
936published by the Free Software Foundation; either version 2 of the
937License, or (at your option) any later version.
938
939This library is distributed in the hope that it will be useful,
940but WITHOUT ANY WARRANTY; without even the implied warranty of
941MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
423a1f3c 942General Public License for more details.
74ad5c7f 943
423a1f3c
JB
944You should have received a copy of the GNU General Public
945License along with this library; see the file COPYING. If
3ef97fb6
LK
946not, write to the Free Software Foundation, Inc., 51 Franklin Street,
947Fifth Floor, Boston, MA 02110-1301, USA.
74ad5c7f
KH
948
949 The author may be reached (Email) at the address mike@ai.mit.edu,
950 or (US mail) as Mike Haertel c/o Free Software Foundation. */
951
952#ifndef _MALLOC_INTERNAL
953#define _MALLOC_INTERNAL
954#include <malloc.h>
955#endif
956
957
958/* Cope with systems lacking `memmove'. */
959#ifndef memmove
960#if (defined (MEMMOVE_MISSING) || \
961 !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG))
962#ifdef emacs
963#undef __malloc_safe_bcopy
964#define __malloc_safe_bcopy safe_bcopy
965#endif
966/* This function is defined in realloc.c. */
0a27e8ed 967extern void __malloc_safe_bcopy PP ((__ptr_t, __ptr_t, __malloc_size_t));
74ad5c7f
KH
968#define memmove(to, from, size) __malloc_safe_bcopy ((from), (to), (size))
969#endif
970#endif
971
972
973/* Debugging hook for free. */
0a27e8ed 974void (*__free_hook) PP ((__ptr_t __ptr));
74ad5c7f
KH
975
976/* List of blocks allocated by memalign. */
977struct alignlist *_aligned_blocks = NULL;
978
979/* Return memory to the heap.
980 Like `free' but don't call a __free_hook if there is one. */
981void
982_free_internal (ptr)
983 __ptr_t ptr;
984{
985 int type;
986 __malloc_size_t block, blocks;
987 register __malloc_size_t i;
988 struct list *prev, *next;
989 __ptr_t curbrk;
990 const __malloc_size_t lesscore_threshold
991 /* Threshold of free space at which we will return some to the system. */
992 = FINAL_FREE_BLOCKS + 2 * __malloc_extra_blocks;
993
994 register struct alignlist *l;
995
996 if (ptr == NULL)
997 return;
998
5dcab13e 999 PROTECT_MALLOC_STATE (0);
177c0ea7 1000
74ad5c7f
KH
1001 for (l = _aligned_blocks; l != NULL; l = l->next)
1002 if (l->aligned == ptr)
1003 {
1004 l->aligned = NULL; /* Mark the slot in the list as free. */
1005 ptr = l->exact;
1006 break;
1007 }
1008
1009 block = BLOCK (ptr);
1010
1011 type = _heapinfo[block].busy.type;
1012 switch (type)
1013 {
1014 case 0:
1015 /* Get as many statistics as early as we can. */
1016 --_chunks_used;
1017 _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
1018 _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
1019
1020 /* Find the free cluster previous to this one in the free list.
1021 Start searching at the last block referenced; this may benefit
1022 programs with locality of allocation. */
1023 i = _heapindex;
1024 if (i > block)
1025 while (i > block)
1026 i = _heapinfo[i].free.prev;
1027 else
1028 {
1029 do
1030 i = _heapinfo[i].free.next;
1031 while (i > 0 && i < block);
1032 i = _heapinfo[i].free.prev;
1033 }
1034
1035 /* Determine how to link this block into the free list. */
1036 if (block == i + _heapinfo[i].free.size)
1037 {
1038 /* Coalesce this block with its predecessor. */
1039 _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
1040 block = i;
1041 }
1042 else
1043 {
1044 /* Really link this block back into the free list. */
1045 _heapinfo[block].free.size = _heapinfo[block].busy.info.size;
1046 _heapinfo[block].free.next = _heapinfo[i].free.next;
1047 _heapinfo[block].free.prev = i;
1048 _heapinfo[i].free.next = block;
1049 _heapinfo[_heapinfo[block].free.next].free.prev = block;
1050 ++_chunks_free;
1051 }
1052
1053 /* Now that the block is linked in, see if we can coalesce it
1054 with its successor (by deleting its successor from the list
1055 and adding in its size). */
1056 if (block + _heapinfo[block].free.size == _heapinfo[block].free.next)
1057 {
1058 _heapinfo[block].free.size
1059 += _heapinfo[_heapinfo[block].free.next].free.size;
1060 _heapinfo[block].free.next
1061 = _heapinfo[_heapinfo[block].free.next].free.next;
1062 _heapinfo[_heapinfo[block].free.next].free.prev = block;
1063 --_chunks_free;
1064 }
1065
1066 /* How many trailing free blocks are there now? */
1067 blocks = _heapinfo[block].free.size;
1068
1069 /* Where is the current end of accessible core? */
1070 curbrk = (*__morecore) (0);
1071
1072 if (_heaplimit != 0 && curbrk == ADDRESS (_heaplimit))
1073 {
1074 /* The end of the malloc heap is at the end of accessible core.
1075 It's possible that moving _heapinfo will allow us to
1076 return some space to the system. */
1077
1078 __malloc_size_t info_block = BLOCK (_heapinfo);
1079 __malloc_size_t info_blocks = _heapinfo[info_block].busy.info.size;
1080 __malloc_size_t prev_block = _heapinfo[block].free.prev;
1081 __malloc_size_t prev_blocks = _heapinfo[prev_block].free.size;
1082 __malloc_size_t next_block = _heapinfo[block].free.next;
1083 __malloc_size_t next_blocks = _heapinfo[next_block].free.size;
1084
1085 if (/* Win if this block being freed is last in core, the info table
1086 is just before it, the previous free block is just before the
1087 info table, and the two free blocks together form a useful
1088 amount to return to the system. */
1089 (block + blocks == _heaplimit &&
1090 info_block + info_blocks == block &&
1091 prev_block != 0 && prev_block + prev_blocks == info_block &&
1092 blocks + prev_blocks >= lesscore_threshold) ||
1093 /* Nope, not the case. We can also win if this block being
1094 freed is just before the info table, and the table extends
1095 to the end of core or is followed only by a free block,
1096 and the total free space is worth returning to the system. */
1097 (block + blocks == info_block &&
1098 ((info_block + info_blocks == _heaplimit &&
1099 blocks >= lesscore_threshold) ||
1100 (info_block + info_blocks == next_block &&
1101 next_block + next_blocks == _heaplimit &&
1102 blocks + next_blocks >= lesscore_threshold)))
1103 )
1104 {
1105 malloc_info *newinfo;
1106 __malloc_size_t oldlimit = _heaplimit;
1107
1108 /* Free the old info table, clearing _heaplimit to avoid
1109 recursion into this code. We don't want to return the
1110 table's blocks to the system before we have copied them to
1111 the new location. */
1112 _heaplimit = 0;
1113 _free_internal (_heapinfo);
1114 _heaplimit = oldlimit;
1115
1116 /* Tell malloc to search from the beginning of the heap for
1117 free blocks, so it doesn't reuse the ones just freed. */
1118 _heapindex = 0;
1119
1120 /* Allocate new space for the info table and move its data. */
1121 newinfo = (malloc_info *) _malloc_internal (info_blocks
1122 * BLOCKSIZE);
5dcab13e 1123 PROTECT_MALLOC_STATE (0);
74ad5c7f
KH
1124 memmove (newinfo, _heapinfo, info_blocks * BLOCKSIZE);
1125 _heapinfo = newinfo;
1126
1127 /* We should now have coalesced the free block with the
1128 blocks freed from the old info table. Examine the entire
1129 trailing free block to decide below whether to return some
1130 to the system. */
1131 block = _heapinfo[0].free.prev;
1132 blocks = _heapinfo[block].free.size;
1133 }
1134
1135 /* Now see if we can return stuff to the system. */
1136 if (block + blocks == _heaplimit && blocks >= lesscore_threshold)
1137 {
1138 register __malloc_size_t bytes = blocks * BLOCKSIZE;
1139 _heaplimit -= blocks;
1140 (*__morecore) (-bytes);
1141 _heapinfo[_heapinfo[block].free.prev].free.next
1142 = _heapinfo[block].free.next;
1143 _heapinfo[_heapinfo[block].free.next].free.prev
1144 = _heapinfo[block].free.prev;
1145 block = _heapinfo[block].free.prev;
1146 --_chunks_free;
1147 _bytes_free -= bytes;
1148 }
1149 }
1150
1151 /* Set the next search to begin at this block. */
1152 _heapindex = block;
1153 break;
1154
1155 default:
1156 /* Do some of the statistics. */
1157 --_chunks_used;
1158 _bytes_used -= 1 << type;
1159 ++_chunks_free;
1160 _bytes_free += 1 << type;
1161
1162 /* Get the address of the first free fragment in this block. */
1163 prev = (struct list *) ((char *) ADDRESS (block) +
1164 (_heapinfo[block].busy.info.frag.first << type));
1165
1166 if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)
1167 {
1168 /* If all fragments of this block are free, remove them
1169 from the fragment list and free the whole block. */
1170 next = prev;
1171 for (i = 1; i < (__malloc_size_t) (BLOCKSIZE >> type); ++i)
1172 next = next->next;
1173 prev->prev->next = next;
1174 if (next != NULL)
1175 next->prev = prev->prev;
1176 _heapinfo[block].busy.type = 0;
1177 _heapinfo[block].busy.info.size = 1;
1178
1179 /* Keep the statistics accurate. */
1180 ++_chunks_used;
1181 _bytes_used += BLOCKSIZE;
1182 _chunks_free -= BLOCKSIZE >> type;
1183 _bytes_free -= BLOCKSIZE;
1184
8094989b
GM
1185#ifdef GC_MALLOC_CHECK
1186 _free_internal (ADDRESS (block));
1187#else
74ad5c7f 1188 free (ADDRESS (block));
8094989b 1189#endif
74ad5c7f
KH
1190 }
1191 else if (_heapinfo[block].busy.info.frag.nfree != 0)
1192 {
1193 /* If some fragments of this block are free, link this
1194 fragment into the fragment list after the first free
1195 fragment of this block. */
1196 next = (struct list *) ptr;
1197 next->next = prev->next;
1198 next->prev = prev;
1199 prev->next = next;
1200 if (next->next != NULL)
1201 next->next->prev = next;
1202 ++_heapinfo[block].busy.info.frag.nfree;
1203 }
1204 else
1205 {
1206 /* No fragments of this block are free, so link this
1207 fragment into the fragment list and announce that
1208 it is the first free fragment of this block. */
1209 prev = (struct list *) ptr;
1210 _heapinfo[block].busy.info.frag.nfree = 1;
1211 _heapinfo[block].busy.info.frag.first = (unsigned long int)
1212 ((unsigned long int) ((char *) ptr - (char *) NULL)
1213 % BLOCKSIZE >> type);
1214 prev->next = _fraghead[type].next;
1215 prev->prev = &_fraghead[type];
1216 prev->prev->next = prev;
1217 if (prev->next != NULL)
1218 prev->next->prev = prev;
1219 }
1220 break;
1221 }
177c0ea7 1222
5dcab13e 1223 PROTECT_MALLOC_STATE (1);
74ad5c7f
KH
1224}
1225
1226/* Return memory to the heap. */
ca9c0567
PE
1227
1228FREE_RETURN_TYPE
74ad5c7f
KH
1229free (ptr)
1230 __ptr_t ptr;
1231{
1232 if (__free_hook != NULL)
1233 (*__free_hook) (ptr);
1234 else
1235 _free_internal (ptr);
1236}
1237
1238/* Define the `cfree' alias for `free'. */
1239#ifdef weak_alias
1240weak_alias (free, cfree)
1241#else
1242void
1243cfree (ptr)
1244 __ptr_t ptr;
1245{
1246 free (ptr);
1247}
1248#endif
1249/* Change the size of a block allocated by `malloc'.
1250 Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
1251 Written May 1989 by Mike Haertel.
1252
1253This library is free software; you can redistribute it and/or
423a1f3c 1254modify it under the terms of the GNU General Public License as
74ad5c7f
KH
1255published by the Free Software Foundation; either version 2 of the
1256License, or (at your option) any later version.
1257
1258This library is distributed in the hope that it will be useful,
1259but WITHOUT ANY WARRANTY; without even the implied warranty of
1260MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
423a1f3c 1261General Public License for more details.
74ad5c7f 1262
423a1f3c
JB
1263You should have received a copy of the GNU General Public
1264License along with this library; see the file COPYING. If
3ef97fb6
LK
1265not, write to the Free Software Foundation, Inc., 51 Franklin Street,
1266Fifth Floor, Boston, MA 02110-1301, USA.
74ad5c7f
KH
1267
1268 The author may be reached (Email) at the address mike@ai.mit.edu,
1269 or (US mail) as Mike Haertel c/o Free Software Foundation. */
1270
1271#ifndef _MALLOC_INTERNAL
1272#define _MALLOC_INTERNAL
1273#include <malloc.h>
1274#endif
1275
1276
1277
1278/* Cope with systems lacking `memmove'. */
1279#if (defined (MEMMOVE_MISSING) || \
1280 !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG))
1281
1282#ifdef emacs
1283#undef __malloc_safe_bcopy
1284#define __malloc_safe_bcopy safe_bcopy
1285#else
1286
1287/* Snarfed directly from Emacs src/dispnew.c:
1288 XXX Should use system bcopy if it handles overlap. */
1289
1290/* Like bcopy except never gets confused by overlap. */
1291
1292void
1293__malloc_safe_bcopy (afrom, ato, size)
1294 __ptr_t afrom;
1295 __ptr_t ato;
1296 __malloc_size_t size;
1297{
1298 char *from = afrom, *to = ato;
1299
1300 if (size <= 0 || from == to)
1301 return;
1302
1303 /* If the source and destination don't overlap, then bcopy can
1304 handle it. If they do overlap, but the destination is lower in
1305 memory than the source, we'll assume bcopy can handle that. */
1306 if (to < from || from + size <= to)
1307 bcopy (from, to, size);
1308
1309 /* Otherwise, we'll copy from the end. */
1310 else
1311 {
1312 register char *endf = from + size;
1313 register char *endt = to + size;
1314
1315 /* If TO - FROM is large, then we should break the copy into
1316 nonoverlapping chunks of TO - FROM bytes each. However, if
1317 TO - FROM is small, then the bcopy function call overhead
1318 makes this not worth it. The crossover point could be about
1319 anywhere. Since I don't think the obvious copy loop is too
1320 bad, I'm trying to err in its favor. */
1321 if (to - from < 64)
1322 {
1323 do
1324 *--endt = *--endf;
1325 while (endf != from);
1326 }
1327 else
1328 {
1329 for (;;)
1330 {
1331 endt -= (to - from);
1332 endf -= (to - from);
1333
1334 if (endt < to)
1335 break;
1336
1337 bcopy (endf, endt, to - from);
1338 }
1339
1340 /* If SIZE wasn't a multiple of TO - FROM, there will be a
1341 little left over. The amount left over is
1342 (endt + (to - from)) - to, which is endt - from. */
1343 bcopy (from, to, endt - from);
1344 }
1345 }
1346}
1347#endif /* emacs */
1348
1349#ifndef memmove
0a27e8ed 1350extern void __malloc_safe_bcopy PP ((__ptr_t, __ptr_t, __malloc_size_t));
74ad5c7f
KH
1351#define memmove(to, from, size) __malloc_safe_bcopy ((from), (to), (size))
1352#endif
1353
1354#endif
1355
1356
1357#define min(A, B) ((A) < (B) ? (A) : (B))
1358
1359/* Debugging hook for realloc. */
0a27e8ed 1360__ptr_t (*__realloc_hook) PP ((__ptr_t __ptr, __malloc_size_t __size));
74ad5c7f
KH
1361
1362/* Resize the given region to the new size, returning a pointer
1363 to the (possibly moved) region. This is optimized for speed;
1364 some benchmarks seem to indicate that greater compactness is
1365 achieved by unconditionally allocating and copying to a
1366 new region. This module has incestuous knowledge of the
1367 internals of both free and malloc. */
1368__ptr_t
1369_realloc_internal (ptr, size)
1370 __ptr_t ptr;
1371 __malloc_size_t size;
1372{
1373 __ptr_t result;
1374 int type;
1375 __malloc_size_t block, blocks, oldlimit;
1376
1377 if (size == 0)
1378 {
1379 _free_internal (ptr);
1380 return _malloc_internal (0);
1381 }
1382 else if (ptr == NULL)
1383 return _malloc_internal (size);
1384
1385 block = BLOCK (ptr);
1386
5dcab13e 1387 PROTECT_MALLOC_STATE (0);
177c0ea7 1388
74ad5c7f
KH
1389 type = _heapinfo[block].busy.type;
1390 switch (type)
1391 {
1392 case 0:
1393 /* Maybe reallocate a large block to a small fragment. */
1394 if (size <= BLOCKSIZE / 2)
1395 {
1396 result = _malloc_internal (size);
1397 if (result != NULL)
1398 {
1399 memcpy (result, ptr, size);
1400 _free_internal (ptr);
1401 return result;
1402 }
1403 }
1404
1405 /* The new size is a large allocation as well;
1406 see if we can hold it in place. */
1407 blocks = BLOCKIFY (size);
1408 if (blocks < _heapinfo[block].busy.info.size)
1409 {
1410 /* The new size is smaller; return
1411 excess memory to the free list. */
1412 _heapinfo[block + blocks].busy.type = 0;
1413 _heapinfo[block + blocks].busy.info.size
1414 = _heapinfo[block].busy.info.size - blocks;
1415 _heapinfo[block].busy.info.size = blocks;
1416 /* We have just created a new chunk by splitting a chunk in two.
1417 Now we will free this chunk; increment the statistics counter
1418 so it doesn't become wrong when _free_internal decrements it. */
1419 ++_chunks_used;
1420 _free_internal (ADDRESS (block + blocks));
1421 result = ptr;
1422 }
1423 else if (blocks == _heapinfo[block].busy.info.size)
1424 /* No size change necessary. */
1425 result = ptr;
1426 else
1427 {
1428 /* Won't fit, so allocate a new region that will.
1429 Free the old region first in case there is sufficient
1430 adjacent free space to grow without moving. */
1431 blocks = _heapinfo[block].busy.info.size;
1432 /* Prevent free from actually returning memory to the system. */
1433 oldlimit = _heaplimit;
1434 _heaplimit = 0;
1435 _free_internal (ptr);
1436 result = _malloc_internal (size);
5dcab13e 1437 PROTECT_MALLOC_STATE (0);
74ad5c7f
KH
1438 if (_heaplimit == 0)
1439 _heaplimit = oldlimit;
1440 if (result == NULL)
1441 {
1442 /* Now we're really in trouble. We have to unfree
1443 the thing we just freed. Unfortunately it might
1444 have been coalesced with its neighbors. */
1445 if (_heapindex == block)
1446 (void) _malloc_internal (blocks * BLOCKSIZE);
1447 else
1448 {
1449 __ptr_t previous
1450 = _malloc_internal ((block - _heapindex) * BLOCKSIZE);
1451 (void) _malloc_internal (blocks * BLOCKSIZE);
1452 _free_internal (previous);
1453 }
1454 return NULL;
1455 }
1456 if (ptr != result)
1457 memmove (result, ptr, blocks * BLOCKSIZE);
1458 }
1459 break;
1460
1461 default:
1462 /* Old size is a fragment; type is logarithm
1463 to base two of the fragment size. */
1464 if (size > (__malloc_size_t) (1 << (type - 1)) &&
1465 size <= (__malloc_size_t) (1 << type))
1466 /* The new size is the same kind of fragment. */
1467 result = ptr;
1468 else
1469 {
1470 /* The new size is different; allocate a new space,
1471 and copy the lesser of the new size and the old. */
1472 result = _malloc_internal (size);
1473 if (result == NULL)
1474 return NULL;
1475 memcpy (result, ptr, min (size, (__malloc_size_t) 1 << type));
1476 _free_internal (ptr);
1477 }
1478 break;
1479 }
1480
5dcab13e 1481 PROTECT_MALLOC_STATE (1);
74ad5c7f
KH
1482 return result;
1483}
1484
1485__ptr_t
1486realloc (ptr, size)
1487 __ptr_t ptr;
1488 __malloc_size_t size;
1489{
1490 if (!__malloc_initialized && !__malloc_initialize ())
1491 return NULL;
1492
1493 return (__realloc_hook != NULL ? *__realloc_hook : _realloc_internal)
1494 (ptr, size);
1495}
1496/* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.
1497
1498This library is free software; you can redistribute it and/or
423a1f3c 1499modify it under the terms of the GNU General Public License as
74ad5c7f
KH
1500published by the Free Software Foundation; either version 2 of the
1501License, or (at your option) any later version.
1502
1503This library is distributed in the hope that it will be useful,
1504but WITHOUT ANY WARRANTY; without even the implied warranty of
1505MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
423a1f3c 1506General Public License for more details.
74ad5c7f 1507
423a1f3c
JB
1508You should have received a copy of the GNU General Public
1509License along with this library; see the file COPYING. If
3ef97fb6
LK
1510not, write to the Free Software Foundation, Inc., 51 Franklin Street,
1511Fifth Floor, Boston, MA 02110-1301, USA.
74ad5c7f
KH
1512
1513 The author may be reached (Email) at the address mike@ai.mit.edu,
1514 or (US mail) as Mike Haertel c/o Free Software Foundation. */
1515
1516#ifndef _MALLOC_INTERNAL
1517#define _MALLOC_INTERNAL
1518#include <malloc.h>
1519#endif
1520
1521/* Allocate an array of NMEMB elements each SIZE bytes long.
1522 The entire array is initialized to zeros. */
1523__ptr_t
1524calloc (nmemb, size)
1525 register __malloc_size_t nmemb;
1526 register __malloc_size_t size;
1527{
1528 register __ptr_t result = malloc (nmemb * size);
1529
1530 if (result != NULL)
1531 (void) memset (result, 0, nmemb * size);
1532
1533 return result;
1534}
1535/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
1536This file is part of the GNU C Library.
1537
1538The GNU C Library is free software; you can redistribute it and/or modify
1539it under the terms of the GNU General Public License as published by
1540the Free Software Foundation; either version 2, or (at your option)
1541any later version.
1542
1543The GNU C Library is distributed in the hope that it will be useful,
1544but WITHOUT ANY WARRANTY; without even the implied warranty of
1545MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1546GNU General Public License for more details.
1547
1548You should have received a copy of the GNU General Public License
1549along with the GNU C Library; see the file COPYING. If not, write to
3ef97fb6
LK
1550the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
1551MA 02110-1301, USA. */
74ad5c7f
KH
1552
1553#ifndef _MALLOC_INTERNAL
1554#define _MALLOC_INTERNAL
1555#include <malloc.h>
1556#endif
1557
1558#ifndef __GNU_LIBRARY__
1559#define __sbrk sbrk
1560#endif
1561
1562#ifdef __GNU_LIBRARY__
1563/* It is best not to declare this and cast its result on foreign operating
1564 systems with potentially hostile include files. */
1565
1566#include <stddef.h>
0a27e8ed 1567extern __ptr_t __sbrk PP ((ptrdiff_t increment));
74ad5c7f
KH
1568#endif
1569
1570#ifndef NULL
1571#define NULL 0
1572#endif
1573
1574/* Allocate INCREMENT more bytes of data space,
1575 and return the start of data space, or NULL on errors.
1576 If INCREMENT is negative, shrink data space. */
1577__ptr_t
1578__default_morecore (increment)
1579 __malloc_ptrdiff_t increment;
1580{
ef6d1039
SM
1581 __ptr_t result;
1582#if defined(CYGWIN)
1583 if (!bss_sbrk_did_unexec)
1584 {
1585 return bss_sbrk (increment);
1586 }
1587#endif
1588 result = (__ptr_t) __sbrk (increment);
74ad5c7f
KH
1589 if (result == (__ptr_t) -1)
1590 return NULL;
1591 return result;
1592}
1593/* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
1594
1595This library is free software; you can redistribute it and/or
423a1f3c 1596modify it under the terms of the GNU General Public License as
74ad5c7f
KH
1597published by the Free Software Foundation; either version 2 of the
1598License, or (at your option) any later version.
1599
1600This library is distributed in the hope that it will be useful,
1601but WITHOUT ANY WARRANTY; without even the implied warranty of
1602MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
423a1f3c 1603General Public License for more details.
74ad5c7f 1604
423a1f3c
JB
1605You should have received a copy of the GNU General Public
1606License along with this library; see the file COPYING. If
3ef97fb6
LK
1607not, write to the Free Software Foundation, Inc., 51 Franklin Street,
1608Fifth Floor, Boston, MA 02110-1301, USA. */
74ad5c7f
KH
1609
1610#ifndef _MALLOC_INTERNAL
1611#define _MALLOC_INTERNAL
1612#include <malloc.h>
1613#endif
1614
1615#if __DJGPP__ - 0 == 1
1616
1617/* There is some problem with memalign in DJGPP v1 and we are supposed
1618 to omit it. Noone told me why, they just told me to do it. */
1619
1620#else
1621
eec2d1de
EZ
1622__ptr_t (*__memalign_hook) PP ((__malloc_size_t __size,
1623 __malloc_size_t __alignment));
74ad5c7f
KH
1624
1625__ptr_t
1626memalign (alignment, size)
1627 __malloc_size_t alignment;
1628 __malloc_size_t size;
1629{
1630 __ptr_t result;
1631 unsigned long int adj, lastadj;
1632
1633 if (__memalign_hook)
1634 return (*__memalign_hook) (alignment, size);
1635
1636 /* Allocate a block with enough extra space to pad the block with up to
1637 (ALIGNMENT - 1) bytes if necessary. */
1638 result = malloc (size + alignment - 1);
1639 if (result == NULL)
1640 return NULL;
1641
1642 /* Figure out how much we will need to pad this particular block
1643 to achieve the required alignment. */
1644 adj = (unsigned long int) ((char *) result - (char *) NULL) % alignment;
1645
1646 do
1647 {
1648 /* Reallocate the block with only as much excess as it needs. */
1649 free (result);
1650 result = malloc (adj + size);
1651 if (result == NULL) /* Impossible unless interrupted. */
1652 return NULL;
1653
1654 lastadj = adj;
1655 adj = (unsigned long int) ((char *) result - (char *) NULL) % alignment;
1656 /* It's conceivable we might have been so unlucky as to get a
1657 different block with weaker alignment. If so, this block is too
1658 short to contain SIZE after alignment correction. So we must
1659 try again and get another block, slightly larger. */
1660 } while (adj > lastadj);
1661
1662 if (adj != 0)
1663 {
1664 /* Record this block in the list of aligned blocks, so that `free'
1665 can identify the pointer it is passed, which will be in the middle
1666 of an allocated block. */
1667
1668 struct alignlist *l;
1669 for (l = _aligned_blocks; l != NULL; l = l->next)
1670 if (l->aligned == NULL)
1671 /* This slot is free. Use it. */
1672 break;
1673 if (l == NULL)
1674 {
1675 l = (struct alignlist *) malloc (sizeof (struct alignlist));
1676 if (l == NULL)
1677 {
1678 free (result);
1679 return NULL;
1680 }
1681 l->next = _aligned_blocks;
1682 _aligned_blocks = l;
1683 }
1684 l->exact = result;
1685 result = l->aligned = (char *) result + alignment - adj;
1686 }
1687
1688 return result;
1689}
1690
1691#endif /* Not DJGPP v1 */
1692/* Allocate memory on a page boundary.
1693 Copyright (C) 1991, 92, 93, 94, 96 Free Software Foundation, Inc.
1694
1695This library is free software; you can redistribute it and/or
423a1f3c 1696modify it under the terms of the GNU General Public License as
74ad5c7f
KH
1697published by the Free Software Foundation; either version 2 of the
1698License, or (at your option) any later version.
1699
1700This library is distributed in the hope that it will be useful,
1701but WITHOUT ANY WARRANTY; without even the implied warranty of
1702MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
423a1f3c 1703General Public License for more details.
74ad5c7f 1704
423a1f3c
JB
1705You should have received a copy of the GNU General Public
1706License along with this library; see the file COPYING. If
3ef97fb6
LK
1707not, write to the Free Software Foundation, Inc., 51 Franklin Street,
1708Fifth Floor, Boston, MA 02110-1301, USA.
74ad5c7f
KH
1709
1710 The author may be reached (Email) at the address mike@ai.mit.edu,
1711 or (US mail) as Mike Haertel c/o Free Software Foundation. */
1712
1713#if defined (_MALLOC_INTERNAL) && defined (GMALLOC_INHIBIT_VALLOC)
1714
1715/* Emacs defines GMALLOC_INHIBIT_VALLOC to avoid this definition
1716 on MSDOS, where it conflicts with a system header file. */
1717
1718#define ELIDE_VALLOC
1719
1720#endif
1721
1722#ifndef ELIDE_VALLOC
1723
1724#if defined (__GNU_LIBRARY__) || defined (_LIBC)
1725#include <stddef.h>
1726#include <sys/cdefs.h>
47582ab3
KH
1727#if defined (__GLIBC__) && __GLIBC__ >= 2
1728/* __getpagesize is already declared in <unistd.h> with return type int */
1729#else
0a27e8ed 1730extern size_t __getpagesize PP ((void));
47582ab3 1731#endif
74ad5c7f
KH
1732#else
1733#include "getpagesize.h"
1734#define __getpagesize() getpagesize()
1735#endif
1736
1737#ifndef _MALLOC_INTERNAL
1738#define _MALLOC_INTERNAL
1739#include <malloc.h>
1740#endif
1741
1742static __malloc_size_t pagesize;
1743
1744__ptr_t
1745valloc (size)
1746 __malloc_size_t size;
1747{
1748 if (pagesize == 0)
1749 pagesize = __getpagesize ();
1750
1751 return memalign (pagesize, size);
1752}
1753
1754#endif /* Not ELIDE_VALLOC. */
a3ba27da
GM
1755
1756#ifdef GC_MCHECK
1757
1758/* Standard debugging hooks for `malloc'.
1759 Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
1760 Written May 1989 by Mike Haertel.
1761
1762This library is free software; you can redistribute it and/or
423a1f3c 1763modify it under the terms of the GNU General Public License as
a3ba27da
GM
1764published by the Free Software Foundation; either version 2 of the
1765License, or (at your option) any later version.
1766
1767This library is distributed in the hope that it will be useful,
1768but WITHOUT ANY WARRANTY; without even the implied warranty of
1769MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
423a1f3c 1770General Public License for more details.
a3ba27da 1771
423a1f3c
JB
1772You should have received a copy of the GNU General Public
1773License along with this library; see the file COPYING. If
3ef97fb6
LK
1774not, write to the Free Software Foundation, Inc., 51 Franklin Street,
1775Fifth Floor, Boston, MA 02110-1301, USA.
a3ba27da
GM
1776
1777 The author may be reached (Email) at the address mike@ai.mit.edu,
1778 or (US mail) as Mike Haertel c/o Free Software Foundation. */
1779
1780#ifdef emacs
1781#include <stdio.h>
1782#else
1783#ifndef _MALLOC_INTERNAL
1784#define _MALLOC_INTERNAL
1785#include <malloc.h>
1786#include <stdio.h>
1787#endif
1788#endif
1789
1790/* Old hook values. */
1791static void (*old_free_hook) __P ((__ptr_t ptr));
1792static __ptr_t (*old_malloc_hook) __P ((__malloc_size_t size));
1793static __ptr_t (*old_realloc_hook) __P ((__ptr_t ptr, __malloc_size_t size));
1794
1795/* Function to call when something awful happens. */
1796static void (*abortfunc) __P ((enum mcheck_status));
1797
1798/* Arbitrary magical numbers. */
1799#define MAGICWORD 0xfedabeeb
1800#define MAGICFREE 0xd8675309
1801#define MAGICBYTE ((char) 0xd7)
1802#define MALLOCFLOOD ((char) 0x93)
1803#define FREEFLOOD ((char) 0x95)
1804
1805struct hdr
1806 {
1807 __malloc_size_t size; /* Exact size requested by user. */
1808 unsigned long int magic; /* Magic number to check header integrity. */
1809 };
1810
1811#if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG)
1812#define flood memset
1813#else
1814static void flood __P ((__ptr_t, int, __malloc_size_t));
1815static void
1816flood (ptr, val, size)
1817 __ptr_t ptr;
1818 int val;
1819 __malloc_size_t size;
1820{
1821 char *cp = ptr;
1822 while (size--)
1823 *cp++ = val;
1824}
1825#endif
1826
1827static enum mcheck_status checkhdr __P ((const struct hdr *));
1828static enum mcheck_status
1829checkhdr (hdr)
1830 const struct hdr *hdr;
1831{
1832 enum mcheck_status status;
1833 switch (hdr->magic)
1834 {
1835 default:
1836 status = MCHECK_HEAD;
1837 break;
1838 case MAGICFREE:
1839 status = MCHECK_FREE;
1840 break;
1841 case MAGICWORD:
1842 if (((char *) &hdr[1])[hdr->size] != MAGICBYTE)
1843 status = MCHECK_TAIL;
1844 else
1845 status = MCHECK_OK;
1846 break;
1847 }
1848 if (status != MCHECK_OK)
1849 (*abortfunc) (status);
1850 return status;
1851}
1852
1853static void freehook __P ((__ptr_t));
1854static void
1855freehook (ptr)
1856 __ptr_t ptr;
1857{
1858 struct hdr *hdr;
177c0ea7 1859
a3ba27da
GM
1860 if (ptr)
1861 {
1862 hdr = ((struct hdr *) ptr) - 1;
1863 checkhdr (hdr);
1864 hdr->magic = MAGICFREE;
1865 flood (ptr, FREEFLOOD, hdr->size);
1866 }
1867 else
1868 hdr = NULL;
177c0ea7 1869
a3ba27da
GM
1870 __free_hook = old_free_hook;
1871 free (hdr);
1872 __free_hook = freehook;
1873}
1874
1875static __ptr_t mallochook __P ((__malloc_size_t));
1876static __ptr_t
1877mallochook (size)
1878 __malloc_size_t size;
1879{
1880 struct hdr *hdr;
1881
1882 __malloc_hook = old_malloc_hook;
1883 hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1);
1884 __malloc_hook = mallochook;
1885 if (hdr == NULL)
1886 return NULL;
1887
1888 hdr->size = size;
1889 hdr->magic = MAGICWORD;
1890 ((char *) &hdr[1])[size] = MAGICBYTE;
1891 flood ((__ptr_t) (hdr + 1), MALLOCFLOOD, size);
1892 return (__ptr_t) (hdr + 1);
1893}
1894
1895static __ptr_t reallochook __P ((__ptr_t, __malloc_size_t));
1896static __ptr_t
1897reallochook (ptr, size)
1898 __ptr_t ptr;
1899 __malloc_size_t size;
1900{
1901 struct hdr *hdr = NULL;
1902 __malloc_size_t osize = 0;
177c0ea7 1903
a3ba27da
GM
1904 if (ptr)
1905 {
1906 hdr = ((struct hdr *) ptr) - 1;
1907 osize = hdr->size;
1908
1909 checkhdr (hdr);
1910 if (size < osize)
1911 flood ((char *) ptr + size, FREEFLOOD, osize - size);
1912 }
177c0ea7 1913
a3ba27da
GM
1914 __free_hook = old_free_hook;
1915 __malloc_hook = old_malloc_hook;
1916 __realloc_hook = old_realloc_hook;
1917 hdr = (struct hdr *) realloc ((__ptr_t) hdr, sizeof (struct hdr) + size + 1);
1918 __free_hook = freehook;
1919 __malloc_hook = mallochook;
1920 __realloc_hook = reallochook;
1921 if (hdr == NULL)
1922 return NULL;
1923
1924 hdr->size = size;
1925 hdr->magic = MAGICWORD;
1926 ((char *) &hdr[1])[size] = MAGICBYTE;
1927 if (size > osize)
1928 flood ((char *) (hdr + 1) + osize, MALLOCFLOOD, size - osize);
1929 return (__ptr_t) (hdr + 1);
1930}
1931
1932static void
1933mabort (status)
1934 enum mcheck_status status;
1935{
1936 const char *msg;
1937 switch (status)
1938 {
1939 case MCHECK_OK:
1940 msg = "memory is consistent, library is buggy";
1941 break;
1942 case MCHECK_HEAD:
1943 msg = "memory clobbered before allocated block";
1944 break;
1945 case MCHECK_TAIL:
1946 msg = "memory clobbered past end of allocated block";
1947 break;
1948 case MCHECK_FREE:
1949 msg = "block freed twice";
1950 break;
1951 default:
1952 msg = "bogus mcheck_status, library is buggy";
1953 break;
1954 }
1955#ifdef __GNU_LIBRARY__
1956 __libc_fatal (msg);
1957#else
1958 fprintf (stderr, "mcheck: %s\n", msg);
1959 fflush (stderr);
1960 abort ();
1961#endif
1962}
1963
1964static int mcheck_used = 0;
1965
1966int
1967mcheck (func)
1968 void (*func) __P ((enum mcheck_status));
1969{
1970 abortfunc = (func != NULL) ? func : &mabort;
1971
1972 /* These hooks may not be safely inserted if malloc is already in use. */
1973 if (!__malloc_initialized && !mcheck_used)
1974 {
1975 old_free_hook = __free_hook;
1976 __free_hook = freehook;
1977 old_malloc_hook = __malloc_hook;
1978 __malloc_hook = mallochook;
1979 old_realloc_hook = __realloc_hook;
1980 __realloc_hook = reallochook;
1981 mcheck_used = 1;
1982 }
1983
1984 return mcheck_used ? 0 : -1;
1985}
1986
1987enum mcheck_status
1988mprobe (__ptr_t ptr)
1989{
1990 return mcheck_used ? checkhdr (ptr) : MCHECK_DISABLED;
1991}
1992
1993#endif /* GC_MCHECK */
ab5796a9
MB
1994
1995/* arch-tag: 93dce5c0-f49a-41b5-86b1-f91c4169c02e
1996 (do not change this comment) */