components/net-snmp/sun/agent/modules/healthMonitor/kr_vmstat.c
changeset 252 ee0fb1eabcbf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/net-snmp/sun/agent/modules/healthMonitor/kr_vmstat.c	Fri May 20 12:17:45 2011 +0530
@@ -0,0 +1,339 @@
+/*
+* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+*
+* U.S. Government Rights - Commercial software. Government users are subject
+* to the Sun Microsystems, Inc. standard license agreement and applicable
+* provisions of the FAR and its supplements.
+*
+*
+* This distribution may include materials developed by third parties. Sun,
+* Sun Microsystems, the Sun logo and Solaris are trademarks or registered
+* trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
+*
+*/
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <memory.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <kstat.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/sysinfo.h>
+#include <sys/vfs.h>
+#include <sys/dnlc.h>
+#include <sys/vmmeter.h>
+
+static  kstat_ctl_t     *kc;            /* libkstat cookie */
+static  int             ncpus;
+static  kstat_t         **cpu_stat_list = NULL;
+static  kstat_t         *sysinfo_ksp, *vminfo_ksp, *system_misc_ksp;
+static  kstat_named_t   *deficit_knp, *lbolt_knp, *clk_intr_knp;
+
+static  void    fail(int, char *, ...);
+static  void    safe_zalloc(void **, int, int);
+
+typedef struct {
+        cpu_sysinfo_t   cpu_sysinfo;
+        cpu_vminfo_t    cpu_vminfo;
+        sysinfo_t       sysinfo;
+        vminfo_t        vminfo;
+        long            deficit;
+} all_stat_t;
+
+static	all_stat_t	s_new, s_old;
+
+#define	denom(x) ((x) ? (x) : 1)
+#define	DELTA(x) (s_new.x - s_old.x)
+
+static  int     hz;
+static  int     pagesize;
+static  int     etime;
+
+static	void	all_stat_init(void);
+static	int	all_stat_load(void);
+static	void	safe_kstat_read(kstat_ctl_t *, kstat_t *, void *);
+static	kstat_t	*safe_kstat_lookup(kstat_ctl_t *, char *, int, char *);
+static	void	*safe_kstat_data_lookup(kstat_t *, char *);
+
+static int fr_time = 0;
+/* Get CPU Process details from kstats- 
+ * Number of processes in runqueue, 
+ * waiting and swapqueue 
+ */
+int 
+krgetprocdetail(int *runque, int *waiting, int *swapque)
+{
+	ulong_t updates;
+
+	if(!fr_time) {
+	/* Initialize a kstat control structure */
+	if ((kc = kstat_open()) == NULL)
+		fail(1, "kstat_open(): can't open /dev/kstat");
+	all_stat_init();
+	fr_time = 1;
+	}
+
+	/* update the kstat header chain or load all_stat structure */ 
+	while (kstat_chain_update(kc) || all_stat_load()) {
+		all_stat_init();
+	}
+
+	updates = denom(DELTA(sysinfo.updates));
+
+#define ADJ(n)  ((adj <= 0) ? n : (adj >= n) ? 1 : n - adj)
+#define adjprintf(fmt, n, val)  adj -= (n + 1) - printf(fmt, ADJ(n), val)
+
+        *runque =  DELTA(sysinfo.runque) / updates;
+        *waiting = DELTA(sysinfo.waiting) / updates;
+        *swapque = DELTA(sysinfo.swpque) / updates;
+
+	/*
+	 * Close the kstat control structure and set it to null.
+	 */
+/*	kstat_close(kc);
+	kc = (kstat_ctl_t *)NULL;*/
+
+	return(0);
+
+}
+
+/* Get RAm details from kstats */
+int 
+krgetramdetail(int *handspread, int *scan)
+{
+	int i;
+	int pages, handspreadpages;
+
+	pagesize = sysconf(_SC_PAGESIZE);
+        hz = sysconf(_SC_CLK_TCK);
+
+	/* default max handspread is 64MB worth of pages */
+	handspreadpages = (64 * 1048576)/sysconf(_SC_PAGESIZE);
+	pages = sysconf(_SC_PHYS_PAGES);
+
+	if(!fr_time) {
+	if ((kc = kstat_open()) == NULL) {
+		fail(1, "kstat_open(): can't open /dev/kstat");
+	}
+
+	/* Initialize the all_stat structure */
+	all_stat_init();
+	fr_time = 1;
+	}
+
+	if (handspreadpages > (pages/4)) {
+		handspreadpages = (int)(pages/4);
+
+	/* update the kstat header chain or load all_stat structure */ 
+        while (kstat_chain_update(kc) || all_stat_load()) 	
+		/* (void) printf("<<State change>>\n"); */
+                all_stat_init();
+	}
+
+        etime = 0;
+        for (i = 0; i < CPU_STATES; i++)
+                etime += DELTA(cpu_sysinfo.cpu[i]);
+
+        etime = denom(((etime / ncpus) + (hz >> 1)) / hz);
+
+	*handspread = handspreadpages;
+        *scan =  DELTA(cpu_vminfo.scan) / etime;
+
+	/*
+	 * Close the kstat control structure and set it to null.
+	 */
+/*	kstat_close(kc);
+	kc = (kstat_ctl_t *)NULL;
+*/
+	return(0);
+}
+
+/* Get ncstat data */
+int 
+krgetncstatdetail(unsigned long *hits, unsigned long *misses)
+{
+        struct ncstats ncstats;
+
+	if(!fr_time) {
+	/* Initialize the all_stat structure */
+	if ((kc = kstat_open()) == NULL) {
+		fail(1, "kstat_open(): can't open /dev/kstat");
+	}
+
+	/* Initialize the all_stat structure */
+	all_stat_init();
+	fr_time =1 ;
+	}
+
+        if (all_stat_load() != 0)
+                fail(1, "all_stat_load() failed");
+
+        safe_kstat_read(kc, safe_kstat_lookup(kc, "unix", 0, "ncstats"), (void *) &ncstats);
+
+	*hits = (unsigned long)ncstats.hits;
+	*misses = (unsigned long)ncstats.misses;
+
+	/*
+	 * Close the kstat control structure and set it to null.
+	 */
+/*	kstat_close(kc);
+	kc = (kstat_ctl_t *)NULL;
+*/
+	return(0);
+}
+
+/* Initialize the all_stat structure */
+static void
+all_stat_init(void)
+{
+	kstat_t *ksp;
+
+	/*
+	 * Global statistics
+	 */
+
+	sysinfo_ksp	= safe_kstat_lookup(kc, "unix", 0, "sysinfo");
+        vminfo_ksp      = safe_kstat_lookup(kc, "unix", 0, "vminfo");
+        system_misc_ksp = safe_kstat_lookup(kc, "unix", 0, "system_misc");
+
+        safe_kstat_read(kc, system_misc_ksp, NULL);
+        deficit_knp     = safe_kstat_data_lookup(system_misc_ksp, "deficit");
+        lbolt_knp       = safe_kstat_data_lookup(system_misc_ksp, "lbolt");
+        clk_intr_knp    = safe_kstat_data_lookup(system_misc_ksp, "clk_intr");
+
+       /*
+         * Per-CPU statistics
+         */
+
+        ncpus = 0;
+        for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next)
+                if (strncmp(ksp->ks_name, "cpu_stat", 8) == 0)
+                        ncpus++;
+
+        safe_zalloc((void **) &cpu_stat_list, ncpus * sizeof (kstat_t *), 1);
+
+        ncpus = 0;
+        for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next)
+                if (strncmp(ksp->ks_name, "cpu_stat", 8) == 0 &&
+                    kstat_read(kc, ksp, NULL) != -1)
+                        cpu_stat_list[ncpus++] = ksp;
+
+        if (ncpus == 0)
+                fail(0, "can't find any cpu statistics");
+
+	(void) memset(&s_new, 0, sizeof (all_stat_t));
+}
+
+/*
+ * load statistics, summing across CPUs where needed
+ */
+
+static int
+all_stat_load(void)
+{
+	int i, j;
+	cpu_stat_t cs;
+	uint *np, *tp;
+
+	s_old = s_new;
+	(void) memset(&s_new, 0, sizeof (all_stat_t));
+
+	/*
+	 * Global statistics
+	 */
+
+	safe_kstat_read(kc, sysinfo_ksp, (void *) &s_new.sysinfo);
+        safe_kstat_read(kc, vminfo_ksp, (void *) &s_new.vminfo);
+        safe_kstat_read(kc, system_misc_ksp, NULL);
+        s_new.deficit = deficit_knp->value.l;
+
+        /*
+         * Per-CPU statistics.
+         * For now, we just sum across all CPUs.  In the future,
+         * we should add options to vmstat for per-CPU data.
+         */
+
+        for (i = 0; i < ncpus; i++) {
+                if (kstat_read(kc, cpu_stat_list[i], (void *) &cs) == -1)
+                        return (1);
+                np = (uint *) &s_new.cpu_sysinfo;
+                tp = (uint *) &cs.cpu_sysinfo;
+                for (j = 0; j < sizeof (cpu_sysinfo_t); j += sizeof (uint_t))
+                        *np++ += *tp++;
+                np = (uint *) &s_new.cpu_vminfo;
+                tp = (uint *) &cs.cpu_vminfo;
+                for (j = 0; j < sizeof (cpu_vminfo_t); j += sizeof (uint_t))
+                        *np++ += *tp++;
+        }
+	return (0);
+}
+
+static void
+fail(int do_perror, char *message, ...)
+{
+	va_list args;
+	int save_errno = errno;
+
+	va_start(args, message);
+	(void) vfprintf(stderr, message, args);
+	va_end(args);
+	if (do_perror)
+		(void) fprintf(stderr, ": %s", strerror(save_errno));
+	(void) fprintf(stderr, "\n");
+	exit(2);
+}
+
+static void
+safe_zalloc(void **ptr, int size, int free_first)
+{
+        if (free_first && *ptr != NULL)
+                free(*ptr);
+        if ((*ptr = (void *) malloc(size)) == NULL)
+                fail(1, "malloc failed");
+        (void) memset(*ptr, 0, size);
+}
+
+
+void
+safe_kstat_read(kstat_ctl_t *kc, kstat_t *ksp, void *data)
+{
+	kid_t kstat_chain_id = kstat_read(kc, ksp, data);
+
+	if (kstat_chain_id == -1)
+		fail(1, "kstat_read(%x, '%s') failed", kc, ksp->ks_name);
+}
+
+kstat_t *
+safe_kstat_lookup(kstat_ctl_t *kc, char *ks_module, int ks_instance,
+	char *ks_name)
+{
+	kstat_t *ksp = kstat_lookup(kc, ks_module, ks_instance, ks_name);
+
+	if (ksp == NULL)
+		fail(0, "kstat_lookup('%s', %d, '%s') failed",
+			ks_module == NULL ? "" : ks_module,
+			ks_instance,
+			ks_name == NULL ? "" : ks_name);
+	return (ksp);
+}
+
+void *
+safe_kstat_data_lookup(kstat_t *ksp, char *name)
+{
+	void *fp = kstat_data_lookup(ksp, name);
+
+	if (fp == NULL)
+		fail(0, "kstat_data_lookup('%s', '%s') failed",
+			ksp->ks_name, name);
+	return (fp);
+}