comparison src/ralloc.c @ 1390:92df75f4167f

(check_memory_limits): Reduce warnlevel when usage drops far enough. (memory_warnings): New function; just set warning data. Use start_of_data if start is 0. [!emacs]: Don't include config.h or lisp.h; instead, use stddef.h. Define POINTER, SIZE, EXCEEDS_LISP_PTR. [!emacs] (safe_bcopy): Define as macro using memmove. (r_alloc_free): Clear *ptr. (r_alloc_init): Renamed from malloc_init. Take no args. Make it static; declare at top of file. (r_alloc): Call r_alloc_init, if not initialized yet. (r_alloc_initialized): Renamed from malloc_initialized; moved to top. (ROUNDUP): Subtract 1, in case arg is already aligned. (check_memory_limits): EXCEEDS_LISP_PTR renamed from EXCEEDS_ELISP_PTR.
author Richard M. Stallman <rms@gnu.org>
date Sun, 11 Oct 1992 20:37:32 +0000
parents 761b9b4fd3ed
children 70d0cd4c5bff
comparison
equal deleted inserted replaced
1389:517c3893ec5b 1390:92df75f4167f
21 21
22 Only relocate the blocs neccessary for SIZE in r_alloc_sbrk, 22 Only relocate the blocs neccessary for SIZE in r_alloc_sbrk,
23 rather than all of them. This means allowing for a possible 23 rather than all of them. This means allowing for a possible
24 hole between the first bloc and the end of malloc storage. */ 24 hole between the first bloc and the end of malloc storage. */
25 25
26 #ifdef emacs
26 #include "config.h" 27 #include "config.h"
27 #include "lisp.h" /* Needed for VALBITS. */ 28 #include "lisp.h" /* Needed for VALBITS. */
29
30 /* Declared in dispnew.c, this version doesn't screw up if regions
31 overlap. */
32 extern void safe_bcopy ();
33 #endif
34
35 #ifndef emacs
36 #include <stddef.h>
37 typedef size_t SIZE;
38 typedef void *POINTER;
39 #define EXCEEDS_LISP_PTR(x) 0
40
41 #define safe_bcopy(x, y, z) memmove (y, x, z)
42 #endif
43
28 #undef NULL 44 #undef NULL
29 #include "mem_limits.h" 45 #include "mem_limits.h"
30 #include "getpagesize.h" 46 #include "getpagesize.h"
31 47
32 #define NIL ((POINTER) 0) 48 #define NIL ((POINTER) 0)
33 49
50 /* A flag to indicate whether we have initialized ralloc yet. For
51 Emacs's sake, please do not make this local to malloc_init; on some
52 machines, the dumping procedure makes all static variables
53 read-only. On these machines, the word static is #defined to be
54 the empty string, meaning that r_alloc_initialized becomes an
55 automatic variable, and loses its value each time Emacs is started up. */
56 static int r_alloc_initialized = 0;
57
58 static void r_alloc_init ();
34 59
35 /* Declarations for working with the malloc, ralloc, and system breaks. */ 60 /* Declarations for working with the malloc, ralloc, and system breaks. */
36 61
37 /* System call to set the break value. */ 62 /* System call to set the break value. */
38 extern POINTER sbrk (); 63 extern POINTER sbrk ();
48 73
49 /* Macros for rounding. Note that rounding to any value is possible 74 /* Macros for rounding. Note that rounding to any value is possible
50 by changing the definition of PAGE. */ 75 by changing the definition of PAGE. */
51 #define PAGE (getpagesize ()) 76 #define PAGE (getpagesize ())
52 #define ALIGNED(addr) (((unsigned int) (addr) & (PAGE - 1)) == 0) 77 #define ALIGNED(addr) (((unsigned int) (addr) & (PAGE - 1)) == 0)
53 #define ROUNDUP(size) (((unsigned int) (size) + PAGE) & ~(PAGE - 1)) 78 #define ROUNDUP(size) (((unsigned int) (size) + PAGE - 1) & ~(PAGE - 1))
54 #define ROUND_TO_PAGE(addr) (addr & (~(PAGE - 1))) 79 #define ROUND_TO_PAGE(addr) (addr & (~(PAGE - 1)))
55 80
56 /* Managing "almost out of memory" warnings. */ 81 /* Managing "almost out of memory" warnings. */
57 82
58 /* Level of warnings issued. */ 83 /* Level of warnings issued. */
65 static void 90 static void
66 check_memory_limits (address) 91 check_memory_limits (address)
67 POINTER address; 92 POINTER address;
68 { 93 {
69 SIZE data_size = address - data_space_start; 94 SIZE data_size = address - data_space_start;
95 int five_percent = lim_data / 20;
70 96
71 switch (warnlevel) 97 switch (warnlevel)
72 { 98 {
73 case 0: 99 case 0:
74 if (data_size > (lim_data / 4) * 3) 100 if (data_size > five_percent * 15)
75 { 101 {
76 warnlevel++; 102 warnlevel++;
77 (*warn_function) ("Warning: past 75% of memory limit"); 103 (*warn_function) ("Warning: past 75% of memory limit");
78 } 104 }
79 break; 105 break;
80 106
81 case 1: 107 case 1:
82 if (data_size > (lim_data / 20) * 17) 108 if (data_size > five_percent * 17)
83 { 109 {
84 warnlevel++; 110 warnlevel++;
85 (*warn_function) ("Warning: past 85% of memory limit"); 111 (*warn_function) ("Warning: past 85% of memory limit");
86 } 112 }
87 break; 113 break;
88 114
89 case 2: 115 case 2:
90 if (data_size > (lim_data / 20) * 19) 116 if (data_size > five_percent * 19)
91 { 117 {
92 warnlevel++; 118 warnlevel++;
93 (*warn_function) ("Warning: past 95% of memory limit"); 119 (*warn_function) ("Warning: past 95% of memory limit");
94 } 120 }
95 break; 121 break;
97 default: 123 default:
98 (*warn_function) ("Warning: past acceptable memory limits"); 124 (*warn_function) ("Warning: past acceptable memory limits");
99 break; 125 break;
100 } 126 }
101 127
102 if (EXCEEDS_ELISP_PTR (address)) 128 /* If we go down below 70% full, issue another 75% warning
103 memory_full (); 129 when we go up again. */
130 if (data_size < five_percent * 14)
131 warnlevel = 0;
132 /* If we go down below 80% full, issue another 85% warning
133 when we go up again. */
134 else if (warnlevel > 1 && data_size < five_percent * 16)
135 warnlevel = 1;
136 /* If we go down below 90% full, issue another 95% warning
137 when we go up again. */
138 else if (warnlevel > 2 && data_size < five_percent * 18)
139 warnlevel = 2;
140
141 if (EXCEEDS_LISP_PTR (address))
142 memory_full ();
104 } 143 }
105 144
106 /* Functions to get and return memory from the system. */ 145 /* Functions to get and return memory from the system. */
107 146
108 /* Obtain SIZE bytes of space. If enough space is not presently available 147 /* Obtain SIZE bytes of space. If enough space is not presently available
194 #define BLOC_PTR_SIZE (sizeof (struct bp)) 233 #define BLOC_PTR_SIZE (sizeof (struct bp))
195 234
196 /* Head and tail of the list of relocatable blocs. */ 235 /* Head and tail of the list of relocatable blocs. */
197 static bloc_ptr first_bloc, last_bloc; 236 static bloc_ptr first_bloc, last_bloc;
198 237
199 /* Declared in dispnew.c, this version doesn't screw up if regions
200 overlap. */
201 extern void safe_bcopy ();
202
203 /* Find the bloc referenced by the address in PTR. Returns a pointer 238 /* Find the bloc referenced by the address in PTR. Returns a pointer
204 to that block. */ 239 to that block. */
205 240
206 static bloc_ptr 241 static bloc_ptr
207 find_bloc (ptr) 242 find_bloc (ptr)
321 /* Interface routines. */ 356 /* Interface routines. */
322 357
323 static int use_relocatable_buffers; 358 static int use_relocatable_buffers;
324 359
325 /* Obtain SIZE bytes of storage from the free pool, or the system, as 360 /* Obtain SIZE bytes of storage from the free pool, or the system, as
326 neccessary. If relocatable blocs are in use, this means relocating 361 necessary. If relocatable blocs are in use, this means relocating
327 them. This function gets plugged into the GNU malloc's __morecore 362 them. This function gets plugged into the GNU malloc's __morecore
328 hook. 363 hook.
329 364
330 If we're out of memory, we should return zero, to imitate the other 365 If we're out of memory, we should return zero, to imitate the other
331 __morecore hook values - in particular, __default_morecore in the 366 __morecore hook values - in particular, __default_morecore in the
378 POINTER *ptr; 413 POINTER *ptr;
379 SIZE size; 414 SIZE size;
380 { 415 {
381 register bloc_ptr new_bloc; 416 register bloc_ptr new_bloc;
382 417
418 if (! r_alloc_initialized)
419 r_alloc_init ();
420
383 new_bloc = get_bloc (size); 421 new_bloc = get_bloc (size);
384 if (new_bloc) 422 if (new_bloc)
385 { 423 {
386 new_bloc->variable = ptr; 424 new_bloc->variable = ptr;
387 *ptr = new_bloc->data; 425 *ptr = new_bloc->data;
390 *ptr = 0; 428 *ptr = 0;
391 429
392 return *ptr; 430 return *ptr;
393 } 431 }
394 432
395 /* Free a bloc of relocatable storage whose data is pointed to by PTR. */ 433 /* Free a bloc of relocatable storage whose data is pointed to by PTR.
434 Store 0 in *PTR to show there's no block allocated. */
396 435
397 void 436 void
398 r_alloc_free (ptr) 437 r_alloc_free (ptr)
399 register POINTER *ptr; 438 register POINTER *ptr;
400 { 439 {
403 dead_bloc = find_bloc (ptr); 442 dead_bloc = find_bloc (ptr);
404 if (dead_bloc == NIL_BLOC) 443 if (dead_bloc == NIL_BLOC)
405 abort (); 444 abort ();
406 445
407 free_bloc (dead_bloc); 446 free_bloc (dead_bloc);
447 *ptr = 0;
408 } 448 }
409 449
410 /* Given a pointer at address PTR to relocatable data, resize it to SIZE. 450 /* Given a pointer at address PTR to relocatable data, resize it to SIZE.
411 Do this by shifting all blocks above this one up in memory, unless 451 Do this by shifting all blocks above this one up in memory, unless
412 SIZE is less than or equal to the current bloc size, in which case 452 SIZE is less than or equal to the current bloc size, in which case
448 488
449 /* The hook `malloc' uses for the function which gets more space 489 /* The hook `malloc' uses for the function which gets more space
450 from the system. */ 490 from the system. */
451 extern POINTER (*__morecore) (); 491 extern POINTER (*__morecore) ();
452 492
453 /* A flag to indicate whether we have initialized ralloc yet. For
454 Emacs's sake, please do not make this local to malloc_init; on some
455 machines, the dumping procedure makes all static variables
456 read-only. On these machines, the word static is #defined to be
457 the empty string, meaning that malloc_initialized becomes an
458 automatic variable, and loses its value each time Emacs is started
459 up. */
460 static int malloc_initialized = 0;
461
462 /* Intialize various things for memory allocation. */ 493 /* Intialize various things for memory allocation. */
463 494
495 static void
496 r_alloc_init ()
497 {
498 if (r_alloc_initialized)
499 return;
500
501 r_alloc_initialized = 1;
502 __morecore = r_alloc_sbrk;
503
504 virtual_break_value = break_value = sbrk (0);
505 if (break_value == (POINTER)NULL)
506 abort ();
507 #if 0 /* The following is unreasonable because warn_func may be 0. */
508 (*warn_func)("memory initialization got 0 from sbrk(0).");
509 #endif
510
511 page_break_value = (POINTER) ROUNDUP (break_value);
512 /* Clear the rest of the last page; this memory is in our address space
513 even though it is after the sbrk value. */
514 bzero (break_value, (page_break_value - break_value));
515 use_relocatable_buffers = 1;
516
517 lim_data = 0;
518 warnlevel = 0;
519
520 get_lim_data ();
521 }
522
523 /* This is the name Emacs expects to call. */
524
464 void 525 void
465 malloc_init (start, warn_func) 526 memory_warnings (start, warn_func)
466 POINTER start; 527 POINTER start;
467 void (*warn_func) (); 528 void (*warn_func) ();
468 { 529 {
469 if (start) 530 if (start)
470 data_space_start = start; 531 data_space_start = start;
471 532 else
472 if (malloc_initialized) 533 data_space_start = start_of_data ();
473 return; 534
474
475 malloc_initialized = 1;
476 __morecore = r_alloc_sbrk;
477
478 virtual_break_value = break_value = sbrk (0);
479 if (break_value == (POINTER)NULL)
480 (*warn_func)("Malloc initialization returned 0 from sbrk(0).");
481
482 page_break_value = (POINTER) ROUNDUP (break_value);
483 bzero (break_value, (page_break_value - break_value));
484 use_relocatable_buffers = 1;
485
486 lim_data = 0;
487 warnlevel = 0;
488 warn_function = warn_func; 535 warn_function = warn_func;
489 536 }
490 get_lim_data ();
491 }