$NetBSD: patch-aj,v 1.4 2003/03/31 03:46:30 jmc Exp $

--- glunix/src/idle/didle_sysinfo.cc.orig	Thu Sep 18 19:04:55 1997
+++ glunix/src/idle/didle_sysinfo.cc	Sun Mar 30 21:52:53 2003
@@ -95,14 +95,34 @@
 #include <kvm.h>
 #include <nlist.h>
 #include <stdio.h>
+
+#ifdef __NetBSD__
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <miscfs/procfs/procfs.h>
+#if __NetBSD_Version__ < 104000200
+#include <vm/vm_swap.h>
+#else /* moved to sys in 1.4.2 */
+#include <sys/swap.h>
+#endif
+#include <sys/sysctl.h>
+#else
 #include <sys/proc.h>
 #include <sys/procfs.h>
 #include <sys/sysinfo.h>
 #include <sys/cpuvar.h>
 #include <sys/time.h>
+#endif
+
 #include <unistd.h>
 #include <bsd.h>
+
+#ifndef __NetBSD__
 #include <vm/anon.h>  // Contains defns for swap virtual memory info
+#endif
 
 #include "clist.h"
 #include "cidle.h"
@@ -120,12 +140,51 @@
 
 #define LOADDOUBLE(la) ((double)(la) / FSCALE)
 #define HASH(x) ((x) >> 1)
+
+#ifdef __NetBSD__
+int getpsize()
+{
+  FILE *file;
+  char *buf;
+
+  file = fopen("/kern/pagesize","r");
+  fscanf(file,"%s",buf);
+  fclose(file);
+  return atoi(buf);
+}
+#define PAGETOK(size) (size) * getpsize()
+
+#else
 #define PAGETOK(size) (size) << 3     // 8K pages
+#endif
 
+#ifndef __NetBSD__
 #define MAX(a, b)  (((a) > (b)) ? (a) : (b))
-
+#endif
 /*****************************************************************************/
 
+#ifdef __NetBSD__
+static struct nlist nlst[] = {
+#define X_CCPU          0
+    { "_ccpu" },                /* 0 */
+#define X_CP_TIME       1
+    { "_cp_time" },             /* 1 */
+#define X_HZ            2
+    { "_hz" },                  /* 2 */
+#define X_STATHZ        3
+    { "_stathz" },              /* 3 */
+#define X_AVENRUN       4
+    { "_averunnable" },         /* 4 */
+#define X_CNT           5
+    { "_cnt" },
+
+    { 0 }
+};
+
+static ulong cp_time_offset,cnt_offset;
+
+#else
+
 /* definitions for indices in the nlist array */
 #define X_AVENRUN		 0
 #define X_MPID			 1
@@ -165,11 +224,11 @@
 
 // These are offsets into kmem for the stats we need
 static ulong avenrunOffset, availrmemOffset, anoninfoOffset, swapfsOffset;
-
+#endif
 /*****************************************************************************/
 
 /* These two declarations are no longer necessary */
-#ifdef 0
+#if 0
 static int cpuStates[NUM_CPUSTATES];
 static int memoryStats[5];
 static char *cpuStateNames[] =
@@ -237,6 +296,45 @@
  *
  * Side effects:
  *****************************************************************************/
+#ifdef __NetBSD__
+Bool
+Idle_InitializeSysinfo(void)
+{
+    int  notFound;
+    int  i;
+
+    if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL) {
+	kd = NULL;
+	perror("(dile)Idle_InitializeSysinfo: kvm_open");
+	return -1;
+    }
+    /* get the list of symbols we want to access in the kernel */
+    if ((notFound = kvm_nlist(kd, nlst)) < 0) {
+	fprintf(stderr, "res: nlist failed\n");
+	return False;
+    }
+    numCpus=1;
+    cp_time_offset = nlst[X_CP_TIME].n_value;
+    cnt_offset = nlst[X_CNT].n_value;
+
+    if (!(procdir = opendir(PROCFS))) {
+	(void) fprintf(stderr, "Unable to open %s\n", PROCFS);
+	return False;
+    }
+    /* handy for later on when we're reading it */
+    if (chdir(PROCFS)) {
+	(void) fprintf(stderr, "Unable to chdir to %s\n", PROCFS);
+	return False;
+    }
+
+    for (i = 0; i < USAGE_TABLE_SIZE; i++) {
+	procUsageTable[i].pid = -1;
+	procUsageTable[i].cpuUsage = 0.0;
+    }
+
+    return True;
+}
+#else
 Bool
 Idle_InitializeSysinfo(void)
 {
@@ -301,7 +399,7 @@
 
     return True;
 }
-
+#endif
 /******************************************************************************
  * Idle_CleanupSysinfo --
  *    Description of purpose and function of the procedure
@@ -333,18 +431,30 @@
  *
  * Side effects:
  *****************************************************************************/
+#ifdef __NetBSD__
+static ProcUsage *
+FindEntry(pid_t pid, double usage)
+#else
 static ProcUsage *
 FindEntry(struct prpsinfo *targProc, double usage)
+#endif
 {
     int         index, start;
     ProcUsage  *candidate;
+#ifdef __NetBSD__
+    index = HASH(pid);
+#else
     ASSERT(targProc != NULL);
-    
     index = HASH(targProc->pr_pid);
+#endif
     start = index;
     while (1) {
 	candidate = &(procUsageTable[index]);
+#ifdef __NetBSD__
+	if (candidate->pid == pid) {
+#else
 	if (candidate->pid == targProc->pr_pid) {
+#endif
 	    /* Has this pid been recycled?  Are we hitting a very old process?
 	       If so, then reset the entry */
 	    if (usage < candidate->cpuUsage) {
@@ -353,7 +463,11 @@
 	    return candidate;
 	}
 	if (candidate->pid == -1) {
+#ifdef __NetBSD__
+	    candidate->pid = pid;
+#else
 	    candidate->pid = targProc->pr_pid;
+#endif
 	    candidate->cpuUsage = 0;
 	    return candidate;
 	}
@@ -379,10 +493,17 @@
  *
  * Side effects:
  *****************************************************************************/
+
+#ifdef __NetBSD__
+static void
+UpdateEntry(ProcUsage *entry, double usage)
+{
+#else
 static void
 UpdateEntry(ProcUsage *entry, struct prpsinfo *proc, double usage)
 {
     UNUSED_PARAM(proc);
+#endif
     ASSERT(entry != NULL);
     entry->cpuUsage = usage;
 }
@@ -408,12 +529,24 @@
 void
 Idle_GetSysInfo(Idle_Load *total, Idle_Load *seq, List_List *glunixProcs)
 {
+
+#ifndef __NetBSD__
     struct prpsinfo  currproc;	/* pointer to current proc structure	*/
+#else
+    struct kinfo_proc *procs;
+    int mib[3],i;
+    size_t size;
+#endif
+
+#ifndef __NetBSD__
     int              fd;
+#endif
     int              activeMemory[2];
     int              vmInUse[2];
     int              cpuUsage[2];
+#ifndef __NetBSD__
     struct dirent         *direntp;
+#endif
     static struct timeval  lastTime = {0, 0};
     struct timeval         currTime;
     double                 alpha, beta;
@@ -459,6 +592,33 @@
     vmInUse[TOTAL] = 0; vmInUse[SEQUENTIAL] = 0;
     cpuUsage[TOTAL] = 0; cpuUsage[SEQUENTIAL] = 0;
     numProcs = 0;
+
+#ifdef __NetBSD__
+    size = 0;
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_PROC;
+    mib[2] = KERN_PROC_ALL;
+
+    sysctl(mib, 3, NULL, &size, NULL, 0);
+    procs = (struct kinfo_proc *)malloc(size);
+    sysctl(mib, 3, procs, &size, NULL, 0);
+    numProcs = size / sizeof(struct kinfo_proc);
+
+    for (i=0; i<numProcs; i++) {
+      activeMemory[TOTAL] += procs[i].kp_eproc.e_xrssize;
+      vmInUse[TOTAL] += procs[i].kp_eproc.e_xsize;
+      currUsage = procs[i].kp_proc.p_rtime.tv_sec * 1.0e9 + procs[i].kp_proc.p_rtime.tv_usec * 1000;
+      oldProc = FindEntry(procs[i].kp_proc.p_pid, currUsage);
+      percentCpu = (currUsage - oldProc->cpuUsage) / timeDiff;
+      UpdateEntry(oldProc, currUsage);
+      cpuUsage[TOTAL] += (int) (percentCpu * 10.0);
+      if (glunixProcs->KeySearch(procs[i].kp_proc.p_pid) == NULL) {
+	activeMemory[SEQUENTIAL] += procs[i].kp_eproc.e_xrssize;
+	vmInUse[SEQUENTIAL] += procs[i].kp_eproc.e_xsize;
+	cpuUsage[SEQUENTIAL] += (int) (percentCpu * 10.0);
+      }
+    }
+#else
     rewinddir(procdir);
     
     while ((direntp = readdir(procdir)) != 0) {
@@ -493,6 +653,7 @@
 	(void) close(fd);
 	numProcs++;
     }
+#endif
     total->mem = activeMemory[TOTAL];
     total->cpu = cpuUsage[TOTAL];
     seq->mem = activeMemory[SEQUENTIAL];
@@ -503,10 +664,21 @@
 void
 Idle_GetSystemInfo(Idle_SystemLoad *sysLoad)
 {
-    struct anoninfo anoninfo;
+#ifndef __NetBSD__
+    int      i;
     long     avenrun[3];
+    struct anoninfo anoninfo;
     int      ani_max, ani_resv, availrmem, swapfs_minfree;
+#else
     int      i;
+    double  avenrun[3];
+    int mib[2];
+    struct vmtotal total;
+    size_t sizeofvmtotal;
+    struct  swapent *sep;
+    int     totalsize, size, totalinuse, inuse, ncounted;
+    int     rnswap, nswap;
+#endif
 
     if (kd == NULL) {
 	sysLoad->loadAvg[0] = 0;
@@ -515,7 +687,48 @@
 	sysLoad->memory = 0;
 	return;
     }
+#ifdef __NetBSD__
 
+    getloadavg(avenrun,3);
+    for (i = 0; i < 3; i++) {
+	sysLoad->loadAvg[i] = avenrun[i];
+    }
+
+    sep = NULL;
+    do {
+        nswap = swapctl(SWAP_NSWAP, 0, 0);
+        if (nswap < 1)
+                break;
+        sep = (struct swapent *)malloc(nswap * sizeof(*sep));
+        if (sep == NULL)
+                break;
+        rnswap = swapctl(SWAP_STATS, (void *)sep, nswap);
+        if (nswap != rnswap)
+                break;
+
+        totalsize = totalinuse = ncounted = 0;
+        for (; rnswap-- > 0; sep++) {
+            ncounted++;
+            size = sep->se_nblks;
+            inuse = sep->se_inuse;
+            totalsize += size;
+            totalinuse += inuse;
+        }
+
+    } while (0);
+    if (sep)
+            free(sep);
+
+    sizeofvmtotal = sizeof(total);
+    mib[0] = CTL_VM;
+    mib[1] = VM_METER;
+    if (sysctl(mib, 2, &total, &sizeofvmtotal, NULL, 0) < 0) {
+            printf("Can't get vmtotals: %s\n",
+                strerror(errno));
+            memset(&total, 0, sizeof(total));
+    }
+    sysLoad->memory = PAGETOK(dbtob(totalsize) - dbtob(totalinuse) + total.t_free);
+#else
     /* get load average array */
     ReadKernelData(avenrunOffset, (char *) avenrun, sizeof (avenrun));
     //
@@ -539,6 +752,7 @@
     sysLoad->memory = PAGETOK(MAX(ani_max - ani_resv, 0) +
 			      availrmem - swapfs_minfree);
 
+#endif
     return;
 }
 
