1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
19
20 #ifdef emacs
21 #include <config.h>
22 #include <setjmp.h>
23 #include "lisp.h"
24 #endif
25
26 #ifndef emacs
27 #include <stddef.h>
28 typedef size_t SIZE;
29 typedef void *POINTER;
30 #define EXCEEDS_LISP_PTR(x) 0
31 #endif
32
33 #include "mem-limits.h"
34
35 #ifdef HAVE_GETRLIMIT
36 #include <sys/resource.h>
37 #endif
38
39 40 41 42 43 44 45
46 enum warnlevel { not_warned, warned_75, warned_85, warned_95 };
47
48 static enum warnlevel warnlevel;
49
50 51
52 static void (*warn_function) ();
53
54
55 static POINTER data_space_start;
56
57
58 static unsigned long lim_data;
59
60
61 #ifdef NO_LIM_DATA
62 static void
63 get_lim_data ()
64 {
65 lim_data = -1;
66 }
67 #else
68
69 #if defined (HAVE_GETRLIMIT) && defined (RLIMIT_AS)
70 static void
71 get_lim_data ()
72 {
73 struct rlimit rlimit;
74
75 getrlimit (RLIMIT_AS, &rlimit);
76 if (rlimit.rlim_cur == RLIM_INFINITY)
77 lim_data = -1;
78 else
79 lim_data = rlimit.rlim_cur;
80 }
81
82 #else
83
84 #ifdef USG
85
86 static void
87 get_lim_data ()
88 {
89 extern long ulimit ();
90
91 lim_data = -1;
92
93
94 #if !defined (ULIMIT_BREAK_VALUE) || defined (GNU_LINUX)
95 lim_data = ulimit (3, 0);
96 #endif
97
98
99 #ifdef ULIMIT_BREAK_VALUE
100 if (lim_data == -1)
101 lim_data = ULIMIT_BREAK_VALUE;
102 #endif
103
104 lim_data -= (long) data_space_start;
105 }
106
107 #else
108 #ifdef WINDOWSNT
109
110 static void
111 get_lim_data ()
112 {
113 extern unsigned long reserved_heap_size;
114 lim_data = reserved_heap_size;
115 }
116
117 #else
118 #if !defined (BSD4_2) && !defined (__osf__)
119
120 #ifdef MSDOS
121 void
122 get_lim_data ()
123 {
124 _go32_dpmi_meminfo info;
125 unsigned long lim1, lim2;
126
127 _go32_dpmi_get_free_memory_information (&info);
128 129 130 131
132 lim1 = info.available_memory;
133 lim2 = info.available_physical_pages;
134
135 if ((long)lim1 == -1L)
136 lim1 = 0;
137 if ((long)lim2 == -1L)
138 lim2 = 0;
139 else
140 lim2 *= 4096;
141 142
143 if (lim1 >= lim2)
144 lim_data = lim1;
145 else
146 lim_data = lim2;
147
148 if (lim_data > 512U * 1024U * 1024U)
149 lim_data = 512U * 1024U * 1024U;
150 }
151
152 unsigned long
153 ret_lim_data ()
154 {
155 get_lim_data ();
156 return lim_data;
157 }
158 #else
159 static void
160 get_lim_data ()
161 {
162 lim_data = vlimit (LIM_DATA, -1);
163 }
164 #endif
165
166 #else
167
168 static void
169 get_lim_data ()
170 {
171 struct rlimit XXrlimit;
172
173 getrlimit (RLIMIT_DATA, &XXrlimit);
174 #ifdef RLIM_INFINITY
175 lim_data = XXrlimit.rlim_cur & RLIM_INFINITY;
176 #else
177 lim_data = XXrlimit.rlim_cur;
178 #endif
179 }
180 #endif
181 #endif
182 #endif
183 #endif
184 #endif
185
186
187
188 static void
189 check_memory_limits ()
190 {
191 #ifdef REL_ALLOC
192 extern POINTER (*real_morecore) ();
193 #endif
194 extern POINTER (*__morecore) ();
195
196 register POINTER cp;
197 unsigned long five_percent;
198 unsigned long data_size;
199 enum warnlevel new_warnlevel;
200
201 if (lim_data == 0)
202 get_lim_data ();
203 five_percent = lim_data / 20;
204
205
206 #ifdef REL_ALLOC
207 if (real_morecore)
208 cp = (char *) (*real_morecore) (0);
209 else
210 #endif
211 cp = (char *) (*__morecore) (0);
212 data_size = (char *) cp - (char *) data_space_start;
213
214 if (!warn_function)
215 return;
216
217
218 new_warnlevel
219 = (data_size > five_percent * 19) ? warned_95
220 : (data_size > five_percent * 17) ? warned_85
221 : (data_size > five_percent * 15) ? warned_75
222 : not_warned;
223
224
225 if (new_warnlevel > warnlevel || new_warnlevel == warned_95)
226 {
227 warnlevel = new_warnlevel;
228 switch (warnlevel)
229 {
230 case warned_75:
231 (*warn_function) ("Warning: past 75% of memory limit");
232 break;
233
234 case warned_85:
235 (*warn_function) ("Warning: past 85% of memory limit");
236 break;
237
238 case warned_95:
239 (*warn_function) ("Warning: past 95% of memory limit");
240 }
241 }
242
243 else
244 {
245 246
247 if (data_size < five_percent * 14)
248 warnlevel = not_warned;
249 250
251 else if (warnlevel > warned_75 && data_size < five_percent * 16)
252 warnlevel = warned_75;
253 254
255 else if (warnlevel > warned_85 && data_size < five_percent * 18)
256 warnlevel = warned_85;
257 }
258
259 if (EXCEEDS_LISP_PTR (cp))
260 (*warn_function) ("Warning: memory in use exceeds lisp pointer size");
261 }
262
263 264 265
266
267 void
268 memory_warnings (start, warnfun)
269 POINTER start;
270 void (*warnfun) ();
271 {
272 extern void (* __after_morecore_hook) ();
273
274 if (start)
275 data_space_start = start;
276 else
277 data_space_start = start_of_data ();
278
279 warn_function = warnfun;
280 __after_morecore_hook = check_memory_limits;
281
282
283 lim_data = 0;
284 }
285
286 287