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