Borrow the code from test/pcpu/cpustat.c to display per-cpu load average on SMP machines.
authorYONETANI Tomokazu <y0netan1@dragonflybsd.org>
Tue, 3 Oct 2006 12:20:11 +0000 (12:20 +0000)
committerYONETANI Tomokazu <y0netan1@dragonflybsd.org>
Tue, 3 Oct 2006 12:20:11 +0000 (12:20 +0000)
contrib/top/display.c
contrib/top/layout.h
contrib/top/machine.h
contrib/top/top.c
contrib/top/top.h
usr.bin/top/machine.c

index 3941abb..6612c11 100644 (file)
@@ -9,7 +9,7 @@
  *  Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
  *
  * $FreeBSD: src/contrib/top/display.c,v 1.4.6.3 2003/04/27 15:32:26 dwmalone Exp $
- * $DragonFly: src/contrib/top/display.c,v 1.2 2003/06/17 04:24:07 dillon Exp $
+ * $DragonFly: src/contrib/top/display.c,v 1.3 2006/10/03 12:20:11 y0netan1 Exp $
  */
 
 /*
@@ -75,7 +75,6 @@ static int num_memory;
 static int num_swap;
 
 static int *lprocstates;
-static int *lcpustates;
 static int *lmemory;
 static int *lswap;
 
@@ -154,7 +153,6 @@ struct statics *statics;
        num_swap = string_count(swap_names);
        lswap = (int *)malloc(num_swap * sizeof(int));
        num_cpustates = string_count(cpustate_names);
-       lcpustates = (int *)malloc(num_cpustates * sizeof(int));
        cpustate_columns = (int *)malloc(num_cpustates * sizeof(int));
 
        memory_names = statics->memory_names;
@@ -372,142 +370,69 @@ int *brkdn;
  *  Assumptions:  cursor is on the PREVIOUS line
  */
 
-static int cpustates_column;
-
-/* cpustates_tag() calculates the correct tag to use to label the line */
-
-char *cpustates_tag()
-
+void
+i_cpustates(struct system_info *si)
 {
-    register char *use;
-
-    static char *short_tag = "CPU: ";
-    static char *long_tag = "CPU states: ";
-
-    /* if length + strlen(long_tag) >= screen_width, then we have to
-       use the shorter tag (we subtract 2 to account for ": ") */
-    if (cpustate_total_length + (int)strlen(long_tag) - 2 >= screen_width)
-    {
-       use = short_tag;
-    }
-    else
-    {
-       use = long_tag;
-    }
-
-    /* set cpustates_column accordingly then return result */
-    cpustates_column = strlen(use);
-    return(use);
-}
-
-i_cpustates(states)
-
-register int *states;
-
-{
-    register int i = 0;
+    register int i;
     register int value;
-    register char **names = cpustate_names;
+    register char **names;
     register char *thisname;
+    int *states = si->cpustates;
+    int cpu;
 
     /* print tag and bump lastline */
-    printf("\n%s", cpustates_tag());
-    lastline++;
-
-    /* now walk thru the names and print the line */
-    while ((thisname = *names++) != NULL)
-    {
-       if (*thisname != '\0')
-       {
-           /* retrieve the value and remember it */
-           value = *states++;
-
-           /* if percentage is >= 1000, print it as 100% */
-           printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
-                  i++ == 0 ? "" : ", ",
-                  ((float)value)/10.,
-                  thisname);
-       }
-    }
-
-    /* copy over values into "last" array */
-    memcpy(lcpustates, states, num_cpustates * sizeof(int));
-}
-
-u_cpustates(states)
-
-register int *states;
-
-{
-    register int value;
-    register char **names = cpustate_names;
-    register char *thisname;
-    register int *lp;
-    register int *colp;
-
-    Move_to(cpustates_column, y_cpustates);
-    lastline = y_cpustates;
-    lp = lcpustates;
-    colp = cpustate_columns;
+    for (cpu = 0; cpu < n_cpus; ++cpu) {
+       if (n_cpus > 1)
+           printf("\nCPU%d states: ", cpu);
+       else
+           printf("\nCPU states: ");
+       lastline++;
 
-    /* we could be much more optimal about this */
-    while ((thisname = *names++) != NULL)
-    {
-       if (*thisname != '\0')
+       /* now walk thru the names and print the line */
+       names = cpustate_names;
+       i = 0;
+       while ((thisname = *names++) != NULL)
        {
-           /* did the value change since last time? */
-           if (*lp != *states)
+           if (*thisname != '\0')
            {
-               /* yes, move and change */
-               Move_to(cpustates_column + *colp, y_cpustates);
-               lastline = y_cpustates;
-
-               /* retrieve value and remember it */
-               value = *states;
-
+               /* retrieve the value and remember it */
+               value = *states++;
                /* if percentage is >= 1000, print it as 100% */
-               printf((value >= 1000 ? "%4.0f" : "%4.1f"),
-                      ((double)value)/10.);
-
-               /* remember it for next time */
-               *lp = value;
+               printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
+                      i++ == 0 ? "" : ", ",
+                      ((float)value)/10.,
+                      thisname);
            }
        }
-
-       /* increment and move on */
-       lp++;
-       states++;
-       colp++;
     }
 }
 
-z_cpustates()
-
+void
+z_cpustates(struct system_info *si)
 {
-    register int i = 0;
-    register char **names = cpustate_names;
+    register int i;
+    register char **names;
     register char *thisname;
-    register int *lp;
+    int cpu;
 
     /* show tag and bump lastline */
-    printf("\n%s", cpustates_tag());
-    lastline++;
+    for (cpu = 0; cpu < n_cpus; ++cpu) {
+       if (n_cpus > 1)
+           printf("\nCPU%d states: ", cpu);
+       else
+           printf("\nCPU states: ");
+       lastline++;
 
-    while ((thisname = *names++) != NULL)
-    {
-       if (*thisname != '\0')
+       i = 0;
+       names = cpustate_names;
+       while ((thisname = *names++) != NULL)
        {
-           printf("%s    %% %s", i++ == 0 ? "" : ", ", thisname);
+           if (*thisname != '\0')
+           {
+               printf("%s    %% %s", i++ == 0 ? "" : ", ", thisname);
+           }
        }
     }
-
-    /* fill the "last" array with all -1s, to insure correct updating */
-    lp = lcpustates;
-    i = num_cpustates;
-    while (--i >= 0)
-    {
-       *lp++ = -1;
-    }
 }
 
 /*
index 5db383f..0faa8d5 100644 (file)
 #define  x_brkdn       15
 #define  y_brkdn       1
 #define  x_mem         5
-#define  y_mem         3
+#define  y_mem         (y_cpustates+(smart_terminal?n_cpus:1))
 #define  x_swap                6
-#define  y_swap                4
-#define  y_message     5
+#define  y_swap                (y_mem+1)
+#define  y_message     (y_swap+1)
 #define  x_header      0
-#define  y_header      6
+#define  y_header      (y_message+1)
 #define  x_idlecursor  0
-#define  y_idlecursor  5
-#define  y_procs       7
+#define  y_idlecursor  (y_message)
+#define  y_procs       (y_header+1)
 
 #define  y_cpustates   2
index a6bd646..04eeefa 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * $FreeBSD: src/contrib/top/machine.h,v 1.4.6.1 2002/08/11 17:09:25 dwmalone Exp $
- * $DragonFly: src/contrib/top/machine.h,v 1.3 2006/02/15 12:54:36 corecode Exp $
+ * $DragonFly: src/contrib/top/machine.h,v 1.4 2006/10/03 12:20:11 y0netan1 Exp $
  */
 
 /*
@@ -33,6 +33,7 @@ struct statics
 #define P_ACTIVE p_active
 #endif
 
+/* CPU1 states follow those of CPU0, and so on for SMP */
 struct system_info
 {
     int    last_pid;
index 44cbca7..32cc2c8 100644 (file)
@@ -14,7 +14,7 @@ char *copyright =
  *  Copyright (c) 1996, William LeFebvre, Group sys Consulting
  *
  * $FreeBSD: src/contrib/top/top.c,v 1.4.6.5 2002/08/11 17:09:25 dwmalone Exp $
- * $DragonFly: src/contrib/top/top.c,v 1.3 2006/02/15 12:54:36 corecode Exp $
+ * $DragonFly: src/contrib/top/top.c,v 1.4 2006/10/03 12:20:11 y0netan1 Exp $
  */
 
 /*
@@ -114,8 +114,8 @@ int i_loadave();
 int u_loadave();
 int i_procstates();
 int u_procstates();
-int i_cpustates();
-int u_cpustates();
+int i_cpustates(struct system_info *);
+int u_cpustates(struct system_info *);
 int i_memory();
 int u_memory();
 int i_swap();
@@ -130,13 +130,14 @@ int u_process();
 /* pointers to display routines */
 int (*d_loadave)() = i_loadave;
 int (*d_procstates)() = i_procstates;
-int (*d_cpustates)() = i_cpustates;
+int (*d_cpustates)(struct system_info *) = i_cpustates;
 int (*d_memory)() = i_memory;
 int (*d_swap)() = i_swap;
 int (*d_message)() = i_message;
 int (*d_header)() = i_header;
 int (*d_process)() = i_process;
 
+int n_cpus = 0;
 
 main(argc, argv)
 
@@ -583,14 +584,14 @@ restart:
        /* display the cpu state percentage breakdown */
        if (dostates)   /* but not the first time */
        {
-           (*d_cpustates)(system_info.cpustates);
+           (*d_cpustates)(&system_info);
        }
        else
        {
            /* we'll do it next time */
            if (smart_terminal)
            {
-               z_cpustates();
+               z_cpustates(&system_info);
            }
            else
            {
@@ -663,7 +664,7 @@ restart:
                {
                    d_loadave = u_loadave;
                    d_procstates = u_procstates;
-                   d_cpustates = u_cpustates;
+                   d_cpustates = i_cpustates;
                    d_memory = u_memory;
                    d_swap = u_swap;
                    d_message = u_message;
index c0b48e7..d979b70 100644 (file)
@@ -8,7 +8,8 @@
 #define VERSION                3
 
 /* Number of lines of header information on the standard screen */
-#define Header_lines   7
+#define Header_lines   (7 + n_cpus - 1)
+extern int n_cpus;
 
 /* Maximum number of columns allowed for display */
 #define MAX_COLS       128
index fefa0f4..f960c2b 100644 (file)
@@ -21,7 +21,7 @@
  *          Hiten Pandya <hmp@backplane.com>
  *
  * $FreeBSD: src/usr.bin/top/machine.c,v 1.29.2.2 2001/07/31 20:27:05 tmm Exp $
- * $DragonFly: src/usr.bin/top/machine.c,v 1.18 2005/11/14 18:50:18 dillon Exp $
+ * $DragonFly: src/usr.bin/top/machine.c,v 1.19 2006/10/03 12:20:11 y0netan1 Exp $
  */
 
 
@@ -133,7 +133,7 @@ static int ccpu;
 
 /* these are for calculating cpu state percentages */
 
-static struct kinfo_cputime cp_time, cp_old;
+static struct kinfo_cputime *cp_time, *cp_old;
 
 /* these are for detailing the process states */
 
@@ -146,7 +146,7 @@ char *procstatenames[] = {
 
 /* these are for detailing the cpu states */
 #define CPU_STATES 5
-int cpu_states[CPU_STATES];
+int *cpu_states;
 char *cpustatenames[CPU_STATES + 1] = {
     "user", "nice", "system", "interrupt", "idle", NULL
 };
@@ -195,7 +195,6 @@ cputime_percentages(int out[CPU_STATES], struct kinfo_cputime *new,
                    struct kinfo_cputime *old)
 {
         struct kinfo_cputime diffs;
-        int i;
        uint64_t total_change, half_total;
 
         /* initialization */
@@ -236,6 +235,10 @@ machine_init(struct statics *statics)
     size_t modelen;
     struct passwd *pw;
 
+    if (n_cpus < 1) {
+       if (kinfo_get_cpus(&n_cpus))
+           err(1, "kinfo_get_cpus failed");
+    }
     modelen = sizeof(smpmode);
     if ((sysctlbyname("machdep.smp_active", &smpmode, &modelen, NULL, 0) < 0 &&
          sysctlbyname("smp.smp_active", &smpmode, &modelen, NULL, 0) < 0) ||
@@ -322,16 +325,41 @@ get_system_info(struct system_info *si)
     int mib[2];
     struct timeval boottime;
     size_t bt_size;
+    size_t len;
+    int cpu;
+
+    if (cpu_states == NULL) {
+       cpu_states = malloc(sizeof(*cpu_states) * CPU_STATES * n_cpus);
+       if (cpu_states == NULL)
+           err(1, "malloc");
+       bzero(cpu_states, sizeof(*cpu_states) * CPU_STATES * n_cpus);
+    }
+    if (cp_time == NULL) {
+       cp_time = malloc(2 * n_cpus * sizeof(cp_time[0]));
+       if (cp_time == NULL)
+           err(1, "cp_time");
+       cp_old = cp_time + n_cpus;
+
+       len = n_cpus * sizeof(cp_old[0]);
+       bzero(cp_time, len);
+       if (sysctlbyname("kern.cputime", cp_old, &len, NULL, 0))
+           err(1, "kern.cputime");
+    }
 
-    if (kinfo_get_sched_cputime(&cp_time))
-       err(1, "kinfo_get_sched_cputime failed");
+    len = n_cpus * sizeof(cp_time[0]);
+    bzero(cp_time, len);
+    if (sysctlbyname("kern.cputime", cp_time, &len, NULL, 0))
+       err(1, "kern.cputime");
 
     getloadavg(si->load_avg, 3);
 
     lastpid = 0;
 
     /* convert cp_time counts to percentages */
-    cputime_percentages(cpu_states, &cp_time, &cp_old);
+    for (cpu = 0; cpu < n_cpus; ++cpu) {
+       cputime_percentages(cpu_states + cpu * CPU_STATES,
+                           &cp_time[cpu], &cp_old[cpu]);
+    }
 
     /* sum memory & swap statistics */
     {