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