Mercurial > emacs
comparison src/vm-limit.c @ 69390:7e58bc915ffe
(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.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Sat, 11 Mar 2006 15:23:45 +0000 |
parents | 01f2a79bee28 |
children | 4c6bb2c4dbcf |
comparison
equal
deleted
inserted
replaced
69389:858b77cfcdf5 | 69390:7e58bc915ffe |
---|---|
30 typedef void *POINTER; | 30 typedef void *POINTER; |
31 #define EXCEEDS_LISP_PTR(x) 0 | 31 #define EXCEEDS_LISP_PTR(x) 0 |
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> |
38 #endif | 41 #endif |
39 | 42 |
42 0 -- no warnings issued. | 45 0 -- no warnings issued. |
43 1 -- 75% warning already issued. | 46 1 -- 75% warning already issued. |
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 () |
57 { | 149 { |
58 #ifdef REL_ALLOC | 150 #ifdef REL_ALLOC |
62 | 154 |
63 | 155 |
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 |
73 | 166 if (RLIM_INFINITY == rlimit.rlim_max) |
74 getrlimit (RLIMIT_DATA, &rlimit); | 167 return; |
168 | |
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; |
78 | 175 |
79 #else /* not HAVE_GETRLIMIT */ | 176 #else /* not HAVE_GETRLIMIT */ |
91 cp = (char *) (*__morecore) (0); | 188 cp = (char *) (*__morecore) (0); |
92 data_size = (char *) cp - (char *) data_space_start; | 189 data_size = (char *) cp - (char *) data_space_start; |
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) |
150 POINTER start; | 251 POINTER start; |
151 void (*warnfun) (); | 252 void (*warnfun) (); |
158 data_space_start = start_of_data (); | 259 data_space_start = start_of_data (); |
159 | 260 |
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 |
170 (do not change this comment) */ | 269 (do not change this comment) */ |