X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/968e9c040adf26740fd77c9dedacf4a513595824..7857982c9fdd085806380117936fec0f529894e8:/src/vm-limit.c diff --git a/src/vm-limit.c b/src/vm-limit.c index 721e740bd0..de31eda0ce 100644 --- a/src/vm-limit.c +++ b/src/vm-limit.c @@ -1,5 +1,6 @@ /* Functions for memory limit warnings. - Copyright (C) 1990, 1992 Free Software Foundation, Inc. + Copyright (C) 1990, 1992, 2002, 2003, 2004, + 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -15,8 +16,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ #ifdef emacs #include @@ -31,6 +32,13 @@ typedef void *POINTER; #endif #include "mem-limits.h" +#include + +#define HAVE_GETRLIMIT + +#ifdef HAVE_GETRLIMIT +#include +#endif /* Level number of warnings already issued. @@ -39,13 +47,102 @@ typedef void *POINTER; 2 -- 85% warning already issued. 3 -- 95% warning issued; keep warning frequently. */ -static int warnlevel; +enum warnlevel { not_warned, warned_75, warned_85, warned_95 }; + +static enum warnlevel warnlevel; /* Function to call to issue a warning; 0 means don't issue them. */ static void (*warn_function) (); -/* Get more memory space, complaining if we're near the end. */ +/* Start of data space; can be changed by calling malloc_init. */ +static POINTER data_space_start; + +/* Number of bytes of writable memory we can expect to be able to get. */ +static unsigned long lim_data; + + +#ifdef NO_LIM_DATA +static void +get_lim_data () +{ + lim_data = -1; +} +#else /* not NO_LIM_DATA */ + +#ifdef USG + +static void +get_lim_data () +{ + extern long ulimit (); + + lim_data = -1; + + /* Use the ulimit call, if we seem to have it. */ +#if !defined (ULIMIT_BREAK_VALUE) || defined (GNU_LINUX) + lim_data = ulimit (3, 0); +#endif + + /* If that didn't work, just use the macro's value. */ +#ifdef ULIMIT_BREAK_VALUE + if (lim_data == -1) + lim_data = ULIMIT_BREAK_VALUE; +#endif + + lim_data -= (long) data_space_start; +} + +#else /* not USG */ +#ifdef WINDOWSNT + +static void +get_lim_data () +{ + extern unsigned long reserved_heap_size; + lim_data = reserved_heap_size; +} + +#else +#if !defined (BSD4_2) && !defined (__osf__) + +#ifdef MSDOS +void +get_lim_data () +{ + _go32_dpmi_meminfo info; + + _go32_dpmi_get_free_memory_information (&info); + lim_data = info.available_memory; +} +#else /* not MSDOS */ +static void +get_lim_data () +{ + lim_data = vlimit (LIM_DATA, -1); +} +#endif /* not MSDOS */ + +#else /* BSD4_2 */ + +static void +get_lim_data () +{ + struct rlimit XXrlimit; + + getrlimit (RLIMIT_DATA, &XXrlimit); +#ifdef RLIM_INFINITY + lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */ +#else + lim_data = XXrlimit.rlim_cur; /* soft limit */ +#endif +} +#endif /* BSD4_2 */ +#endif /* not WINDOWSNT */ +#endif /* not USG */ +#endif /* not NO_LIM_DATA */ + +/* Verify amount of memory available, complaining if we're near the end. */ static void check_memory_limits () @@ -59,6 +156,24 @@ check_memory_limits () register POINTER cp; unsigned long five_percent; unsigned long data_size; + enum warnlevel new_warnlevel; + +#ifdef HAVE_GETRLIMIT + struct rlimit rlimit; + + getrlimit (RLIMIT_AS, &rlimit); + + if (RLIM_INFINITY == rlimit.rlim_max) + return; + + /* This is a nonsensical case, but it happens -- rms. */ + if (rlimit.rlim_cur > rlimit.rlim_max) + return; + + five_percent = rlimit.rlim_max / 20; + data_size = rlimit.rlim_cur; + +#else /* not HAVE_GETRLIMIT */ if (lim_data == 0) get_lim_data (); @@ -73,57 +188,63 @@ check_memory_limits () cp = (char *) (*__morecore) (0); data_size = (char *) cp - (char *) data_space_start; - if (warn_function) - switch (warnlevel) - { - case 0: - if (data_size > five_percent * 15) - { - warnlevel++; - (*warn_function) ("Warning: past 75% of memory limit"); - } - break; - - case 1: - if (data_size > five_percent * 17) - { - warnlevel++; - (*warn_function) ("Warning: past 85% of memory limit"); - } - break; - - case 2: - if (data_size > five_percent * 19) - { - warnlevel++; - (*warn_function) ("Warning: past 95% of memory limit"); - } - break; - - default: - (*warn_function) ("Warning: past acceptable memory limits"); - break; - } - - /* If we go down below 70% full, issue another 75% warning - when we go up again. */ - if (data_size < five_percent * 14) - warnlevel = 0; - /* If we go down below 80% full, issue another 85% warning - when we go up again. */ - else if (warnlevel > 1 && data_size < five_percent * 16) - warnlevel = 1; - /* If we go down below 90% full, issue another 95% warning - when we go up again. */ - else if (warnlevel > 2 && data_size < five_percent * 18) - warnlevel = 2; +#endif /* not HAVE_GETRLIMIT */ + + if (!warn_function) + return; + + /* What level of warning does current memory usage demand? */ + if (data_size > five_percent * 19) + new_warnlevel = warned_95; + else if (data_size > five_percent * 17) + new_warnlevel = warned_85; + else if (data_size > five_percent * 15) + new_warnlevel = warned_75; + else + new_warnlevel = not_warned; + + /* If we have gone up a level, give the appropriate warning. */ + if (new_warnlevel > warnlevel || new_warnlevel == warned_95) + { + warnlevel = new_warnlevel; + switch (warnlevel) + { + case warned_75: + (*warn_function) ("Warning: past 75% of memory limit"); + break; + + case warned_85: + (*warn_function) ("Warning: past 85% of memory limit"); + break; + + case warned_95: + (*warn_function) ("Warning: past 95% of memory limit"); + } + } + /* Handle going down in usage levels, with some hysteresis. */ + else + { + /* If we go down below 70% full, issue another 75% warning + when we go up again. */ + if (data_size < five_percent * 14) + warnlevel = not_warned; + /* If we go down below 80% full, issue another 85% warning + when we go up again. */ + else if (warnlevel > warned_75 && data_size < five_percent * 16) + warnlevel = warned_75; + /* If we go down below 90% full, issue another 95% warning + when we go up again. */ + else if (warnlevel > warned_85 && data_size < five_percent * 18) + warnlevel = warned_85; + } if (EXCEEDS_LISP_PTR (cp)) (*warn_function) ("Warning: memory in use exceeds lisp pointer size"); } - -/* Cause reinitialization based on job parameters; - also declare where the end of pure storage is. */ + +/* Enable memory usage warnings. + START says where the end of pure storage is. + WARNFUN specifies the function to call to issue a warning. */ void memory_warnings (start, warnfun) @@ -140,8 +261,9 @@ memory_warnings (start, warnfun) warn_function = warnfun; __after_morecore_hook = check_memory_limits; -#ifdef WINDOWSNT /* Force data limit to be recalculated on each run. */ lim_data = 0; -#endif } + +/* arch-tag: eab04eda-1f69-447a-8d9f-95f0a3983ca5 + (do not change this comment) */