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) */