summaryrefslogtreecommitdiffstats
path: root/loadav.c
diff options
context:
space:
mode:
Diffstat (limited to 'loadav.c')
-rw-r--r--loadav.c396
1 files changed, 396 insertions, 0 deletions
diff --git a/loadav.c b/loadav.c
new file mode 100644
index 0000000..ef05c86
--- /dev/null
+++ b/loadav.c
@@ -0,0 +1,396 @@
+/* Copyright (c) 2008, 2009
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Micah Cowan (micah@cowan.name)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Copyright (c) 1987 Oliver Laumann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#ifdef ultrix
+# include <sys/fixpoint.h>
+#endif
+
+/* mach stuff included here to prevent index macro conflict */
+#ifdef NeXT
+# include <sys/version.h>
+# if KERNEL_MAJOR_VERSION > 2
+# include <mach/mach.h>
+# else
+# include <mach.h>
+# endif
+#endif
+
+#ifdef _AIX
+#include <sys/kinfo.h>
+extern int getkerninfo(int op, char *buf, int *buf_size, int32long64_t arg);
+#endif
+
+#include "config.h"
+#include "screen.h"
+
+#include "extern.h"
+
+#ifdef LOADAV
+
+static int GetLoadav __P((void));
+
+static LOADAV_TYPE loadav[LOADAV_NUM];
+static int loadok;
+
+
+
+/***************************************************************/
+
+#if defined(linux) && !defined(LOADAV_DONE)
+#define LOADAV_DONE
+/*
+ * This is the easy way. It relies in /proc being mounted.
+ * For the big and ugly way refer to previous screen version.
+ */
+void
+InitLoadav()
+{
+ loadok = 1;
+}
+
+static int
+GetLoadav()
+{
+ FILE *fp;
+ char buf[128], *s;
+ int i;
+ double d, e;
+
+ if ((fp = secfopen("/proc/loadavg", "r")) == NULL)
+ return 0;
+ *buf = 0;
+ fgets(buf, sizeof(buf), fp);
+ fclose(fp);
+ /* can't use fscanf because the decimal point symbol depends on
+ * the locale but the kernel uses always '.'.
+ */
+ s = buf;
+ for (i = 0; i < (LOADAV_NUM > 3 ? 3 : LOADAV_NUM); i++)
+ {
+ d = e = 0;
+ while(*s == ' ')
+ s++;
+ if (*s == 0)
+ break;
+ for(;;)
+ {
+ if (*s == '.')
+ e = 1;
+ else if (*s >= '0' && *s <= '9')
+ {
+ d = d * 10 + (*s - '0');
+ if (e)
+ e *= 10;
+ }
+ else
+ break;
+ s++;
+ }
+ loadav[i] = e ? d / e : d;
+ }
+ return i;
+}
+#endif /* linux */
+
+/***************************************************************/
+
+#if defined(LOADAV_GETLOADAVG) && !defined(LOADAV_DONE)
+#define LOADAV_DONE
+void
+InitLoadav()
+{
+ loadok = 1;
+}
+
+static int
+GetLoadav()
+{
+ return getloadavg(loadav, LOADAV_NUM);
+}
+#endif
+
+/***************************************************************/
+
+#if defined(apollo) && !defined(LOADAV_DONE)
+#define LOADAV_DONE
+void
+InitLoadav()
+{
+ loadok = 1;
+}
+
+static int
+GetLoadav()
+{
+ proc1_$get_loadav(loadav);
+ return LOADAV_NUM;
+}
+#endif
+
+/***************************************************************/
+
+#if defined(NeXT) && !defined(LOADAV_DONE)
+#define LOADAV_DONE
+
+static processor_set_t default_set;
+
+void
+InitLoadav()
+{
+ kern_return_t error;
+
+ error = processor_set_default(host_self(), &default_set);
+ if (error != KERN_SUCCESS)
+ mach_error("Error calling processor_set_default", error);
+ else
+ loadok = 1;
+}
+
+static int
+GetLoadav()
+{
+ unsigned int info_count;
+ struct processor_set_basic_info info;
+ host_t host;
+
+ info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
+ if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO, &host, (processor_set_info_t)&info, &info_count) != KERN_SUCCESS)
+ return 0;
+ loadav[0] = (float)info.load_average / LOAD_SCALE;
+ return 1;
+}
+#endif
+
+/***************************************************************/
+
+#if defined(sun) && defined(SVR4) && !defined(LOADAV_DONE)
+#define LOADAV_DONE
+
+#include <kstat.h>
+
+static kstat_ctl_t *kc;
+
+void
+InitLoadav()
+{
+ loadok = (kc = kstat_open()) != 0;
+}
+
+static int
+GetLoadav()
+{
+ kstat_t *ks;
+ kstat_named_t *avgs[3];
+ int i;
+
+ kstat_chain_update(kc);
+ if ((ks = kstat_lookup(kc, "unix", -1, "system_misc")) == 0 || kstat_read(kc, ks, (void *)0) == -1)
+ return (loadok = 0);
+ avgs[0] = kstat_data_lookup(ks, "avenrun_1min");
+ avgs[1] = kstat_data_lookup(ks, "avenrun_5min");
+ avgs[2] = kstat_data_lookup(ks, "avenrun_15min");
+ for (i = 0; i < 3; i++)
+ {
+ if (avgs[i] == 0 || avgs[i]->data_type != KSTAT_DATA_ULONG)
+ return (loadok = 0);
+ loadav[i] = avgs[i]->value.ul;
+ }
+ return 3;
+}
+
+#endif
+
+/***************************************************************/
+
+#if defined(__osf__) && defined(__alpha) && !defined(LOADAV_DONE)
+#define LOADAV_DONE
+
+struct rtentry; struct mbuf; /* shut up gcc on OSF/1 4.0 */
+#include <sys/table.h>
+
+void
+InitLoadav()
+{
+ loadok = 1;
+}
+
+static int
+GetLoadav()
+{
+ struct tbl_loadavg tbl;
+ int i;
+
+ if (table(TBL_LOADAVG, 0, &tbl, 1, sizeof(struct tbl_loadavg)) != 1)
+ return 0;
+
+ if (tbl.tl_lscale)
+ {
+ /* in long */
+ for (i = 0; i < LOADAV_NUM; i++)
+ loadav[i] = (double) tbl.tl_avenrun.l[i] / tbl.tl_lscale;
+ }
+ else
+ {
+ /* in double */
+ for (i = 0; i < LOADAV_NUM; i++)
+ loadav[i] = tbl.tl_avenrun.d[i];
+ }
+ return LOADAV_NUM;
+}
+#endif
+
+
+/***************************************************************/
+
+#if defined(_AIX) && !defined(LOADAV_DONE)
+#define LOADAV_DONE
+/*
+ * AIX uses KINFO_GET_AVENRUN syscall
+ */
+void
+InitLoadav()
+{
+ loadok = 1;
+}
+
+static int
+GetLoadav()
+{
+ long long avenrun[3];
+ int avsize = 3 * sizeof(long long);
+ int i;
+
+ if (getkerninfo(KINFO_GET_AVENRUN, (char *)&avenrun, &avsize, 0) < 0)
+ {
+ return 0;
+ }
+
+ for (i = 0; i < (LOADAV_NUM > 3 ? 3 : LOADAV_NUM); i++)
+ {
+ loadav[i] = avenrun[i];
+ }
+
+ return i;
+}
+#endif /* _AIX */
+
+/***************************************************************/
+
+#if !defined(LOADAV_DONE)
+/*
+ * The old fashion way: open kernel and read avenrun
+ *
+ * Header File includes
+ */
+
+# ifdef NLIST_STRUCT
+# include <nlist.h>
+# else
+# include <a.out.h>
+# endif
+# ifndef NLIST_DECLARED
+extern int nlist __P((char *, struct nlist *));
+# endif
+
+#ifdef LOADAV_USE_NLIST64
+# define nlist nlist64
+#endif
+
+static struct nlist nl[2];
+static int kmemf;
+
+#ifdef _IBMR2
+# define nlist(u,l) knlist(l,1,sizeof(*l))
+#endif
+
+void
+InitLoadav()
+{
+ debug("Init Kmem...\n");
+ if ((kmemf = open("/dev/kmem", O_RDONLY)) == -1)
+ return;
+# if !defined(_AUX_SOURCE) && !defined(AUX)
+# ifdef NLIST_NAME_UNION
+ nl[0].n_un.n_name = LOADAV_AVENRUN;
+# else
+ nl[0].n_name = LOADAV_AVENRUN;
+# endif
+# else
+ strncpy(nl[0].n_name, LOADAV_AVENRUN, sizeof(nl[0].n_name));
+# endif
+ debug2("Searching in %s for %s\n", LOADAV_UNIX, nl[0].n_name);
+ nlist(LOADAV_UNIX, nl);
+ if (nl[0].n_value == 0)
+ {
+ close(kmemf);
+ return;
+ }
+# if 0 /* no longer needed (Al.Smith@aeschi.ch.eu.org) */
+# ifdef sgi
+ nl[0].n_value &= (unsigned long)-1 >> 1; /* clear upper bit */
+# endif /* sgi */
+# endif
+ debug1("AvenrunSym found (0x%lx)!!\n", nl[0].n_value);
+ loadok = 1;
+}
+
+static int
+GetLoadav()
+{
+ if (lseek(kmemf, (off_t) nl[0].n_value, 0) == (off_t)-1)
+ return 0;
+ if (read(kmemf, (char *) loadav, sizeof(loadav)) != sizeof(loadav))
+ return 0;
+ return LOADAV_NUM;
+}
+#endif
+
+/***************************************************************/
+
+#ifndef FIX_TO_DBL
+#define FIX_TO_DBL(l) ((double)(l) / LOADAV_SCALE)
+#endif
+
+void
+AddLoadav(p)
+char *p;
+{
+ int i, j;
+ if (loadok == 0)
+ return;
+ j = GetLoadav();
+ for (i = 0; i < j; i++)
+ {
+ sprintf(p, " %2.2f" + !i, FIX_TO_DBL(loadav[i]));
+ p += strlen(p);
+ }
+}
+
+#endif /* LOADAV */