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