diff options
| -rw-r--r-- | src/ralloc.c | 109 |
1 files changed, 77 insertions, 32 deletions
diff --git a/src/ralloc.c b/src/ralloc.c index c43218eaefc..3f65c063850 100644 --- a/src/ralloc.c +++ b/src/ralloc.c | |||
| @@ -23,14 +23,39 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 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 | ||
| @@ -50,7 +75,7 @@ static POINTER page_break_value; | |||
| 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. */ |
| @@ -67,11 +92,12 @@ 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"); |
| @@ -79,7 +105,7 @@ check_memory_limits (address) | |||
| 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"); |
| @@ -87,7 +113,7 @@ check_memory_limits (address) | |||
| 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"); |
| @@ -99,8 +125,21 @@ check_memory_limits (address) | |||
| 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. */ |
| @@ -196,10 +235,6 @@ typedef struct bp | |||
| 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 | ||
| @@ -323,7 +358,7 @@ free_bloc (bloc) | |||
| 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 | ||
| @@ -380,6 +415,9 @@ r_alloc (ptr, 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 | { |
| @@ -392,7 +430,8 @@ r_alloc (ptr, size) | |||
| 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) |
| @@ -405,6 +444,7 @@ r_alloc_free (ptr) | |||
| 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. |
| @@ -450,42 +490,47 @@ r_re_alloc (ptr, size) | |||
| 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 | ||
| 464 | void | 495 | static void |
| 465 | malloc_init (start, warn_func) | 496 | r_alloc_init () |
| 466 | POINTER start; | ||
| 467 | void (*warn_func) (); | ||
| 468 | { | 497 | { |
| 469 | if (start) | 498 | if (r_alloc_initialized) |
| 470 | data_space_start = start; | ||
| 471 | |||
| 472 | if (malloc_initialized) | ||
| 473 | return; | 499 | return; |
| 474 | 500 | ||
| 475 | malloc_initialized = 1; | 501 | r_alloc_initialized = 1; |
| 476 | __morecore = r_alloc_sbrk; | 502 | __morecore = r_alloc_sbrk; |
| 477 | 503 | ||
| 478 | virtual_break_value = break_value = sbrk (0); | 504 | virtual_break_value = break_value = sbrk (0); |
| 479 | if (break_value == (POINTER)NULL) | 505 | if (break_value == (POINTER)NULL) |
| 480 | (*warn_func)("Malloc initialization returned 0 from sbrk(0)."); | 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 | ||
| 481 | 510 | ||
| 482 | page_break_value = (POINTER) ROUNDUP (break_value); | 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. */ | ||
| 483 | bzero (break_value, (page_break_value - break_value)); | 514 | bzero (break_value, (page_break_value - break_value)); |
| 484 | use_relocatable_buffers = 1; | 515 | use_relocatable_buffers = 1; |
| 485 | 516 | ||
| 486 | lim_data = 0; | 517 | lim_data = 0; |
| 487 | warnlevel = 0; | 518 | warnlevel = 0; |
| 488 | warn_function = warn_func; | ||
| 489 | 519 | ||
| 490 | get_lim_data (); | 520 | get_lim_data (); |
| 491 | } | 521 | } |
| 522 | |||
| 523 | /* This is the name Emacs expects to call. */ | ||
| 524 | |||
| 525 | void | ||
| 526 | memory_warnings (start, warn_func) | ||
| 527 | POINTER start; | ||
| 528 | void (*warn_func) (); | ||
| 529 | { | ||
| 530 | if (start) | ||
| 531 | data_space_start = start; | ||
| 532 | else | ||
| 533 | data_space_start = start_of_data (); | ||
| 534 | |||
| 535 | warn_function = warn_func; | ||
| 536 | } | ||