*** empty log message ***
[bpt/emacs.git] / src / vmsgmalloc.c
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, 1999 Free Software Foundation, Inc.
9 Written May 1989 by Mike Haertel.
10
11 This file is part of GNU Emacs.
12
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.
17
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.
22
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.
27
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. */
30
31 #ifndef _MALLOC_H
32
33 #define _MALLOC_H 1
34
35 #ifdef __cplusplus
36 extern "C"
37 {
38 #endif
39
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. */
55
56 #ifndef NULL
57 #define NULL 0
58 #endif
59
60 #if defined (HAVE_CONFIG_H) || defined (emacs)
61 #include <config.h>
62 #endif
63
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
79
80
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));
90
91 /* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
92 extern __ptr_t memalign __P ((size_t __alignment, size_t __size));
93
94 /* Allocate SIZE bytes on a page boundary. */
95 extern __ptr_t valloc __P ((size_t __size));
96
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
107
108 #ifdef _MALLOC_INTERNAL
109
110 #include <stdio.h> /* Harmless, gets __GNU_LIBRARY__ defined. */
111
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
125
126
127 #if defined(__GNU_LIBRARY__) || defined(__STDC__)
128 #include <limits.h>
129 #else
130 #define CHAR_BIT 8
131 #endif
132
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)
146
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)
150
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
154
155 /* Data structure giving per-block information. */
156 typedef union
157 {
158 /* Heap information for a busy block. */
159 struct
160 {
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
165 {
166 struct
167 {
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
178 {
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;
184
185 /* Pointer to first block of the heap. */
186 extern char *_heapbase;
187
188 /* Table indexed by block number giving per-block information. */
189 extern malloc_info *_heapinfo;
190
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))
194
195 /* Current search index for the heap table. */
196 extern size_t _heapindex;
197
198 /* Limit of valid info table indices. */
199 extern size_t _heaplimit;
200
201 /* Doubly linked lists of free fragments. */
202 struct list
203 {
204 struct list *next;
205 struct list *prev;
206 };
207
208 /* Free list headers for each fragment size. */
209 extern struct list _fraghead[];
210
211 /* List of blocks allocated with `memalign' (or `valloc'). */
212 struct alignlist
213 {
214 struct alignlist *next;
215 __ptr_t aligned; /* The address that memaligned returned. */
216 __ptr_t exact; /* The address that malloc returned. */
217 };
218 extern struct alignlist *_aligned_blocks;
219
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;
225
226 /* Internal version of `free' used in `morecore' (malloc.c). */
227 extern void _free_internal __P ((__ptr_t __ptr));
228
229 #endif /* _MALLOC_INTERNAL. */
230
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));
235
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));
240
241 /* Default value of `__morecore'. */
242 extern __ptr_t __default_morecore __P ((ptrdiff_t __size));
243
244 /* Default value of `__lesscore'. */
245 extern __ptr_t __default_lesscore __P ((__ptr_t __ptr, ptrdiff_t __size));
246
247 #ifdef VMS
248 /* Default value of `__morecore'. */
249 extern __ptr_t __vms_morecore __P ((ptrdiff_t __size));
250
251 /* Default value of `__lesscore'. */
252 extern __ptr_t __vms_lesscore __P ((__ptr_t __ptr, ptrdiff_t __size));
253 #endif
254
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));
258
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));
262
263 /* Nonzero if `malloc' has been called and done its initialization. */
264 extern int __malloc_initialized;
265
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));
270
271 /* Activate a standard collection of debugging hooks. */
272 extern int mcheck __P ((void (*__func) __P ((void))));
273
274 /* Activate a standard collection of tracing hooks. */
275 extern void mtrace __P ((void));
276
277 /* Statistics available to the user. */
278 struct mstats
279 {
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. */
285 };
286
287 /* Pick up the current statistics. */
288 extern struct mstats mstats __P ((void));
289
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 *))));
293
294
295 /* Relocating allocator. */
296
297 /* Allocate SIZE bytes, and store the address in *HANDLEPTR. */
298 extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, size_t __size));
299
300 /* Free the storage allocated in HANDLEPTR. */
301 extern void r_alloc_free __P ((__ptr_t *__handleptr));
302
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));
305
306
307 #ifdef __cplusplus
308 }
309 #endif
310
311 #endif /* malloc.h */
312 /* Memory allocator `malloc'.
313 Copyright 1990, 1991, 1992, 1993 Free Software Foundation
314 Written May 1989 by Mike Haertel.
315
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.
320
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.
325
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.
330
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. */
333
334 #ifndef _MALLOC_INTERNAL
335 #define _MALLOC_INTERNAL
336 #include <malloc.h>
337 #endif
338
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
346
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
353
354 /* Pointer to the base of the first block. */
355 char *_heapbase;
356
357 /* Block information table. Allocated with align/__free (not malloc/free). */
358 malloc_info *_heapinfo;
359
360 /* Number of info entries. */
361 static size_t heapsize;
362
363 /* Search index in the info table. */
364 size_t _heapindex;
365
366 /* Limit of valid info table indices. */
367 size_t _heaplimit;
368
369 /* Free lists for each fragment size. */
370 struct list _fraghead[BLOCKLOG];
371
372 /* Instrumentation. */
373 size_t _chunks_used;
374 size_t _bytes_used;
375 size_t _chunks_free;
376 size_t _bytes_free;
377
378 /* Are you experienced? */
379 int __malloc_initialized;
380
381 void (*__after_morecore_hook) __P ((void));
382
383 /* Aligned allocation. */
384 static __ptr_t align __P ((size_t));
385 static __ptr_t
386 align (size)
387 size_t size;
388 {
389 __ptr_t result;
390 unsigned long int adj;
391
392 result = (*__morecore) (size);
393 adj = (unsigned long int) ((unsigned long int) ((char *) result -
394 (char *) NULL)) % BLOCKSIZE;
395 if (adj != 0)
396 {
397 adj = BLOCKSIZE - adj;
398 (void) (*__morecore) (adj);
399 result = (char *) result + adj;
400 }
401
402 if (__after_morecore_hook)
403 (*__after_morecore_hook) ();
404
405 return result;
406 }
407
408 /* Set everything up and remember that we have. */
409 static int initialize __P ((void));
410 static int
411 initialize ()
412 {
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;
434 }
435
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;
442 {
443 __ptr_t result;
444 malloc_info *newinfo, *oldinfo;
445 size_t newsize;
446
447 result = align (size);
448 if (result == NULL)
449 return NULL;
450
451 /* Check if we need to grow the info table. */
452 if ((size_t) BLOCK ((char *) result + size) > heapsize)
453 {
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)
459 {
460 (*__lesscore) (result, size);
461 return NULL;
462 }
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;
472 }
473
474 _heaplimit = BLOCK ((char *) result + size);
475 return result;
476 }
477
478 /* Allocate memory from the heap. */
479 __ptr_t
480 malloc (size)
481 size_t size;
482 {
483 __ptr_t result;
484 size_t block, blocks, lastblocks, start;
485 register size_t i;
486 struct list *next;
487
488 if (size == 0)
489 return NULL;
490
491 if (__malloc_hook != NULL)
492 return (*__malloc_hook) (size);
493
494 if (!__malloc_initialized)
495 if (!initialize ())
496 return NULL;
497
498 if (size < sizeof (struct list))
499 size = sizeof (struct list);
500
501 /* Determine the allocation policy based on the request size. */
502 if (size <= BLOCKSIZE / 2)
503 {
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;
510
511 /* Look in the fragment lists for a
512 free fragment of the desired size. */
513 next = _fraghead[log].next;
514 if (next != NULL)
515 {
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;
528
529 /* Update the statistics. */
530 ++_chunks_used;
531 _bytes_used += 1 << log;
532 --_chunks_free;
533 _bytes_free -= 1 << log;
534 }
535 else
536 {
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;
542
543 /* Link all fragments but the first into the free list. */
544 for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i)
545 {
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;
555 }
556
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;
562
563 _chunks_free += (BLOCKSIZE >> log) - 1;
564 _bytes_free += BLOCKSIZE - (1 << log);
565 _bytes_used -= BLOCKSIZE - (1 << log);
566 }
567 }
568 else
569 {
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)
577 {
578 block = _heapinfo[block].free.next;
579 if (block == start)
580 {
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)
589 {
590 _heapinfo[block].free.size = blocks;
591 _bytes_free += (blocks - lastblocks) * BLOCKSIZE;
592 continue;
593 }
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;
603 }
604 }
605
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)
610 {
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;
622 }
623 else
624 {
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;
632 }
633
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;
639 }
640
641 return result;
642 }
643 /* Free a block of memory allocated by `malloc'.
644 Copyright 1990, 1991, 1992 Free Software Foundation
645 Written May 1989 by Mike Haertel.
646
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.
651
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.
656
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.
661
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. */
664
665 #ifndef _MALLOC_INTERNAL
666 #define _MALLOC_INTERNAL
667 #include <malloc.h>
668 #endif
669
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
677
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
684
685 /* List of blocks allocated by memalign. */
686 struct alignlist *_aligned_blocks = NULL;
687
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;
693 {
694 int type;
695 size_t block, blocks;
696 register size_t i;
697 struct list *prev, *next;
698
699 block = BLOCK (ptr);
700
701 type = _heapinfo[block].busy.type;
702 switch (type)
703 {
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;
709
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
718 {
719 do
720 i = _heapinfo[i].free.next;
721 while (i > 0 && i < block);
722 i = _heapinfo[i].free.prev;
723 }
724
725 /* Determine how to link this block into the free list. */
726 if (block == i + _heapinfo[i].free.size)
727 {
728 /* Coalesce this block with its predecessor. */
729 _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
730 block = i;
731 }
732 else
733 {
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;
741 }
742
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)
747 {
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;
754 }
755
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))
760 {
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;
771 }
772
773 /* Set the next search to begin at this block. */
774 _heapindex = block;
775 break;
776
777 default:
778 /* Do some of the statistics. */
779 --_chunks_used;
780 _bytes_used -= 1 << type;
781 ++_chunks_free;
782 _bytes_free += 1 << type;
783
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
795
796 if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)
797 {
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;
808
809 /* Keep the statistics accurate. */
810 ++_chunks_used;
811 _bytes_used += BLOCKSIZE;
812 _chunks_free -= BLOCKSIZE >> type;
813 _bytes_free -= BLOCKSIZE;
814
815 free (ADDRESS (block));
816 }
817 else if (_heapinfo[block].busy.info.frag.nfree != 0)
818 {
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;
840 }
841 else
842 {
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;
856 }
857 break;
858 }
859 }
860
861 /* Return memory to the heap. */
862 void
863 free (ptr)
864 __ptr_t ptr;
865 {
866 register struct alignlist *l;
867
868 if (ptr == NULL)
869 return;
870
871 for (l = _aligned_blocks; l != NULL; l = l->next)
872 if (l->aligned == ptr)
873 {
874 l->aligned = NULL; /* Mark the slot in the list as free. */
875 ptr = l->exact;
876 break;
877 }
878
879 if (__free_hook != NULL)
880 (*__free_hook) (ptr);
881 else
882 _free_internal (ptr);
883 }
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.
887
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.
892
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.
897
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.
902
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. */
905
906 #ifndef _MALLOC_INTERNAL
907 #define _MALLOC_INTERNAL
908 #include <malloc.h>
909 #endif
910
911 #define min(A, B) ((A) < (B) ? (A) : (B))
912
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
919
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;
930 {
931 __ptr_t result;
932 int type;
933 size_t block, blocks, oldlimit;
934
935 if (size == 0)
936 {
937 free (ptr);
938 return malloc (0);
939 }
940 else if (ptr == NULL)
941 return malloc (size);
942
943 if (__realloc_hook != NULL)
944 return (*__realloc_hook) (ptr, size);
945
946 block = BLOCK (ptr);
947
948 type = _heapinfo[block].busy.type;
949 switch (type)
950 {
951 case 0:
952 /* Maybe reallocate a large block to a small fragment. */
953 if (size <= BLOCKSIZE / 2)
954 {
955 result = malloc (size);
956 if (result != NULL)
957 {
958 memcpy (result, ptr, size);
959 free (ptr);
960 return result;
961 }
962 }
963
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)
968 {
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;
977 }
978 else if (blocks == _heapinfo[block].busy.info.size)
979 /* No size change necessary. */
980 result = ptr;
981 else
982 {
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)
994 {
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
1001 {
1002 __ptr_t previous = malloc ((block - _heapindex) * BLOCKSIZE);
1003 (void) malloc (blocks * BLOCKSIZE);
1004 free (previous);
1005 }
1006 return NULL;
1007 }
1008 if (ptr != result)
1009 memmove (result, ptr, blocks * BLOCKSIZE);
1010 }
1011 break;
1012
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
1020 {
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);
1028 }
1029 break;
1030 }
1031
1032 return result;
1033 }
1034 /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
1035
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.
1040
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.
1045
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.
1050
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. */
1053
1054 #ifndef _MALLOC_INTERNAL
1055 #define _MALLOC_INTERNAL
1056 #include <malloc.h>
1057 #endif
1058
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;
1065 {
1066 register __ptr_t result = malloc (nmemb * size);
1067
1068 if (result != NULL)
1069 (void) memset (result, 0, nmemb * size);
1070
1071 return result;
1072 }
1073 /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
1074 This file is part of the GNU C Library.
1075
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.
1080
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.
1085
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. */
1089
1090 #ifndef _MALLOC_INTERNAL
1091 #define _MALLOC_INTERNAL
1092 #include <malloc.h>
1093 #endif
1094
1095 #ifndef __GNU_LIBRARY__
1096 #define __sbrk sbrk
1097 #ifdef VMS
1098 #define __brk brk
1099 #endif
1100 #endif
1101
1102 extern __ptr_t __sbrk __P ((int increment));
1103
1104 #ifndef NULL
1105 #define NULL 0
1106 #endif
1107
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.
1112
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.
1120
1121 N.B. This is experimental, but it worked quite fine on Emacs 18.
1122 */
1123 #ifndef VMS_ALLOCATION_SIZE
1124 #define VMS_ALLOCATION_SIZE (512*(512+128))
1125 #endif
1126
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];
1131
1132 __ptr_t
1133 __vms_initial_morecore (increment)
1134 ptrdiff_t increment;
1135 {
1136 __ptr_t result = NULL;
1137 __ptr_t temp;
1138
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)
1151 {
1152 if (increment >= 0)
1153 result = vms_current_brk;
1154 else
1155 result = temp;
1156 vms_current_brk = temp;
1157 }
1158 return result;
1159 }
1160
1161 __ptr_t
1162 __vms_initial_lesscore (ptr, size)
1163 __ptr_t ptr;
1164 ptrdiff_t size;
1165 {
1166 if (ptr >= vms_initial_buffer
1167 && ptr < vms_initial_buffer+VMS_ALLOCATION_SIZE)
1168 {
1169 vms_current_brk = ptr;
1170 return vms_current_brk;
1171 }
1172 return vms_current_brk;
1173 }
1174
1175 VMS_present_buffer()
1176 {
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);
1180 }
1181 #endif /* defined(emacs) && defined(VMS) */
1182
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... */
1191
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
1199
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;
1206 {
1207 __ptr_t result;
1208 #ifdef VMS
1209 __ptr_t temp;
1210
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
1219
1220 if (vms_brk_info_fetched < 0)
1221 {
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
1238 }
1239
1240 if (increment < 0)
1241 {
1242 printf("BZZZZZT! ERROR: __default_morecore does NOT take negative args\n");
1243 return NULL;
1244 }
1245
1246 if (increment > 0)
1247 {
1248 result = vms_brk_current;
1249 temp = vms_brk_current + increment;
1250
1251 if (temp > vms_brk_end)
1252 {
1253 __ptr_t foo;
1254
1255 foo = __sbrk (0);
1256 if (foo == vms_brk_end)
1257 {
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
1270 }
1271 else
1272 {
1273 result = __sbrk (increment);
1274
1275 if (result == (__ptr_t) -1)
1276 return NULL;
1277
1278 temp = result + increment;
1279 }
1280
1281 vms_brk_end = __sbrk(0);
1282 }
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;
1289 }
1290 #ifdef RL_DEBUG
1291 printf(" nothing more...\n");
1292 #endif
1293
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)
1298 {
1299 /* the value has changed.
1300 Let's trust the system and modify our value */
1301 vms_brk_current = vms_brk_end = temp;
1302 }
1303 return vms_brk_current;
1304
1305 #else /* not VMS */
1306 result = __sbrk ((int) increment);
1307 if (result == (__ptr_t) -1)
1308 return NULL;
1309 return result;
1310 #endif /* VMS */
1311 }
1312
1313 __ptr_t
1314 __default_lesscore (ptr, size)
1315 __ptr_t ptr;
1316 ptrdiff_t size;
1317 {
1318 #ifdef VMS
1319 if (vms_brk_end != 0)
1320 {
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
1334 }
1335
1336 return vms_brk_current;
1337 #else /* not VMS */
1338 __default_morecore (-size);
1339 #endif
1340 }
1341
1342 /* Allocate memory on a page boundary.
1343 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
1344
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.
1349
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.
1354
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.
1359
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. */
1362
1363 #ifndef _MALLOC_INTERNAL
1364 #define _MALLOC_INTERNAL
1365 #include <malloc.h>
1366 #endif
1367
1368 #if defined (emacs) || defined (HAVE_CONFIG_H)
1369 #include "config.h"
1370 #endif
1371
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
1394
1395 static size_t pagesize;
1396
1397 __ptr_t
1398 valloc (size)
1399 size_t size;
1400 {
1401 if (pagesize == 0)
1402 pagesize = __getpagesize ();
1403
1404 return memalign (pagesize, size);
1405 }
1406 /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
1407
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.
1412
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.
1417
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. */
1422
1423 #ifndef _MALLOC_INTERNAL
1424 #define _MALLOC_INTERNAL
1425 #include <malloc.h>
1426 #endif
1427
1428 __ptr_t
1429 memalign (alignment, size)
1430 size_t alignment;
1431 size_t size;
1432 {
1433 __ptr_t result;
1434 unsigned long int adj;
1435
1436 size = ((size + alignment - 1) / alignment) * alignment;
1437
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)
1444 {
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)
1451 {
1452 l = (struct alignlist *) malloc (sizeof (struct alignlist));
1453 if (l == NULL)
1454 {
1455 free (result);
1456 return NULL;
1457 }
1458 }
1459 l->exact = result;
1460 result = l->aligned = (char *) result + alignment - adj;
1461 l->next = _aligned_blocks;
1462 _aligned_blocks = l;
1463 }
1464
1465 return result;
1466 }
1467
1468 #ifdef VMS
1469 struct vms_malloc_data
1470 {
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[] =
1482 {
1483 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1484 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
1485 };
1486
1487 struct vms_core_routines
1488 {
1489 __ptr_t (*__morecore) __P ((ptrdiff_t increment));
1490 __ptr_t (*__lesscore) __P ((__ptr_t address, ptrdiff_t increment));
1491 } ____vms_core_routines[] =
1492 {
1493 { __vms_initial_morecore, __vms_initial_lesscore },
1494 { __default_morecore, __default_lesscore },
1495 { 0, 0 }
1496 };
1497
1498 static int current_vms_data = -1;
1499 static int current_vms_core_routines = 0;
1500
1501 static void use_vms_core_routines (int i)
1502 {
1503 current_vms_core_routines = i;
1504 current_vms_data = i;
1505 }
1506
1507 static void use_vms_data (int i)
1508 {
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;
1520 }
1521
1522 static void store_vms_data (int i)
1523 {
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;
1534 }
1535
1536 static void store_current_vms_data ()
1537 {
1538 switch (current_vms_data)
1539 {
1540 case 0:
1541 case 1:
1542 store_vms_data (current_vms_data);
1543 break;
1544 }
1545 }
1546
1547 __ptr_t __vms_morecore (increment)
1548 ptrdiff_t increment;
1549 {
1550 return
1551 (*____vms_core_routines[current_vms_core_routines].__morecore) (increment);
1552 }
1553
1554 __ptr_t __vms_lesscore (ptr, increment)
1555 __ptr_t ptr;
1556 ptrdiff_t increment;
1557 {
1558 return
1559 (*____vms_core_routines[current_vms_core_routines].__lesscore) (ptr,increment);
1560 }
1561
1562 __ptr_t __vms_malloc (size)
1563 size_t size;
1564 {
1565 __ptr_t result;
1566 int old_current_vms_data = current_vms_data;
1567
1568 __malloc_hook = 0;
1569
1570 store_current_vms_data ();
1571
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)
1579 {
1580 use_vms_data (1);
1581 result = malloc (size);
1582 store_vms_data (1);
1583 vms_out_initial = 1;
1584 }
1585 __malloc_hook = __vms_malloc;
1586 if (old_current_vms_data != -1)
1587 use_vms_data (current_vms_data);
1588 return result;
1589 }
1590
1591 void __vms_free (ptr)
1592 __ptr_t ptr;
1593 {
1594 int old_current_vms_data = current_vms_data;
1595
1596 __free_hook = 0;
1597
1598 store_current_vms_data ();
1599
1600 if (ptr >= vms_initial_buffer && ptr <= vms_end_brk)
1601 {
1602 use_vms_data (0);
1603 free (ptr);
1604 store_vms_data (0);
1605 }
1606 else
1607 {
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;
1613 }
1614 __free_hook = __vms_free;
1615 if (old_current_vms_data != -1)
1616 use_vms_data (current_vms_data);
1617 }
1618
1619 __ptr_t __vms_realloc (ptr, size)
1620 __ptr_t ptr;
1621 size_t size;
1622 {
1623 __ptr_t result;
1624 int old_current_vms_data = current_vms_data;
1625
1626 __realloc_hook = 0;
1627
1628 store_current_vms_data ();
1629
1630 if (ptr >= vms_initial_buffer && ptr <= vms_end_brk)
1631 {
1632 use_vms_data (0);
1633 result = realloc (ptr, size);
1634 store_vms_data (0);
1635 }
1636 else
1637 {
1638 use_vms_data (1);
1639 result = realloc (ptr, size);
1640 store_vms_data (1);
1641 }
1642 __realloc_hook = __vms_realloc;
1643 if (old_current_vms_data != -1)
1644 use_vms_data (current_vms_data);
1645 return result;
1646 }
1647 #endif /* VMS */
1648 /* Standard debugging hooks for `malloc'.
1649 Copyright 1990, 1991, 1992 Free Software Foundation
1650 Written May 1989 by Mike Haertel.
1651
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.
1656
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.
1661
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.
1666
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. */
1669
1670 #ifndef _MALLOC_INTERNAL
1671 #define _MALLOC_INTERNAL
1672 #include <malloc.h>
1673 #endif
1674
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));
1679
1680 /* Function to call when something awful happens. */
1681 static void (*abortfunc) __P ((void));
1682
1683 /* Arbitrary magical numbers. */
1684 #define MAGICWORD 0xfedabeeb
1685 #define MAGICBYTE ((char) 0xd7)
1686
1687 struct hdr
1688 {
1689 size_t size; /* Exact size requested by user. */
1690 unsigned long int magic; /* Magic number to check header integrity. */
1691 };
1692
1693 static void checkhdr __P ((__const struct hdr *));
1694 static void
1695 checkhdr (hdr)
1696 __const struct hdr *hdr;
1697 {
1698 if (hdr->magic != MAGICWORD || ((char *) &hdr[1])[hdr->size] != MAGICBYTE)
1699 (*abortfunc) ();
1700 }
1701
1702 static void freehook __P ((__ptr_t));
1703 static void
1704 freehook (ptr)
1705 __ptr_t ptr;
1706 {
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;
1713 }
1714
1715 static __ptr_t mallochook __P ((size_t));
1716 static __ptr_t
1717 mallochook (size)
1718 size_t size;
1719 {
1720 struct hdr *hdr;
1721
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;
1727
1728 hdr->size = size;
1729 hdr->magic = MAGICWORD;
1730 ((char *) &hdr[1])[size] = MAGICBYTE;
1731 return (__ptr_t) (hdr + 1);
1732 }
1733
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;
1739 {
1740 struct hdr *hdr = ((struct hdr *) ptr) - 1;
1741
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;
1752
1753 hdr->size = size;
1754 ((char *) &hdr[1])[size] = MAGICBYTE;
1755 return (__ptr_t) (hdr + 1);
1756 }
1757
1758 int
1759 mcheck (func)
1760 void (*func) __P ((void));
1761 {
1762 extern void abort __P ((void));
1763 static int mcheck_used = 0;
1764
1765 abortfunc = (func != NULL) ? func : abort;
1766
1767 /* These hooks may not be safely inserted if malloc is already in use. */
1768 if (!__malloc_initialized && !mcheck_used)
1769 {
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;
1777 }
1778
1779 return mcheck_used ? 0 : -1;
1780 }
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.
1785
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.
1790
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.
1795
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.
1800
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. */
1803
1804 #ifndef _MALLOC_INTERNAL
1805 #define _MALLOC_INTERNAL
1806 #include <malloc.h>
1807 #endif
1808
1809 #include <stdio.h>
1810
1811 #ifndef __GNU_LIBRARY__
1812 extern char *getenv ();
1813 #else
1814 #include <stdlib.h>
1815 #endif
1816
1817 static FILE *mallstream;
1818 static char mallenv[]= "MALLOC_TRACE";
1819 static char mallbuf[BUFSIZ]; /* Buffer for the output. */
1820
1821 /* Address to breakpoint on accesses to... */
1822 __ptr_t mallwatch;
1823
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));
1830
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. */
1835
1836 void tr_break __P ((void));
1837 void
1838 tr_break ()
1839 {
1840 }
1841
1842 static void tr_freehook __P ((__ptr_t));
1843 static void
1844 tr_freehook (ptr)
1845 __ptr_t ptr;
1846 {
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;
1853 }
1854
1855 static __ptr_t tr_morecore __P ((ptrdiff_t));
1856 static __ptr_t
1857 tr_morecore (increment)
1858 ptrdiff_t increment;
1859 {
1860 __ptr_t p;
1861
1862 __morecore = tr_old_morecore;
1863 p = (__ptr_t) (*__morecore) (increment);
1864 __morecore = tr_morecore;
1865
1866 fprintf (mallstream, "$ %p %d\n", p, increment);
1867
1868 return p;
1869 }
1870
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;
1876 {
1877 __ptr_t p;
1878
1879 __lesscore = tr_old_lesscore;
1880 p = (__ptr_t) (*__lesscore) (ptr, increment);
1881 __lesscore = tr_lesscore;
1882
1883 fprintf (mallstream, "* %p (%p, %d)\n", p, ptr, increment);
1884
1885 return p;
1886 }
1887
1888 static __ptr_t tr_mallochook __P ((size_t));
1889 static __ptr_t
1890 tr_mallochook (size)
1891 size_t size;
1892 {
1893 __ptr_t hdr;
1894
1895 __malloc_hook = tr_old_malloc_hook;
1896 hdr = (__ptr_t) malloc (size);
1897 __malloc_hook = tr_mallochook;
1898
1899 /* We could be printing a NULL here; that's OK. */
1900 fprintf (mallstream, "+ %p %x\n", hdr, size);
1901
1902 if (hdr == mallwatch)
1903 tr_break ();
1904
1905 return hdr;
1906 }
1907
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;
1913 {
1914 __ptr_t hdr;
1915
1916 if (ptr == mallwatch)
1917 tr_break ();
1918
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);
1931
1932 if (hdr == mallwatch)
1933 tr_break ();
1934
1935 return hdr;
1936 }
1937
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! */
1942
1943 void
1944 mtrace ()
1945 {
1946 char *mallfile;
1947
1948 mallfile = getenv (mallenv);
1949 if (mallfile != NULL || mallwatch != NULL)
1950 {
1951 mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w");
1952 if (mallstream != NULL)
1953 {
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;
1971 }
1972 }
1973 }
1974 /* Access the statistics maintained by `malloc'.
1975 Copyright 1990, 1991, 1992 Free Software Foundation
1976 Written May 1989 by Mike Haertel.
1977
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.
1982
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.
1987
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.
1992
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. */
1995
1996 #ifndef _MALLOC_INTERNAL
1997 #define _MALLOC_INTERNAL
1998 #include <malloc.h>
1999 #endif
2000
2001 struct mstats
2002 mstats ()
2003 {
2004 struct mstats result;
2005
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;
2012 }