$OpenBSD: patch-sysdeps_openbsd_cpu_c,v 1.6 2014/09/08 07:40:29 jasper Exp $

From 7326f8816d025a31b9625e9b1776c1bf455f5793 Mon Sep 17 00:00:00 2001
From: Jasper Lievisse Adriaanse <jasper@humppa.nl>
Date: Mon, 1 Sep 2014 15:21:31 +0200
Subject: Add SMP support for OpenBSD

--- sysdeps/openbsd/cpu.c.orig	Mon Apr 28 23:09:24 2014
+++ sysdeps/openbsd/cpu.c	Fri Jul 11 18:58:37 2014
@@ -26,18 +26,22 @@
 
 #include <glibtop_suid.h>
 
-#include <sys/sched.h>
-
 static const unsigned long _glibtop_sysdeps_cpu =
 (1L << GLIBTOP_CPU_TOTAL) + (1L << GLIBTOP_CPU_USER) +
 (1L << GLIBTOP_CPU_NICE) + (1L << GLIBTOP_CPU_SYS) +
 (1L << GLIBTOP_CPU_IDLE) + (1L << GLIBTOP_CPU_FREQUENCY) +
 (1L << GLIBTOP_CPU_IRQ);
 
+static const unsigned long _glibtop_sysdeps_cpu_smp =
+(1L << GLIBTOP_XCPU_TOTAL) + (1L << GLIBTOP_XCPU_USER) +
+(1L << GLIBTOP_XCPU_NICE) + (1L << GLIBTOP_XCPU_SYS) +
+(1L << GLIBTOP_XCPU_IDLE) + (1L << GLIBTOP_XCPU_IRQ);
+
 /* MIB array for sysctl */
 static int mib_length=2;
-static int mib [] = { CTL_KERN, KERN_CLOCKRATE };
-static int mib2 [] = { CTL_KERN, KERN_CPTIME };
+static int mib_cr [] = { CTL_KERN, KERN_CLOCKRATE };
+static int mib_cptime [] = { CTL_KERN, KERN_CPTIME };
+static int mib_cptime_s [] = { CTL_KERN, KERN_CPTIME2, 0 };
 
 /* Init function. */
 
@@ -45,6 +49,9 @@ void
 _glibtop_init_cpu_s (glibtop *server)
 {
 	server->sysdeps.cpu = _glibtop_sysdeps_cpu;
+
+	if (server->ncpu)
+		server->sysdeps.cpu |= _glibtop_sysdeps_cpu_smp;
 }
 
 /* Provides information about cpu usage. */
@@ -52,13 +59,13 @@ _glibtop_init_cpu_s (glibtop *server)
 void
 glibtop_get_cpu_s (glibtop *server, glibtop_cpu *buf)
 {
-	gulong cpts [CPUSTATES];
-
-	/* sysctl vars*/
+	long cpts [CPUSTATES];
+	int64_t *cp_times = NULL;
 	struct clockinfo ci;
 	size_t length;
+	int ncpu, i;
 
-	glibtop_init_p (server, (1L << GLIBTOP_SYSDEPS_CPU), 0);
+	glibtop_init_s (&server, GLIBTOP_SYSDEPS_CPU, 0);
 
 	memset (buf, 0, sizeof (glibtop_cpu));
 
@@ -67,14 +74,14 @@ glibtop_get_cpu_s (glibtop *server, glibtop_cpu *buf)
 		return;
 
 	length = sizeof (cpts);
-	if (sysctl (mib2, mib_length, cpts, &length, NULL, 0)) {
+	if (sysctl (mib_cptime, mib_length, cpts, &length, NULL, 0)) {
 		glibtop_warn_io_r (server, "sysctl (kern.cptime)");
 		return;
 	}
 
 	/* Get the clockrate data */
 	length = sizeof (struct clockinfo);
-	if (sysctl (mib, mib_length, &ci, &length, NULL, 0)) {
+	if (sysctl (mib_cr, mib_length, &ci, &length, NULL, 0)) {
 		glibtop_warn_io_r (server, "sysctl (kern.clockrate)");
 		return;
 	}
@@ -87,15 +94,55 @@ glibtop_get_cpu_s (glibtop *server, glibtop_cpu *buf)
 	buf->sys = cpts [CP_SYS];
 	/* set idle time */
 	buf->idle = cpts [CP_IDLE];
-	/* set interrupt time */
+	/* set irq */
 	buf->irq = cpts [CP_INTR];
 
 	/* set frequency */
-	buf->frequency = ci.hz;
+	buf->frequency = (ci.stathz ? ci.stathz : ci.hz);
 	/* set total */
-	buf->total = cpts [CP_USER] + cpts [CP_NICE]
+	buf->total = cpts [CP_USER] + cpts [CP_NICE] \
 		+ cpts [CP_SYS] + cpts [CP_IDLE] + cpts [CP_INTR];
 
+	ncpu = server->ncpu + 1;
+
+	/*
+	if (!cp_times) {
+		if ((cp_times = calloc(sizeof(int64_t *), ncpu)) == NULL)
+			return;
+	}
+	*/
+
+	length = CPUSTATES * sizeof(int64_t);
+	for (i = 0; i < ncpu; i++) {
+		mib_cptime_s[2] = i;
+		cp_times = g_malloc (length);
+		if (sysctl (mib_cptime_s, 3, cp_times, &length, NULL, 0) < 0)
+			free(cp_times);
+
+		if (cp_times) {
+			buf->xcpu_user[i] = cp_times[CP_USER];
+			buf->xcpu_nice[i] = cp_times[CP_NICE];
+			buf->xcpu_sys[i] = cp_times[CP_SYS];
+			buf->xcpu_idle[i] = cp_times[CP_IDLE];
+			buf->xcpu_irq[i] = cp_times[CP_INTR];
+		} else {
+			buf->xcpu_user[i] = cpts [CP_USER] / ncpu;
+			buf->xcpu_nice[i] = cpts [CP_NICE] / ncpu;
+			buf->xcpu_sys[i] = cpts [CP_SYS] / ncpu;
+			buf->xcpu_idle[i] = cpts [CP_IDLE] / ncpu;
+			buf->xcpu_irq[i] = cpts [CP_INTR] / ncpu;
+		}
+		buf->xcpu_total[i] = buf->xcpu_user[i] + buf->xcpu_nice[i] \
+				     + buf->xcpu_sys[i] + buf->xcpu_idle[i] \
+				     + buf->xcpu_irq[i];
+	}
+
+	g_free (cp_times);
+
 	/* Set the flags last. */
 	buf->flags = _glibtop_sysdeps_cpu;
+
+	if (ncpu > 1) {
+		buf->flags |= _glibtop_sysdeps_cpu_smp;
+	}
 }
