diff options
| author | Richard M. Stallman | 2006-03-11 15:24:02 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 2006-03-11 15:24:02 +0000 |
| commit | 395d3972b1ffbcbe1a81052163be27345d0ca8fb (patch) | |
| tree | 156d82ccf671edfe2884ca5b931c8ac3585ed691 | |
| parent | 02b370adb2780a76ef926b7a8f394fe32a72b7ee (diff) | |
| download | emacs-395d3972b1ffbcbe1a81052163be27345d0ca8fb.tar.gz emacs-395d3972b1ffbcbe1a81052163be27345d0ca8fb.zip | |
(get_lim_data, lim_data, data_space_start): Moved from mem-limits.h.
(enum warnlevel): New data type.
(check_memory_limits): Rewrite the logic about warnings.
Use standard `struct rlimit'. Check return values for nonsense.
(memory_warnings): Always clear lim_data.
| -rw-r--r-- | src/ChangeLog | 18 | ||||
| -rw-r--r-- | src/vm-limit.c | 211 |
2 files changed, 173 insertions, 56 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 6d7ef065cf8..e83940cecd6 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,21 @@ | |||
| 1 | 2006-03-11 Richard Stallman <rms@gnu.org> | ||
| 2 | |||
| 3 | * vm-limit.c (get_lim_data, lim_data, data_space_start): | ||
| 4 | Moved from mem-limits.h. | ||
| 5 | (enum warnlevel): New data type. | ||
| 6 | (check_memory_limits): Rewrite the logic about warnings. | ||
| 7 | Use standard `struct rlimit'. Check return values for nonsense. | ||
| 8 | (memory_warnings): Always clear lim_data. | ||
| 9 | |||
| 10 | * mem-limits.h (get_lim_data, lim_data, data_space_start): | ||
| 11 | Moved to vm-limit.c. | ||
| 12 | |||
| 13 | * xterm.c (x_fully_uncatch_errors, x_catching_errors): New functions. | ||
| 14 | |||
| 15 | * eval.c (unwind_to_catch): Call x_fully_uncatch_errors. | ||
| 16 | (internal_condition_case_1, internal_condition_case_2): | ||
| 17 | Abort if within unclosed x_catch_errors. | ||
| 18 | |||
| 1 | 2006-03-11 Romain Francoise <romain@orebokech.com> | 19 | 2006-03-11 Romain Francoise <romain@orebokech.com> |
| 2 | 20 | ||
| 3 | * process.c (Vprocess_adaptive_read_buffering): Doc fix. | 21 | * process.c (Vprocess_adaptive_read_buffering): Doc fix. |
diff --git a/src/vm-limit.c b/src/vm-limit.c index 48d13c323ae..de31eda0cec 100644 --- a/src/vm-limit.c +++ b/src/vm-limit.c | |||
| @@ -32,6 +32,9 @@ typedef void *POINTER; | |||
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | #include "mem-limits.h" | 34 | #include "mem-limits.h" |
| 35 | #include <sys/resource.h> | ||
| 36 | |||
| 37 | #define HAVE_GETRLIMIT | ||
| 35 | 38 | ||
| 36 | #ifdef HAVE_GETRLIMIT | 39 | #ifdef HAVE_GETRLIMIT |
| 37 | #include <sys/resource.h> | 40 | #include <sys/resource.h> |
| @@ -44,13 +47,102 @@ typedef void *POINTER; | |||
| 44 | 2 -- 85% warning already issued. | 47 | 2 -- 85% warning already issued. |
| 45 | 3 -- 95% warning issued; keep warning frequently. | 48 | 3 -- 95% warning issued; keep warning frequently. |
| 46 | */ | 49 | */ |
| 47 | static int warnlevel; | 50 | enum warnlevel { not_warned, warned_75, warned_85, warned_95 }; |
| 51 | |||
| 52 | static enum warnlevel warnlevel; | ||
| 48 | 53 | ||
| 49 | /* Function to call to issue a warning; | 54 | /* Function to call to issue a warning; |
| 50 | 0 means don't issue them. */ | 55 | 0 means don't issue them. */ |
| 51 | static void (*warn_function) (); | 56 | static void (*warn_function) (); |
| 52 | 57 | ||
| 53 | /* Get more memory space, complaining if we're near the end. */ | 58 | /* Start of data space; can be changed by calling malloc_init. */ |
| 59 | static POINTER data_space_start; | ||
| 60 | |||
| 61 | /* Number of bytes of writable memory we can expect to be able to get. */ | ||
| 62 | static unsigned long lim_data; | ||
| 63 | |||
| 64 | |||
| 65 | #ifdef NO_LIM_DATA | ||
| 66 | static void | ||
| 67 | get_lim_data () | ||
| 68 | { | ||
| 69 | lim_data = -1; | ||
| 70 | } | ||
| 71 | #else /* not NO_LIM_DATA */ | ||
| 72 | |||
| 73 | #ifdef USG | ||
| 74 | |||
| 75 | static void | ||
| 76 | get_lim_data () | ||
| 77 | { | ||
| 78 | extern long ulimit (); | ||
| 79 | |||
| 80 | lim_data = -1; | ||
| 81 | |||
| 82 | /* Use the ulimit call, if we seem to have it. */ | ||
| 83 | #if !defined (ULIMIT_BREAK_VALUE) || defined (GNU_LINUX) | ||
| 84 | lim_data = ulimit (3, 0); | ||
| 85 | #endif | ||
| 86 | |||
| 87 | /* If that didn't work, just use the macro's value. */ | ||
| 88 | #ifdef ULIMIT_BREAK_VALUE | ||
| 89 | if (lim_data == -1) | ||
| 90 | lim_data = ULIMIT_BREAK_VALUE; | ||
| 91 | #endif | ||
| 92 | |||
| 93 | lim_data -= (long) data_space_start; | ||
| 94 | } | ||
| 95 | |||
| 96 | #else /* not USG */ | ||
| 97 | #ifdef WINDOWSNT | ||
| 98 | |||
| 99 | static void | ||
| 100 | get_lim_data () | ||
| 101 | { | ||
| 102 | extern unsigned long reserved_heap_size; | ||
| 103 | lim_data = reserved_heap_size; | ||
| 104 | } | ||
| 105 | |||
| 106 | #else | ||
| 107 | #if !defined (BSD4_2) && !defined (__osf__) | ||
| 108 | |||
| 109 | #ifdef MSDOS | ||
| 110 | void | ||
| 111 | get_lim_data () | ||
| 112 | { | ||
| 113 | _go32_dpmi_meminfo info; | ||
| 114 | |||
| 115 | _go32_dpmi_get_free_memory_information (&info); | ||
| 116 | lim_data = info.available_memory; | ||
| 117 | } | ||
| 118 | #else /* not MSDOS */ | ||
| 119 | static void | ||
| 120 | get_lim_data () | ||
| 121 | { | ||
| 122 | lim_data = vlimit (LIM_DATA, -1); | ||
| 123 | } | ||
| 124 | #endif /* not MSDOS */ | ||
| 125 | |||
| 126 | #else /* BSD4_2 */ | ||
| 127 | |||
| 128 | static void | ||
| 129 | get_lim_data () | ||
| 130 | { | ||
| 131 | struct rlimit XXrlimit; | ||
| 132 | |||
| 133 | getrlimit (RLIMIT_DATA, &XXrlimit); | ||
| 134 | #ifdef RLIM_INFINITY | ||
| 135 | lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */ | ||
| 136 | #else | ||
| 137 | lim_data = XXrlimit.rlim_cur; /* soft limit */ | ||
| 138 | #endif | ||
| 139 | } | ||
| 140 | #endif /* BSD4_2 */ | ||
| 141 | #endif /* not WINDOWSNT */ | ||
| 142 | #endif /* not USG */ | ||
| 143 | #endif /* not NO_LIM_DATA */ | ||
| 144 | |||
| 145 | /* Verify amount of memory available, complaining if we're near the end. */ | ||
| 54 | 146 | ||
| 55 | static void | 147 | static void |
| 56 | check_memory_limits () | 148 | check_memory_limits () |
| @@ -64,14 +156,19 @@ check_memory_limits () | |||
| 64 | register POINTER cp; | 156 | register POINTER cp; |
| 65 | unsigned long five_percent; | 157 | unsigned long five_percent; |
| 66 | unsigned long data_size; | 158 | unsigned long data_size; |
| 159 | enum warnlevel new_warnlevel; | ||
| 67 | 160 | ||
| 68 | #ifdef HAVE_GETRLIMIT | 161 | #ifdef HAVE_GETRLIMIT |
| 69 | struct rlimit { | 162 | struct rlimit rlimit; |
| 70 | rlim_t rlim_cur; | 163 | |
| 71 | rlim_t rlim_max; | 164 | getrlimit (RLIMIT_AS, &rlimit); |
| 72 | } rlimit; | 165 | |
| 166 | if (RLIM_INFINITY == rlimit.rlim_max) | ||
| 167 | return; | ||
| 73 | 168 | ||
| 74 | getrlimit (RLIMIT_DATA, &rlimit); | 169 | /* This is a nonsensical case, but it happens -- rms. */ |
| 170 | if (rlimit.rlim_cur > rlimit.rlim_max) | ||
| 171 | return; | ||
| 75 | 172 | ||
| 76 | five_percent = rlimit.rlim_max / 20; | 173 | five_percent = rlimit.rlim_max / 20; |
| 77 | data_size = rlimit.rlim_cur; | 174 | data_size = rlimit.rlim_cur; |
| @@ -93,57 +190,61 @@ check_memory_limits () | |||
| 93 | 190 | ||
| 94 | #endif /* not HAVE_GETRLIMIT */ | 191 | #endif /* not HAVE_GETRLIMIT */ |
| 95 | 192 | ||
| 96 | if (warn_function) | 193 | if (!warn_function) |
| 97 | switch (warnlevel) | 194 | return; |
| 98 | { | 195 | |
| 99 | case 0: | 196 | /* What level of warning does current memory usage demand? */ |
| 100 | if (data_size > five_percent * 15) | 197 | if (data_size > five_percent * 19) |
| 101 | { | 198 | new_warnlevel = warned_95; |
| 102 | warnlevel++; | 199 | else if (data_size > five_percent * 17) |
| 103 | (*warn_function) ("Warning: past 75% of memory limit"); | 200 | new_warnlevel = warned_85; |
| 104 | } | 201 | else if (data_size > five_percent * 15) |
| 105 | break; | 202 | new_warnlevel = warned_75; |
| 106 | 203 | else | |
| 107 | case 1: | 204 | new_warnlevel = not_warned; |
| 108 | if (data_size > five_percent * 17) | 205 | |
| 109 | { | 206 | /* If we have gone up a level, give the appropriate warning. */ |
| 110 | warnlevel++; | 207 | if (new_warnlevel > warnlevel || new_warnlevel == warned_95) |
| 111 | (*warn_function) ("Warning: past 85% of memory limit"); | 208 | { |
| 112 | } | 209 | warnlevel = new_warnlevel; |
| 113 | break; | 210 | switch (warnlevel) |
| 114 | 211 | { | |
| 115 | case 2: | 212 | case warned_75: |
| 116 | if (data_size > five_percent * 19) | 213 | (*warn_function) ("Warning: past 75% of memory limit"); |
| 117 | { | 214 | break; |
| 118 | warnlevel++; | 215 | |
| 119 | (*warn_function) ("Warning: past 95% of memory limit"); | 216 | case warned_85: |
| 120 | } | 217 | (*warn_function) ("Warning: past 85% of memory limit"); |
| 121 | break; | 218 | break; |
| 122 | 219 | ||
| 123 | default: | 220 | case warned_95: |
| 124 | (*warn_function) ("Warning: past acceptable memory limits"); | 221 | (*warn_function) ("Warning: past 95% of memory limit"); |
| 125 | break; | 222 | } |
| 126 | } | 223 | } |
| 127 | 224 | /* Handle going down in usage levels, with some hysteresis. */ | |
| 128 | /* If we go down below 70% full, issue another 75% warning | 225 | else |
| 129 | when we go up again. */ | 226 | { |
| 130 | if (data_size < five_percent * 14) | 227 | /* If we go down below 70% full, issue another 75% warning |
| 131 | warnlevel = 0; | 228 | when we go up again. */ |
| 132 | /* If we go down below 80% full, issue another 85% warning | 229 | if (data_size < five_percent * 14) |
| 133 | when we go up again. */ | 230 | warnlevel = not_warned; |
| 134 | else if (warnlevel > 1 && data_size < five_percent * 16) | 231 | /* If we go down below 80% full, issue another 85% warning |
| 135 | warnlevel = 1; | 232 | when we go up again. */ |
| 136 | /* If we go down below 90% full, issue another 95% warning | 233 | else if (warnlevel > warned_75 && data_size < five_percent * 16) |
| 137 | when we go up again. */ | 234 | warnlevel = warned_75; |
| 138 | else if (warnlevel > 2 && data_size < five_percent * 18) | 235 | /* If we go down below 90% full, issue another 95% warning |
| 139 | warnlevel = 2; | 236 | when we go up again. */ |
| 237 | else if (warnlevel > warned_85 && data_size < five_percent * 18) | ||
| 238 | warnlevel = warned_85; | ||
| 239 | } | ||
| 140 | 240 | ||
| 141 | if (EXCEEDS_LISP_PTR (cp)) | 241 | if (EXCEEDS_LISP_PTR (cp)) |
| 142 | (*warn_function) ("Warning: memory in use exceeds lisp pointer size"); | 242 | (*warn_function) ("Warning: memory in use exceeds lisp pointer size"); |
| 143 | } | 243 | } |
| 144 | 244 | ||
| 145 | /* Cause reinitialization based on job parameters; | 245 | /* Enable memory usage warnings. |
| 146 | also declare where the end of pure storage is. */ | 246 | START says where the end of pure storage is. |
| 247 | WARNFUN specifies the function to call to issue a warning. */ | ||
| 147 | 248 | ||
| 148 | void | 249 | void |
| 149 | memory_warnings (start, warnfun) | 250 | memory_warnings (start, warnfun) |
| @@ -160,10 +261,8 @@ memory_warnings (start, warnfun) | |||
| 160 | warn_function = warnfun; | 261 | warn_function = warnfun; |
| 161 | __after_morecore_hook = check_memory_limits; | 262 | __after_morecore_hook = check_memory_limits; |
| 162 | 263 | ||
| 163 | #ifdef WINDOWSNT | ||
| 164 | /* Force data limit to be recalculated on each run. */ | 264 | /* Force data limit to be recalculated on each run. */ |
| 165 | lim_data = 0; | 265 | lim_data = 0; |
| 166 | #endif | ||
| 167 | } | 266 | } |
| 168 | 267 | ||
| 169 | /* arch-tag: eab04eda-1f69-447a-8d9f-95f0a3983ca5 | 268 | /* arch-tag: eab04eda-1f69-447a-8d9f-95f0a3983ca5 |