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