#endif
#include "mem-limits.h"
+#include <sys/resource.h>
+
+#define HAVE_GETRLIMIT
#ifdef HAVE_GETRLIMIT
#include <sys/resource.h>
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;
+\f
+
+#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 */
+\f
+/* Verify amount of memory available, complaining if we're near the end. */
static void
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;
#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. */
+\f
+/* 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)
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