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