Mercurial > emacs
diff 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 |
line wrap: on
line diff
--- a/src/vm-limit.c Sat Mar 11 15:21:13 2006 +0000 +++ b/src/vm-limit.c Sat Mar 11 15:23:45 2006 +0000 @@ -32,6 +32,9 @@ #endif #include "mem-limits.h" +#include <sys/resource.h> + +#define HAVE_GETRLIMIT #ifdef HAVE_GETRLIMIT #include <sys/resource.h> @@ -44,13 +47,102 @@ 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 () @@ -64,14 +156,19 @@ register POINTER cp; unsigned long five_percent; unsigned long data_size; + enum warnlevel new_warnlevel; #ifdef HAVE_GETRLIMIT - struct rlimit { - rlim_t rlim_cur; - rlim_t rlim_max; - } rlimit; + struct rlimit rlimit; + + getrlimit (RLIMIT_AS, &rlimit); - getrlimit (RLIMIT_DATA, &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; @@ -93,57 +190,61 @@ #endif /* not HAVE_GETRLIMIT */ - if (warn_function) - switch (warnlevel) - { - case 0: - if (data_size > five_percent * 15) - { - warnlevel++; - (*warn_function) ("Warning: past 75% of memory limit"); - } - break; + if (!warn_function) + return; - case 1: - if (data_size > five_percent * 17) - { - warnlevel++; - (*warn_function) ("Warning: past 85% of memory limit"); - } - break; + /* 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 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; - } + case warned_85: + (*warn_function) ("Warning: past 85% of memory limit"); + 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; + 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) @@ -160,10 +261,8 @@ 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