From: YONETANI Tomokazu Date: Tue, 3 Oct 2006 12:20:11 +0000 (+0000) Subject: Borrow the code from test/pcpu/cpustat.c to display per-cpu load average on SMP machines. X-Git-Tag: v2.0.1~4310 X-Git-Url: https://gitweb.dragonflybsd.org/~nant/dragonfly.git/commitdiff_plain/edb881dd7448eebfcd7f90bdfd77cee0f16d5866 Borrow the code from test/pcpu/cpustat.c to display per-cpu load average on SMP machines. --- diff --git a/contrib/top/display.c b/contrib/top/display.c index 3941abb8c7..6612c11b61 100644 --- a/contrib/top/display.c +++ b/contrib/top/display.c @@ -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; - } } /* diff --git a/contrib/top/layout.h b/contrib/top/layout.h index 5db383f87e..0faa8d5a4e 100644 --- a/contrib/top/layout.h +++ b/contrib/top/layout.h @@ -16,14 +16,14 @@ #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 diff --git a/contrib/top/machine.h b/contrib/top/machine.h index a6bd646648..04eeefad1d 100644 --- a/contrib/top/machine.h +++ b/contrib/top/machine.h @@ -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; diff --git a/contrib/top/top.c b/contrib/top/top.c index 44cbca7657..32cc2c8bca 100644 --- a/contrib/top/top.c +++ b/contrib/top/top.c @@ -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; diff --git a/contrib/top/top.h b/contrib/top/top.h index c0b48e79ad..d979b70b4a 100644 --- a/contrib/top/top.h +++ b/contrib/top/top.h @@ -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 diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c index fefa0f4c70..f960c2b32e 100644 --- a/usr.bin/top/machine.c +++ b/usr.bin/top/machine.c @@ -21,7 +21,7 @@ * Hiten Pandya * * $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 */ {