From: Richard M. Stallman Date: Sat, 11 Mar 2006 15:24:02 +0000 (+0000) Subject: (get_lim_data, lim_data, data_space_start): Moved from mem-limits.h. X-Git-Tag: emacs-pretest-22.0.90~3688 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=395d3972b1ffbcbe1a81052163be27345d0ca8fb;p=emacs.git (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. --- diff --git a/src/ChangeLog b/src/ChangeLog index 6d7ef065cf8..e83940cecd6 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,21 @@ +2006-03-11 Richard Stallman + + * vm-limit.c (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. + + * mem-limits.h (get_lim_data, lim_data, data_space_start): + Moved to vm-limit.c. + + * xterm.c (x_fully_uncatch_errors, x_catching_errors): New functions. + + * eval.c (unwind_to_catch): Call x_fully_uncatch_errors. + (internal_condition_case_1, internal_condition_case_2): + Abort if within unclosed x_catch_errors. + 2006-03-11 Romain Francoise * process.c (Vprocess_adaptive_read_buffering): Doc fix. diff --git a/src/vm-limit.c b/src/vm-limit.c index 48d13c323ae..de31eda0cec 100644 --- a/src/vm-limit.c +++ b/src/vm-limit.c @@ -32,6 +32,9 @@ typedef void *POINTER; #endif #include "mem-limits.h" +#include + +#define HAVE_GETRLIMIT #ifdef HAVE_GETRLIMIT #include @@ -44,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 () @@ -64,14 +156,19 @@ check_memory_limits () 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); + + if (RLIM_INFINITY == rlimit.rlim_max) + return; - getrlimit (RLIMIT_DATA, &rlimit); + /* 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 @@ check_memory_limits () #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; - - 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; + 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) @@ -160,10 +261,8 @@ 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