summaryrefslogtreecommitdiff
path: root/sysutils/xperfmon/files/freebsd_system.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysutils/xperfmon/files/freebsd_system.c')
-rw-r--r--sysutils/xperfmon/files/freebsd_system.c248
1 files changed, 240 insertions, 8 deletions
diff --git a/sysutils/xperfmon/files/freebsd_system.c b/sysutils/xperfmon/files/freebsd_system.c
index f81966510b86..a4cd856c9b1a 100644
--- a/sysutils/xperfmon/files/freebsd_system.c
+++ b/sysutils/xperfmon/files/freebsd_system.c
@@ -48,10 +48,10 @@
#include <sys/param.h>
#endif
-#if (defined(BSD) && (BSD >= 199306))
+#if (defined(BSD) && (BSD >= 199506))
# include <osreldate.h>
#else
-# error You have to use at least a FreeBSD 2.X system
+# error You have to use at least a FreeBSD 2.2.X system
#endif
#include <X11/IntrinsicP.h>
@@ -74,12 +74,15 @@
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/dkstat.h>
+#ifdef HAVE_DEVSTAT
+#include <devstat.h>
+#endif
#include <sys/buf.h>
#include <sys/vmmeter.h>
#include <vm/vm.h>
#include <sys/time.h>
#include <net/if.h>
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#if __FreeBSD_version >= 300000
#include <net/if_var.h>
#endif
#include <netinet/in.h>
@@ -128,6 +131,12 @@
#define WANT_STAT(x) (poss_stats[(x)] != NO_STAT)
+#ifdef HAVE_DEVSTAT
+/* the old values */
+#define DK_NDRIVE 8
+#define DK_NAMELEN 8
+#endif
+
/*
Function Prototypes
*/
@@ -136,6 +145,11 @@ static void kread(int nlx, void *addr, size_t size);
static void collect_stats(void);
static int total_disk_transfers(void);
static int get_swapspace(void);
+#ifdef HAVE_DEVSTAT
+void init_devstat(void);
+int get_devstat(void);
+#endif /* HAVE_DEVSTAT */
+
/*
Variables & Structs
@@ -146,8 +160,25 @@ static kvm_t *kd;
static char errbuf[_POSIX2_LINE_MAX];
static char dr_name[DK_NDRIVE][DK_NAMELEN];
static double etime;
+#ifdef HAVE_DEVSTAT
+long generation;
+devstat_select_mode select_mode;
+struct devstat_match *matches;
+int num_matches;
+int num_selected, num_selections;
+long select_generation;
+static struct statinfo cur, last;
+int num_devices;
+struct device_selection *dev_select;
+char nodisk;
+#endif /* HAVE_DEVSTAT */
+
+#if __FreeBSD_version >= 220000
+float current_values[NUM_GRAPHS];
+#else
int current_values[NUM_GRAPHS];
+#endif
stat_type stats;
extern Widget perfmon[NUM_GRAPHS];
@@ -161,6 +192,7 @@ static struct _nfsStats {
int nfsServer, nfsClient;
} nfsStats, old_nfsStats;
+/* NB that we'll have to include machine/asname.h when the kernel goes ELF */
struct nlist nl[] = {
#define X_CPTIME 0
{ "_cp_time" },
@@ -169,7 +201,11 @@ struct nlist nl[] = {
#define X_BOOTTIME 2
{ "_boottime" },
#define X_DKXFER 3
+#ifdef HAVE_DEVSTAT
+ { "_hz" }, /* just a placeholder */
+#else
{ "_dk_xfer" },
+#endif
#define X_HZ 4
{ "_hz" },
#define N_IFNET 5
@@ -193,7 +229,9 @@ struct nlist nl[] = {
struct {
long time[CPUSTATES];
+#ifndef HAVE_DEVSTAT
long xfer[DK_NDRIVE];
+#endif
struct vmmeter Sum;
struct vmmeter Rate;
int interrupts;
@@ -212,6 +250,9 @@ void sys_setup()
{
get_namelist(getbootfile(), _PATH_KMEM);
collect_stats();
+#ifdef HAVE_DEVSTAT
+ init_devstat();
+#endif
/* hack to enforce a resize of the 'Free Swap' graph
without this the left border always displays the first drawn line
cause this field isn't resized very often due to slow change of
@@ -227,7 +268,7 @@ void sys_setup()
void update_stats()
{
int state;
- double pct, tot;;
+ double pct, tot, loadavg[3];
collect_stats();
@@ -238,16 +279,34 @@ void update_stats()
pct = 100 / tot;
else
pct = 0;
+
+#if __FreeBSD_version >= 220000
+ if (getloadavg(loadavg, sizeof(loadavg) / sizeof(loadavg[0])) == -1 ) {
+ fprintf( stderr, "xperfmon++: getloadavg returned no values\n" );
+ current_values[LOAD] = 0;
+ } else {
+ current_values[LOAD] = loadavg[0]*100;
+ /* fprintf( stderr, "loadavg: %f %f %f\n", loadavg[0], loadavg[1], loadavg[2] ); */
+ }
+#endif
+
+#if __FreeBSD_version >= 220000
+ current_values[USER_CPU_PERCENTAGE] = s.time[CP_USER] * pct;
+ current_values[NICE_CPU_PERCENTAGE] = s.time[CP_NICE] * pct;
+ current_values[SYSTEM_CPU_PERCENTAGE] = s.time[CP_SYS] * pct;
+ current_values[INTER_CPU_PERCENTAGE] = s.time[CP_INTR] * pct;
+#else
current_values[USER_CPU_PERCENTAGE] = (s.time[CP_USER] + s.time[CP_NICE]) * pct;
current_values[SYSTEM_CPU_PERCENTAGE] = (s.time[CP_SYS] + s.time[CP_INTR]) * pct;;
+#endif
current_values[IDLE_CPU_PERCENTAGE] = s.time[CP_IDLE] * pct;
if (perfmon[FREE_MEM]) {
if(!first_time_getswap)
- current_values[FREE_MEM] = get_swapspace();
+ current_values[FREE_MEM] = get_swapspace();
else {
- current_values[FREE_MEM] = 100;
- first_time_getswap = 0;
+ current_values[FREE_MEM] = 100;
+ first_time_getswap = 0;
}
}
if (perfmon[DISK_TRANSFERS])
@@ -275,8 +334,12 @@ total_disk_transfers()
{
register int i, total_xfers = 0;
+#ifdef HAVE_DEVSTAT
+ total_xfers = get_devstat();
+#else
for(i=0; i < DK_NDRIVE; i++)
total_xfers += s.xfer[i];
+#endif
return(total_xfers/etime);
}
@@ -292,7 +355,9 @@ collect_stats()
int mib[3], size;
kread(X_CPTIME, s.time, sizeof(s.time));
+#ifndef HAVE_DEVSTAT
kread(X_DKXFER, s.xfer, sizeof(s.xfer));
+#endif
kread(X_SUM, &sum, sizeof(sum) );
nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value;
@@ -307,11 +372,13 @@ collect_stats()
free(intrcnt);
etime = 0;
+#ifndef HAVE_DEVSTAT
for (i=0; i < DK_NDRIVE; i++) {
tmp = s.xfer[i];
s.xfer[i] -= s1.xfer[i];
s1.xfer[i] = tmp;
}
+#endif
for (i=0; i < CPUSTATES; i++) {
tmp = s.time[i];
s.time[i] -= s1.time[i];
@@ -382,7 +449,11 @@ collect_stats()
size = sizeof(nfsstats);
mib[0] = CTL_FS;
- mib[1] = MOUNT_NFS;
+#if (__FreeBSD_version >= 300003) /* ?? */
+ mib[1] = MNT_EXPORTED;
+#else
+ mib[1] = MNT_NFS;
+#endif
mib[2] = NFS_NFSSTATS;
if (sysctl( mib, 3, &nfsstats, &size, NULL, 0) < 0)
@@ -631,3 +702,164 @@ get_swapspace()
free(sw);
return((100*nfree)/avail); /* return free swap in percent */
}
+
+#ifdef HAVE_DEVSTAT
+/* routines which use libdevstat */
+/* this is partly taken from FreeBSD - /usr/src/usr.sbin/iostat */
+void
+init_devstat(void)
+{
+ /*
+ * Make sure that the userland devstat version matches the kernel
+ * devstat version.
+ */
+ if (checkversion() < 0) {
+ nodisk++;
+ return;
+ }
+
+ /* find out how many devices we have */
+ if ((num_devices = getnumdevs()) < 0) {
+ nodisk++;
+ return;
+ }
+
+ cur.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo));
+ last.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo));
+ bzero(cur.dinfo, sizeof(struct devinfo));
+ bzero(last.dinfo, sizeof(struct devinfo));
+
+ /*
+ * Grab all the devices. We don't look to see if the list has
+ * changed here, since it almost certainly has. We only look for
+ * errors.
+ */
+ if (getdevs(&cur) == -1) {
+ nodisk++;
+ return;
+ }
+
+ num_devices = cur.dinfo->numdevs;
+ generation = cur.dinfo->generation;
+
+ dev_select = NULL;
+
+ /* only interested in disks */
+ matches = NULL;
+ if (buildmatch("da", &matches, &num_matches) != 0) {
+ nodisk++;
+ return;
+ }
+
+ if (num_matches == 0)
+ select_mode = DS_SELECT_ADD;
+ else
+ select_mode = DS_SELECT_ONLY;
+
+ /*
+ * At this point, selectdevs will almost surely indicate that the
+ * device list has changed, so we don't look for return values of 0
+ * or 1. If we get back -1, though, there is an error.
+ */
+ if (selectdevs(&dev_select, &num_selected,
+ &num_selections, &select_generation,
+ generation, cur.dinfo->devices, num_devices,
+ matches, num_matches,
+ NULL, 0,
+ select_mode, DK_NDRIVE, 0) == -1)
+ nodisk++;
+}
+
+int
+get_devstat(void)
+{
+ register int dn;
+ long double busy_seconds;
+ u_int64_t total_transfers;
+ struct devinfo *tmp_dinfo;
+ int total_xfers = 0;
+
+ if (nodisk == 0) {
+ /*
+ * Here what we want to do is refresh our device stats.
+ * getdevs() returns 1 when the device list has changed.
+ * If the device list has changed, we want to go through
+ * the selection process again, in case a device that we
+ * were previously displaying has gone away.
+ */
+ switch (getdevs(&cur)) {
+ case -1:
+ return (0);
+ case 1: {
+ int retval;
+
+ num_devices = cur.dinfo->numdevs;
+ generation = cur.dinfo->generation;
+ retval = selectdevs(&dev_select, &num_selected,
+ &num_selections, &select_generation,
+ generation, cur.dinfo->devices,
+ num_devices, matches, num_matches,
+ NULL, 0,
+ select_mode, DK_NDRIVE, 0);
+ switch(retval) {
+ case -1:
+ return (0);
+ case 1:
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ /*
+ * Calculate elapsed time up front, since it's the same for all
+ * devices.
+ */
+ busy_seconds = compute_etime(cur.busy_time, last.busy_time);
+
+ /* this is the first time thru so just copy cur to last */
+ if (last.dinfo->numdevs == 0) {
+ tmp_dinfo = last.dinfo;
+ last.dinfo = cur.dinfo;
+ cur.dinfo = tmp_dinfo;
+ last.busy_time = cur.busy_time;
+ return (0);
+ }
+
+
+ for (dn = 0; dn < num_devices; dn++) {
+ int di;
+
+ if ((dev_select[dn].selected == 0)
+ || (dev_select[dn].selected > DK_NDRIVE))
+ continue;
+
+ di = dev_select[dn].position;
+
+ if (compute_stats(&cur.dinfo->devices[di],
+ &last.dinfo->devices[di], busy_seconds,
+ NULL, &total_transfers,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL)!= 0)
+ break;
+ total_xfers += (int)total_transfers;
+ }
+
+ tmp_dinfo = last.dinfo;
+ last.dinfo = cur.dinfo;
+ cur.dinfo = tmp_dinfo;
+
+ last.busy_time = cur.busy_time;
+
+ } else
+ /* no disks found ? */
+ total_xfers = 0;
+
+ return (total_xfers);
+}
+#endif /* HAVE_DEVSTAT */