aboutsummaryrefslogtreecommitdiffstats
path: root/src/vm-limit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm-limit.c')
-rw-r--r--src/vm-limit.c184
1 files changed, 65 insertions, 119 deletions
diff --git a/src/vm-limit.c b/src/vm-limit.c
index 2a71e88695a..3fca8bd26c1 100644
--- a/src/vm-limit.c
+++ b/src/vm-limit.c
@@ -1,5 +1,5 @@
1/* Functions for memory limit warnings. 1/* Functions for memory limit warnings.
2 Copyright (C) 1990, 1992, 2001-2012 Free Software Foundation, Inc. 2 Copyright (C) 1990, 1992, 2001-2013 Free Software Foundation, Inc.
3 3
4This file is part of GNU Emacs. 4This file is part of GNU Emacs.
5 5
@@ -19,7 +19,37 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19#include <config.h> 19#include <config.h>
20#include <unistd.h> /* for 'environ', on AIX */ 20#include <unistd.h> /* for 'environ', on AIX */
21#include "lisp.h" 21#include "lisp.h"
22#include "mem-limits.h" 22
23#ifdef MSDOS
24#include <dpmi.h>
25extern int etext;
26#endif
27
28/* Some systems need this before <sys/resource.h>. */
29#include <sys/types.h>
30
31#ifdef HAVE_SYS_RESOURCE_H
32# include <sys/time.h>
33# include <sys/resource.h>
34#else
35# if HAVE_SYS_VLIMIT_H
36# include <sys/vlimit.h> /* Obsolete, says glibc */
37# endif
38#endif
39
40/* Start of data. It is OK if this is approximate; it's used only as
41 a heuristic. */
42#ifdef DATA_START
43# define data_start ((char *) DATA_START)
44#else
45extern char data_start[];
46# ifndef HAVE_DATA_START
47/* Initialize to nonzero, so that it's put into data and not bss.
48 Link this file's object code first, so that this symbol is near the
49 start of data. */
50char data_start[1] = { 1 };
51# endif
52#endif
23 53
24/* 54/*
25 Level number of warnings already issued. 55 Level number of warnings already issued.
@@ -31,59 +61,45 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
31enum warnlevel { not_warned, warned_75, warned_85, warned_95 }; 61enum warnlevel { not_warned, warned_75, warned_85, warned_95 };
32static enum warnlevel warnlevel; 62static enum warnlevel warnlevel;
33 63
34typedef void *POINTER;
35
36/* Function to call to issue a warning; 64/* Function to call to issue a warning;
37 0 means don't issue them. */ 65 0 means don't issue them. */
38static void (*warn_function) (const char *); 66static void (*warn_function) (const char *);
39 67
40/* Start of data space; can be changed by calling malloc_init. */ 68/* Start of data space; can be changed by calling memory_warnings. */
41static POINTER data_space_start; 69static char *data_space_start;
42 70
43/* Number of bytes of writable memory we can expect to be able to get. */ 71/* Number of bytes of writable memory we can expect to be able to get. */
44static size_t lim_data; 72static size_t lim_data;
45 73
46 74/* Return true if PTR cannot be represented as an Emacs Lisp object. */
47#if defined (HAVE_GETRLIMIT) && defined (RLIMIT_AS) 75static bool
48static void 76exceeds_lisp_ptr (void *ptr)
49get_lim_data (void)
50{ 77{
51 struct rlimit rlimit; 78 return (! USE_LSB_TAG
52 79 && VAL_MAX < UINTPTR_MAX
53 getrlimit (RLIMIT_AS, &rlimit); 80 && ((uintptr_t) ptr & ~DATA_SEG_BITS) >> VALBITS != 0);
54 if (rlimit.rlim_cur == RLIM_INFINITY)
55 lim_data = -1;
56 else
57 lim_data = rlimit.rlim_cur;
58} 81}
59 82
60#else /* not HAVE_GETRLIMIT */ 83#ifdef HAVE_GETRLIMIT
61 84
62#ifdef USG 85# ifndef RLIMIT_AS
86# define RLIMIT_AS RLIMIT_DATA
87# endif
63 88
64static void 89static void
65get_lim_data (void) 90get_lim_data (void)
66{ 91{
67 extern long ulimit (); 92 /* Set LIM_DATA to the minimum of the maximum object size and the
68 93 maximum address space. Don't bother to check for values like
69 lim_data = -1; 94 RLIM_INFINITY since in practice they are not much less than SIZE_MAX. */
70 95 struct rlimit rlimit;
71 /* Use the ulimit call, if we seem to have it. */ 96 lim_data
72#if !defined (ULIMIT_BREAK_VALUE) || defined (GNU_LINUX) 97 = (getrlimit (RLIMIT_AS, &rlimit) == 0 && rlimit.rlim_cur <= SIZE_MAX
73 lim_data = ulimit (3, 0); 98 ? rlimit.rlim_cur
74#endif 99 : SIZE_MAX);
75
76 /* If that didn't work, just use the macro's value. */
77#ifdef ULIMIT_BREAK_VALUE
78 if (lim_data == -1)
79 lim_data = ULIMIT_BREAK_VALUE;
80#endif
81
82 lim_data -= (long) data_space_start;
83} 100}
84 101
85#else /* not USG */ 102#elif defined WINDOWSNT
86#ifdef WINDOWSNT
87 103
88#include "w32heap.h" 104#include "w32heap.h"
89 105
@@ -94,10 +110,8 @@ get_lim_data (void)
94 lim_data = reserved_heap_size; 110 lim_data = reserved_heap_size;
95} 111}
96 112
97#else 113#elif defined MSDOS
98#if !defined (BSD4_2) && !defined (CYGWIN)
99 114
100#ifdef MSDOS
101void 115void
102get_lim_data (void) 116get_lim_data (void)
103{ 117{
@@ -135,32 +149,9 @@ ret_lim_data (void)
135 get_lim_data (); 149 get_lim_data ();
136 return lim_data; 150 return lim_data;
137} 151}
138#else /* not MSDOS */
139static void
140get_lim_data (void)
141{
142 lim_data = vlimit (LIM_DATA, -1);
143}
144#endif /* not MSDOS */
145
146#else /* BSD4_2 || CYGWIN */
147
148static void
149get_lim_data (void)
150{
151 struct rlimit XXrlimit;
152
153 getrlimit (RLIMIT_DATA, &XXrlimit);
154#ifdef RLIM_INFINITY
155 lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */
156#else 152#else
157 lim_data = XXrlimit.rlim_cur; /* soft limit */ 153# error "get_lim_data not implemented on this machine"
158#endif 154#endif
159}
160#endif /* BSD4_2 */
161#endif /* not WINDOWSNT */
162#endif /* not USG */
163#endif /* not HAVE_GETRLIMIT */
164 155
165/* Verify amount of memory available, complaining if we're near the end. */ 156/* Verify amount of memory available, complaining if we're near the end. */
166 157
@@ -168,11 +159,13 @@ static void
168check_memory_limits (void) 159check_memory_limits (void)
169{ 160{
170#ifdef REL_ALLOC 161#ifdef REL_ALLOC
171 extern POINTER (*real_morecore) (ptrdiff_t); 162 extern void *(*real_morecore) (ptrdiff_t);
163#else
164 void *(*real_morecore) (ptrdiff_t) = 0;
172#endif 165#endif
173 extern POINTER (*__morecore) (ptrdiff_t); 166 extern void *(*__morecore) (ptrdiff_t);
174 167
175 register POINTER cp; 168 char *cp;
176 size_t five_percent; 169 size_t five_percent;
177 size_t data_size; 170 size_t data_size;
178 enum warnlevel new_warnlevel; 171 enum warnlevel new_warnlevel;
@@ -182,13 +175,8 @@ check_memory_limits (void)
182 five_percent = lim_data / 20; 175 five_percent = lim_data / 20;
183 176
184 /* Find current end of memory and issue warning if getting near max */ 177 /* Find current end of memory and issue warning if getting near max */
185#ifdef REL_ALLOC 178 cp = (real_morecore ? real_morecore : __morecore) (0);
186 if (real_morecore) 179 data_size = cp - data_space_start;
187 cp = (char *) (*real_morecore) (0);
188 else
189#endif
190 cp = (char *) (*__morecore) (0);
191 data_size = (char *) cp - (char *) data_space_start;
192 180
193 if (!warn_function) 181 if (!warn_function)
194 return; 182 return;
@@ -235,62 +223,20 @@ check_memory_limits (void)
235 warnlevel = warned_85; 223 warnlevel = warned_85;
236 } 224 }
237 225
238 if (EXCEEDS_LISP_PTR (cp)) 226 if (exceeds_lisp_ptr (cp))
239 (*warn_function) ("Warning: memory in use exceeds lisp pointer size"); 227 (*warn_function) ("Warning: memory in use exceeds lisp pointer size");
240} 228}
241 229
242#if !defined (CANNOT_DUMP) || !defined (SYSTEM_MALLOC)
243/* Some systems that cannot dump also cannot implement these. */
244
245/*
246 * Return the address of the start of the data segment prior to
247 * doing an unexec. After unexec the return value is undefined.
248 * See crt0.c for further information and definition of data_start.
249 *
250 * Apparently, on BSD systems this is etext at startup. On
251 * USG systems (swapping) this is highly mmu dependent and
252 * is also dependent on whether or not the program is running
253 * with shared text. Generally there is a (possibly large)
254 * gap between end of text and start of data with shared text.
255 *
256 */
257
258char *
259start_of_data (void)
260{
261#ifdef BSD_SYSTEM
262 extern char etext;
263 return (POINTER)(&etext);
264#elif defined DATA_START
265 return ((POINTER) DATA_START);
266#elif defined ORDINARY_LINK
267 /*
268 * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
269 * data_start isn't defined. We take the address of environ, which
270 * is known to live at or near the start of the system crt0.c, and
271 * we don't sweat the handful of bytes that might lose.
272 */
273 return ((POINTER) &environ);
274#else
275 extern int data_start;
276 return ((POINTER) &data_start);
277#endif
278}
279#endif /* (not CANNOT_DUMP or not SYSTEM_MALLOC) */
280
281/* Enable memory usage warnings. 230/* Enable memory usage warnings.
282 START says where the end of pure storage is. 231 START says where the end of pure storage is.
283 WARNFUN specifies the function to call to issue a warning. */ 232 WARNFUN specifies the function to call to issue a warning. */
284 233
285void 234void
286memory_warnings (POINTER start, void (*warnfun) (const char *)) 235memory_warnings (void *start, void (*warnfun) (const char *))
287{ 236{
288 extern void (* __after_morecore_hook) (void); /* From gmalloc.c */ 237 extern void (* __after_morecore_hook) (void); /* From gmalloc.c */
289 238
290 if (start) 239 data_space_start = start ? start : data_start;
291 data_space_start = start;
292 else
293 data_space_start = start_of_data ();
294 240
295 warn_function = warnfun; 241 warn_function = warnfun;
296 __after_morecore_hook = check_memory_limits; 242 __after_morecore_hook = check_memory_limits;