diff options
| author | Richard M. Stallman | 1995-02-06 22:52:25 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1995-02-06 22:52:25 +0000 |
| commit | 276cbe5a5f38c5b3313245ceea7d06e01da47f33 (patch) | |
| tree | 3a0bf568b850e4dad7769ebc2bc62dbf6ce7ac19 /src/alloc.c | |
| parent | d07ee75af95c5bd43654da65452e5628198a300c (diff) | |
| download | emacs-276cbe5a5f38c5b3313245ceea7d06e01da47f33.tar.gz emacs-276cbe5a5f38c5b3313245ceea7d06e01da47f33.zip | |
(emacs_blocked_malloc): Set __malloc_extra_blocks here.
(malloc_hysteresis): New variable.
(init_alloc_once): Initialize malloc_hysteresis.
(buffer_memory_full): New function.
(refill_memory_reserve): New function.
(SPARE_MEMORY): New macro.
(emacs_blocked_free): If no spare_memory now, and enough free
space is available, get a new spare.
(__malloc_size_t, _bytes_used): Declared.
(bytes_used_when_full): New variable.
(syms_of_alloc): Improve memory exhausted error message.
(init_alloc_once): Allocate spare_memory.
(memory_full): Free spare_memory.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 98 |
1 files changed, 97 insertions, 1 deletions
diff --git a/src/alloc.c b/src/alloc.c index f36bf7e3e1e..48bd856d6d5 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -32,6 +32,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 32 | 32 | ||
| 33 | #include "syssignal.h" | 33 | #include "syssignal.h" |
| 34 | 34 | ||
| 35 | /* The following come from gmalloc.c. */ | ||
| 36 | |||
| 37 | #if defined (__STDC__) && __STDC__ | ||
| 38 | #include <stddef.h> | ||
| 39 | #define __malloc_size_t size_t | ||
| 40 | #else | ||
| 41 | #define __malloc_size_t unsigned int | ||
| 42 | #endif | ||
| 43 | extern __malloc_size_t _bytes_used; | ||
| 44 | extern int __malloc_extra_blocks; | ||
| 45 | |||
| 35 | #define max(A,B) ((A) > (B) ? (A) : (B)) | 46 | #define max(A,B) ((A) > (B) ? (A) : (B)) |
| 36 | 47 | ||
| 37 | /* Macro to verify that storage intended for Lisp objects is not | 48 | /* Macro to verify that storage intended for Lisp objects is not |
| @@ -50,6 +61,9 @@ do \ | |||
| 50 | } \ | 61 | } \ |
| 51 | } while (0) | 62 | } while (0) |
| 52 | 63 | ||
| 64 | /* Value of _bytes_used, when spare_memory was freed. */ | ||
| 65 | static __malloc_size_t bytes_used_when_full; | ||
| 66 | |||
| 53 | /* Number of bytes of consing done since the last gc */ | 67 | /* Number of bytes of consing done since the last gc */ |
| 54 | int consing_since_gc; | 68 | int consing_since_gc; |
| 55 | 69 | ||
| @@ -73,6 +87,16 @@ extern | |||
| 73 | int undo_limit; | 87 | int undo_limit; |
| 74 | int undo_strong_limit; | 88 | int undo_strong_limit; |
| 75 | 89 | ||
| 90 | /* Points to memory space allocated as "spare", | ||
| 91 | to be freed if we run out of memory. */ | ||
| 92 | static char *spare_memory; | ||
| 93 | |||
| 94 | /* Amount of spare memory to keep in reserve. */ | ||
| 95 | #define SPARE_MEMORY (1 << 14) | ||
| 96 | |||
| 97 | /* Number of extra blocks malloc should get when it needs more core. */ | ||
| 98 | static int malloc_hysteresis; | ||
| 99 | |||
| 76 | /* Non-nil means defun should do purecopy on the function definition */ | 100 | /* Non-nil means defun should do purecopy on the function definition */ |
| 77 | Lisp_Object Vpurify_flag; | 101 | Lisp_Object Vpurify_flag; |
| 78 | 102 | ||
| @@ -164,8 +188,42 @@ display_malloc_warning () | |||
| 164 | } | 188 | } |
| 165 | 189 | ||
| 166 | /* Called if malloc returns zero */ | 190 | /* Called if malloc returns zero */ |
| 191 | |||
| 167 | memory_full () | 192 | memory_full () |
| 168 | { | 193 | { |
| 194 | #ifndef SYSTEM_MALLOC | ||
| 195 | bytes_used_when_full = _bytes_used; | ||
| 196 | #endif | ||
| 197 | |||
| 198 | /* The first time we get here, free the spare memory. */ | ||
| 199 | if (spare_memory) | ||
| 200 | { | ||
| 201 | free (spare_memory); | ||
| 202 | spare_memory = 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | /* This used to call error, but if we've run out of memory, we could get | ||
| 206 | infinite recursion trying to build the string. */ | ||
| 207 | while (1) | ||
| 208 | Fsignal (Qerror, memory_signal_data); | ||
| 209 | } | ||
| 210 | |||
| 211 | /* Called if we can't allocate relocatable space for a buffer. */ | ||
| 212 | |||
| 213 | void | ||
| 214 | buffer_memory_full () | ||
| 215 | { | ||
| 216 | /* If buffers use the relocating allocator, | ||
| 217 | no need to free spare_memory, because we may have plenty of malloc | ||
| 218 | space left that we could get, and if we don't, the malloc that fails | ||
| 219 | will itself cause spare_memory to be freed. | ||
| 220 | If buffers don't use the relocating allocator, | ||
| 221 | treat this like any other failing malloc. */ | ||
| 222 | |||
| 223 | #ifndef REL_ALLOC | ||
| 224 | memory_full (); | ||
| 225 | #endif | ||
| 226 | |||
| 169 | /* This used to call error, but if we've run out of memory, we could get | 227 | /* This used to call error, but if we've run out of memory, we could get |
| 170 | infinite recursion trying to build the string. */ | 228 | infinite recursion trying to build the string. */ |
| 171 | while (1) | 229 | while (1) |
| @@ -236,6 +294,8 @@ static void * (*old_realloc_hook) (); | |||
| 236 | extern void (*__free_hook) (); | 294 | extern void (*__free_hook) (); |
| 237 | static void (*old_free_hook) (); | 295 | static void (*old_free_hook) (); |
| 238 | 296 | ||
| 297 | /* This function is used as the hook for free to call. */ | ||
| 298 | |||
| 239 | static void | 299 | static void |
| 240 | emacs_blocked_free (ptr) | 300 | emacs_blocked_free (ptr) |
| 241 | void *ptr; | 301 | void *ptr; |
| @@ -243,10 +303,37 @@ emacs_blocked_free (ptr) | |||
| 243 | BLOCK_INPUT; | 303 | BLOCK_INPUT; |
| 244 | __free_hook = old_free_hook; | 304 | __free_hook = old_free_hook; |
| 245 | free (ptr); | 305 | free (ptr); |
| 306 | /* If we released our reserve (due to running out of memory), | ||
| 307 | and we have a fair amount free once again, | ||
| 308 | try to set aside another reserve in case we run out once more. */ | ||
| 309 | if (spare_memory == 0 | ||
| 310 | /* Verify there is enough space that even with the malloc | ||
| 311 | hysteresis this call won't run out again. | ||
| 312 | The code here is correct as long as SPARE_MEMORY | ||
| 313 | is substantially larger than the block size malloc uses. */ | ||
| 314 | && (bytes_used_when_full | ||
| 315 | > _bytes_used + max (malloc_hysteresis, 4) * SPARE_MEMORY)) | ||
| 316 | spare_memory = (char *) malloc (SPARE_MEMORY); | ||
| 317 | |||
| 246 | __free_hook = emacs_blocked_free; | 318 | __free_hook = emacs_blocked_free; |
| 247 | UNBLOCK_INPUT; | 319 | UNBLOCK_INPUT; |
| 248 | } | 320 | } |
| 249 | 321 | ||
| 322 | /* If we released our reserve (due to running out of memory), | ||
| 323 | and we have a fair amount free once again, | ||
| 324 | try to set aside another reserve in case we run out once more. | ||
| 325 | |||
| 326 | This is called when a relocatable block is freed in ralloc.c. */ | ||
| 327 | |||
| 328 | void | ||
| 329 | refill_memory_reserve () | ||
| 330 | { | ||
| 331 | if (spare_memory == 0) | ||
| 332 | spare_memory = (char *) malloc (SPARE_MEMORY); | ||
| 333 | } | ||
| 334 | |||
| 335 | /* This function is the malloc hook that Emacs uses. */ | ||
| 336 | |||
| 250 | static void * | 337 | static void * |
| 251 | emacs_blocked_malloc (size) | 338 | emacs_blocked_malloc (size) |
| 252 | unsigned size; | 339 | unsigned size; |
| @@ -255,6 +342,7 @@ emacs_blocked_malloc (size) | |||
| 255 | 342 | ||
| 256 | BLOCK_INPUT; | 343 | BLOCK_INPUT; |
| 257 | __malloc_hook = old_malloc_hook; | 344 | __malloc_hook = old_malloc_hook; |
| 345 | __malloc_extra_blocks = malloc_hysteresis; | ||
| 258 | value = (void *) malloc (size); | 346 | value = (void *) malloc (size); |
| 259 | __malloc_hook = emacs_blocked_malloc; | 347 | __malloc_hook = emacs_blocked_malloc; |
| 260 | UNBLOCK_INPUT; | 348 | UNBLOCK_INPUT; |
| @@ -2258,6 +2346,14 @@ init_alloc_once () | |||
| 2258 | #endif /* LISP_FLOAT_TYPE */ | 2346 | #endif /* LISP_FLOAT_TYPE */ |
| 2259 | INIT_INTERVALS; | 2347 | INIT_INTERVALS; |
| 2260 | 2348 | ||
| 2349 | #ifdef REL_ALLOC | ||
| 2350 | malloc_hysteresis = 32; | ||
| 2351 | #else | ||
| 2352 | malloc_hysteresis = 0; | ||
| 2353 | #endif | ||
| 2354 | |||
| 2355 | spare_memory = (char *) malloc (SPARE_MEMORY); | ||
| 2356 | |||
| 2261 | ignore_warnings = 0; | 2357 | ignore_warnings = 0; |
| 2262 | gcprolist = 0; | 2358 | gcprolist = 0; |
| 2263 | staticidx = 0; | 2359 | staticidx = 0; |
| @@ -2318,7 +2414,7 @@ which includes both saved text and other data."); | |||
| 2318 | /* We build this in advance because if we wait until we need it, we might | 2414 | /* We build this in advance because if we wait until we need it, we might |
| 2319 | not be able to allocate the memory to hold it. */ | 2415 | not be able to allocate the memory to hold it. */ |
| 2320 | memory_signal_data | 2416 | memory_signal_data |
| 2321 | = Fcons (Qerror, Fcons (build_string ("Memory exhausted"), Qnil)); | 2417 | = Fcons (Qerror, Fcons (build_string ("Memory exhausted--use M-x save-some-buffers RET"), Qnil)); |
| 2322 | staticpro (&memory_signal_data); | 2418 | staticpro (&memory_signal_data); |
| 2323 | 2419 | ||
| 2324 | defsubr (&Scons); | 2420 | defsubr (&Scons); |