1 /* Block-relocating memory allocator.
2 Copyright (C) 1993, 1995, 2000 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
23 Only relocate the blocs necessary for SIZE in r_alloc_sbrk,
24 rather than all of them. This means allowing for a possible
25 hole between the first bloc and the end of malloc storage. */
30 #include "lisp.h" /* Needed for VALBITS. */
36 typedef POINTER_TYPE
*POINTER
;
39 /* Declared in dispnew.c, this version doesn't screw up if regions
42 extern void safe_bcopy ();
44 #ifdef DOUG_LEA_MALLOC
46 extern int mallopt ();
47 #else /* not DOUG_LEA_MALLOC */
49 extern size_t __malloc_extra_blocks
;
50 #endif /* SYSTEM_MALLOC */
51 #endif /* not DOUG_LEA_MALLOC */
58 typedef void *POINTER
;
63 #define safe_bcopy(x, y, z) memmove (y, x, z)
64 #define bzero(x, len) memset (x, 0, len)
66 #endif /* not emacs */
69 #include "getpagesize.h"
71 #define NIL ((POINTER) 0)
73 /* A flag to indicate whether we have initialized ralloc yet. For
74 Emacs's sake, please do not make this local to malloc_init; on some
75 machines, the dumping procedure makes all static variables
76 read-only. On these machines, the word static is #defined to be
77 the empty string, meaning that r_alloc_initialized becomes an
78 automatic variable, and loses its value each time Emacs is started
81 static int r_alloc_initialized
= 0;
83 static void r_alloc_init ();
86 /* Declarations for working with the malloc, ralloc, and system breaks. */
88 /* Function to set the real break value. */
89 POINTER (*real_morecore
) ();
91 /* The break value, as seen by malloc. */
92 static POINTER virtual_break_value
;
94 /* The address of the end of the last data in use by ralloc,
95 including relocatable blocs as well as malloc data. */
96 static POINTER break_value
;
98 /* This is the size of a page. We round memory requests to this boundary. */
101 /* Whenever we get memory from the system, get this many extra bytes. This
102 must be a multiple of page_size. */
103 static int extra_bytes
;
105 /* Macros for rounding. Note that rounding to any value is possible
106 by changing the definition of PAGE. */
107 #define PAGE (getpagesize ())
108 #define ALIGNED(addr) (((unsigned long int) (addr) & (page_size - 1)) == 0)
109 #define ROUNDUP(size) (((unsigned long int) (size) + page_size - 1) \
111 #define ROUND_TO_PAGE(addr) (addr & (~(page_size - 1)))
113 #define MEM_ALIGN sizeof(double)
114 #define MEM_ROUNDUP(addr) (((unsigned long int)(addr) + MEM_ALIGN - 1) \
117 /* The hook `malloc' uses for the function which gets more space
120 #ifndef SYSTEM_MALLOC
121 extern POINTER (*__morecore
) ();
126 /***********************************************************************
127 Implementation using sbrk
128 ***********************************************************************/
130 /* Data structures of heaps and blocs. */
132 /* The relocatable objects, or blocs, and the malloc data
133 both reside within one or more heaps.
134 Each heap contains malloc data, running from `start' to `bloc_start',
135 and relocatable objects, running from `bloc_start' to `free'.
137 Relocatable objects may relocate within the same heap
138 or may move into another heap; the heaps themselves may grow
141 We try to make just one heap and make it larger as necessary.
142 But sometimes we can't do that, because we can't get contiguous
143 space to add onto the heap. When that happens, we start a new heap. */
149 /* Start of memory range of this heap. */
151 /* End of memory range of this heap. */
153 /* Start of relocatable data in this heap. */
155 /* Start of unused space in this heap. */
157 /* First bloc in this heap. */
158 struct bp
*first_bloc
;
159 /* Last bloc in this heap. */
160 struct bp
*last_bloc
;
163 #define NIL_HEAP ((heap_ptr) 0)
164 #define HEAP_PTR_SIZE (sizeof (struct heap))
166 /* This is the first heap object.
167 If we need additional heap objects, each one resides at the beginning of
168 the space it covers. */
169 static struct heap heap_base
;
171 /* Head and tail of the list of heaps. */
172 static heap_ptr first_heap
, last_heap
;
174 /* These structures are allocated in the malloc arena.
175 The linked list is kept in order of increasing '.data' members.
176 The data blocks abut each other; if b->next is non-nil, then
177 b->data + b->size == b->next->data.
179 An element with variable==NIL denotes a freed block, which has not yet
180 been collected. They may only appear while r_alloc_freeze > 0, and will be
181 freed when the arena is thawed. Currently, these blocs are not reusable,
182 while the arena is frozen. Very inefficient. */
191 POINTER new_data
; /* temporarily used for relocation */
192 struct heap
*heap
; /* Heap this bloc is in. */
195 #define NIL_BLOC ((bloc_ptr) 0)
196 #define BLOC_PTR_SIZE (sizeof (struct bp))
198 /* Head and tail of the list of relocatable blocs. */
199 static bloc_ptr first_bloc
, last_bloc
;
201 static int use_relocatable_buffers
;
203 /* If >0, no relocation whatsoever takes place. */
204 static int r_alloc_freeze_level
;
207 /* Functions to get and return memory from the system. */
209 /* Find the heap that ADDRESS falls within. */
217 for (heap
= last_heap
; heap
; heap
= heap
->prev
)
219 if (heap
->start
<= address
&& address
<= heap
->end
)
226 /* Find SIZE bytes of space in a heap.
227 Try to get them at ADDRESS (which must fall within some heap's range)
228 if we can get that many within one heap.
230 If enough space is not presently available in our reserve, this means
231 getting more page-aligned space from the system. If the returned space
232 is not contiguous to the last heap, allocate a new heap, and append it
234 obtain does not try to keep track of whether space is in use
235 or not in use. It just returns the address of SIZE bytes that
236 fall within a single heap. If you call obtain twice in a row
237 with the same arguments, you typically get the same value.
238 to the heap list. It's the caller's responsibility to keep
239 track of what space is in use.
241 Return the address of the space if all went well, or zero if we couldn't
242 allocate the memory. */
245 obtain (address
, size
)
250 SIZE already_available
;
252 /* Find the heap that ADDRESS falls within. */
253 for (heap
= last_heap
; heap
; heap
= heap
->prev
)
255 if (heap
->start
<= address
&& address
<= heap
->end
)
262 /* If we can't fit SIZE bytes in that heap,
263 try successive later heaps. */
264 while (heap
&& (char *) address
+ size
> (char *) heap
->end
)
267 if (heap
== NIL_HEAP
)
269 address
= heap
->bloc_start
;
272 /* If we can't fit them within any existing heap,
274 if (heap
== NIL_HEAP
)
276 POINTER
new = (*real_morecore
)(0);
279 already_available
= (char *)last_heap
->end
- (char *)address
;
281 if (new != last_heap
->end
)
283 /* Someone else called sbrk. Make a new heap. */
285 heap_ptr new_heap
= (heap_ptr
) MEM_ROUNDUP (new);
286 POINTER bloc_start
= (POINTER
) MEM_ROUNDUP ((POINTER
)(new_heap
+ 1));
288 if ((*real_morecore
) ((char *) bloc_start
- (char *) new) != new)
291 new_heap
->start
= new;
292 new_heap
->end
= bloc_start
;
293 new_heap
->bloc_start
= bloc_start
;
294 new_heap
->free
= bloc_start
;
295 new_heap
->next
= NIL_HEAP
;
296 new_heap
->prev
= last_heap
;
297 new_heap
->first_bloc
= NIL_BLOC
;
298 new_heap
->last_bloc
= NIL_BLOC
;
299 last_heap
->next
= new_heap
;
300 last_heap
= new_heap
;
302 address
= bloc_start
;
303 already_available
= 0;
306 /* Add space to the last heap (which we may have just created).
307 Get some extra, so we can come here less often. */
309 get
= size
+ extra_bytes
- already_available
;
310 get
= (char *) ROUNDUP ((char *)last_heap
->end
+ get
)
311 - (char *) last_heap
->end
;
313 if ((*real_morecore
) (get
) != last_heap
->end
)
316 last_heap
->end
= (char *) last_heap
->end
+ get
;
322 /* Return unused heap space to the system
323 if there is a lot of unused space now.
324 This can make the last heap smaller;
325 it can also eliminate the last heap entirely. */
333 /* Add the amount of space beyond break_value
334 in all heaps which have extend beyond break_value at all. */
336 for (h
= last_heap
; h
&& break_value
< h
->end
; h
= h
->prev
)
338 excess
+= (char *) h
->end
- (char *) ((break_value
< h
->bloc_start
)
339 ? h
->bloc_start
: break_value
);
342 if (excess
> extra_bytes
* 2 && (*real_morecore
) (0) == last_heap
->end
)
344 /* Keep extra_bytes worth of empty space.
345 And don't free anything unless we can free at least extra_bytes. */
346 excess
-= extra_bytes
;
348 if ((char *)last_heap
->end
- (char *)last_heap
->bloc_start
<= excess
)
350 /* This heap should have no blocs in it. */
351 if (last_heap
->first_bloc
!= NIL_BLOC
352 || last_heap
->last_bloc
!= NIL_BLOC
)
355 /* Return the last heap, with its header, to the system. */
356 excess
= (char *)last_heap
->end
- (char *)last_heap
->start
;
357 last_heap
= last_heap
->prev
;
358 last_heap
->next
= NIL_HEAP
;
362 excess
= (char *) last_heap
->end
363 - (char *) ROUNDUP ((char *)last_heap
->end
- excess
);
364 last_heap
->end
= (char *) last_heap
->end
- excess
;
367 if ((*real_morecore
) (- excess
) == 0)
369 /* If the system didn't want that much memory back, adjust
370 the end of the last heap to reflect that. This can occur
371 if break_value is still within the original data segment. */
372 last_heap
->end
= (char *) last_heap
->end
+ excess
;
373 /* Make sure that the result of the adjustment is accurate.
374 It should be, for the else clause above; the other case,
375 which returns the entire last heap to the system, seems
376 unlikely to trigger this mode of failure. */
377 if (last_heap
->end
!= (*real_morecore
) (0))
383 /* Return the total size in use by relocating allocator,
384 above where malloc gets space. */
387 r_alloc_size_in_use ()
389 return (char *) break_value
- (char *) virtual_break_value
;
392 /* The meat - allocating, freeing, and relocating blocs. */
394 /* Find the bloc referenced by the address in PTR. Returns a pointer
401 register bloc_ptr p
= first_bloc
;
403 while (p
!= NIL_BLOC
)
405 if (p
->variable
== ptr
&& p
->data
== *ptr
)
414 /* Allocate a bloc of SIZE bytes and append it to the chain of blocs.
415 Returns a pointer to the new bloc, or zero if we couldn't allocate
416 memory for the new block. */
422 register bloc_ptr new_bloc
;
423 register heap_ptr heap
;
425 if (! (new_bloc
= (bloc_ptr
) malloc (BLOC_PTR_SIZE
))
426 || ! (new_bloc
->data
= obtain (break_value
, size
)))
434 break_value
= (char *) new_bloc
->data
+ size
;
436 new_bloc
->size
= size
;
437 new_bloc
->next
= NIL_BLOC
;
438 new_bloc
->variable
= (POINTER
*) NIL
;
439 new_bloc
->new_data
= 0;
441 /* Record in the heap that this space is in use. */
442 heap
= find_heap (new_bloc
->data
);
443 heap
->free
= break_value
;
445 /* Maintain the correspondence between heaps and blocs. */
446 new_bloc
->heap
= heap
;
447 heap
->last_bloc
= new_bloc
;
448 if (heap
->first_bloc
== NIL_BLOC
)
449 heap
->first_bloc
= new_bloc
;
451 /* Put this bloc on the doubly-linked list of blocs. */
454 new_bloc
->prev
= last_bloc
;
455 last_bloc
->next
= new_bloc
;
456 last_bloc
= new_bloc
;
460 first_bloc
= last_bloc
= new_bloc
;
461 new_bloc
->prev
= NIL_BLOC
;
467 /* Calculate new locations of blocs in the list beginning with BLOC,
468 relocating it to start at ADDRESS, in heap HEAP. If enough space is
469 not presently available in our reserve, call obtain for
472 Store the new location of each bloc in its new_data field.
473 Do not touch the contents of blocs or break_value. */
476 relocate_blocs (bloc
, heap
, address
)
481 register bloc_ptr b
= bloc
;
483 /* No need to ever call this if arena is frozen, bug somewhere! */
484 if (r_alloc_freeze_level
)
489 /* If bloc B won't fit within HEAP,
490 move to the next heap and try again. */
491 while (heap
&& (char *) address
+ b
->size
> (char *) heap
->end
)
494 if (heap
== NIL_HEAP
)
496 address
= heap
->bloc_start
;
499 /* If BLOC won't fit in any heap,
500 get enough new space to hold BLOC and all following blocs. */
501 if (heap
== NIL_HEAP
)
503 register bloc_ptr tb
= b
;
506 /* Add up the size of all the following blocs. */
507 while (tb
!= NIL_BLOC
)
515 /* Get that space. */
516 address
= obtain (address
, s
);
523 /* Record the new address of this bloc
524 and update where the next bloc can start. */
525 b
->new_data
= address
;
527 address
= (char *) address
+ b
->size
;
534 /* Reorder the bloc BLOC to go before bloc BEFORE in the doubly linked list.
535 This is necessary if we put the memory of space of BLOC
536 before that of BEFORE. */
539 reorder_bloc (bloc
, before
)
540 bloc_ptr bloc
, before
;
544 /* Splice BLOC out from where it is. */
553 /* Splice it in before BEFORE. */
564 /* Update the records of which heaps contain which blocs, starting
565 with heap HEAP and bloc BLOC. */
568 update_heap_bloc_correspondence (bloc
, heap
)
574 /* Initialize HEAP's status to reflect blocs before BLOC. */
575 if (bloc
!= NIL_BLOC
&& bloc
->prev
!= NIL_BLOC
&& bloc
->prev
->heap
== heap
)
577 /* The previous bloc is in HEAP. */
578 heap
->last_bloc
= bloc
->prev
;
579 heap
->free
= (char *) bloc
->prev
->data
+ bloc
->prev
->size
;
583 /* HEAP contains no blocs before BLOC. */
584 heap
->first_bloc
= NIL_BLOC
;
585 heap
->last_bloc
= NIL_BLOC
;
586 heap
->free
= heap
->bloc_start
;
589 /* Advance through blocs one by one. */
590 for (b
= bloc
; b
!= NIL_BLOC
; b
= b
->next
)
592 /* Advance through heaps, marking them empty,
593 till we get to the one that B is in. */
596 if (heap
->bloc_start
<= b
->data
&& b
->data
<= heap
->end
)
599 /* We know HEAP is not null now,
600 because there has to be space for bloc B. */
601 heap
->first_bloc
= NIL_BLOC
;
602 heap
->last_bloc
= NIL_BLOC
;
603 heap
->free
= heap
->bloc_start
;
606 /* Update HEAP's status for bloc B. */
607 heap
->free
= (char *) b
->data
+ b
->size
;
609 if (heap
->first_bloc
== NIL_BLOC
)
610 heap
->first_bloc
= b
;
612 /* Record that B is in HEAP. */
616 /* If there are any remaining heaps and no blocs left,
617 mark those heaps as empty. */
621 heap
->first_bloc
= NIL_BLOC
;
622 heap
->last_bloc
= NIL_BLOC
;
623 heap
->free
= heap
->bloc_start
;
628 /* Resize BLOC to SIZE bytes. This relocates the blocs
629 that come after BLOC in memory. */
632 resize_bloc (bloc
, size
)
641 /* No need to ever call this if arena is frozen, bug somewhere! */
642 if (r_alloc_freeze_level
)
645 if (bloc
== NIL_BLOC
|| size
== bloc
->size
)
648 for (heap
= first_heap
; heap
!= NIL_HEAP
; heap
= heap
->next
)
650 if (heap
->bloc_start
<= bloc
->data
&& bloc
->data
<= heap
->end
)
654 if (heap
== NIL_HEAP
)
657 old_size
= bloc
->size
;
660 /* Note that bloc could be moved into the previous heap. */
661 address
= (bloc
->prev
? (char *) bloc
->prev
->data
+ bloc
->prev
->size
662 : (char *) first_heap
->bloc_start
);
665 if (heap
->bloc_start
<= address
&& address
<= heap
->end
)
670 if (! relocate_blocs (bloc
, heap
, address
))
672 bloc
->size
= old_size
;
678 for (b
= last_bloc
; b
!= bloc
; b
= b
->prev
)
683 b
->data
= b
->new_data
;
687 safe_bcopy (b
->data
, b
->new_data
, b
->size
);
688 *b
->variable
= b
->data
= b
->new_data
;
694 bloc
->data
= bloc
->new_data
;
698 safe_bcopy (bloc
->data
, bloc
->new_data
, old_size
);
699 bzero ((char *) bloc
->new_data
+ old_size
, size
- old_size
);
700 *bloc
->variable
= bloc
->data
= bloc
->new_data
;
705 for (b
= bloc
; b
!= NIL_BLOC
; b
= b
->next
)
710 b
->data
= b
->new_data
;
714 safe_bcopy (b
->data
, b
->new_data
, b
->size
);
715 *b
->variable
= b
->data
= b
->new_data
;
720 update_heap_bloc_correspondence (bloc
, heap
);
722 break_value
= (last_bloc
? (char *) last_bloc
->data
+ last_bloc
->size
723 : (char *) first_heap
->bloc_start
);
727 /* Free BLOC from the chain of blocs, relocating any blocs above it.
728 This may return space to the system. */
734 heap_ptr heap
= bloc
->heap
;
736 if (r_alloc_freeze_level
)
738 bloc
->variable
= (POINTER
*) NIL
;
742 resize_bloc (bloc
, 0);
744 if (bloc
== first_bloc
&& bloc
== last_bloc
)
746 first_bloc
= last_bloc
= NIL_BLOC
;
748 else if (bloc
== last_bloc
)
750 last_bloc
= bloc
->prev
;
751 last_bloc
->next
= NIL_BLOC
;
753 else if (bloc
== first_bloc
)
755 first_bloc
= bloc
->next
;
756 first_bloc
->prev
= NIL_BLOC
;
760 bloc
->next
->prev
= bloc
->prev
;
761 bloc
->prev
->next
= bloc
->next
;
764 /* Update the records of which blocs are in HEAP. */
765 if (heap
->first_bloc
== bloc
)
767 if (bloc
->next
!= 0 && bloc
->next
->heap
== heap
)
768 heap
->first_bloc
= bloc
->next
;
770 heap
->first_bloc
= heap
->last_bloc
= NIL_BLOC
;
772 if (heap
->last_bloc
== bloc
)
774 if (bloc
->prev
!= 0 && bloc
->prev
->heap
== heap
)
775 heap
->last_bloc
= bloc
->prev
;
777 heap
->first_bloc
= heap
->last_bloc
= NIL_BLOC
;
784 /* Interface routines. */
786 /* Obtain SIZE bytes of storage from the free pool, or the system, as
787 necessary. If relocatable blocs are in use, this means relocating
788 them. This function gets plugged into the GNU malloc's __morecore
791 We provide hysteresis, never relocating by less than extra_bytes.
793 If we're out of memory, we should return zero, to imitate the other
794 __morecore hook values - in particular, __default_morecore in the
795 GNU malloc package. */
804 if (! r_alloc_initialized
)
807 if (! use_relocatable_buffers
)
808 return (*real_morecore
) (size
);
811 return virtual_break_value
;
815 /* Allocate a page-aligned space. GNU malloc would reclaim an
816 extra space if we passed an unaligned one. But we could
817 not always find a space which is contiguous to the previous. */
818 POINTER new_bloc_start
;
819 heap_ptr h
= first_heap
;
820 SIZE get
= ROUNDUP (size
);
822 address
= (POINTER
) ROUNDUP (virtual_break_value
);
824 /* Search the list upward for a heap which is large enough. */
825 while ((char *) h
->end
< (char *) MEM_ROUNDUP ((char *)address
+ get
))
830 address
= (POINTER
) ROUNDUP (h
->start
);
833 /* If not found, obtain more space. */
836 get
+= extra_bytes
+ page_size
;
838 if (! obtain (address
, get
))
841 if (first_heap
== last_heap
)
842 address
= (POINTER
) ROUNDUP (virtual_break_value
);
844 address
= (POINTER
) ROUNDUP (last_heap
->start
);
848 new_bloc_start
= (POINTER
) MEM_ROUNDUP ((char *)address
+ get
);
850 if (first_heap
->bloc_start
< new_bloc_start
)
852 /* This is no clean solution - no idea how to do it better. */
853 if (r_alloc_freeze_level
)
856 /* There is a bug here: if the above obtain call succeeded, but the
857 relocate_blocs call below does not succeed, we need to free
858 the memory that we got with obtain. */
860 /* Move all blocs upward. */
861 if (! relocate_blocs (first_bloc
, h
, new_bloc_start
))
864 /* Note that (POINTER)(h+1) <= new_bloc_start since
865 get >= page_size, so the following does not destroy the heap
867 for (b
= last_bloc
; b
!= NIL_BLOC
; b
= b
->prev
)
869 safe_bcopy (b
->data
, b
->new_data
, b
->size
);
870 *b
->variable
= b
->data
= b
->new_data
;
873 h
->bloc_start
= new_bloc_start
;
875 update_heap_bloc_correspondence (first_bloc
, h
);
879 /* Give up managing heaps below the one the new
880 virtual_break_value points to. */
881 first_heap
->prev
= NIL_HEAP
;
882 first_heap
->next
= h
->next
;
883 first_heap
->start
= h
->start
;
884 first_heap
->end
= h
->end
;
885 first_heap
->free
= h
->free
;
886 first_heap
->first_bloc
= h
->first_bloc
;
887 first_heap
->last_bloc
= h
->last_bloc
;
888 first_heap
->bloc_start
= h
->bloc_start
;
890 if (first_heap
->next
)
891 first_heap
->next
->prev
= first_heap
;
893 last_heap
= first_heap
;
896 bzero (address
, size
);
900 SIZE excess
= (char *)first_heap
->bloc_start
901 - ((char *)virtual_break_value
+ size
);
903 address
= virtual_break_value
;
905 if (r_alloc_freeze_level
== 0 && excess
> 2 * extra_bytes
)
907 excess
-= extra_bytes
;
908 first_heap
->bloc_start
909 = (POINTER
) MEM_ROUNDUP ((char *)first_heap
->bloc_start
- excess
);
911 relocate_blocs (first_bloc
, first_heap
, first_heap
->bloc_start
);
913 for (b
= first_bloc
; b
!= NIL_BLOC
; b
= b
->next
)
915 safe_bcopy (b
->data
, b
->new_data
, b
->size
);
916 *b
->variable
= b
->data
= b
->new_data
;
920 if ((char *)virtual_break_value
+ size
< (char *)first_heap
->start
)
922 /* We found an additional space below the first heap */
923 first_heap
->start
= (POINTER
) ((char *)virtual_break_value
+ size
);
927 virtual_break_value
= (POINTER
) ((char *)address
+ size
);
928 break_value
= (last_bloc
929 ? (char *) last_bloc
->data
+ last_bloc
->size
930 : (char *) first_heap
->bloc_start
);
938 /* Allocate a relocatable bloc of storage of size SIZE. A pointer to
939 the data is returned in *PTR. PTR is thus the address of some variable
940 which will use the data area.
942 The allocation of 0 bytes is valid.
943 In case r_alloc_freeze is set, a best fit of unused blocs could be done
944 before allocating a new area. Not yet done.
946 If we can't allocate the necessary memory, set *PTR to zero, and
954 register bloc_ptr new_bloc
;
956 if (! r_alloc_initialized
)
959 new_bloc
= get_bloc (MEM_ROUNDUP (size
));
962 new_bloc
->variable
= ptr
;
963 *ptr
= new_bloc
->data
;
971 /* Free a bloc of relocatable storage whose data is pointed to by PTR.
972 Store 0 in *PTR to show there's no block allocated. */
976 register POINTER
*ptr
;
978 register bloc_ptr dead_bloc
;
980 if (! r_alloc_initialized
)
983 dead_bloc
= find_bloc (ptr
);
984 if (dead_bloc
== NIL_BLOC
)
987 free_bloc (dead_bloc
);
991 refill_memory_reserve ();
995 /* Given a pointer at address PTR to relocatable data, resize it to SIZE.
996 Do this by shifting all blocks above this one up in memory, unless
997 SIZE is less than or equal to the current bloc size, in which case
1000 In case r_alloc_freeze is set, a new bloc is allocated, and the
1001 memory copied to it. Not very efficient. We could traverse the
1002 bloc_list for a best fit of free blocs first.
1004 Change *PTR to reflect the new bloc, and return this value.
1006 If more memory cannot be allocated, then leave *PTR unchanged, and
1010 r_re_alloc (ptr
, size
)
1014 register bloc_ptr bloc
;
1016 if (! r_alloc_initialized
)
1020 return r_alloc (ptr
, size
);
1024 return r_alloc (ptr
, 0);
1027 bloc
= find_bloc (ptr
);
1028 if (bloc
== NIL_BLOC
)
1031 if (size
< bloc
->size
)
1033 /* Wouldn't it be useful to actually resize the bloc here? */
1034 /* I think so too, but not if it's too expensive... */
1035 if ((bloc
->size
- MEM_ROUNDUP (size
) >= page_size
)
1036 && r_alloc_freeze_level
== 0)
1038 resize_bloc (bloc
, MEM_ROUNDUP (size
));
1039 /* Never mind if this fails, just do nothing... */
1040 /* It *should* be infallible! */
1043 else if (size
> bloc
->size
)
1045 if (r_alloc_freeze_level
)
1048 new_bloc
= get_bloc (MEM_ROUNDUP (size
));
1051 new_bloc
->variable
= ptr
;
1052 *ptr
= new_bloc
->data
;
1053 bloc
->variable
= (POINTER
*) NIL
;
1060 if (! resize_bloc (bloc
, MEM_ROUNDUP (size
)))
1067 /* Disable relocations, after making room for at least SIZE bytes
1068 of non-relocatable heap if possible. The relocatable blocs are
1069 guaranteed to hold still until thawed, even if this means that
1070 malloc must return a null pointer. */
1073 r_alloc_freeze (size
)
1076 if (! r_alloc_initialized
)
1079 /* If already frozen, we can't make any more room, so don't try. */
1080 if (r_alloc_freeze_level
> 0)
1082 /* If we can't get the amount requested, half is better than nothing. */
1083 while (size
> 0 && r_alloc_sbrk (size
) == 0)
1085 ++r_alloc_freeze_level
;
1087 r_alloc_sbrk (-size
);
1094 if (! r_alloc_initialized
)
1097 if (--r_alloc_freeze_level
< 0)
1100 /* This frees all unused blocs. It is not too inefficient, as the resize
1101 and bcopy is done only once. Afterwards, all unreferenced blocs are
1102 already shrunk to zero size. */
1103 if (!r_alloc_freeze_level
)
1105 bloc_ptr
*b
= &first_bloc
;
1107 if (!(*b
)->variable
)
1115 #if defined (emacs) && defined (DOUG_LEA_MALLOC)
1117 /* Reinitialize the morecore hook variables after restarting a dumped
1118 Emacs. This is needed when using Doug Lea's malloc from GNU libc. */
1122 /* Only do this if the hook has been reset, so that we don't get an
1123 infinite loop, in case Emacs was linked statically. */
1124 if (__morecore
!= r_alloc_sbrk
)
1126 real_morecore
= __morecore
;
1127 __morecore
= r_alloc_sbrk
;
1131 #endif /* emacs && DOUG_LEA_MALLOC */
1144 if (!r_alloc_initialized
)
1147 assert (first_heap
);
1148 assert (last_heap
->end
<= (POINTER
) sbrk (0));
1149 assert ((POINTER
) first_heap
< first_heap
->start
);
1150 assert (first_heap
->start
<= virtual_break_value
);
1151 assert (virtual_break_value
<= first_heap
->end
);
1153 for (h
= first_heap
; h
; h
= h
->next
)
1155 assert (h
->prev
== ph
);
1156 assert ((POINTER
) ROUNDUP (h
->end
) == h
->end
);
1157 #if 0 /* ??? The code in ralloc.c does not really try to ensure
1158 the heap start has any sort of alignment.
1159 Perhaps it should. */
1160 assert ((POINTER
) MEM_ROUNDUP (h
->start
) == h
->start
);
1162 assert ((POINTER
) MEM_ROUNDUP (h
->bloc_start
) == h
->bloc_start
);
1163 assert (h
->start
<= h
->bloc_start
&& h
->bloc_start
<= h
->end
);
1167 assert (ph
->end
< h
->start
);
1168 assert (h
->start
<= (POINTER
)h
&& (POINTER
)(h
+1) <= h
->bloc_start
);
1171 if (h
->bloc_start
<= break_value
&& break_value
<= h
->end
)
1178 assert (last_heap
== ph
);
1180 for (b
= first_bloc
; b
; b
= b
->next
)
1182 assert (b
->prev
== pb
);
1183 assert ((POINTER
) MEM_ROUNDUP (b
->data
) == b
->data
);
1184 assert ((SIZE
) MEM_ROUNDUP (b
->size
) == b
->size
);
1187 for (h
= first_heap
; h
; h
= h
->next
)
1189 if (h
->bloc_start
<= b
->data
&& b
->data
+ b
->size
<= h
->end
)
1196 if (pb
&& pb
->data
+ pb
->size
!= b
->data
)
1198 assert (ph
&& b
->data
== h
->bloc_start
);
1201 if (ph
->bloc_start
<= pb
->data
1202 && pb
->data
+ pb
->size
<= ph
->end
)
1204 assert (pb
->data
+ pb
->size
+ b
->size
> ph
->end
);
1209 assert (ph
->bloc_start
+ b
->size
> ph
->end
);
1217 assert (last_bloc
== pb
);
1220 assert (last_bloc
->data
+ last_bloc
->size
== break_value
);
1222 assert (first_heap
->bloc_start
== break_value
);
1229 /***********************************************************************
1231 ***********************************************************************/
1233 /* Initialize various things for memory allocation. */
1238 if (r_alloc_initialized
)
1240 r_alloc_initialized
= 1;
1243 #ifndef SYSTEM_MALLOC
1244 real_morecore
= __morecore
;
1245 __morecore
= r_alloc_sbrk
;
1247 first_heap
= last_heap
= &heap_base
;
1248 first_heap
->next
= first_heap
->prev
= NIL_HEAP
;
1249 first_heap
->start
= first_heap
->bloc_start
1250 = virtual_break_value
= break_value
= (*real_morecore
) (0);
1251 if (break_value
== NIL
)
1254 extra_bytes
= ROUNDUP (50000);
1257 #ifdef DOUG_LEA_MALLOC
1258 mallopt (M_TOP_PAD
, 64 * 4096);
1260 #ifndef SYSTEM_MALLOC
1261 /* Give GNU malloc's morecore some hysteresis
1262 so that we move all the relocatable blocks much less often. */
1263 __malloc_extra_blocks
= 64;
1267 #ifndef SYSTEM_MALLOC
1268 first_heap
->end
= (POINTER
) ROUNDUP (first_heap
->start
);
1270 /* The extra call to real_morecore guarantees that the end of the
1271 address space is a multiple of page_size, even if page_size is
1272 not really the page size of the system running the binary in
1273 which page_size is stored. This allows a binary to be built on a
1274 system with one page size and run on a system with a smaller page
1276 (*real_morecore
) ((char *) first_heap
->end
- (char *) first_heap
->start
);
1278 /* Clear the rest of the last page; this memory is in our address space
1279 even though it is after the sbrk value. */
1280 /* Doubly true, with the additional call that explicitly adds the
1281 rest of that page to the address space. */
1282 bzero (first_heap
->start
,
1283 (char *) first_heap
->end
- (char *) first_heap
->start
);
1284 virtual_break_value
= break_value
= first_heap
->bloc_start
= first_heap
->end
;
1287 use_relocatable_buffers
= 1;
1290 /* arch-tag: 6a524a15-faff-44c8-95d4-a5da6f55110f
1291 (do not change this comment) */