aboutsummaryrefslogtreecommitdiffstats
path: root/src/ralloc.c
diff options
context:
space:
mode:
authorBill Wohler2012-11-24 19:43:02 -0800
committerBill Wohler2012-11-24 19:43:02 -0800
commit5244bc019bf7376caff3bb198ff674e0ad9fb0e6 (patch)
tree02ee1615e904771f692ec2957c79a08ae029a13d /src/ralloc.c
parent9f7e719509474e92f85955e22e57ffeebd4e96f3 (diff)
parentc07a6ded1df2f4156badc9add2953579622c3722 (diff)
downloademacs-5244bc019bf7376caff3bb198ff674e0ad9fb0e6.tar.gz
emacs-5244bc019bf7376caff3bb198ff674e0ad9fb0e6.zip
Merge from trunk.
Diffstat (limited to 'src/ralloc.c')
-rw-r--r--src/ralloc.c234
1 files changed, 107 insertions, 127 deletions
diff --git a/src/ralloc.c b/src/ralloc.c
index 62189ad8fc7..e5bf76b0e6d 100644
--- a/src/ralloc.c
+++ b/src/ralloc.c
@@ -1,5 +1,5 @@
1/* Block-relocating memory allocator. 1/* Block-relocating memory allocator.
2 Copyright (C) 1993, 1995, 2000-2011 Free Software Foundation, Inc. 2 Copyright (C) 1993, 1995, 2000-2012 Free Software Foundation, Inc.
3 3
4This file is part of GNU Emacs. 4This file is part of GNU Emacs.
5 5
@@ -25,15 +25,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
25#ifdef emacs 25#ifdef emacs
26 26
27#include <config.h> 27#include <config.h>
28#include <setjmp.h> 28
29#include "lisp.h" /* Needed for VALBITS. */ 29#include "lisp.h" /* Needed for VALBITS. */
30#include "blockinput.h" 30#include "blockinput.h"
31 31
32#include <unistd.h> 32#include <unistd.h>
33 33
34typedef POINTER_TYPE *POINTER;
35typedef size_t SIZE;
36
37#ifdef DOUG_LEA_MALLOC 34#ifdef DOUG_LEA_MALLOC
38#define M_TOP_PAD -2 35#define M_TOP_PAD -2
39extern int mallopt (int, int); 36extern int mallopt (int, int);
@@ -47,9 +44,6 @@ extern size_t __malloc_extra_blocks;
47 44
48#include <stddef.h> 45#include <stddef.h>
49 46
50typedef size_t SIZE;
51typedef void *POINTER;
52
53#include <unistd.h> 47#include <unistd.h>
54#include <malloc.h> 48#include <malloc.h>
55 49
@@ -58,6 +52,8 @@ typedef void *POINTER;
58 52
59#include "getpagesize.h" 53#include "getpagesize.h"
60 54
55typedef size_t SIZE;
56typedef void *POINTER;
61#define NIL ((POINTER) 0) 57#define NIL ((POINTER) 0)
62 58
63/* A flag to indicate whether we have initialized ralloc yet. For 59/* A flag to indicate whether we have initialized ralloc yet. For
@@ -76,7 +72,7 @@ static void r_alloc_init (void);
76/* Declarations for working with the malloc, ralloc, and system breaks. */ 72/* Declarations for working with the malloc, ralloc, and system breaks. */
77 73
78/* Function to set the real break value. */ 74/* Function to set the real break value. */
79POINTER (*real_morecore) (long int); 75POINTER (*real_morecore) (ptrdiff_t);
80 76
81/* The break value, as seen by malloc. */ 77/* The break value, as seen by malloc. */
82static POINTER virtual_break_value; 78static POINTER virtual_break_value;
@@ -95,20 +91,18 @@ static int extra_bytes;
95/* Macros for rounding. Note that rounding to any value is possible 91/* Macros for rounding. Note that rounding to any value is possible
96 by changing the definition of PAGE. */ 92 by changing the definition of PAGE. */
97#define PAGE (getpagesize ()) 93#define PAGE (getpagesize ())
98#define ALIGNED(addr) (((unsigned long int) (addr) & (page_size - 1)) == 0) 94#define ROUNDUP(size) (((size_t) (size) + page_size - 1) \
99#define ROUNDUP(size) (((unsigned long int) (size) + page_size - 1) \ 95 & ~((size_t)(page_size - 1)))
100 & ~(page_size - 1))
101#define ROUND_TO_PAGE(addr) (addr & (~(page_size - 1)))
102 96
103#define MEM_ALIGN sizeof (double) 97#define MEM_ALIGN sizeof (double)
104#define MEM_ROUNDUP(addr) (((unsigned long int)(addr) + MEM_ALIGN - 1) \ 98#define MEM_ROUNDUP(addr) (((size_t)(addr) + MEM_ALIGN - 1) \
105 & ~(MEM_ALIGN - 1)) 99 & ~(MEM_ALIGN - 1))
106 100
107/* The hook `malloc' uses for the function which gets more space 101/* The hook `malloc' uses for the function which gets more space
108 from the system. */ 102 from the system. */
109 103
110#ifndef SYSTEM_MALLOC 104#ifndef SYSTEM_MALLOC
111extern POINTER (*__morecore) (long int); 105extern POINTER (*__morecore) (ptrdiff_t);
112#endif 106#endif
113 107
114 108
@@ -151,7 +145,6 @@ typedef struct heap
151} *heap_ptr; 145} *heap_ptr;
152 146
153#define NIL_HEAP ((heap_ptr) 0) 147#define NIL_HEAP ((heap_ptr) 0)
154#define HEAP_PTR_SIZE (sizeof (struct heap))
155 148
156/* This is the first heap object. 149/* This is the first heap object.
157 If we need additional heap objects, each one resides at the beginning of 150 If we need additional heap objects, each one resides at the beginning of
@@ -244,7 +237,7 @@ obtain (POINTER address, SIZE size)
244 } 237 }
245 238
246 if (! heap) 239 if (! heap)
247 abort (); 240 emacs_abort ();
248 241
249 /* If we can't fit SIZE bytes in that heap, 242 /* If we can't fit SIZE bytes in that heap,
250 try successive later heaps. */ 243 try successive later heaps. */
@@ -315,7 +308,7 @@ static void
315relinquish (void) 308relinquish (void)
316{ 309{
317 register heap_ptr h; 310 register heap_ptr h;
318 long excess = 0; 311 ptrdiff_t excess = 0;
319 312
320 /* Add the amount of space beyond break_value 313 /* Add the amount of space beyond break_value
321 in all heaps which have extend beyond break_value at all. */ 314 in all heaps which have extend beyond break_value at all. */
@@ -334,47 +327,39 @@ relinquish (void)
334 327
335 if ((char *)last_heap->end - (char *)last_heap->bloc_start <= excess) 328 if ((char *)last_heap->end - (char *)last_heap->bloc_start <= excess)
336 { 329 {
337 /* This heap should have no blocs in it. */ 330 heap_ptr lh_prev;
331
332 /* This heap should have no blocs in it. If it does, we
333 cannot return it to the system. */
338 if (last_heap->first_bloc != NIL_BLOC 334 if (last_heap->first_bloc != NIL_BLOC
339 || last_heap->last_bloc != NIL_BLOC) 335 || last_heap->last_bloc != NIL_BLOC)
340 abort (); 336 return;
341 337
342 /* Return the last heap, with its header, to the system. */ 338 /* Return the last heap, with its header, to the system. */
343 excess = (char *)last_heap->end - (char *)last_heap->start; 339 excess = (char *)last_heap->end - (char *)last_heap->start;
344 last_heap = last_heap->prev; 340 lh_prev = last_heap->prev;
345 last_heap->next = NIL_HEAP; 341 /* If the system doesn't want that much memory back, leave
342 last_heap unaltered to reflect that. This can occur if
343 break_value is still within the original data segment. */
344 if ((*real_morecore) (- excess) != 0)
345 {
346 last_heap = lh_prev;
347 last_heap->next = NIL_HEAP;
348 }
346 } 349 }
347 else 350 else
348 { 351 {
349 excess = (char *) last_heap->end 352 excess = (char *) last_heap->end
350 - (char *) ROUNDUP ((char *)last_heap->end - excess); 353 - (char *) ROUNDUP ((char *)last_heap->end - excess);
351 last_heap->end = (char *) last_heap->end - excess; 354 /* If the system doesn't want that much memory back, leave
352 } 355 the end of the last heap unchanged to reflect that. This
353 356 can occur if break_value is still within the original
354 if ((*real_morecore) (- excess) == 0) 357 data segment. */
355 { 358 if ((*real_morecore) (- excess) != 0)
356 /* If the system didn't want that much memory back, adjust 359 last_heap->end = (char *) last_heap->end - excess;
357 the end of the last heap to reflect that. This can occur
358 if break_value is still within the original data segment. */
359 last_heap->end = (char *) last_heap->end + excess;
360 /* Make sure that the result of the adjustment is accurate.
361 It should be, for the else clause above; the other case,
362 which returns the entire last heap to the system, seems
363 unlikely to trigger this mode of failure. */
364 if (last_heap->end != (*real_morecore) (0))
365 abort ();
366 } 360 }
367 } 361 }
368} 362}
369
370/* Return the total size in use by relocating allocator,
371 above where malloc gets space. */
372
373long
374r_alloc_size_in_use (void)
375{
376 return (char *) break_value - (char *) virtual_break_value;
377}
378 363
379/* The meat - allocating, freeing, and relocating blocs. */ 364/* The meat - allocating, freeing, and relocating blocs. */
380 365
@@ -412,7 +397,7 @@ get_bloc (SIZE size)
412 register bloc_ptr new_bloc; 397 register bloc_ptr new_bloc;
413 register heap_ptr heap; 398 register heap_ptr heap;
414 399
415 if (! (new_bloc = (bloc_ptr) malloc (BLOC_PTR_SIZE)) 400 if (! (new_bloc = malloc (BLOC_PTR_SIZE))
416 || ! (new_bloc->data = obtain (break_value, size))) 401 || ! (new_bloc->data = obtain (break_value, size)))
417 { 402 {
418 free (new_bloc); 403 free (new_bloc);
@@ -468,7 +453,7 @@ relocate_blocs (bloc_ptr bloc, heap_ptr heap, POINTER address)
468 453
469 /* No need to ever call this if arena is frozen, bug somewhere! */ 454 /* No need to ever call this if arena is frozen, bug somewhere! */
470 if (r_alloc_freeze_level) 455 if (r_alloc_freeze_level)
471 abort (); 456 emacs_abort ();
472 457
473 while (b) 458 while (b)
474 { 459 {
@@ -592,7 +577,7 @@ resize_bloc (bloc_ptr bloc, SIZE size)
592 577
593 /* No need to ever call this if arena is frozen, bug somewhere! */ 578 /* No need to ever call this if arena is frozen, bug somewhere! */
594 if (r_alloc_freeze_level) 579 if (r_alloc_freeze_level)
595 abort (); 580 emacs_abort ();
596 581
597 if (bloc == NIL_BLOC || size == bloc->size) 582 if (bloc == NIL_BLOC || size == bloc->size)
598 return 1; 583 return 1;
@@ -604,7 +589,7 @@ resize_bloc (bloc_ptr bloc, SIZE size)
604 } 589 }
605 590
606 if (heap == NIL_HEAP) 591 if (heap == NIL_HEAP)
607 abort (); 592 emacs_abort ();
608 593
609 old_size = bloc->size; 594 old_size = bloc->size;
610 bloc->size = size; 595 bloc->size = size;
@@ -636,7 +621,8 @@ resize_bloc (bloc_ptr bloc, SIZE size)
636 } 621 }
637 else 622 else
638 { 623 {
639 memmove (b->new_data, b->data, b->size); 624 if (b->new_data != b->data)
625 memmove (b->new_data, b->data, b->size);
640 *b->variable = b->data = b->new_data; 626 *b->variable = b->data = b->new_data;
641 } 627 }
642 } 628 }
@@ -647,7 +633,8 @@ resize_bloc (bloc_ptr bloc, SIZE size)
647 } 633 }
648 else 634 else
649 { 635 {
650 memmove (bloc->new_data, bloc->data, old_size); 636 if (bloc->new_data != bloc->data)
637 memmove (bloc->new_data, bloc->data, old_size);
651 memset ((char *) bloc->new_data + old_size, 0, size - old_size); 638 memset ((char *) bloc->new_data + old_size, 0, size - old_size);
652 *bloc->variable = bloc->data = bloc->new_data; 639 *bloc->variable = bloc->data = bloc->new_data;
653 } 640 }
@@ -663,7 +650,8 @@ resize_bloc (bloc_ptr bloc, SIZE size)
663 } 650 }
664 else 651 else
665 { 652 {
666 memmove (b->new_data, b->data, b->size); 653 if (b->new_data != b->data)
654 memmove (b->new_data, b->data, b->size);
667 *b->variable = b->data = b->new_data; 655 *b->variable = b->data = b->new_data;
668 } 656 }
669 } 657 }
@@ -683,6 +671,7 @@ static void
683free_bloc (bloc_ptr bloc) 671free_bloc (bloc_ptr bloc)
684{ 672{
685 heap_ptr heap = bloc->heap; 673 heap_ptr heap = bloc->heap;
674 heap_ptr h;
686 675
687 if (r_alloc_freeze_level) 676 if (r_alloc_freeze_level)
688 { 677 {
@@ -712,20 +701,38 @@ free_bloc (bloc_ptr bloc)
712 bloc->prev->next = bloc->next; 701 bloc->prev->next = bloc->next;
713 } 702 }
714 703
715 /* Update the records of which blocs are in HEAP. */ 704 /* Sometimes, 'heap' obtained from bloc->heap above is not really a
716 if (heap->first_bloc == bloc) 705 'heap' structure. It can even be beyond the current break point,
717 { 706 which will cause crashes when we dereference it below (see
718 if (bloc->next != 0 && bloc->next->heap == heap) 707 bug#12242). Evidently, the reason is bloc allocations done while
719 heap->first_bloc = bloc->next; 708 use_relocatable_buffers was non-positive, because additional
720 else 709 memory we get then is not recorded in the heaps we manage. If
721 heap->first_bloc = heap->last_bloc = NIL_BLOC; 710 bloc->heap records such a "heap", we cannot (and don't need to)
722 } 711 update its records. So we validate the 'heap' value by making
723 if (heap->last_bloc == bloc) 712 sure it is one of the heaps we manage via the heaps linked list,
713 and don't touch a 'heap' that isn't found there. This avoids
714 accessing memory we know nothing about. */
715 for (h = first_heap; h != NIL_HEAP; h = h->next)
716 if (heap == h)
717 break;
718
719 if (h)
724 { 720 {
725 if (bloc->prev != 0 && bloc->prev->heap == heap) 721 /* Update the records of which blocs are in HEAP. */
726 heap->last_bloc = bloc->prev; 722 if (heap->first_bloc == bloc)
727 else 723 {
728 heap->first_bloc = heap->last_bloc = NIL_BLOC; 724 if (bloc->next != 0 && bloc->next->heap == heap)
725 heap->first_bloc = bloc->next;
726 else
727 heap->first_bloc = heap->last_bloc = NIL_BLOC;
728 }
729 if (heap->last_bloc == bloc)
730 {
731 if (bloc->prev != 0 && bloc->prev->heap == heap)
732 heap->last_bloc = bloc->prev;
733 else
734 heap->first_bloc = heap->last_bloc = NIL_BLOC;
735 }
729 } 736 }
730 737
731 relinquish (); 738 relinquish ();
@@ -745,8 +752,8 @@ free_bloc (bloc_ptr bloc)
745 __morecore hook values - in particular, __default_morecore in the 752 __morecore hook values - in particular, __default_morecore in the
746 GNU malloc package. */ 753 GNU malloc package. */
747 754
748POINTER 755static POINTER
749r_alloc_sbrk (long int size) 756r_alloc_sbrk (ptrdiff_t size)
750{ 757{
751 register bloc_ptr b; 758 register bloc_ptr b;
752 POINTER address; 759 POINTER address;
@@ -754,7 +761,7 @@ r_alloc_sbrk (long int size)
754 if (! r_alloc_initialized) 761 if (! r_alloc_initialized)
755 r_alloc_init (); 762 r_alloc_init ();
756 763
757 if (! use_relocatable_buffers) 764 if (use_relocatable_buffers <= 0)
758 return (*real_morecore) (size); 765 return (*real_morecore) (size);
759 766
760 if (size == 0) 767 if (size == 0)
@@ -816,7 +823,8 @@ r_alloc_sbrk (long int size)
816 header. */ 823 header. */
817 for (b = last_bloc; b != NIL_BLOC; b = b->prev) 824 for (b = last_bloc; b != NIL_BLOC; b = b->prev)
818 { 825 {
819 memmove (b->new_data, b->data, b->size); 826 if (b->new_data != b->data)
827 memmove (b->new_data, b->data, b->size);
820 *b->variable = b->data = b->new_data; 828 *b->variable = b->data = b->new_data;
821 } 829 }
822 830
@@ -862,7 +870,8 @@ r_alloc_sbrk (long int size)
862 870
863 for (b = first_bloc; b != NIL_BLOC; b = b->next) 871 for (b = first_bloc; b != NIL_BLOC; b = b->next)
864 { 872 {
865 memmove (b->new_data, b->data, b->size); 873 if (b->new_data != b->data)
874 memmove (b->new_data, b->data, b->size);
866 *b->variable = b->data = b->new_data; 875 *b->variable = b->data = b->new_data;
867 } 876 }
868 } 877 }
@@ -929,7 +938,7 @@ r_alloc_free (register POINTER *ptr)
929 938
930 dead_bloc = find_bloc (ptr); 939 dead_bloc = find_bloc (ptr);
931 if (dead_bloc == NIL_BLOC) 940 if (dead_bloc == NIL_BLOC)
932 abort (); /* Double free? PTR not originally used to allocate? */ 941 emacs_abort (); /* Double free? PTR not originally used to allocate? */
933 942
934 free_bloc (dead_bloc); 943 free_bloc (dead_bloc);
935 *ptr = 0; 944 *ptr = 0;
@@ -971,7 +980,7 @@ r_re_alloc (POINTER *ptr, SIZE size)
971 980
972 bloc = find_bloc (ptr); 981 bloc = find_bloc (ptr);
973 if (bloc == NIL_BLOC) 982 if (bloc == NIL_BLOC)
974 abort (); /* Already freed? PTR not originally used to allocate? */ 983 emacs_abort (); /* Already freed? PTR not originally used to allocate? */
975 984
976 if (size < bloc->size) 985 if (size < bloc->size)
977 { 986 {
@@ -1009,52 +1018,6 @@ r_re_alloc (POINTER *ptr, SIZE size)
1009 return *ptr; 1018 return *ptr;
1010} 1019}
1011 1020
1012/* Disable relocations, after making room for at least SIZE bytes
1013 of non-relocatable heap if possible. The relocatable blocs are
1014 guaranteed to hold still until thawed, even if this means that
1015 malloc must return a null pointer. */
1016
1017void
1018r_alloc_freeze (long int size)
1019{
1020 if (! r_alloc_initialized)
1021 r_alloc_init ();
1022
1023 /* If already frozen, we can't make any more room, so don't try. */
1024 if (r_alloc_freeze_level > 0)
1025 size = 0;
1026 /* If we can't get the amount requested, half is better than nothing. */
1027 while (size > 0 && r_alloc_sbrk (size) == 0)
1028 size /= 2;
1029 ++r_alloc_freeze_level;
1030 if (size > 0)
1031 r_alloc_sbrk (-size);
1032}
1033
1034void
1035r_alloc_thaw (void)
1036{
1037
1038 if (! r_alloc_initialized)
1039 r_alloc_init ();
1040
1041 if (--r_alloc_freeze_level < 0)
1042 abort ();
1043
1044 /* This frees all unused blocs. It is not too inefficient, as the resize
1045 and memcpy is done only once. Afterwards, all unreferenced blocs are
1046 already shrunk to zero size. */
1047 if (!r_alloc_freeze_level)
1048 {
1049 bloc_ptr *b = &first_bloc;
1050 while (*b)
1051 if (!(*b)->variable)
1052 free_bloc (*b);
1053 else
1054 b = &(*b)->next;
1055 }
1056}
1057
1058 1021
1059#if defined (emacs) && defined (DOUG_LEA_MALLOC) 1022#if defined (emacs) && defined (DOUG_LEA_MALLOC)
1060 1023
@@ -1190,12 +1153,23 @@ r_alloc_reset_variable (POINTER *old, POINTER *new)
1190 } 1153 }
1191 1154
1192 if (bloc == NIL_BLOC || bloc->variable != old) 1155 if (bloc == NIL_BLOC || bloc->variable != old)
1193 abort (); /* Already freed? OLD not originally used to allocate? */ 1156 emacs_abort (); /* Already freed? OLD not originally used to allocate? */
1194 1157
1195 /* Update variable to point to the new location. */ 1158 /* Update variable to point to the new location. */
1196 bloc->variable = new; 1159 bloc->variable = new;
1197} 1160}
1198 1161
1162void
1163r_alloc_inhibit_buffer_relocation (int inhibit)
1164{
1165 if (use_relocatable_buffers > 1)
1166 use_relocatable_buffers = 1;
1167 if (inhibit)
1168 use_relocatable_buffers--;
1169 else if (use_relocatable_buffers < 1)
1170 use_relocatable_buffers++;
1171}
1172
1199 1173
1200/*********************************************************************** 1174/***********************************************************************
1201 Initialization 1175 Initialization
@@ -1220,20 +1194,26 @@ r_alloc_init (void)
1220 first_heap->start = first_heap->bloc_start 1194 first_heap->start = first_heap->bloc_start
1221 = virtual_break_value = break_value = (*real_morecore) (0); 1195 = virtual_break_value = break_value = (*real_morecore) (0);
1222 if (break_value == NIL) 1196 if (break_value == NIL)
1223 abort (); 1197 emacs_abort ();
1224 1198
1225 extra_bytes = ROUNDUP (50000); 1199 extra_bytes = ROUNDUP (50000);
1226#endif 1200#endif
1227 1201
1228#ifdef DOUG_LEA_MALLOC 1202#ifdef DOUG_LEA_MALLOC
1229 BLOCK_INPUT; 1203 block_input ();
1230 mallopt (M_TOP_PAD, 64 * 4096); 1204 mallopt (M_TOP_PAD, 64 * 4096);
1231 UNBLOCK_INPUT; 1205 unblock_input ();
1232#else 1206#else
1233#ifndef SYSTEM_MALLOC 1207#ifndef SYSTEM_MALLOC
1234 /* Give GNU malloc's morecore some hysteresis 1208 /* Give GNU malloc's morecore some hysteresis so that we move all
1235 so that we move all the relocatable blocks much less often. */ 1209 the relocatable blocks much less often. The number used to be
1236 __malloc_extra_blocks = 64; 1210 64, but alloc.c would override that with 32 in code that was
1211 removed when SYNC_INPUT became the only input handling mode.
1212 That code was conditioned on !DOUG_LEA_MALLOC, so the call to
1213 mallopt above is left unchanged. (Actually, I think there's no
1214 system nowadays that uses DOUG_LEA_MALLOC and also uses
1215 REL_ALLOC.) */
1216 __malloc_extra_blocks = 32;
1237#endif 1217#endif
1238#endif 1218#endif
1239 1219