*** kvm_read.c.orig	Fri Jun  4 15:45:13 1999
--- kvm_read.c	Fri Jun  4 15:49:13 1999
***************
*** 0 ****
--- 1,194 ----
+ /*
+  * This file obtains memory usage via FreeBSD's kvm library.
+  * It is a modified version of read_mem.c which is
+  * Copyright (c) 1999  Albert Dorofeev <Albert@mail.dma.be>
+  * use this in place of that file for FreeBSD systems.
+  *
+  * This software is distributed under GPL. For details see LICENSE file.
+  */
+ 
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ 
+ #include "state.h"
+ 
+ #include <err.h>
+ #include <kvm.h>
+ #include <nlist.h>
+ #include <sys/rlist.h>
+ #include <sys/conf.h>
+ #include <sys/vmmeter.h>
+ #include <sys/types.h>
+ #include <sys/sysctl.h>
+ #include <vm/vm_param.h>
+ 
+ extern struct asmem_state state;
+ 
+ kvm_t	*kd;
+ 
+ #define	SVAR(var) __STRING(var)	/* to force expansion */
+ #define	KGET(idx, var)							\
+ 	KGET1(idx, &var, sizeof(var), SVAR(var))
+ #define	KGET1(idx, p, s, msg)						\
+ 	KGET2(nl[idx].n_value, p, s, msg)
+ #define	KGET2(addr, p, s, msg)						\
+ 	if (kvm_read(kd, (u_long)(addr), p, s) != s)			\
+ 		warnx("cannot read %s: %s", msg, kvm_geterr(kd))
+ 
+ struct nlist nl[] = {
+ #define VM_SWAPLIST 0
+     { "_swaplist" },/* list of free swap areas */
+ #define VM_SWDEVT   1
+ 	{ "_swdevt" },  /* list of swap devices and sizes */
+ #define VM_NSWAP    2
+ 	{ "_nswap" },   /* size of largest swap device */
+ #define VM_NSWDEV   3
+ 	{ "_nswdev" },  /* number of swap devices */
+ #define VM_DMMAX    4
+ 	{ "_dmmax" },   /* maximum size of a swap block */
+ #define X_CNT		5
+ 	{ "_cnt" },
+ #define X_BUFSPACE  6
+     { "_bufspace" },    /* K in buffer cache */
+ 	{ "" }
+ };
+ 
+ int close_meminfo()
+ {
+ 	kvm_close(kd);
+ 	return 0;
+ }
+ 
+ int read_meminfo()
+ {
+ 
+ 	int nswap, nswdev, dmmax;
+ 	int i, avail, nfree, used, bufspace = 0;
+ 	struct swdevt *sw;
+ 	struct vmmeter sum;
+ 	long *perdev;
+ 	struct rlist head;
+ 	struct rlisthdr swaplist;
+ 	struct rlist *swapptr;
+ 	u_long ptr;
+ 
+ 	KGET(VM_NSWAP, nswap);
+ 	KGET(VM_NSWDEV, nswdev);
+ 	KGET(VM_DMMAX, dmmax);
+ 	KGET1(VM_SWAPLIST, &swaplist, sizeof swaplist, "swaplist");
+ 	if ((sw = (struct swdevt*)malloc(nswdev * sizeof(*sw))) == NULL ||
+ 	    (perdev = (long *)malloc(nswdev * sizeof(*perdev))) == NULL)
+ 		errx(1, "malloc");
+ 	KGET1(VM_SWDEVT, &ptr, sizeof ptr, "swdevt");
+ 	KGET2(ptr, sw, nswdev * sizeof(*sw), "*swdevt");
+ 
+ 	/* Count up swap space. */
+ 	nfree = 0;
+ 	memset(perdev, 0, nswdev * sizeof(*perdev));
+ 	swapptr = swaplist.rlh_list;
+ 	while (swapptr) {
+ 		int	top, bottom, next_block;
+ 
+ 		KGET2(swapptr, &head, sizeof(struct rlist), "swapptr");
+ 
+ 		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;
+ 	}
+ 
+ 	avail = 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;
+ 		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);
+ 
+ 	state.fresh.swap_total = avail * 512;
+ 	state.fresh.swap_used = used * 512;
+ 	state.fresh.swap_free = (avail - used) * 512;
+ 
+ 	KGET(X_CNT, sum);
+ 	KGET(X_BUFSPACE, bufspace);
+ 
+ 	state.fresh.total = sum.v_page_size * sum.v_page_count;
+ 	state.fresh.used = sum.v_page_size * (sum.v_page_count - sum.v_free_count);
+ 	state.fresh.free = sum.v_page_size * sum.v_free_count;
+ 	state.fresh.shared = 0;
+ 	state.fresh.cached = sum.v_page_size * sum.v_cache_count;
+ 
+ 	state.fresh.buffers = bufspace;
+ 	return(0);
+ 
+ }
+ 
+ int open_meminfo()
+ {
+ 
+ 	if (kd == 0) {
+ 		kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, 0);
+ 		if (kd != NULL) {
+ 			if (kvm_nlist(kd, nl) < 0) {
+ 				errx(1, "kvm_nlist: %s", kvm_geterr(kd));
+ 			}
+ 
+ 			if (nl[0].n_type == 0) {
+ 				errx(1, "no namelist");
+ 			}
+ 		} else {
+ 			warnx("kvm not available");
+ 			return(-1);
+ 		}
+ 	}
+ 	return(0);
+ }
+ 
+ 
