Mercurial > hg > xemacs-beta
comparison src/ralloc.c @ 272:c5d627a313b1 r21-0b34
Import from CVS: tag r21-0b34
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:28:48 +0200 |
parents | 084402c475ba |
children | ca9a9ec9c1c1 |
comparison
equal
deleted
inserted
replaced
271:c7b7086b0a39 | 272:c5d627a313b1 |
---|---|
25 | 25 |
26 Only relocate the blocs necessary for SIZE in r_alloc_sbrk, | 26 Only relocate the blocs necessary for SIZE in r_alloc_sbrk, |
27 rather than all of them. This means allowing for a possible | 27 rather than all of them. This means allowing for a possible |
28 hole between the first bloc and the end of malloc storage. */ | 28 hole between the first bloc and the end of malloc storage. */ |
29 | 29 |
30 #ifdef HAVE_CONFIG_H | |
31 #include <config.h> | |
32 #endif | |
33 | |
34 #ifdef HAVE_UNISTD_H | |
35 #include <unistd.h> /* for getpagesize() */ | |
36 #endif | |
37 | |
30 #ifdef emacs | 38 #ifdef emacs |
31 | 39 |
32 #include <config.h> | 40 #include "lisp.h" |
33 #include "lisp.h" /* Needed for VALBITS. */ | 41 #include <malloc.h> |
34 | |
35 #undef NULL | |
36 | 42 |
37 /* The important properties of this type are that 1) it's a pointer, and | 43 /* The important properties of this type are that 1) it's a pointer, and |
38 2) arithmetic on it should work as if the size of the object pointed | 44 2) arithmetic on it should work as if the size of the object pointed |
39 to has a size of 1. */ | 45 to has a size of 1. */ |
40 #if 0 /* Arithmetic on void* is a GCC extension. */ | 46 #if 0 /* Arithmetic on void* is a GCC extension. */ |
49 typedef unsigned char *POINTER; | 55 typedef unsigned char *POINTER; |
50 | 56 |
51 typedef unsigned long SIZE; | 57 typedef unsigned long SIZE; |
52 | 58 |
53 #ifdef DOUG_LEA_MALLOC | 59 #ifdef DOUG_LEA_MALLOC |
54 #define M_TOP_PAD -2 | 60 #define M_TOP_PAD -2 |
55 extern int mallopt (); | |
56 #endif | 61 #endif |
57 | 62 |
58 #include "getpagesize.h" | 63 #include "getpagesize.h" |
59 | 64 |
60 #include <string.h> | 65 #include <string.h> |
66 void refill_memory_reserve (void); | |
61 | 67 |
62 #else /* Not emacs. */ | 68 #else /* Not emacs. */ |
63 | 69 |
64 #include <stddef.h> | 70 #include <stddef.h> |
65 | 71 |
70 #include <malloc.h> | 76 #include <malloc.h> |
71 #include <string.h> | 77 #include <string.h> |
72 | 78 |
73 #endif /* emacs. */ | 79 #endif /* emacs. */ |
74 | 80 |
81 void init_ralloc (void); | |
75 #define safe_bcopy(x, y, z) memmove (y, x, z) | 82 #define safe_bcopy(x, y, z) memmove (y, x, z) |
76 | 83 |
77 #define NIL ((POINTER) 0) | 84 #define NIL ((POINTER) 0) |
78 | 85 |
79 | 86 |
89 | 96 |
90 | 97 |
91 /* Declarations for working with the malloc, ralloc, and system breaks. */ | 98 /* Declarations for working with the malloc, ralloc, and system breaks. */ |
92 | 99 |
93 /* Function to set the real break value. */ | 100 /* Function to set the real break value. */ |
94 static POINTER (*real_morecore) (); | 101 static POINTER (*real_morecore) (long size); |
95 | 102 |
96 /* The break value, as seen by malloc (). */ | 103 /* The break value, as seen by malloc (). */ |
97 static POINTER virtual_break_value; | 104 static POINTER virtual_break_value; |
98 | 105 |
99 /* The break value, viewed by the relocatable blocs. */ | 106 /* The break value, viewed by the relocatable blocs. */ |
100 static POINTER break_value; | 107 static POINTER break_value; |
101 | |
102 /* The REAL (i.e., page aligned) break value of the process. */ | |
103 static POINTER page_break_value; | |
104 | 108 |
105 /* This is the size of a page. We round memory requests to this boundary. */ | 109 /* This is the size of a page. We round memory requests to this boundary. */ |
106 static int page_size; | 110 static int page_size; |
107 | 111 |
108 /* Whenever we get memory from the system, get this many extra bytes. This | 112 /* Whenever we get memory from the system, get this many extra bytes. This |
133 but they never move. | 137 but they never move. |
134 | 138 |
135 We try to make just one heap and make it larger as necessary. | 139 We try to make just one heap and make it larger as necessary. |
136 But sometimes we can't do that, because we can't get contiguous | 140 But sometimes we can't do that, because we can't get contiguous |
137 space to add onto the heap. When that happens, we start a new heap. */ | 141 space to add onto the heap. When that happens, we start a new heap. */ |
138 | 142 |
139 typedef struct heap | 143 typedef struct heap |
140 { | 144 { |
141 struct heap *next; | 145 struct heap *next; |
142 struct heap *prev; | 146 struct heap *prev; |
143 /* Start of memory range of this heap. */ | 147 /* Start of memory range of this heap. */ |
207 /* Functions to get and return memory from the system. */ | 211 /* Functions to get and return memory from the system. */ |
208 | 212 |
209 /* Find the heap that ADDRESS falls within. */ | 213 /* Find the heap that ADDRESS falls within. */ |
210 | 214 |
211 static heap_ptr | 215 static heap_ptr |
212 find_heap (address) | 216 find_heap (POINTER address) |
213 POINTER address; | |
214 { | 217 { |
215 heap_ptr heap; | 218 heap_ptr heap; |
216 | 219 |
217 for (heap = last_heap; heap; heap = heap->prev) | 220 for (heap = last_heap; heap; heap = heap->prev) |
218 { | 221 { |
381 } | 384 } |
382 | 385 |
383 /* Return the total size in use by relocating allocator, | 386 /* Return the total size in use by relocating allocator, |
384 above where malloc gets space. */ | 387 above where malloc gets space. */ |
385 | 388 |
389 long r_alloc_size_in_use (void); | |
386 long | 390 long |
387 r_alloc_size_in_use () | 391 r_alloc_size_in_use () |
388 { | 392 { |
389 return break_value - virtual_break_value; | 393 return break_value - virtual_break_value; |
390 } | 394 } |
464 } | 468 } |
465 | 469 |
466 /* Calculate new locations of blocs in the list beginning with BLOC, | 470 /* Calculate new locations of blocs in the list beginning with BLOC, |
467 relocating it to start at ADDRESS, in heap HEAP. If enough space is | 471 relocating it to start at ADDRESS, in heap HEAP. If enough space is |
468 not presently available in our reserve, call obtain for | 472 not presently available in our reserve, call obtain for |
469 more space. | 473 more space. |
470 | 474 |
471 Store the new location of each bloc in its new_data field. | 475 Store the new location of each bloc in its new_data field. |
472 Do not touch the contents of blocs or break_value. */ | 476 Do not touch the contents of blocs or break_value. */ |
473 | 477 |
474 static int | 478 static int |
475 relocate_blocs (bloc, heap, address) | 479 relocate_blocs (bloc_ptr bloc, heap_ptr heap, POINTER address) |
476 bloc_ptr bloc; | |
477 heap_ptr heap; | |
478 POINTER address; | |
479 { | 480 { |
480 register bloc_ptr b = bloc; | 481 register bloc_ptr b = bloc; |
481 | 482 |
482 /* No need to ever call this if arena is frozen, bug somewhere! */ | 483 /* No need to ever call this if arena is frozen, bug somewhere! */ |
483 if (r_alloc_freeze_level) | 484 if (r_alloc_freeze_level) |
484 abort(); | 485 abort(); |
485 | 486 |
486 while (b) | 487 while (b) |
487 { | 488 { |
488 /* If bloc B won't fit within HEAP, | 489 /* If bloc B won't fit within HEAP, |
503 register SIZE s = 0; | 504 register SIZE s = 0; |
504 | 505 |
505 /* Add up the size of all the following blocs. */ | 506 /* Add up the size of all the following blocs. */ |
506 while (tb != NIL_BLOC) | 507 while (tb != NIL_BLOC) |
507 { | 508 { |
508 if (tb->variable) | 509 if (tb->variable) |
509 s += tb->size; | 510 s += tb->size; |
510 | 511 |
511 tb = tb->next; | 512 tb = tb->next; |
512 } | 513 } |
513 | 514 |
520 } | 521 } |
521 | 522 |
522 /* Record the new address of this bloc | 523 /* Record the new address of this bloc |
523 and update where the next bloc can start. */ | 524 and update where the next bloc can start. */ |
524 b->new_data = address; | 525 b->new_data = address; |
525 if (b->variable) | 526 if (b->variable) |
526 address += b->size; | 527 address += b->size; |
527 b = b->next; | 528 b = b->next; |
528 } | 529 } |
529 | 530 |
530 return 1; | 531 return 1; |
531 } | 532 } |
532 | 533 |
534 #if 0 /* unused */ | |
533 /* Reorder the bloc BLOC to go before bloc BEFORE in the doubly linked list. | 535 /* Reorder the bloc BLOC to go before bloc BEFORE in the doubly linked list. |
534 This is necessary if we put the memory of space of BLOC | 536 This is necessary if we put the memory of space of BLOC |
535 before that of BEFORE. */ | 537 before that of BEFORE. */ |
536 | 538 |
537 static void | 539 static void |
538 reorder_bloc (bloc, before) | 540 reorder_bloc (bloc_ptr bloc, bloc_ptr before) |
539 bloc_ptr bloc, before; | |
540 { | 541 { |
541 bloc_ptr prev, next; | 542 bloc_ptr prev, next; |
542 | 543 |
543 /* Splice BLOC out from where it is. */ | 544 /* Splice BLOC out from where it is. */ |
544 prev = bloc->prev; | 545 prev = bloc->prev; |
557 bloc->prev = prev; | 558 bloc->prev = prev; |
558 | 559 |
559 before->prev = bloc; | 560 before->prev = bloc; |
560 bloc->next = before; | 561 bloc->next = before; |
561 } | 562 } |
563 #endif /* unused */ | |
562 | 564 |
563 /* Update the records of which heaps contain which blocs, starting | 565 /* Update the records of which heaps contain which blocs, starting |
564 with heap HEAP and bloc BLOC. */ | 566 with heap HEAP and bloc BLOC. */ |
565 | 567 |
566 static void | 568 static void |
567 update_heap_bloc_correspondence (bloc, heap) | 569 update_heap_bloc_correspondence (bloc_ptr bloc, heap_ptr heap) |
568 bloc_ptr bloc; | |
569 heap_ptr heap; | |
570 { | 570 { |
571 register bloc_ptr b; | 571 register bloc_ptr b; |
572 | 572 |
573 /* Initialize HEAP's status to reflect blocs before BLOC. */ | 573 /* Initialize HEAP's status to reflect blocs before BLOC. */ |
574 if (bloc != NIL_BLOC && bloc->prev != NIL_BLOC && bloc->prev->heap == heap) | 574 if (bloc != NIL_BLOC && bloc->prev != NIL_BLOC && bloc->prev->heap == heap) |
626 | 626 |
627 /* Resize BLOC to SIZE bytes. This relocates the blocs | 627 /* Resize BLOC to SIZE bytes. This relocates the blocs |
628 that come after BLOC in memory. */ | 628 that come after BLOC in memory. */ |
629 | 629 |
630 static int | 630 static int |
631 resize_bloc (bloc, size) | 631 resize_bloc (bloc_ptr bloc, SIZE size) |
632 bloc_ptr bloc; | |
633 SIZE size; | |
634 { | 632 { |
635 register bloc_ptr b; | 633 register bloc_ptr b; |
636 heap_ptr heap; | 634 heap_ptr heap; |
637 POINTER address; | 635 POINTER address; |
638 SIZE old_size; | 636 SIZE old_size; |
639 | 637 |
640 /* No need to ever call this if arena is frozen, bug somewhere! */ | 638 /* No need to ever call this if arena is frozen, bug somewhere! */ |
641 if (r_alloc_freeze_level) | 639 if (r_alloc_freeze_level) |
642 abort(); | 640 abort(); |
643 | 641 |
644 if (bloc == NIL_BLOC || size == bloc->size) | 642 if (bloc == NIL_BLOC || size == bloc->size) |
645 return 1; | 643 return 1; |
646 | 644 |
678 { | 676 { |
679 if (!b->variable) | 677 if (!b->variable) |
680 { | 678 { |
681 b->size = 0; | 679 b->size = 0; |
682 b->data = b->new_data; | 680 b->data = b->new_data; |
683 } | 681 } |
684 else | 682 else |
685 { | 683 { |
686 safe_bcopy (b->data, b->new_data, b->size); | 684 safe_bcopy (b->data, b->new_data, b->size); |
687 *b->variable = b->data = b->new_data; | 685 *b->variable = b->data = b->new_data; |
688 } | 686 } |
689 } | 687 } |
705 { | 703 { |
706 if (!b->variable) | 704 if (!b->variable) |
707 { | 705 { |
708 b->size = 0; | 706 b->size = 0; |
709 b->data = b->new_data; | 707 b->data = b->new_data; |
710 } | 708 } |
711 else | 709 else |
712 { | 710 { |
713 safe_bcopy (b->data, b->new_data, b->size); | 711 safe_bcopy (b->data, b->new_data, b->size); |
714 *b->variable = b->data = b->new_data; | 712 *b->variable = b->data = b->new_data; |
715 } | 713 } |
716 } | 714 } |
734 if (r_alloc_freeze_level) | 732 if (r_alloc_freeze_level) |
735 { | 733 { |
736 bloc->variable = (POINTER *) NIL; | 734 bloc->variable = (POINTER *) NIL; |
737 return; | 735 return; |
738 } | 736 } |
739 | 737 |
740 resize_bloc (bloc, 0); | 738 resize_bloc (bloc, 0); |
741 | 739 |
742 if (bloc == first_bloc && bloc == last_bloc) | 740 if (bloc == first_bloc && bloc == last_bloc) |
743 { | 741 { |
744 first_bloc = last_bloc = NIL_BLOC; | 742 first_bloc = last_bloc = NIL_BLOC; |
790 | 788 |
791 If we're out of memory, we should return zero, to imitate the other | 789 If we're out of memory, we should return zero, to imitate the other |
792 __morecore hook values - in particular, __default_morecore in the | 790 __morecore hook values - in particular, __default_morecore in the |
793 GNU malloc package. */ | 791 GNU malloc package. */ |
794 | 792 |
793 POINTER r_alloc_sbrk (long size); | |
795 POINTER | 794 POINTER |
796 r_alloc_sbrk (long size) | 795 r_alloc_sbrk (long size) |
797 { | 796 { |
798 register bloc_ptr b; | 797 register bloc_ptr b; |
799 POINTER address; | 798 POINTER address; |
845 new_bloc_start = (POINTER) MEM_ROUNDUP ((char *)address + get); | 844 new_bloc_start = (POINTER) MEM_ROUNDUP ((char *)address + get); |
846 | 845 |
847 if (first_heap->bloc_start < new_bloc_start) | 846 if (first_heap->bloc_start < new_bloc_start) |
848 { | 847 { |
849 /* This is no clean solution - no idea how to do it better. */ | 848 /* This is no clean solution - no idea how to do it better. */ |
850 if (r_alloc_freeze_level) | 849 if (r_alloc_freeze_level) |
851 return NIL; | 850 return NIL; |
852 | 851 |
853 /* There is a bug here: if the above obtain call succeeded, but the | 852 /* There is a bug here: if the above obtain call succeeded, but the |
854 relocate_blocs call below does not succeed, we need to free | 853 relocate_blocs call below does not succeed, we need to free |
855 the memory that we got with obtain. */ | 854 the memory that we got with obtain. */ |
940 before allocating a new area. Not yet done. | 939 before allocating a new area. Not yet done. |
941 | 940 |
942 If we can't allocate the necessary memory, set *PTR to zero, and | 941 If we can't allocate the necessary memory, set *PTR to zero, and |
943 return zero. */ | 942 return zero. */ |
944 | 943 |
944 POINTER r_alloc (POINTER *ptr, SIZE size); | |
945 POINTER | 945 POINTER |
946 r_alloc (POINTER *ptr, SIZE size) | 946 r_alloc (POINTER *ptr, SIZE size) |
947 { | 947 { |
948 bloc_ptr new_bloc; | 948 bloc_ptr new_bloc; |
949 | 949 |
963 } | 963 } |
964 | 964 |
965 /* Free a bloc of relocatable storage whose data is pointed to by PTR. | 965 /* Free a bloc of relocatable storage whose data is pointed to by PTR. |
966 Store 0 in *PTR to show there's no block allocated. */ | 966 Store 0 in *PTR to show there's no block allocated. */ |
967 | 967 |
968 void r_alloc_free (POINTER *ptr); | |
968 void | 969 void |
969 r_alloc_free (POINTER *ptr) | 970 r_alloc_free (POINTER *ptr) |
970 { | 971 { |
971 register bloc_ptr dead_bloc; | 972 register bloc_ptr dead_bloc; |
972 | 973 |
997 Change *PTR to reflect the new bloc, and return this value. | 998 Change *PTR to reflect the new bloc, and return this value. |
998 | 999 |
999 If more memory cannot be allocated, then leave *PTR unchanged, and | 1000 If more memory cannot be allocated, then leave *PTR unchanged, and |
1000 return zero. */ | 1001 return zero. */ |
1001 | 1002 |
1003 POINTER r_re_alloc (POINTER *ptr, SIZE size); | |
1002 POINTER | 1004 POINTER |
1003 r_re_alloc (POINTER *ptr, SIZE size) | 1005 r_re_alloc (POINTER *ptr, SIZE size) |
1004 { | 1006 { |
1005 register bloc_ptr bloc; | 1007 register bloc_ptr bloc; |
1006 | 1008 |
1007 if (! r_alloc_initialized) | 1009 if (! r_alloc_initialized) |
1008 init_ralloc (); | 1010 init_ralloc (); |
1009 | 1011 |
1010 if (!*ptr) | 1012 if (!*ptr) |
1011 return r_alloc (ptr, size); | 1013 return r_alloc (ptr, size); |
1012 if (!size) | 1014 if (!size) |
1013 { | 1015 { |
1014 r_alloc_free (ptr); | 1016 r_alloc_free (ptr); |
1015 return r_alloc (ptr, 0); | 1017 return r_alloc (ptr, 0); |
1016 } | 1018 } |
1017 | 1019 |
1018 bloc = find_bloc (ptr); | 1020 bloc = find_bloc (ptr); |
1019 if (bloc == NIL_BLOC) | 1021 if (bloc == NIL_BLOC) |
1020 abort (); | 1022 abort (); |
1021 | 1023 |
1022 if (size < bloc->size) | 1024 if (size < bloc->size) |
1023 { | 1025 { |
1024 /* Wouldn't it be useful to actually resize the bloc here? */ | 1026 /* Wouldn't it be useful to actually resize the bloc here? */ |
1025 /* I think so too, but not if it's too expensive... */ | 1027 /* I think so too, but not if it's too expensive... */ |
1026 if ((bloc->size - MEM_ROUNDUP (size) >= page_size) | 1028 if ((bloc->size - MEM_ROUNDUP (size) >= page_size) |
1027 && r_alloc_freeze_level == 0) | 1029 && r_alloc_freeze_level == 0) |
1028 { | 1030 { |
1029 resize_bloc (bloc, MEM_ROUNDUP (size)); | 1031 resize_bloc (bloc, MEM_ROUNDUP (size)); |
1030 /* Never mind if this fails, just do nothing... */ | 1032 /* Never mind if this fails, just do nothing... */ |
1031 /* It *should* be infallible! */ | 1033 /* It *should* be infallible! */ |
1032 } | 1034 } |
1044 bloc->variable = (POINTER *) NIL; | 1046 bloc->variable = (POINTER *) NIL; |
1045 } | 1047 } |
1046 else | 1048 else |
1047 return NIL; | 1049 return NIL; |
1048 } | 1050 } |
1049 else | 1051 else |
1050 { | 1052 { |
1051 if (! resize_bloc (bloc, MEM_ROUNDUP (size))) | 1053 if (! resize_bloc (bloc, MEM_ROUNDUP (size))) |
1052 return NIL; | 1054 return NIL; |
1053 } | 1055 } |
1054 } | 1056 } |
1058 /* Disable relocations, after making room for at least SIZE bytes | 1060 /* Disable relocations, after making room for at least SIZE bytes |
1059 of non-relocatable heap if possible. The relocatable blocs are | 1061 of non-relocatable heap if possible. The relocatable blocs are |
1060 guaranteed to hold still until thawed, even if this means that | 1062 guaranteed to hold still until thawed, even if this means that |
1061 malloc must return a null pointer. */ | 1063 malloc must return a null pointer. */ |
1062 | 1064 |
1065 void r_alloc_freeze (long size); | |
1063 void | 1066 void |
1064 r_alloc_freeze (size) | 1067 r_alloc_freeze (long size) |
1065 long size; | |
1066 { | 1068 { |
1067 if (! r_alloc_initialized) | 1069 if (! r_alloc_initialized) |
1068 init_ralloc (); | 1070 init_ralloc (); |
1069 | 1071 |
1070 /* If already frozen, we can't make any more room, so don't try. */ | 1072 /* If already frozen, we can't make any more room, so don't try. */ |
1076 ++r_alloc_freeze_level; | 1078 ++r_alloc_freeze_level; |
1077 if (size > 0) | 1079 if (size > 0) |
1078 r_alloc_sbrk (-size); | 1080 r_alloc_sbrk (-size); |
1079 } | 1081 } |
1080 | 1082 |
1083 void r_alloc_thaw (void); | |
1081 void | 1084 void |
1082 r_alloc_thaw () | 1085 r_alloc_thaw () |
1083 { | 1086 { |
1084 | 1087 |
1085 if (! r_alloc_initialized) | 1088 if (! r_alloc_initialized) |
1086 init_ralloc (); | 1089 init_ralloc (); |
1087 | 1090 |
1088 if (--r_alloc_freeze_level < 0) | 1091 if (--r_alloc_freeze_level < 0) |
1089 abort (); | 1092 abort (); |
1090 | 1093 |
1091 /* This frees all unused blocs. It is not too inefficient, as the resize | 1094 /* This frees all unused blocs. It is not too inefficient, as the resize |
1092 and bcopy is done only once. Afterwards, all unreferenced blocs are | 1095 and bcopy is done only once. Afterwards, all unreferenced blocs are |
1093 already shrunk to zero size. */ | 1096 already shrunk to zero size. */ |
1094 if (!r_alloc_freeze_level) | 1097 if (!r_alloc_freeze_level) |
1095 { | 1098 { |
1096 bloc_ptr *b = &first_bloc; | 1099 bloc_ptr *b = &first_bloc; |
1097 while (*b) | 1100 while (*b) |
1098 if (!(*b)->variable) | 1101 if (!(*b)->variable) |
1099 free_bloc (*b); | 1102 free_bloc (*b); |
1100 else | 1103 else |
1101 b = &(*b)->next; | 1104 b = &(*b)->next; |
1102 } | 1105 } |
1103 } | 1106 } |
1104 | 1107 |
1105 | 1108 |
1106 /* The hook `malloc' uses for the function which gets more space | 1109 /* The hook `malloc' uses for the function which gets more space |
1107 from the system. */ | 1110 from the system. */ |
1108 extern POINTER (*__morecore) (); | 1111 /* extern POINTER (*__morecore) (long size); */ |
1109 | 1112 |
1110 /* Initialize various things for memory allocation. */ | 1113 /* Initialize various things for memory allocation. */ |
1114 | |
1115 #define SET_FUN_PTR(fun_ptr, fun_val) \ | |
1116 (*((void **) (&fun_ptr)) = ((void *) (fun_val))) | |
1111 | 1117 |
1112 void | 1118 void |
1113 init_ralloc (void) | 1119 init_ralloc (void) |
1114 { | 1120 { |
1115 if (r_alloc_initialized) | 1121 if (r_alloc_initialized) |
1116 return; | 1122 return; |
1117 | 1123 |
1118 r_alloc_initialized = 1; | 1124 r_alloc_initialized = 1; |
1119 real_morecore = __morecore; | 1125 SET_FUN_PTR (real_morecore, __morecore); |
1120 __morecore = r_alloc_sbrk; | 1126 SET_FUN_PTR (__morecore, r_alloc_sbrk); |
1121 | 1127 |
1122 first_heap = last_heap = &heap_base; | 1128 first_heap = last_heap = &heap_base; |
1123 first_heap->next = first_heap->prev = NIL_HEAP; | 1129 first_heap->next = first_heap->prev = NIL_HEAP; |
1124 first_heap->start = first_heap->bloc_start | 1130 first_heap->start = first_heap->bloc_start |
1125 = virtual_break_value = break_value = (*real_morecore) (0); | 1131 = virtual_break_value = break_value = (*real_morecore) (0); |
1160 | 1166 |
1161 #if defined (emacs) && defined (DOUG_LEA_MALLOC) | 1167 #if defined (emacs) && defined (DOUG_LEA_MALLOC) |
1162 | 1168 |
1163 /* Reinitialize the morecore hook variables after restarting a dumped | 1169 /* Reinitialize the morecore hook variables after restarting a dumped |
1164 Emacs. This is needed when using Doug Lea's malloc from GNU libc. */ | 1170 Emacs. This is needed when using Doug Lea's malloc from GNU libc. */ |
1171 void r_alloc_reinit (void); | |
1165 void | 1172 void |
1166 r_alloc_reinit () | 1173 r_alloc_reinit () |
1167 { | 1174 { |
1168 /* Only do this if the hook has been reset, so that we don't get an | 1175 /* Only do this if the hook has been reset, so that we don't get an |
1169 infinite loop, in case Emacs was linked statically. */ | 1176 infinite loop, in case Emacs was linked statically. */ |
1170 if (__morecore != r_alloc_sbrk) | 1177 if ( ((void*) __morecore) != (void *) (r_alloc_sbrk)) |
1171 { | 1178 { |
1172 real_morecore = __morecore; | 1179 SET_FUN_PTR (real_morecore, __morecore); |
1173 __morecore = r_alloc_sbrk; | 1180 SET_FUN_PTR (__morecore, r_alloc_sbrk); |
1174 } | 1181 } |
1175 } | 1182 } |
1176 #if 0 | 1183 #if 0 |
1177 #ifdef DEBUG | 1184 #ifdef DEBUG |
1178 | 1185 |
1409 | 1416 |
1410 | 1417 |
1411 /* We settle for a standard doubly-linked-list. The dynarr type isn't | 1418 /* We settle for a standard doubly-linked-list. The dynarr type isn't |
1412 very amenable to deletion of items in the middle, so we conjure up | 1419 very amenable to deletion of items in the middle, so we conjure up |
1413 yet another stupid datastructure. The structure is maintained as a | 1420 yet another stupid datastructure. The structure is maintained as a |
1414 ring, and the singleton ring has the sole element as it's left and | 1421 ring, and the singleton ring has the sole element as its left and |
1415 right neighbours. */ | 1422 right neighbours. */ |
1416 | 1423 |
1417 static void init_MHASH_table (void); /* Forward reference */ | 1424 static void init_MHASH_table (void); /* Forward reference */ |
1418 | 1425 |
1419 typedef struct alloc_dll | 1426 typedef struct alloc_dll |
1496 | 1503 |
1497 /* Simple hash check. */ | 1504 /* Simple hash check. */ |
1498 struct { | 1505 struct { |
1499 int n_hits; /* How many addresses map to this? */ | 1506 int n_hits; /* How many addresses map to this? */ |
1500 MMAP_HANDLE handle; /* What is the current handle? */ | 1507 MMAP_HANDLE handle; /* What is the current handle? */ |
1501 VM_ADDR addr; /* What is it's VM address? */ | 1508 VM_ADDR addr; /* What is its VM address? */ |
1502 } MHASH_HITS[ MHASH_PRIME ]; | 1509 } MHASH_HITS[ MHASH_PRIME ]; |
1503 | 1510 |
1504 static void | 1511 static void |
1505 init_MHASH_table (void) | 1512 init_MHASH_table (void) |
1506 { | 1513 { |
1525 int hval = addr_shift % MHASH_PRIME; /* We could have addresses which are -ve | 1532 int hval = addr_shift % MHASH_PRIME; /* We could have addresses which are -ve |
1526 when converted to signed ints */ | 1533 when converted to signed ints */ |
1527 return ((hval >= 0) ? hval : MHASH_PRIME + hval); | 1534 return ((hval >= 0) ? hval : MHASH_PRIME + hval); |
1528 } | 1535 } |
1529 | 1536 |
1530 /* Add a VM address with it's corresponding handle to the table. */ | 1537 /* Add a VM address with its corresponding handle to the table. */ |
1531 static void | 1538 static void |
1532 MHASH_ADD (VM_ADDR addr, MMAP_HANDLE h) | 1539 MHASH_ADD (VM_ADDR addr, MMAP_HANDLE h) |
1533 { | 1540 { |
1534 int kVal = MHASH( addr ); | 1541 int kVal = MHASH( addr ); |
1535 if (MHASH_HITS[kVal].n_hits++ == 0) | 1542 if (MHASH_HITS[kVal].n_hits++ == 0) |
1557 /* Metering malloc performance. */ | 1564 /* Metering malloc performance. */ |
1558 #ifdef MMAP_METERING | 1565 #ifdef MMAP_METERING |
1559 /* If we're metering, we introduce some extra symbols to aid the noble | 1566 /* If we're metering, we introduce some extra symbols to aid the noble |
1560 cause of bloating XEmacs core size. */ | 1567 cause of bloating XEmacs core size. */ |
1561 | 1568 |
1562 Lisp_Object Qmm_times_mapped; | 1569 static Lisp_Object Qmmap_times_mapped; |
1563 Lisp_Object Qmm_pages_mapped; | 1570 static Lisp_Object Qmmap_pages_mapped; |
1564 Lisp_Object Qmm_times_unmapped; | 1571 static Lisp_Object Qmmap_times_unmapped; |
1565 Lisp_Object Qmm_times_remapped; | 1572 static Lisp_Object Qmmap_times_remapped; |
1566 Lisp_Object Qmm_didnt_copy; | 1573 static Lisp_Object Qmmap_didnt_copy; |
1567 Lisp_Object Qmm_pages_copied; | 1574 static Lisp_Object Qmmap_pages_copied; |
1568 Lisp_Object Qmm_average_bumpval; | 1575 static Lisp_Object Qmmap_average_bumpval; |
1569 Lisp_Object Qmm_wastage; | 1576 static Lisp_Object Qmmap_wastage; |
1570 Lisp_Object Qmm_live_pages; | 1577 static Lisp_Object Qmmap_live_pages; |
1571 Lisp_Object Qmm_addr_looked_up; | 1578 static Lisp_Object Qmmap_addr_looked_up; |
1572 Lisp_Object Qmm_hash_worked; | 1579 static Lisp_Object Qmmap_hash_worked; |
1573 Lisp_Object Qmm_addrlist_size; | 1580 static Lisp_Object Qmmap_addrlist_size; |
1574 | 1581 |
1575 #define M_Map 0 /* How many times allocated? */ | 1582 #define M_Map 0 /* How many times allocated? */ |
1576 #define M_Pages_Map 1 /* How many pages allocated? */ | 1583 #define M_Pages_Map 1 /* How many pages allocated? */ |
1577 #define M_Unmap 2 /* How many times freed? */ | 1584 #define M_Unmap 2 /* How many times freed? */ |
1578 #define M_Remap 3 /* How many times increased in size? */ | 1585 #define M_Remap 3 /* How many times increased in size? */ |
1592 static int meter[N_Meterables]; | 1599 static int meter[N_Meterables]; |
1593 | 1600 |
1594 DEFUN ("mmap-allocator-status", Fmmap_allocator_status, 0, 0, 0, /* | 1601 DEFUN ("mmap-allocator-status", Fmmap_allocator_status, 0, 0, 0, /* |
1595 Return some information about mmap-based allocator. | 1602 Return some information about mmap-based allocator. |
1596 | 1603 |
1597 mmap-addrlist-size: number of entries in address picking list. | 1604 mmap-times-mapped: number of times r_alloc was called. |
1598 mmap-times-mapped: number of times r_alloc was called. | 1605 mmap-pages-mapped: number of pages mapped by r_alloc calls only. |
1599 mmap-pages-mapped: number of pages mapped by r_alloc calls only. | 1606 mmap-times-unmapped: number of times r_free was called. |
1600 mmap-times-unmapped: number of times r_free was called. | 1607 mmap-times-remapped: number of times r_re_alloc was called. |
1601 mmap-times-remapped: number of times r_re_alloc was called. | 1608 mmap-didnt-copy: number of times re-alloc did NOT have to move the block. |
1602 mmap-didnt-copy: number of times re-alloc didn\'t have to move the block. | 1609 mmap-pages-copied: total number of pages copied. |
1603 mmap-pages-copied: total number of pages copied. | 1610 mmap-average-bumpval: average increase in size demanded to re-alloc. |
1604 mmap-average-bumpval: average increase in size demanded to re-alloc. | 1611 mmap-wastage: total number of bytes allocated, but not currently in use. |
1605 mmap-wastage: total number of bytes allocated, but not currently in use. | 1612 mmap-live-pages: total number of pages live. |
1606 mmap-live-pages: total number of pages live. | 1613 mmap-addr-looked-up: total number of times needed to check if addr is in block. |
1614 mmap-hash-worked: total number of times the simple hash check worked. | |
1615 mmap-addrlist-size: number of entries in address picking list. | |
1607 */ | 1616 */ |
1608 ()) | 1617 ()) |
1609 { | 1618 { |
1610 Lisp_Object result; | 1619 Lisp_Object result = Qnil; |
1611 | 1620 |
1612 result = Fcons (Fcons (Qmm_addrlist_size, MLVAL (M_Addrlist_Size)), Qnil); | 1621 result = cons3 (Qmmap_addrlist_size, MLVAL (M_Addrlist_Size), result); |
1613 result = Fcons (Fcons (Qmm_hash_worked, MLVAL (M_Hash_Worked)), result); | 1622 result = cons3 (Qmmap_hash_worked, MLVAL (M_Hash_Worked), result); |
1614 result = Fcons (Fcons (Qmm_addr_looked_up, MLVAL (M_Address_Lookup)), result); | 1623 result = cons3 (Qmmap_addr_looked_up, MLVAL (M_Address_Lookup), result); |
1615 result = Fcons (Fcons (Qmm_live_pages, MLVAL (M_Live_Pages)), result); | 1624 result = cons3 (Qmmap_live_pages, MLVAL (M_Live_Pages), result); |
1616 result = Fcons (Fcons (Qmm_wastage, MLVAL (M_Wastage)), result); | 1625 result = cons3 (Qmmap_wastage, MLVAL (M_Wastage), result); |
1617 result = Fcons (Fcons (Qmm_average_bumpval, MLVAL (M_Average_Bumpval)), | 1626 result = cons3 (Qmmap_average_bumpval,MLVAL (M_Average_Bumpval), result); |
1618 result); | 1627 result = cons3 (Qmmap_pages_copied, MLVAL (M_Copy_Pages), result); |
1619 result = Fcons (Fcons (Qmm_pages_copied, MLVAL (M_Copy_Pages)), result); | 1628 result = cons3 (Qmmap_didnt_copy, MLVAL (M_Didnt_Copy), result); |
1620 result = Fcons (Fcons (Qmm_didnt_copy, MLVAL (M_Didnt_Copy)), result); | 1629 result = cons3 (Qmmap_times_remapped, MLVAL (M_Remap), result); |
1621 result = Fcons (Fcons (Qmm_times_remapped, MLVAL (M_Remap)), result); | 1630 result = cons3 (Qmmap_times_unmapped, MLVAL (M_Unmap), result); |
1622 result = Fcons (Fcons (Qmm_times_unmapped, MLVAL (M_Unmap)), result); | 1631 result = cons3 (Qmmap_pages_mapped, MLVAL (M_Pages_Map), result); |
1623 result = Fcons (Fcons (Qmm_pages_mapped, MLVAL (M_Pages_Map)), result); | 1632 result = cons3 (Qmmap_times_mapped, MLVAL (M_Map), result); |
1624 result = Fcons (Fcons (Qmm_times_mapped, MLVAL (M_Map)), result); | |
1625 | 1633 |
1626 return result; | 1634 return result; |
1627 } | 1635 } |
1628 | 1636 |
1629 #else /* !MMAP_METERING */ | 1637 #else /* !MMAP_METERING */ |
1669 marked unavailable and not attempted thereafter. The scheme will | 1677 marked unavailable and not attempted thereafter. The scheme will |
1670 keep fragmenting the large empty block until it finds an address | 1678 keep fragmenting the large empty block until it finds an address |
1671 which can be successfully mmapped, or until there are no free | 1679 which can be successfully mmapped, or until there are no free |
1672 blocks of the given size left. | 1680 blocks of the given size left. |
1673 | 1681 |
1674 Note that this scheme, given it's first-fit strategy, is prone to | 1682 Note that this scheme, given its first-fit strategy, is prone to |
1675 fragmentation of the first part of memory earmarked for this | 1683 fragmentation of the first part of memory earmarked for this |
1676 purpose. [ACP Vol I]. We can't use the workaround of using a | 1684 purpose. [ACP Vol I]. We can't use the workaround of using a |
1677 randomized first fit because we don't want to presume too much | 1685 randomized first fit because we don't want to presume too much |
1678 about the memory map. Instead, we try to coalesce empty or | 1686 about the memory map. Instead, we try to coalesce empty or |
1679 unavailable blocks at any available opportunity. */ | 1687 unavailable blocks at any available opportunity. */ |
2028 | 2036 |
2029 void | 2037 void |
2030 syms_of_ralloc (void) | 2038 syms_of_ralloc (void) |
2031 { | 2039 { |
2032 #ifdef MMAP_METERING | 2040 #ifdef MMAP_METERING |
2033 defsymbol (&Qmm_times_mapped, "mmap-times-mapped"); | 2041 defsymbol (&Qmmap_times_mapped, "mmap-times-mapped"); |
2034 defsymbol (&Qmm_pages_mapped, "mmap-pages-mapped"); | 2042 defsymbol (&Qmmap_pages_mapped, "mmap-pages-mapped"); |
2035 defsymbol (&Qmm_times_unmapped, "mmap-times-unmapped"); | 2043 defsymbol (&Qmmap_times_unmapped, "mmap-times-unmapped"); |
2036 defsymbol (&Qmm_times_remapped, "mmap-times-remapped"); | 2044 defsymbol (&Qmmap_times_remapped, "mmap-times-remapped"); |
2037 defsymbol (&Qmm_didnt_copy, "mmap-didnt-copy"); | 2045 defsymbol (&Qmmap_didnt_copy, "mmap-didnt-copy"); |
2038 defsymbol (&Qmm_pages_copied, "mmap-pages-copied"); | 2046 defsymbol (&Qmmap_pages_copied, "mmap-pages-copied"); |
2039 defsymbol (&Qmm_average_bumpval, "mmap-average-bumpval"); | 2047 defsymbol (&Qmmap_average_bumpval, "mmap-average-bumpval"); |
2040 defsymbol (&Qmm_wastage, "mmap-wastage"); | 2048 defsymbol (&Qmmap_wastage, "mmap-wastage"); |
2041 defsymbol (&Qmm_live_pages, "mmap-live-pages"); | 2049 defsymbol (&Qmmap_live_pages, "mmap-live-pages"); |
2042 defsymbol (&Qmm_addr_looked_up, "mmap-had-to-look-up-address"); | 2050 defsymbol (&Qmmap_addr_looked_up, "mmap-addr-looked-up"); |
2043 defsymbol (&Qmm_hash_worked, "mmap-hash-table-worked"); | 2051 defsymbol (&Qmmap_hash_worked, "mmap-hash-worked"); |
2044 defsymbol (&Qmm_addrlist_size, "mmap-addrlist-size"); | 2052 defsymbol (&Qmmap_addrlist_size, "mmap-addrlist-size"); |
2045 DEFSUBR (Fmmap_allocator_status); | 2053 DEFSUBR (Fmmap_allocator_status); |
2046 #endif /* MMAP_METERING */ | 2054 #endif /* MMAP_METERING */ |
2047 } | 2055 } |
2048 | 2056 |
2049 void | 2057 void |