aboutsummaryrefslogtreecommitdiff
path: root/usr.bin/top/machine.c
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2008-01-18 01:43:14 +0000
committerPeter Wemm <peter@FreeBSD.org>2008-01-18 01:43:14 +0000
commit031175705e680c9646cd915cea2f4f4436dbf1a5 (patch)
tree75cd88d63d25954bc6c8db1fe30b1e7fa9322f7e /usr.bin/top/machine.c
parent905925d349a2ac1a70db39cd6de88d7f66f690cc (diff)
downloadsrc-031175705e680c9646cd915cea2f4f4436dbf1a5.tar.gz
src-031175705e680c9646cd915cea2f4f4436dbf1a5.zip
Add a -P flag to display per-cpu cpu usage stats.
Notes
Notes: svn path=/head/; revision=175420
Diffstat (limited to 'usr.bin/top/machine.c')
-rw-r--r--usr.bin/top/machine.c100
1 files changed, 95 insertions, 5 deletions
diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c
index d6fa14c04286..5e7579b46467 100644
--- a/usr.bin/top/machine.c
+++ b/usr.bin/top/machine.c
@@ -51,6 +51,7 @@
#include "machine.h"
#include "screen.h"
#include "utils.h"
+#include "layout.h"
#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
#define SMPUNAMELEN 13
@@ -220,6 +221,17 @@ char *ordernames[] = {
};
#endif
+/* Per-cpu time states */
+static int maxcpu;
+static int maxid;
+static int ncpus;
+static u_long cpumask;
+static long *times;
+static long *pcpu_cp_time;
+static long *pcpu_cp_old;
+static long *pcpu_cp_diff;
+static int *pcpu_cpu_states;
+
static int compare_jid(const void *a, const void *b);
static int compare_pid(const void *a, const void *b);
static const char *format_nice(const struct kinfo_proc *pp);
@@ -286,6 +298,56 @@ machine_init(struct statics *statics, char do_unames)
statics->order_names = ordernames;
#endif
+ /* Adjust display based on ncpus */
+ if (pcpu_stats) {
+ int i, j, empty;
+ size_t size;
+
+ cpumask = 0;
+ ncpus = 0;
+ GETSYSCTL("kern.smp.maxcpus", maxcpu);
+ size = sizeof(long) * maxcpu * CPUSTATES;
+ times = malloc(size);
+ if (times == NULL)
+ err(1, "malloc %zd bytes", size);
+ if (sysctlbyname("kern.cp_times", times, &size, NULL, 0) == -1)
+ err(1, "sysctlbyname kern.cp_times");
+ maxid = (size / CPUSTATES / sizeof(long)) - 1;
+ for (i = 0; i <= maxid; i++) {
+ empty = 1;
+ for (j = 0; empty && j < CPUSTATES; j++) {
+ if (times[i * CPUSTATES + j] != 0)
+ empty = 0;
+ }
+ if (!empty) {
+ cpumask |= (1ul << i);
+ ncpus++;
+ }
+ }
+
+ if (ncpus > 1) {
+ y_mem += ncpus - 1; /* 3 */
+ y_swap += ncpus - 1; /* 4 */
+ y_idlecursor += ncpus - 1; /* 5 */
+ y_message += ncpus - 1; /* 5 */
+ y_header += ncpus - 1; /* 6 */
+ y_procs += ncpus - 1; /* 7 */
+ Header_lines += ncpus - 1; /* 7 */
+ }
+ size = sizeof(long) * ncpus * CPUSTATES;
+ pcpu_cp_time = malloc(size);
+ pcpu_cp_old = malloc(size);
+ pcpu_cp_diff = malloc(size);
+ pcpu_cpu_states = malloc(size);
+ bzero(pcpu_cp_time, size);
+ bzero(pcpu_cp_old, size);
+ bzero(pcpu_cp_diff, size);
+ bzero(pcpu_cpu_states, size);
+ statics->ncpus = ncpus;
+ } else {
+ statics->ncpus = 1;
+ }
+
/* all done! */
return (0);
}
@@ -327,6 +389,7 @@ static int swappgsin = -1;
static int swappgsout = -1;
extern struct timeval timeout;
+
void
get_system_info(struct system_info *si)
{
@@ -335,10 +398,17 @@ get_system_info(struct system_info *si)
int mib[2];
struct timeval boottime;
size_t bt_size;
- int i;
+ int i, j;
+ size_t size;
/* get the cp_time array */
- GETSYSCTL("kern.cp_time", cp_time);
+ if (pcpu_stats) {
+ size = (maxid + 1) * CPUSTATES * sizeof(long);
+ if (sysctlbyname("kern.cp_times", pcpu_cp_time, &size, NULL, 0) == -1)
+ err(1, "sysctlbyname kern.cp_times");
+ } else {
+ GETSYSCTL("kern.cp_time", cp_time);
+ }
GETSYSCTL("vm.loadavg", sysload);
GETSYSCTL("kern.lastpid", lastpid);
@@ -346,8 +416,20 @@ get_system_info(struct system_info *si)
for (i = 0; i < 3; i++)
si->load_avg[i] = (double)sysload.ldavg[i] / sysload.fscale;
- /* convert cp_time counts to percentages */
- total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
+ if (pcpu_stats) {
+ for (i = j = 0; i <= maxid; i++, j++) {
+ if (cpumask && (1ul << i) == 0)
+ continue;
+ /* convert cp_time counts to percentages */
+ percentages(CPUSTATES, &pcpu_cpu_states[j * CPUSTATES],
+ &pcpu_cp_time[j * CPUSTATES],
+ &pcpu_cp_old[j * CPUSTATES],
+ &pcpu_cp_diff[j * CPUSTATES]);
+ }
+ } else {
+ /* convert cp_time counts to percentages */
+ percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
+ }
/* sum memory & swap statistics */
{
@@ -401,7 +483,15 @@ get_system_info(struct system_info *si)
}
/* set arrays and strings */
- si->cpustates = cpu_states;
+ if (pcpu_stats) {
+ si->cpustates = pcpu_cpu_states;
+ si->cpumask = cpumask;
+ si->ncpus = ncpus;
+ } else {
+ si->cpustates = cpu_states;
+ si->cpumask = 1;
+ si->ncpus = 1;
+ }
si->memory = memory_stats;
si->swap = swap_stats;