summaryrefslogtreecommitdiff
path: root/sysutils/xperfmon3/files/freebsd_system.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysutils/xperfmon3/files/freebsd_system.c')
-rw-r--r--sysutils/xperfmon3/files/freebsd_system.c1528
1 files changed, 775 insertions, 753 deletions
diff --git a/sysutils/xperfmon3/files/freebsd_system.c b/sysutils/xperfmon3/files/freebsd_system.c
index d20ec2c08751..2e28cbfd3256 100644
--- a/sysutils/xperfmon3/files/freebsd_system.c
+++ b/sysutils/xperfmon3/files/freebsd_system.c
@@ -1,889 +1,911 @@
+
/*
- * Perfmon Performance Monitor
+ * freebsd_system.c für FreeBSD-3.X
+ * COPYRIGHT 1998 by Lars Köller <Lars.Koeller@Uni-Bielefeld.de>
+ *
+ * Work has started on 7th Sep 1998 on Northsea island Föhr.
*
- * Copyright 1985, Massachusetts Institute of Technology
- * Copyright 1989, PCS Computer Systeme GmbH, West Germany
- * Copyright 1994, Sterling Software @ NASA-Ames Research Center
- * Copyright 1995, Regents of the University of California,
- * Lars Köller <Lars.Koeller@Uni-Bielefeld.DE>
+ * $Id: freebsd_system.c,v 3.4 1998/11/15 16:50:04 lkoeller Exp lkoeller $
+ */
+
+/*
+ * Copyright (c) 1998 Lars Köller
+ * All rights reserved.
*
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of PCS and Sterling Software not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. PCS and Sterling Software makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
- * PCS & STERLING SOFTWARE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL PCS & STERLING SOFTWARE
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*
- * Original Author: Emanuel Jay Berkenbilt, MIT Project Athena
- * Author: Thomas A. Baghli, PCS Computer Systeme GmbH, West Germany
- * tom@meepmeep.pcs.com
- * 1994 Revision
- * Author: Roger Smith, Sterling Software @ NASA-Ames Research Center
- * Moffett Field, California, rsmith@proteus.arc.nasa.gov
- * 1995, ... FreeBSD 2.x, 3.x Version
- * Author: Lars Köller, Univerity of Bielefeld, Germany
- * Lars.Koeller@Uni-Bielefeld.DE
*/
-/* This file contains only system functions - that is the functions that
- * get the information the performance monitor is monitoring. No calls
- * to any X routines should be made here. The reason for doing this is
- * so that as the X toolkit becomes available and the X window system
- * improves no changes will have to be made to this file, and as this
- * program is made available for a new type of machine, only this file
- * will need to be changed.
+/*
+ *
+ * Parts of this program are derived from the iostat program:
+ *
+ * Copyright (c) 1997, 1998 Kenneth D. Merry.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
*/
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
+/*
+ * Parts of this program are derived from other original FreeBSD programs:
+ *
+ * Copyright (c) 1986, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
-#if (defined(BSD) && (BSD >= 199506))
-# include <osreldate.h>
-#else
-# error You have to use at least a FreeBSD 2.2.X system
+#ifndef LINT
+static char rcsid[] = "$Id: freebsd_system.c,v 3.4 1998/11/15 16:50:04 lkoeller Exp lkoeller $";
#endif
+#include "fbsd_vers.h"
+
#include <X11/IntrinsicP.h>
#include "system.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <unistd.h>
-#include <paths.h>
-#include <kvm.h>
-#include <nlist.h>
-#include <limits.h>
-#include <errno.h>
-#include <err.h>
+#include "is.h"
#include <sys/file.h>
#include <sys/param.h>
+#include <sys/types.h>
#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 <vm/vm.h>
#include <net/if.h>
-#if __FreeBSD_version >= 300000
#include <net/if_var.h>
-#endif
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/conf.h>
#include <sys/rlist.h>
#include <sys/mount.h>
#include <nfs/rpcv2.h>
-#include <nfs/nfsv2.h>
+#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
-#ifndef CTL_FS
-#define CTL_FS CTL_VFS /* compatibility w/ Lite1 */
-#endif
-
-/*
- * It's a mess with all these version numbers:
- *
- * 2.0-RELEASE: 199411
- * 2.1-current's: 199501, 199503
- * 2.0.5-RELEASE: 199504
- * 2.2-current before 2.1: 199508
- * 2.1.0-RELEASE: 199511
- * 2.2-current before 2.1.5: 199512
- * 2.1.5-RELEASE: 199607
- * 2.2-current before 2.1.6: 199608
- * 2.1.6-RELEASE: 199612
- * 2.1.7-RELEASE: 199612
- * 2.2-RELEASE: 220000 (ahhhhh)
- * 3.0-current as of Feb 1997: 300000 (ohhhhh)
- */
-
-/*
- * FreeBSD version 2.2 and greater have NFSv3
- */
-#if __FreeBSD_version >= 220000
-# define HAS_NFS_V3
-#endif /* FreeBSD_version */
-
-#include "is.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <paths.h>
+#include <kvm.h>
+#include <nlist.h>
+#include <limits.h>
+#include <errno.h>
+#include <err.h>
+#include <devstat.h>
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-#define WANT_STAT(x) (poss_stats[(x)] != NO_STAT)
+struct nlist namelist[] = {
+#define X_HZ 0
+ { "_hz" },
+#define X_STATHZ 1
+ { "_stathz" },
+#define X_CP_TIME 2
+ { "_cp_time" },
+#define X_TK_NIN 3
+ { "_tk_nin" },
+#define X_TK_NOUT 4
+ { "_tk_nout" },
+#define N_IFNET 5
+ { "_ifnet" },
+#define X_INTRCNT 6
+ { "_intrcnt" },
+#define X_EINTRCNT 7
+ { "_eintrcnt" },
+#define X_BOOTTIME 8
+ { "_boottime" },
+#if __FreeBSD_version < 400000
+#define VM_NSWAP 9
+ { "_nswap" },
+#define VM_NSWDEV 10
+ { "_nswdev" },
+#define VM_DMMAX 11
+ { "_dmmax" },
+#define VM_SWAPLIST 12
+ { "_swaplist" },
+#define VM_SWDEVT 13
+ { "_swdevt" },
+#define X_END 13
+ { NULL },
+#else
+#define X_END 8
+ { NULL },
+#endif /* __FreeBSD_version < 400000 */
-#ifdef HAVE_DEVSTAT
-/* the old values */
-#define DK_NDRIVE 8
-#define DK_NAMELEN 8
-#endif
+};
-/*
- Function Prototypes
-*/
-static int get_namelist(const char *kernel_name, const char *memory_name);
-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 */
+extern Widget perfmon[NUM_GRAPHS];
+extern char *info1;
+double current_values[NUM_GRAPHS];
-/*
- Variables & Structs
-*/
-static unsigned long *intrcnt;
-static int nintr, hz;
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];
-
-static struct packet {
- int input, output, collisions;
-} packets, old_packets;
+static int has_nfs;
+static int hz, stathz;
+static double etime, pct;
+static long tmp;
+struct vfsconf vfc;
+/*
+ * Variables holding the statistic information
+ */
+static struct statinfo cur, last;
static struct nfsstats nfsstats;
static struct _nfsStats {
- int nfsServer, nfsClient;
+ int ServerCalls, ServerCacheHit, ServerCacheMis;
+ int ClientCalls, ClientCacheHit, ClientCacheMis;
} nfsStats, old_nfsStats;
+static struct _packets {
+ int input, output, collisions;
+} packets, old_packets;
+static int interrupts, old_interrupts;
-/* NB that we'll have to include machine/asname.h when the kernel goes ELF */
-struct nlist nl[] = {
-#define X_CPTIME 0
- { "_cp_time" },
-#define X_SUM 1
- { "_cnt" },
-#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
- { "_ifnet" },
-#define X_INTRCNT 6
- { "_intrcnt" },
-#define X_EINTRCNT 7
- { "_eintrcnt" },
-#if __FreeBSD_version < 400000
-#define VM_NSWAP 8
- { "_nswap" }, /* size of largest swap device */
-#define VM_NSWDEV 9
- { "_nswdev" }, /* number of swap devices */
-#define VM_DMMAX 10
- { "_dmmax" }, /* maximum size of a swap block */
-#define VM_SWAPLIST 11
- { "_swaplist" },/* list of free swap areas */
-#define VM_SWDEVT 12
- { "_swdevt" }, /* list of swap devices and sizes */
-#endif
- { "" },
-};
-
-struct {
- long time[CPUSTATES];
-#ifndef HAVE_DEVSTAT
- long xfer[DK_NDRIVE];
-#endif
- struct vmmeter Sum;
- struct vmmeter Rate;
- int interrupts;
-} s, s1;
-
-int first_time_getswap;
+/*
+ * Variables need for devstat to get diskio statistics
+ */
+static struct statinfo cur, last;
+static struct devstat_match *matches = NULL;
+static struct device_selection *dev_select = NULL;
+static devstat_select_mode select_mode;
+static int num_matches = 0, num_devices = 0;
+static int num_selected = 0, num_selections = 0;
+static int num_devices_specified = 0, maxshowdevs;
+static long generation, select_generation;
+static char **specified_devices = NULL;
+static struct _diskstat {
+ long double da_trsf, da_mb;
+ long double cd_trsf, cd_mb;
+ long double sa_trsf, sa_mb;
+} diskstat;
+
+void sys_setup(void);
+void update_stats(void);
+
+static void get_namelist(const char *kernel_name, const char *memory_name);
+static void kread(int nlx, void *addr, size_t size);
+static double get_load(void);
+static void get_cpustat(void);
+static void get_ttystat(void);
+static void get_interrupts(void);
+static void init_diskio(void);
+static void get_diskio(void);
+static double get_swapspace(void);
+static void get_netstat(void);
+static void get_nfsstat(void);
-#define rate s.Rate
-#define sum s.Sum
-/*
- This routine does all necessary setting up of structures
- that will handle system calls.
-*/
-void sys_setup()
+void
+sys_setup(void)
{
- 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
- the free swapspace! */
- first_time_getswap = 1;
- etime = 1.0;
+ get_namelist(getbootfile(), _PATH_MEM);
+
+ get_cpustat();
+ get_load();
+ get_ttystat();
+ get_interrupts();
+ init_diskio();
+ get_diskio();
+
+ /*
+ * To force first scale of 'free swapspace' to 100%, we need this hack!
+ * Wee use a value < 0 cause it's not a valid value!
+ */
+ current_values[FREE_MEM] = -0.4 * SCALE_HACK;
+
+ get_netstat();
+
+ /*
+ * Check if we have NFS in the kernel
+ */
+ if (getvfsbyname("nfs", &vfc) < 0) {
+ fprintf(stderr, "xperfmon++: getvfsbyname: NFS not compiled into kernel\n");
+ has_nfs = FALSE;
+ } else {
+ has_nfs = TRUE;
+ get_nfsstat();
+ }
}
-/*
- Update the data structures
-*/
-void update_stats()
+void
+update_stats(void)
{
- int state;
- double pct, tot, loadavg[3];
+ static int firsttime = 1;
+ /*
+ * For any stat we need etime, so get it!
+ */
+ get_cpustat();
+ current_values[ USER_CPU_PERCENTAGE] = cur.cp_time[CP_USER] * pct * SCALE_HACK;
+ current_values[ NICE_CPU_PERCENTAGE] = cur.cp_time[CP_NICE] * pct * SCALE_HACK;
+ current_values[SYSTEM_CPU_PERCENTAGE] = cur.cp_time[CP_SYS] * pct * SCALE_HACK;
+ current_values[ INTER_CPU_PERCENTAGE] = cur.cp_time[CP_INTR] * pct * SCALE_HACK;
+ current_values[ IDLE_CPU_PERCENTAGE] = cur.cp_time[CP_IDLE] * pct * SCALE_HACK;
+
+ if (perfmon[LOAD])
+ current_values[LOAD] = get_load() * SCALE_HACK;
+
+ if (perfmon[TTY_CHARS_IN] || perfmon[TTY_CHARS_OUT]) {
+ get_ttystat();
+ current_values[TTY_IN] = cur.tk_nin/etime * SCALE_HACK;
+ current_values[TTY_OUT] = cur.tk_nout/etime * SCALE_HACK;
+ }
- collect_stats();
+ if (perfmon[INTERRUPTS]) {
+ get_interrupts();
+ current_values[INTERRUPTS] = (interrupts - old_interrupts)/etime * SCALE_HACK;
+ }
- tot = 0;
- for (state = 0; state < CPUSTATES; ++state)
- tot += s.time[state];
- if (tot)
- pct = 100 / tot;
+ /*
+ * The first time called, we want to get 100%
+ * for the full scale of the graph!
+ */
+ if (perfmon[FREE_MEM] && !firsttime)
+ current_values[FREE_MEM] =
+ (current_values[FREE_MEM] < 0 ? 100.0 * SCALE_HACK : get_swapspace() * SCALE_HACK);
else
- pct = 0;
+ --firsttime;
+
+ if (perfmon[DISK_TRANSFERS] || perfmon[DISK_MB] ||
+ perfmon[TAPE_TRANSFERS] || perfmon[TAPE_MB] ||
+ perfmon[CDROM_TRANSFERS] || perfmon[CDROM_MB] ) {
+ get_diskio();
+ current_values[DISK_TRANSFERS] = diskstat.da_trsf * SCALE_HACK;
+ current_values[DISK_MB] = diskstat.da_mb * SCALE_HACK;
+ current_values[TAPE_TRANSFERS] = diskstat.sa_trsf * SCALE_HACK;
+ current_values[TAPE_MB] = diskstat.sa_mb * SCALE_HACK;
+ current_values[CDROM_TRANSFERS] = diskstat.cd_trsf * SCALE_HACK;
+ current_values[CDROM_MB] = diskstat.cd_mb * SCALE_HACK;
+ }
-#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] ); */
+ if (perfmon[INPUT_PACKETS] || perfmon[OUTPUT_PACKETS] ||
+ perfmon[COLLISION_PACKETS]){
+ get_netstat();
+ current_values[ INPUT_PACKETS] =
+ (packets.input - old_packets.input)/etime * SCALE_HACK;
+ current_values[ OUTPUT_PACKETS] =
+ (packets.output - old_packets.output)/etime * SCALE_HACK;
+ current_values[COLLISION_PACKETS] =
+ (packets.collisions - old_packets.collisions)/etime * SCALE_HACK;
}
-#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();
- else {
- current_values[FREE_MEM] = 100;
- first_time_getswap = 0;
- }
+ if (has_nfs && (perfmon[NFS_CLIENT_CALLS] ||
+ perfmon[NFS_CLIENT_HIT] ||
+ perfmon[NFS_CLIENT_MIS] ||
+ perfmon[NFS_SERVER_CALLS] ||
+ perfmon[NFS_SERVER_HIT] ||
+ perfmon[NFS_SERVER_MIS])) {
+ get_nfsstat();
+ current_values[NFS_CLIENT_CALLS] =
+ (nfsStats.ClientCalls - old_nfsStats.ClientCalls)/etime * SCALE_HACK;
+ current_values[NFS_SERVER_CALLS] =
+ (nfsStats.ServerCalls - old_nfsStats.ServerCalls)/etime * SCALE_HACK;
+ current_values[NFS_CLIENT_HIT] =
+ (nfsStats.ClientCacheHit - old_nfsStats.ClientCacheHit)/etime * SCALE_HACK;
+ current_values[NFS_CLIENT_MIS] =
+ (nfsStats.ClientCacheMis - old_nfsStats.ClientCacheMis)/etime * SCALE_HACK;
+ current_values[NFS_SERVER_HIT] =
+ (nfsStats.ServerCacheHit - old_nfsStats.ServerCacheHit)/etime * SCALE_HACK;
+ current_values[NFS_SERVER_MIS] =
+ (nfsStats.ServerCacheMis - old_nfsStats.ServerCacheMis)/etime * SCALE_HACK;
}
- if (perfmon[DISK_TRANSFERS])
- current_values[DISK_TRANSFERS] = total_disk_transfers();
- if (perfmon[INTERRUPTS])
- current_values[INTERRUPTS] = (s.interrupts - s1.interrupts)/etime;
- if (perfmon[INPUT_PACKETS])
- current_values[INPUT_PACKETS] = (packets.input - old_packets.input)/etime;
- if (perfmon[OUTPUT_PACKETS])
- current_values[OUTPUT_PACKETS] = (packets.output - old_packets.output)/etime;
- if (perfmon[COLLISION_PACKETS])
- current_values[COLLISION_PACKETS] = (packets.collisions - old_packets.collisions)/etime;
- if (perfmon[NFS_CLIENT_CALLS])
- current_values[NFS_CLIENT_CALLS] = (nfsStats.nfsClient - old_nfsStats.nfsClient)/etime;
- if (perfmon[NFS_SERVER_CALLS])
- current_values[NFS_SERVER_CALLS] = (nfsStats.nfsServer - old_nfsStats.nfsServer)/etime;
}
-/*
- Collect the overall disk transfer rates
-*/
-int
-total_disk_transfers()
+static void
+get_namelist(kernel_name, memory_name)
+ const char *kernel_name, *memory_name;
{
- register int i, total_xfers = 0;
+ register int i, ret;
+ time_t now, boottime;
+ int nintv;
-#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);
+ kd = kvm_openfiles(kernel_name, memory_name, NULL, O_RDONLY, errbuf);
+ if (kd == 0)
+ errx(1, "xperfmon++: kvm_openfiles: %s", errbuf);
+
+ if ((ret = kvm_nlist(kd, namelist)) != 0) {
+ if (ret > 0) {
+ (void)fprintf(stderr, "xperfmon++: undefined symbols:");
+ for (i = 0; i < sizeof(namelist)/sizeof(namelist[0]); i++)
+ if (namelist[i].n_type == 0 || namelist[i].n_value == 0)
+ fprintf(stderr, "%s", namelist[i].n_name);
+ fprintf(stderr, "\n");
+ } else
+ errx(1, "xperfmon++: kvm_nlist: %s", kvm_geterr(kd));
+ exit(1);
+ }
+
+ kread(X_HZ, &hz, sizeof(hz));
+ kread(X_STATHZ, &stathz, sizeof(stathz));
+
+ if (stathz)
+ hz = stathz;
+
+ kread(X_BOOTTIME, &boottime, sizeof(boottime));
+ time(&now);
+ nintv = now - boottime;
+ if (nintv <= 0 || nintv > 60*60*24*365*10)
+ errx(1, "Time makes no sense ... namelist must be wrong", NULL);
}
-/*
- Collect all the data
-*/
-void
-collect_stats()
+static void
+kread(nlx, addr, size)
+ int nlx; void *addr; size_t size;
{
- off_t ifnetaddr;
- register int i, tmp;
- int mib[3], size;
-#if (__FreeBSD_version >= 300004)
- struct vfsconf vfc;
-#endif
+ char *sym;
- 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) );
+ if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) {
+ sym = namelist[nlx].n_name;
+ if (*sym == '_')
+ ++sym;
+ errx(1, "xperfmon++: %s: %s", sym, kvm_geterr(kd));
+ }
+}
- nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value;
- if ((intrcnt = (unsigned long *) malloc((size_t) nintr)) == NULL)
- err(1, "xperfmon++ malloc in collect_stats");
- nintr /= sizeof(long);
- kread(X_INTRCNT, intrcnt, (size_t) nintr*sizeof(long));
- s1.interrupts = s.interrupts;
- s.interrupts = 0;
- for (i = 0; i < nintr; i++)
- s.interrupts += *(intrcnt + i);
- 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];
- s1.time[i] = tmp;
- etime += s.time[i];
+static void
+get_cpustat(void)
+{
+ register int i;
+ double tot;
+
+ kread(X_CP_TIME, cur.cp_time, sizeof(cur.cp_time));
+
+ etime = 0.0;
+ for (i = 0; i < CPUSTATES; i++) {
+ tmp = cur.cp_time[i];
+ cur.cp_time[i] -= last.cp_time[i];
+ last.cp_time[i] = tmp;
+ etime += cur.cp_time[i];
}
- if(etime == 0.)
- etime = 1.;
- etime /= hz;
+ tot = etime;
-/*
- Collect the Network-Traffic
-*/
+ if (etime == 0.0 )
+ etime = 1.0;
- if ((ifnetaddr = nl[N_IFNET].n_value) != 0) {
-#if __FreeBSD_version < 300000
- struct ifnet ifnet;
- kread(N_IFNET, &ifnetaddr, sizeof(ifnetaddr));
- old_packets = packets;
- packets.input = packets.output = packets.collisions = 0;
- while (ifnetaddr) {
- kvm_read(kd, ifnetaddr, &ifnet, sizeof ifnet );
- packets.input += ifnet.if_ipackets;
- packets.output += ifnet.if_opackets;
- packets.collisions += ifnet.if_collisions;
- ifnetaddr = (u_long) ifnet.if_next;
- }
-#else /* 3.0-current, Jan 1997 */
- /* Stolen from netstat/if.c */
- struct ifnet ifnet;
- struct ifnethead ifnethead;
- u_long ifaddraddr, ifnetfound;
- struct ifaddr ifa;
+ etime /= (float)hz;
- if(kvm_read(kd, ifnetaddr, (char *)&ifnethead, sizeof ifnethead) == -1)
- return;
- ifnetaddr = (u_long)ifnethead.tqh_first;
- if(kvm_read(kd, ifnetaddr, (char *)&ifnet, sizeof ifnet) == -1)
- return;
+ /*
+ * scale to percent
+ */
+ if(tot)
+ pct = 100.0 / tot;
+ else
+ pct = 0;
+}
- old_packets = packets;
- packets.input = packets.output = packets.collisions = 0;
- ifaddraddr = 0;
- while (ifnetaddr || ifaddraddr) {
- if (ifaddraddr == 0) {
- ifnetfound = ifnetaddr;
- if(kvm_read(kd, ifnetaddr, (char *)&ifnet, sizeof ifnet) == -1)
- return;
- ifnetaddr = (u_long)ifnet.if_link.tqe_next;
- ifaddraddr = (u_long)ifnet.if_addrhead.tqh_first;
- }
- if (kvm_read(kd, ifaddraddr, (char *)&ifa, sizeof ifa) == -1) {
- ifaddraddr = 0;
- continue;
- }
- ifaddraddr = (u_long)ifa.ifa_link.tqe_next;
- packets.input += ifnet.if_ipackets;
- packets.output += ifnet.if_opackets;
- packets.collisions += ifnet.if_collisions;
- }
-#endif
- }
+static double
+get_load(void)
+{
+ double loadavg[3];
-/*
- Collect the NFS and RPC Calls
-*/
-
- size = sizeof(nfsstats);
- mib[0] = CTL_FS;
-#if (__FreeBSD_version >= 300004)
- if (getvfsbyname("nfs", &vfc) < 0)
- /* no NFS in the kernel */
+ loadavg[0] = 0.0;
+ if (getloadavg(loadavg, sizeof(loadavg)/sizeof(loadavg[0])) == -1) {
+ fprintf(stderr, "xperfmon++: getloadavg() returned no values\n");
return;
- mib[1] = vfc.vfc_typenum;
-#else
- mib[1] = MOUNT_NFS;
-#endif
- mib[2] = NFS_NFSSTATS;
-
- if (sysctl( mib, 3, &nfsstats, &size, NULL, 0) < 0)
- return;
- else {
- old_nfsStats = nfsStats;
-
- nfsStats.nfsClient = nfsstats.rpccnt[NFSPROC_GETATTR] +
- nfsstats.rpccnt[NFSPROC_SETATTR] +
- nfsstats.rpccnt[NFSPROC_LOOKUP] +
- nfsstats.rpccnt[NFSPROC_READLINK] +
- nfsstats.rpccnt[NFSPROC_READ] +
- nfsstats.rpccnt[NFSPROC_WRITE] +
- nfsstats.rpccnt[NFSPROC_CREATE] +
- nfsstats.rpccnt[NFSPROC_REMOVE] +
- nfsstats.rpccnt[NFSPROC_RENAME] +
- nfsstats.rpccnt[NFSPROC_LINK] +
- nfsstats.rpccnt[NFSPROC_SYMLINK] +
- nfsstats.rpccnt[NFSPROC_MKDIR] +
- nfsstats.rpccnt[NFSPROC_RMDIR] +
- nfsstats.rpccnt[NFSPROC_READDIR] +
-#ifndef HAS_NFS_V3
- nfsstats.rpccnt[NFSPROC_STATFS] +
- nfsstats.rpccnt[NQNFSPROC_READDIRLOOK] +
-#else /* HAS_NFS_V3 */
- nfsstats.rpccnt[NFSPROC_READDIRPLUS] +
- nfsstats.rpccnt[NFSPROC_FSSTAT] +
- nfsstats.rpccnt[NFSPROC_FSINFO] +
- nfsstats.rpccnt[NFSPROC_PATHCONF] +
- nfsstats.rpccnt[NFSPROC_COMMIT] +
-#endif /* HAS_NFS_V3 */
- nfsstats.rpccnt[NQNFSPROC_GETLEASE] +
- nfsstats.rpccnt[NQNFSPROC_VACATED] +
- nfsstats.rpccnt[NQNFSPROC_EVICTED];
-
- nfsStats.nfsServer = nfsstats.srvrpccnt[NFSPROC_GETATTR] +
- nfsstats.srvrpccnt[NFSPROC_SETATTR] +
- nfsstats.srvrpccnt[NFSPROC_LOOKUP] +
- nfsstats.srvrpccnt[NFSPROC_READLINK] +
- nfsstats.srvrpccnt[NFSPROC_READ] +
- nfsstats.srvrpccnt[NFSPROC_WRITE] +
- nfsstats.srvrpccnt[NFSPROC_CREATE] +
- nfsstats.srvrpccnt[NFSPROC_REMOVE] +
- nfsstats.srvrpccnt[NFSPROC_RENAME] +
- nfsstats.srvrpccnt[NFSPROC_LINK] +
- nfsstats.srvrpccnt[NFSPROC_SYMLINK] +
- nfsstats.srvrpccnt[NFSPROC_MKDIR] +
- nfsstats.srvrpccnt[NFSPROC_RMDIR] +
- nfsstats.srvrpccnt[NFSPROC_READDIR] +
-#ifndef HAS_NFS_V3
- nfsstats.srvrpccnt[NFSPROC_STATFS] +
- nfsstats.srvrpccnt[NQNFSPROC_READDIRLOOK] +
-#else /* HAS_NFS_V3 */
- nfsstats.srvrpccnt[NFSPROC_READDIRPLUS] +
- nfsstats.srvrpccnt[NFSPROC_FSSTAT] +
- nfsstats.srvrpccnt[NFSPROC_FSINFO] +
- nfsstats.srvrpccnt[NFSPROC_PATHCONF] +
- nfsstats.srvrpccnt[NFSPROC_COMMIT] +
-#endif /* HAS_NFS_V3 */
- nfsstats.srvrpccnt[NQNFSPROC_GETLEASE] +
- nfsstats.srvrpccnt[NQNFSPROC_VACATED] +
- nfsstats.srvrpccnt[NQNFSPROC_EVICTED];
}
+ return(loadavg[0]);
}
-/*
- Reads the nlist from the kernel
-*/
-int
-get_namelist(kernel_name, memory_name)
- const char *kernel_name, *memory_name;
+static void
+get_ttystat(void)
{
- time_t now;
- time_t boottime;
- register int i, c;
- int nintv;
+ kread(X_TK_NIN, &cur.tk_nin, sizeof(cur.tk_nin));
+ kread(X_TK_NOUT, &cur.tk_nout, sizeof(cur.tk_nout));
- kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
- if (kd == 0) {
- (void)fprintf(stderr, "xperfmon++: kvm_openfiles: %s\n", errbuf);
- exit(1);
- }
+ tmp = cur.tk_nin;
+ cur.tk_nin -= last.tk_nin;
+ last.tk_nin = tmp;
- if ((c = kvm_nlist(kd, nl)) != 0) {
- if (c > 0) {
- (void)fprintf(stderr,"xperfmon++: undefined symbols:");
- for (c = 0; c < sizeof(nl)/sizeof(nl[0]); c++)
- if (nl[c].n_type == 0)
- fprintf(stderr, " %s", nl[c].n_name);
- (void)fputc('\n', stderr);
- } else
- (void)fprintf(stderr, "xperfmon++: kvm_nlist: %s\n", kvm_geterr(kd)); exit(1);
- }
+ tmp = cur.tk_nout;
+ cur.tk_nout -= last.tk_nout;
+ last.tk_nout = tmp;
+}
- kread(X_BOOTTIME, &boottime, sizeof(boottime));
- kread(X_HZ, &hz, sizeof(hz));
- for (i = 0; i < DK_NDRIVE; i++) {
- strcpy(dr_name[i], "xx");
- }
- time(&now);
- nintv = now - boottime;
- if (nintv <= 0 || nintv > 60*60*24*365*10) {
- fprintf(stderr,
- "Time makes no sense... namelist must be wrong.\n");
- exit(1);
- }
- return(nintv);
+
+static void
+get_interrupts(void)
+{
+ register int i;
+ unsigned long *intrcnt;
+ int nintr;
+
+ nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value;
+ if ((intrcnt = (unsigned long *)malloc((size_t) nintr)) == NULL)
+ err(1, "xperfmon++: malloc failed in get_interrupts()");
+ nintr /= sizeof(long);
+ kread(X_INTRCNT, intrcnt, (size_t)nintr*sizeof(long));
+ old_interrupts = interrupts;
+ for (i = 0, interrupts = 0; i < nintr; i++)
+ interrupts += *(intrcnt + i);
+ free(intrcnt);
}
/*
- Kread reads something from the kernel, given its nlist index.
-*/
+ * Parts extracted from /usr/src/usr.bin/nfsstat/nfsstat.c
+ * pay attention Copyrights!
+ */
static void
-kread(nlx, addr, size)
- int nlx;
- void *addr;
- size_t size;
+get_nfsstat(void)
{
- char *sym;
-
- if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) {
- sym = nl[nlx].n_name;
- if (*sym == '_')
- ++sym;
- (void)fprintf(stderr,
- "xpermon++: symbol %s not defined\n", sym);
- exit(1);
- }
- if (kvm_read(kd, nl[nlx].n_value, addr, size) != size) {
- sym = nl[nlx].n_name;
- if (*sym == '_')
- ++sym;
- (void)fprintf(stderr, "xperfmon++: %s: %s\n", sym, kvm_geterr(kd));
- exit(1);
- }
+ int name[3];
+ size_t size = sizeof(nfsstats);
+
+ name[0] = CTL_VFS;
+ name[1] = vfc.vfc_typenum;
+ name[2] = NFS_NFSSTATS;
+ if (sysctl(name, 3, &nfsstats, &size, (void *)0, (size_t)0) < 0) {
+ fprintf(stderr, "xperfmon++: get_nfsstat(): Can?%t get NFS statistics with sysctl()\n");
+ return;
+ }
+
+ old_nfsStats = nfsStats;
+
+ nfsStats.ClientCalls = nfsstats.rpccnt[NFSPROC_GETATTR] +
+ nfsstats.rpccnt[NFSPROC_SETATTR] +
+ nfsstats.rpccnt[NFSPROC_LOOKUP] +
+ nfsstats.rpccnt[NFSPROC_READLINK] +
+ nfsstats.rpccnt[NFSPROC_READ] +
+ nfsstats.rpccnt[NFSPROC_WRITE] +
+ nfsstats.rpccnt[NFSPROC_CREATE] +
+ nfsstats.rpccnt[NFSPROC_REMOVE] +
+ nfsstats.rpccnt[NFSPROC_RENAME] +
+ nfsstats.rpccnt[NFSPROC_LINK] +
+ nfsstats.rpccnt[NFSPROC_SYMLINK] +
+ nfsstats.rpccnt[NFSPROC_MKDIR] +
+ nfsstats.rpccnt[NFSPROC_RMDIR] +
+ nfsstats.rpccnt[NFSPROC_READDIR] +
+ nfsstats.rpccnt[NFSPROC_READDIRPLUS]+
+ nfsstats.rpccnt[NFSPROC_ACCESS] +
+ nfsstats.rpccnt[NFSPROC_MKNOD] +
+ nfsstats.rpccnt[NFSPROC_FSSTAT] +
+ nfsstats.rpccnt[NFSPROC_FSINFO] +
+ nfsstats.rpccnt[NFSPROC_PATHCONF] +
+ nfsstats.rpccnt[NFSPROC_COMMIT] +
+ nfsstats.rpccnt[NQNFSPROC_GETLEASE] +
+ nfsstats.rpccnt[NQNFSPROC_VACATED] +
+ nfsstats.rpccnt[NQNFSPROC_EVICTED];
+
+ nfsStats.ClientCacheHit = nfsstats.attrcache_hits +
+ nfsstats.lookupcache_hits +
+ nfsstats.biocache_reads -
+ nfsstats.read_bios +
+ nfsstats.biocache_writes -
+ nfsstats.write_bios +
+ nfsstats.biocache_readlinks -
+ nfsstats.readlink_bios +
+ nfsstats.biocache_readdirs -
+ nfsstats.readdir_bios +
+ nfsstats.direofcache_hits;
+
+ nfsStats.ClientCacheMis = nfsstats.attrcache_misses +
+ nfsstats.lookupcache_misses +
+ nfsstats.read_bios +
+ nfsstats.write_bios +
+ nfsstats.readlink_bios +
+ nfsstats.readdir_bios +
+ nfsstats.direofcache_misses;
+
+ nfsStats.ServerCalls = nfsstats.srvrpccnt[NFSPROC_GETATTR] +
+ nfsstats.srvrpccnt[NFSPROC_SETATTR] +
+ nfsstats.srvrpccnt[NFSPROC_LOOKUP] +
+ nfsstats.srvrpccnt[NFSPROC_READLINK] +
+ nfsstats.srvrpccnt[NFSPROC_READ] +
+ nfsstats.srvrpccnt[NFSPROC_WRITE] +
+ nfsstats.srvrpccnt[NFSPROC_CREATE] +
+ nfsstats.srvrpccnt[NFSPROC_REMOVE] +
+ nfsstats.srvrpccnt[NFSPROC_RENAME] +
+ nfsstats.srvrpccnt[NFSPROC_LINK] +
+ nfsstats.srvrpccnt[NFSPROC_SYMLINK] +
+ nfsstats.srvrpccnt[NFSPROC_MKDIR] +
+ nfsstats.srvrpccnt[NFSPROC_RMDIR] +
+ nfsstats.srvrpccnt[NFSPROC_READDIR] +
+ nfsstats.srvrpccnt[NFSPROC_READDIRPLUS]+
+ nfsstats.srvrpccnt[NFSPROC_ACCESS] +
+ nfsstats.srvrpccnt[NFSPROC_MKNOD] +
+ nfsstats.srvrpccnt[NFSPROC_FSSTAT] +
+ nfsstats.srvrpccnt[NFSPROC_FSINFO] +
+ nfsstats.srvrpccnt[NFSPROC_PATHCONF] +
+ nfsstats.srvrpccnt[NFSPROC_COMMIT] +
+ nfsstats.srvrpccnt[NQNFSPROC_GETLEASE] +
+ nfsstats.srvrpccnt[NQNFSPROC_VACATED] +
+ nfsstats.srvrpccnt[NQNFSPROC_EVICTED];
+
+ nfsStats.ServerCacheHit = nfsstats.srvcache_inproghits +
+ nfsstats.srvcache_idemdonehits +
+ nfsstats.srvcache_nonidemdonehits;
+
+ nfsStats.ServerCacheMis = nfsstats.srvcache_misses;
}
+
/*
- * get_swapspace is based on a program called swapinfo written
- * by Kevin Lahey <kml@rokkaku.atl.ga.us>.
+ * Stolen from /usr/src/usr.sbin/pstat/pstat.c and
+ * /usr/src/usr.bin/top/machine.c (pay attention Copyrights!)
*/
-int
-get_swapspace()
+static double
+get_swapspace(void)
{
#if __FreeBSD_version >= 400000
- /* based on swapmode from /usr/src/usr.bin/top/machine.c */
- int n;
- int percentfree;
- struct kvm_swap swapary[1];
-
- n = kvm_getswapinfo(kd, swapary, 1, 0);
- if (n < 0)
- return(0);
-
- percentfree = (int)((((double)swapary[0].ksw_total -
- (double)swapary[0].ksw_used) * 100.0) /
- (double)swapary[0].ksw_total);
- return(percentfree);
-#else
- char *header;
- int hlen, nswap, nswdev, dmmax;
- int i, div, avail, nfree, npfree, used;
- struct swdevt *sw;
- long blocksize, *perdev;
- struct rlist head;
-#if __FreeBSD_version >= 220000
- struct rlisthdr swaplist;
- struct rlist *swapptr;
-#else
- struct rlist *swaplist;
-#endif
- u_long ptr;
- kread(VM_NSWAP, &nswap, sizeof(nswap));
- kread(VM_NSWDEV, &nswdev, sizeof(nswdev));
- kread(VM_DMMAX, &dmmax, sizeof(dmmax));
- kread(VM_SWAPLIST, &swaplist, sizeof(swaplist));
- if ((sw = malloc(nswdev * sizeof(*sw))) == NULL ||
- (perdev = malloc(nswdev * sizeof(*perdev))) == NULL)
- err(1, "xperfmon++ malloc in get_swapspace");
- kread(VM_SWDEVT, &ptr, sizeof(ptr));
- kvm_read(kd, ptr, sw, nswdev * sizeof(*sw));
- /* Count up swap space. */
- nfree = 0;
- memset(perdev, 0, nswdev * sizeof(*perdev));
-#if __FreeBSD_version >= 220000
- swapptr = swaplist.rlh_list;
- while (swapptr) {
-#else
- while (swaplist) {
-#endif
- int top, bottom, next_block;
-#if __FreeBSD_version >= 220000
- kvm_read(kd, (u_long)swapptr, &head, sizeof(struct rlist));
-#else
- kvm_read(kd, (u_long)swaplist, &head, sizeof(struct rlist));
-#endif
- top = head.rl_end;
- bottom = head.rl_start;
-
- nfree += top - bottom + 1;
-
- /*
- * Swap space is split up among the configured disks.
- *
- * For interleaved swap devices, the first dmmax blocks
- * of swap space some from the first disk, the next dmmax
- * blocks from the next, and so on up to nswap blocks.
- *
- * The list of free space joins adjacent free blocks,
- * ignoring device boundries. If we want to keep track
- * of this information per device, we'll just have to
- * extract it ourselves.
- */
- while (top / dmmax != bottom / dmmax) {
- next_block = ((bottom + dmmax) / dmmax);
- perdev[(bottom / dmmax) % nswdev] +=
- next_block * dmmax - bottom;
- bottom = next_block * dmmax;
- }
- perdev[(bottom / dmmax) % nswdev] +=
- top - bottom + 1;
-#if __FreeBSD_version >= 220000
- swapptr = head.rl_next;
+ /* based on swapmode from /usr/src/usr.bin/top/machine.c */
+ int n;
+ int percentfree;
+ struct kvm_swap swapary[1];
+
+ n = kvm_getswapinfo(kd, swapary, 1, 0);
+ if (n < 0)
+ return(0);
+
+ percentfree = ((((double)swapary[0].ksw_total -
+ (double)swapary[0].ksw_used) * 100.0) /
+ (double)swapary[0].ksw_total);
+ return(percentfree);
+
#else
- swaplist = head.rl_next;
-#endif
- }
-
- header = getbsize(&hlen, &blocksize);
- div = blocksize / 512;
- avail = npfree = 0;
- for (i = 0; i < nswdev; i++) {
- int xsize, xfree;
-
- /*
- * Don't report statistics for partitions which have not
- * yet been activated via swapon(8).
- */
- if (!(sw[i].sw_flags & SW_FREED))
- continue;
-
- /* The first dmmax is never allocated to avoid trashing of
- * disklabels
- */
- xsize = sw[i].sw_nblks - dmmax;
- xfree = perdev[i];
- used = xsize - xfree;
- npfree++;
- avail += xsize;
+ /* based on /usr/src/usr.sbin/pstat/pstat.c */
+ char *header;
+ int hlen, nswap, nswdev, dmmax;
+ int i, div, avail, nfree, npfree, used;
+ struct swdevt *sw;
+ long blocksize, *perdev;
+ struct rlist head;
+ struct rlisthdr swaplist;
+ struct rlist *swapptr;
+ u_long ptr;
+
+ kread(VM_NSWAP, &nswap, sizeof(nswap));
+ kread(VM_NSWDEV, &nswdev, sizeof(nswdev));
+ kread(VM_DMMAX, &dmmax, sizeof(dmmax));
+ kread(VM_SWAPLIST, &swaplist, sizeof(swaplist));
+ if ((sw = malloc(nswdev * sizeof(*sw))) == NULL ||
+ (perdev = malloc(nswdev * sizeof(*perdev))) == NULL)
+ err(1, "xperfmon++ malloc in get_swapspace");
+ kread(VM_SWDEVT, &ptr, sizeof(ptr));
+ kvm_read(kd, ptr, sw, nswdev * sizeof(*sw));
+
+ /* Count up swap space. */
+ nfree = 0;
+ memset(perdev, 0, nswdev * sizeof(*perdev));
+ swapptr = swaplist.rlh_list;
+ while (swapptr) {
+ int top, bottom, next_block;
+ kvm_read(kd, (u_long)swapptr, &head, sizeof(struct rlist));
+ top = head.rl_end;
+ bottom = head.rl_start;
+
+ nfree += top - bottom + 1;
+
+ /*
+ * Swap space is split up among the configured disks.
+ *
+ * For interleaved swap devices, the first dmmax blocks
+ * of swap space some from the first disk, the next dmmax
+ * blocks from the next, and so on up to nswap blocks.
+ *
+ * The list of free space joins adjacent free blocks,
+ * ignoring device boundries. If we want to keep track
+ * of this information per device, we'll just have to
+ * extract it ourselves.
+ */
+ while (top / dmmax != bottom / dmmax) {
+ next_block = ((bottom + dmmax) / dmmax);
+ perdev[(bottom / dmmax) % nswdev] +=
+ next_block * dmmax - bottom;
+ bottom = next_block * dmmax;
}
+ perdev[(bottom / dmmax) % nswdev] +=
+ top - bottom + 1;
+ swapptr = head.rl_next;
+ }
+ header = getbsize(&hlen, &blocksize);
+ div = blocksize / 512;
+ avail = npfree = 0;
+ for (i = 0; i < nswdev; i++) {
+ int xsize, xfree;
/*
- * If only one partition has been set up via swapon(8), we don't
- * need to bother with totals.
+ * Don't report statistics for partitions which have not
+ * yet been activated via swapon(8).
*/
- used = avail - nfree;
+ if (!(sw[i].sw_flags & SW_FREED))
+ continue;
+
+ /* The first dmmax is never allocated to avoid trashing of
+ * disklabels
+ */
+ xsize = sw[i].sw_nblks - dmmax;
+ xfree = perdev[i];
+ used = xsize - xfree;
+ npfree++;
+ avail += xsize;
+ }
+
+ /*
+ * If only one partition has been set up via swapon(8), we don't
+ * need to bother with totals.
+ */
+ used = avail - nfree;
+ free(sw);
+ free(perdev);
+
+ return((100.0*nfree)/avail);
- free(perdev);
- free(sw);
- return((100*nfree)/avail); /* return free swap in percent */
#endif /* __FreeBSD_version >= 400000 */
}
-#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));
+/*
+ * Stolen from /usr/src/usr.bin/netstat/if.c
+ * pay attention Copyrights!
+ */
+static void
+get_netstat(void)
+{
+ off_t ifnetaddr;
- /*
- * 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;
- }
+ if ((ifnetaddr = namelist[N_IFNET].n_value) != 0) {
+ struct ifnet ifnet;
+ struct ifnethead ifnethead;
+ u_long ifaddraddr, ifnetfound;
+ struct ifaddr ifa;
- num_devices = cur.dinfo->numdevs;
- generation = cur.dinfo->generation;
+ if(kvm_read(kd, ifnetaddr, (char *)&ifnethead, sizeof(ifnethead)) == -1)
+ return;
+ ifnetaddr = (u_long)ifnethead.tqh_first;
+ if(kvm_read(kd, ifnetaddr, (char *)&ifnet, sizeof(ifnet)) == -1)
+ return;
- dev_select = NULL;
+ old_packets = packets;
+ packets.input = packets.output = packets.collisions = 0;
+ ifaddraddr = 0;
+ while (ifnetaddr || ifaddraddr) {
+ if (ifaddraddr == 0) {
+ ifnetfound = ifnetaddr;
+ if(kvm_read(kd, ifnetaddr, (char *)&ifnet, sizeof ifnet) == -1)
+ return;
+ ifnetaddr = (u_long)ifnet.if_link.tqe_next;
+ ifaddraddr = (u_long)ifnet.if_addrhead.tqh_first;
+ }
+ if (kvm_read(kd, ifaddraddr, (char *)&ifa, sizeof ifa) == -1) {
+ ifaddraddr = 0;
+ continue;
+ }
+ ifaddraddr = (u_long)ifa.ifa_link.tqe_next;
- /* only interested in disks */
- matches = NULL;
- if (buildmatch("da", &matches, &num_matches) != 0) {
- nodisk++;
- return;
+ packets.input += ifnet.if_ipackets;
+ packets.output += ifnet.if_opackets;
+ packets.collisions += ifnet.if_collisions;
}
+ }
+}
- 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++;
+/*
+ * Many thanks to Kenneth Merry <ken@plutotech.com> who helped to code
+ * the initial disk statistic routines
+ */
+static void
+init_diskio(void)
+{
+ int retval, i;
+
+ 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));
+
+ if (checkversion() < 0)
+ errx(1, "xperfmon++: %s", devstat_errbuf);
+
+ /*
+ * man muß über specified devices gehen, um da1,... zu
+ * selektieren, siehe /usr/src/usr.sbin/iostat/iostat.c
+ */
+
+/* printf("%s\n", info1); LK!!! */
+ if (buildmatch("da", &matches, &num_matches) != 0)
+ errx(1, "xperfmon++: %s", devstat_errbuf);
+ if (buildmatch("sa", &matches, &num_matches) != 0)
+ errx(1, "xperfmon++: %s", devstat_errbuf);
+ if (buildmatch("cd", &matches, &num_matches) != 0)
+ errx(1, "xperfmon++: %s", devstat_errbuf);
+
+ if (getdevs(&cur) == -1)
+ errx(1, "xperfmon++: %s", devstat_errbuf);
+
+ maxshowdevs = 50;
+
+ 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,
+ specified_devices, num_devices_specified,
+ DS_SELECT_ONLY, maxshowdevs, 0);
+ switch (retval) {
+ case -1:
+ errx(1, "xperfmon++: %s", devstat_errbuf);
+ break;
+ default:
+ break;
+ }
}
-int
-get_devstat(void)
+
+static void
+get_diskio(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)) {
+ register int i, dn;
+ long double busy_seconds;
+ long double transfers_per_second, mb_per_second;
+ struct devinfo *tmp_dinfo;
+ int retval;
+
+ tmp_dinfo = last.dinfo;
+ last.dinfo = cur.dinfo;
+ cur.dinfo = tmp_dinfo;
+ last.busy_time = cur.busy_time;
+
+ switch (getdevs(&cur)) {
+ case -1:
+ errx(1, "xperfmon++: %s", devstat_errbuf);
+ break;
+ 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,
+ specified_devices, num_devices_specified,
+ DS_SELECT_ONLY, maxshowdevs, 0);
+ switch (retval) {
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;
- }
+ errx(1, "xperfmon++: %s", devstat_errbuf);
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);
+ break;
}
+ default:
+ break;
+ }
+ /*
+ * Calculate elapsed time up front, since it's the same for all
+ * devices.
+ */
- for (dn = 0; dn < num_devices; dn++) {
- int di;
+ diskstat.da_trsf = diskstat.da_mb = 0.0;
+ diskstat.sa_trsf = diskstat.sa_mb = 0.0;
+ diskstat.cd_trsf = diskstat.cd_mb = 0.0;
- if ((dev_select[dn].selected == 0)
- || (dev_select[dn].selected > DK_NDRIVE))
- continue;
+ busy_seconds = compute_etime(cur.busy_time, last.busy_time);
- di = dev_select[dn].position;
+ for (dn = 0; dn < num_devices; dn++) {
+ int di;
- 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;
- }
+ if (dev_select[dn].selected == 0)
+ continue;
- tmp_dinfo = last.dinfo;
- last.dinfo = cur.dinfo;
- cur.dinfo = tmp_dinfo;
+ di = dev_select[dn].position;
- last.busy_time = cur.busy_time;
+ if (compute_stats(&cur.dinfo->devices[di],
+ &last.dinfo->devices[di], busy_seconds,
+ NULL, NULL,
+ NULL, NULL,
+ &transfers_per_second, &mb_per_second,
+ NULL, NULL) != 0)
+ errx(1, "xperfmon++: %s", devstat_errbuf);
- } else
- /* no disks found ? */
- total_xfers = 0;
+ if (strcmp(cur.dinfo->devices[di].device_name, "da") == 0 ||
+ strcmp(cur.dinfo->devices[di].device_name, "wd") == 0) {
+#ifdef DEBUG
+ printf( "da%d: %Lf %Lf\n", cur.dinfo->devices[di].unit_number, transfers_per_second, mb_per_second);
+#endif
+ diskstat.da_trsf += transfers_per_second;
+ diskstat.da_mb += mb_per_second;
+ }
+ if (strcmp(cur.dinfo->devices[di].device_name, "sa") == 0) {
+#ifdef DEBUG
+ printf( "sa%d: %Lf %Lf\n", cur.dinfo->devices[di].unit_number, transfers_per_second, mb_per_second);
+#endif
+ diskstat.sa_trsf += transfers_per_second;
+ diskstat.sa_mb += mb_per_second;
+ }
+ if (strcmp(cur.dinfo->devices[di].device_name, "cd") == 0 ||
+ strcmp(cur.dinfo->devices[di].device_name, "acd") == 0) {
+#ifdef DEBUG
+ printf( "cd%d: %Lf %Lf\n", cur.dinfo->devices[di].unit_number, transfers_per_second, mb_per_second);
+#endif
+ diskstat.cd_trsf += transfers_per_second;
+ diskstat.cd_mb += mb_per_second;
+ }
+
+ }
- return (total_xfers);
}
-#endif /* HAVE_DEVSTAT */