diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2005-06-08 22:36:44 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2005-06-08 22:36:44 +0000 |
commit | d8d35b90679f0c4c39638afa56d4dfa1a14f0cd4 (patch) | |
tree | 2da4281c272a7fe88962c1caba31e6b562de1a09 /usr.bin | |
parent | 09fc260787b747e5484efa3b2527d23b187115f3 (diff) |
Multi-cpu support for top. Each cpu now gets its own stats line.
Based on work by todd@ at the hackathon.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/top/display.c | 244 | ||||
-rw-r--r-- | usr.bin/top/display.h | 6 | ||||
-rw-r--r-- | usr.bin/top/layout.h | 12 | ||||
-rw-r--r-- | usr.bin/top/machine.c | 63 | ||||
-rw-r--r-- | usr.bin/top/machine.h | 4 | ||||
-rw-r--r-- | usr.bin/top/top.c | 5 | ||||
-rw-r--r-- | usr.bin/top/top.h | 10 | ||||
-rw-r--r-- | usr.bin/top/utils.c | 15 | ||||
-rw-r--r-- | usr.bin/top/utils.h | 4 |
9 files changed, 238 insertions, 125 deletions
diff --git a/usr.bin/top/display.c b/usr.bin/top/display.c index f5d1e289c77..a652d300708 100644 --- a/usr.bin/top/display.c +++ b/usr.bin/top/display.c @@ -1,4 +1,4 @@ -/* $OpenBSD: display.c,v 1.19 2005/04/13 02:33:09 deraadt Exp $ */ +/* $OpenBSD: display.c,v 1.20 2005/06/08 22:36:43 millert Exp $ */ /* * Top users/processes display for Unix @@ -46,8 +46,11 @@ */ #include <sys/types.h> +#include <sys/time.h> +#include <sys/sched.h> #include <stdio.h> #include <ctype.h> +#include <err.h> #include <stdlib.h> #include <string.h> #include <signal.h> @@ -74,7 +77,7 @@ static int last_hi = 0; /* used in u_process and u_endscreen */ static int lastline = 0; static int display_width = MAX_COLS; -static char *cpustates_tag(void); +static char *cpustates_tag(int); static int string_count(char **); static void summary_format(char *, size_t, int *, char **); static void line_update(char *, char *, int, int); @@ -94,11 +97,20 @@ static int num_procstates; static int num_cpustates; static int *lprocstates; -static int *lcpustates; +static int64_t **lcpustates; static int *cpustate_columns; static int cpustate_total_length; +/* display ips */ +int y_mem; +int y_message; +int y_header; +int y_idlecursor; +int y_procs; +extern int ncpu; +int Header_lines; + static enum { OFF, ON, ERASE } header_status = ON; @@ -126,8 +138,8 @@ display_resize(void) display_width = MAX_COLS - 1; /* now, allocate space for the screen buffer */ - screenbuf = (char *) malloc(display_lines * display_width); - if (screenbuf == (char *) NULL) + screenbuf = malloc(display_lines * display_width); + if (screenbuf == NULL) return (-1); /* return number of lines available */ @@ -138,9 +150,16 @@ display_resize(void) int display_init(struct statics * statics) { - int display_lines, *ip, i; + int display_lines, *ip, i, cpu; char **pp; + y_mem = 2 + ncpu; + y_message = 3 + ncpu; + y_header = 4 + ncpu; + y_idlecursor = 3 + ncpu; + y_procs = 5 + ncpu; + Header_lines = 5 + ncpu; + /* call resize to do the dirty work */ display_lines = display_resize(); @@ -149,12 +168,24 @@ display_init(struct statics * statics) /* save pointers and allocate space for names */ procstate_names = statics->procstate_names; num_procstates = string_count(procstate_names); - lprocstates = (int *) malloc(num_procstates * sizeof(int)); + lprocstates = malloc(num_procstates * sizeof(int)); + if (lprocstates == NULL) + err(1, NULL); cpustate_names = statics->cpustate_names; num_cpustates = string_count(cpustate_names); - lcpustates = (int *) malloc(num_cpustates * sizeof(int)); - cpustate_columns = (int *) malloc(num_cpustates * sizeof(int)); + lcpustates = malloc(ncpu * sizeof(int64_t *)); + if (lcpustates == NULL) + err(1, NULL); + for (cpu = 0; cpu < ncpu; cpu++) { + lcpustates[cpu] = malloc(num_cpustates * sizeof(int64_t)); + if (lcpustates[cpu] == NULL) + err(1, NULL); + } + + cpustate_columns = malloc(num_cpustates * sizeof(int)); + if (cpustate_columns == NULL) + err(1, NULL); memory_names = statics->memory_names; @@ -339,112 +370,149 @@ static int cpustates_column; /* cpustates_tag() calculates the correct tag to use to label the line */ static char * -cpustates_tag(void) +cpustates_tag(int cpu) { - static char *short_tag = "CPU: "; - static char *long_tag = "CPU states: "; - char *use; + static char *tag; + static int cpulen, old_width; + int i; - /* - * 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); + if (cpulen == 0 && ncpu > 1) { + /* compute length of the cpu string */ + for (i = ncpu; i > 0; cpulen++, i /= 10) + continue; + } + + if (old_width == screen_width) { + if (ncpu > 1) { + /* just store the cpu number in the tag */ + i = tag[3 + cpulen]; + snprintf(tag + 3, cpulen + 1, "%.*d", cpulen, cpu); + tag[3 + cpulen] = i; + } + } else { + /* + * use a long tag if it will fit, otherwise use short one. + */ + free(tag); + if (cpustate_total_length + 10 + cpulen >= screen_width) + i = asprintf(&tag, "CPU%.*d: ", cpulen, cpu); + else + i = asprintf(&tag, "CPU%.*d states: ", cpulen, cpu); + if (i == -1) + tag = NULL; + else { + cpustates_column = strlen(tag); + old_width = screen_width; + } + } + return (tag); } void -i_cpustates(int *states) +i_cpustates(int64_t *ostates) { - int i = 0, value; + int i, cpu, value; + int64_t *states; char **names = cpustate_names, *thisname; - /* print tag and bump lastline */ - printf("\n%s", cpustates_tag()); - lastline++; + for (cpu = 0; cpu < ncpu; cpu++) { + /* print tag and bump lastline */ + printf("\n%s", cpustates_tag(cpu)); + 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); + /* now walk thru the names and print the line */ + names = cpustate_names; + i = 0; + states = ostates + (CPUSTATES * cpu); + 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)); + /* copy over values into "last" array */ + memcpy(lcpustates[cpu], ostates, num_cpustates * sizeof(int64_t)); + } } void -u_cpustates(int *states) +u_cpustates(int64_t *ostates) { - char **names = cpustate_names, *thisname; - int value, *lp, *colp; - - Move_to(cpustates_column, y_cpustates); - lastline = y_cpustates; - lp = lcpustates; - colp = cpustate_columns; - - /* we could be much more optimal about this */ - while ((thisname = *names++) != NULL) { - if (*thisname != '\0') { - /* did the value change since last time? */ - if (*lp != *states) { - /* yes, move and change */ - Move_to(cpustates_column + *colp, y_cpustates); - lastline = y_cpustates; - - /* retrieve value and remember it */ - value = *states; - - /* if percentage is >= 1000, print it as 100% */ - printf((value >= 1000 ? "%4.0f" : "%4.1f"), - ((double) value) / 10.); + char **names, *thisname; + int cpu, value, *colp; + int64_t *lp, *states; + + for (cpu = 0; cpu < ncpu; cpu++) { + lastline = y_cpustates + cpu; + states = ostates + (CPUSTATES * cpu); + Move_to(cpustates_column, lastline); + lp = lcpustates[cpu]; + colp = cpustate_columns; + + /* we could be much more optimal about this */ + names = cpustate_names; + while ((thisname = *names++) != NULL) { + if (*thisname != '\0') { + /* did the value change since last time? */ + if (*lp != *states) { + /* yes, move and change */ + lastline = y_cpustates + cpu; + Move_to(cpustates_column + *colp, + lastline); + + /* retrieve 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 = *states; + /* remember it for next time */ + *lp = *states; + } } + /* increment and move on */ + lp++; + states++; + colp++; } - /* increment and move on */ - lp++; - states++; - colp++; } } void z_cpustates(void) { - char **names = cpustate_names, *thisname; - int i = 0, *lp; + char **names, *thisname; + int cpu, i; + int64_t *lp; - /* show tag and bump lastline */ - printf("\n%s", cpustates_tag()); - lastline++; + for (cpu = 0; cpu < ncpu; cpu++) { + /* show tag and bump lastline */ + printf("\n%s", cpustates_tag(cpu)); + lastline++; - while ((thisname = *names++) != NULL) { - if (*thisname != '\0') - printf("%s %% %s", i++ == 0 ? "" : ", ", thisname); - } + names = cpustate_names; + i = 0; + while ((thisname = *names++) != NULL) { + 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; + /* fill the "last" array with all -1s, to ensure correct updating */ + lp = lcpustates[cpu]; + i = num_cpustates; + while (--i >= 0) + *lp++ = -1; + } } static char memory_buffer[MAX_COLS]; diff --git a/usr.bin/top/display.h b/usr.bin/top/display.h index 532e27c6fa3..643efecc3e3 100644 --- a/usr.bin/top/display.h +++ b/usr.bin/top/display.h @@ -1,4 +1,4 @@ -/* $OpenBSD: display.h,v 1.6 2003/06/13 04:29:59 pvalchev Exp $ */ +/* $OpenBSD: display.h,v 1.7 2005/06/08 22:36:43 millert Exp $ */ /* * Top users/processes display for Unix @@ -40,8 +40,8 @@ extern void u_loadave(int, double *); extern void i_timeofday(time_t *); extern void i_procstates(int, int *); extern void u_procstates(int, int *); -extern void i_cpustates(int *); -extern void u_cpustates(int *); +extern void i_cpustates(int64_t *); +extern void u_cpustates(int64_t *); extern void z_cpustates(void); extern void i_memory(int *); extern void u_memory(int *); diff --git a/usr.bin/top/layout.h b/usr.bin/top/layout.h index 5b91271d32f..c3e1264ef0f 100644 --- a/usr.bin/top/layout.h +++ b/usr.bin/top/layout.h @@ -1,4 +1,4 @@ -/* $OpenBSD: layout.h,v 1.2 2002/07/15 17:20:36 deraadt Exp $ */ +/* $OpenBSD: layout.h,v 1.3 2005/06/08 22:36:43 millert Exp $ */ /* * Top users/processes display for Unix @@ -46,12 +46,12 @@ #define x_brkdn 15 #define y_brkdn 1 #define x_mem 8 -#define y_mem 3 -#define y_message 4 +extern int y_mem; +extern int y_message; #define x_header 0 -#define y_header 5 +extern int y_header; #define x_idlecursor 0 -#define y_idlecursor 4 -#define y_procs 6 +extern int y_idlecursor; +extern int y_procs; #define y_cpustates 2 diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c index 0cb2d9a9065..1950a27a706 100644 --- a/usr.bin/top/machine.c +++ b/usr.bin/top/machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machine.c,v 1.47 2004/12/06 15:57:04 markus Exp $ */ +/* $OpenBSD: machine.c,v 1.48 2005/06/08 22:36:43 millert Exp $ */ /*- * Copyright (c) 1994 Thorsten Lockert <tholo@sigmasoft.com> @@ -96,9 +96,9 @@ char *state_abbrev[] = { static int stathz; /* these are for calculating cpu state percentages */ -static long cp_time[CPUSTATES]; -static long cp_old[CPUSTATES]; -static long cp_diff[CPUSTATES]; +static int64_t **cp_time; +static int64_t **cp_old; +static int64_t **cp_diff; /* these are for detailing the process states */ int process_states[8]; @@ -109,7 +109,7 @@ char *procstatenames[] = { }; /* these are for detailing the cpu states */ -int cpu_states[CPUSTATES]; +int64_t *cpu_states; char *cpustatenames[] = { "user", "nice", "system", "interrupt", "idle", NULL }; @@ -162,12 +162,28 @@ int machine_init(struct statics *statics) { size_t size = sizeof(ncpu); - int mib[2], pagesize; + int mib[2], pagesize, cpu; mib[0] = CTL_HW; mib[1] = HW_NCPU; if (sysctl(mib, 2, &ncpu, &size, NULL, 0) == -1) return (-1); + cpu_states = malloc(ncpu * CPUSTATES * sizeof(int64_t)); + if (cpu_states == NULL) + err(1, NULL); + cp_time = malloc(ncpu * sizeof(int64_t *)); + cp_old = malloc(ncpu * sizeof(int64_t *)); + cp_diff = malloc(ncpu * sizeof(int64_t *)); + if (cp_time == NULL || cp_old == NULL || cp_diff == NULL) + err(1, NULL); + for (cpu = 0; cpu < ncpu; cpu++) { + cp_time[cpu] = malloc(CPUSTATES * sizeof(int64_t)); + cp_old[cpu] = malloc(CPUSTATES * sizeof(int64_t)); + cp_diff[cpu] = malloc(CPUSTATES * sizeof(int64_t)); + if (cp_time[cpu] == NULL || cp_old[cpu] == NULL || + cp_diff[cpu] == NULL) + err(1, NULL); + } stathz = getstathz(); if (stathz == -1) @@ -216,16 +232,37 @@ get_system_info(struct system_info *si) { static int sysload_mib[] = {CTL_VM, VM_LOADAVG}; static int vmtotal_mib[] = {CTL_VM, VM_METER}; - static int cp_time_mib[] = {CTL_KERN, KERN_CPTIME}; struct loadavg sysload; struct vmtotal vmtotal; double *infoloadp; size_t size; int i; - - size = sizeof(cp_time); - if (sysctl(cp_time_mib, 2, &cp_time, &size, NULL, 0) < 0) - warn("sysctl kern.cp_time failed"); + int64_t *tmpstate; + + if (ncpu > 1) { + size = CPUSTATES * sizeof(int64_t); + for (i = 0; i < ncpu; i++) { + int cp_time_mib[] = {CTL_KERN, KERN_CPTIME2, i}; + tmpstate = cpu_states + (CPUSTATES * i); + if (sysctl(cp_time_mib, 3, cp_time[i], &size, NULL, 0) < 0) + warn("sysctl kern.cp_time2 failed"); + /* convert cp_time2 counts to percentages */ + (void) percentages(CPUSTATES, tmpstate, cp_time[i], + cp_old[i], cp_diff[i]); + } + } else { + int cp_time_mib[] = {CTL_KERN, KERN_CPTIME}; + long cp_time_tmp[CPUSTATES]; + + size = sizeof(cp_time_tmp); + if (sysctl(cp_time_mib, 2, cp_time_tmp, &size, NULL, 0) < 0) + warn("sysctl kern.cp_time failed"); + for (i = 0; i < CPUSTATES; i++) + cp_time[0][i] = cp_time_tmp[i]; + /* convert cp_time counts to percentages */ + (void) percentages(CPUSTATES, cpu_states, cp_time[0], + cp_old[0], cp_diff[0]); + } size = sizeof(sysload); if (sysctl(sysload_mib, 2, &sysload, &size, NULL, 0) < 0) @@ -234,8 +271,6 @@ get_system_info(struct system_info *si) for (i = 0; i < 3; i++) *infoloadp++ = ((double) sysload.ldavg[i]) / sysload.fscale; - /* convert cp_time counts to percentages */ - (void) percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff); /* get total -- systemwide main memory usage structure */ size = sizeof(vmtotal); @@ -380,7 +415,7 @@ state_abbr(struct kinfo_proc2 *pp) static char buf[10]; if (ncpu > 1 && pp->p_cpuid != KI_NOCPU) - snprintf(buf, sizeof buf, "%s/%d", + snprintf(buf, sizeof buf, "%s/%llu", state_abbrev[(unsigned char)pp->p_stat], pp->p_cpuid); else snprintf(buf, sizeof buf, "%s", diff --git a/usr.bin/top/machine.h b/usr.bin/top/machine.h index 5a7adc8097c..4a7243cb108 100644 --- a/usr.bin/top/machine.h +++ b/usr.bin/top/machine.h @@ -1,4 +1,4 @@ -/* $OpenBSD: machine.h,v 1.12 2004/10/07 06:26:12 otto Exp $ */ +/* $OpenBSD: machine.h,v 1.13 2005/06/08 22:36:43 millert Exp $ */ /* * Top users/processes display for Unix @@ -55,7 +55,7 @@ struct system_info { int p_active; /* number of procs considered * "active" */ int *procstates; - int *cpustates; + int64_t *cpustates; int *memory; }; diff --git a/usr.bin/top/top.c b/usr.bin/top/top.c index 1c4be009ecb..e0cb26faec9 100644 --- a/usr.bin/top/top.c +++ b/usr.bin/top/top.c @@ -1,4 +1,4 @@ -/* $OpenBSD: top.c,v 1.38 2005/05/14 09:03:31 jmc Exp $ */ +/* $OpenBSD: top.c,v 1.39 2005/06/08 22:36:43 millert Exp $ */ /* * Top users/processes display for Unix @@ -42,6 +42,7 @@ const char copyright[] = "Copyright (c) 1984 through 1996, William LeFebvre"; #include <stdlib.h> #include <limits.h> #include <unistd.h> +#include <sys/stat.h> /* includes specific to top */ #include "display.h" /* interface to display package */ @@ -79,7 +80,7 @@ int order_index; /* pointers to display routines */ void (*d_loadave)(int, double *) = i_loadave; void (*d_procstates)(int, int *) = i_procstates; -void (*d_cpustates)(int *) = i_cpustates; +void (*d_cpustates)(int64_t *) = i_cpustates; void (*d_memory)(int *) = i_memory; void (*d_message)(void) = i_message; void (*d_header)(char *) = i_header; diff --git a/usr.bin/top/top.h b/usr.bin/top/top.h index d99393704e5..b2165b35200 100644 --- a/usr.bin/top/top.h +++ b/usr.bin/top/top.h @@ -1,4 +1,4 @@ -/* $OpenBSD: top.h,v 1.5 2003/06/13 21:52:25 deraadt Exp $ */ +/* $OpenBSD: top.h,v 1.6 2005/06/08 22:36:43 millert Exp $ */ /* * Top users/processes display for Unix @@ -40,7 +40,7 @@ #define VERSION 3 /* Number of lines of header information on the standard screen */ -#define Header_lines 6 +extern int Header_lines; /* Maximum number of columns allowed for display */ #define MAX_COLS 128 @@ -82,3 +82,9 @@ extern uid_t userid(char *); /* version.c */ extern char *version_string(void); +extern int y_mem; +extern int y_message; +extern int y_header; +extern int y_idlecursor; +extern int y_procs; +extern int num_CPUS; diff --git a/usr.bin/top/utils.c b/usr.bin/top/utils.c index 17cf3576243..38e4dd5577b 100644 --- a/usr.bin/top/utils.c +++ b/usr.bin/top/utils.c @@ -1,4 +1,4 @@ -/* $OpenBSD: utils.c,v 1.15 2004/11/22 15:26:53 pat Exp $ */ +/* $OpenBSD: utils.c,v 1.16 2005/06/08 22:36:43 millert Exp $ */ /* * Top users/processes display for Unix @@ -34,6 +34,7 @@ #include <sys/param.h> #include <sys/sysctl.h> +#include <err.h> #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -162,10 +163,12 @@ argparse(char *line, int *cntp) cnt += 3; /* allocate a char * array to hold the pointers */ - argarray = (char **) malloc(cnt * sizeof(char *)); + if ((argarray = malloc(cnt * sizeof(char *))) == NULL) + err(1, NULL); /* allocate another array to hold the strings themselves */ - args = (char *) malloc(length + 2); + if ((args = malloc(length + 2)) == NULL) + err(1, NULL); /* initialization for main loop */ from = line; @@ -207,9 +210,9 @@ argparse(char *line, int *cntp) * useful on BSD mchines for calculating cpu state percentages. */ int -percentages(int cnt, int *out, long *new, long *old, long *diffs) +percentages(int cnt, int64_t *out, int64_t *new, int64_t *old, int64_t *diffs) { - long change, total_change, *dp, half_total; + int64_t change, total_change, *dp, half_total; int i; /* initialization */ @@ -220,7 +223,7 @@ percentages(int cnt, int *out, long *new, long *old, long *diffs) for (i = 0; i < cnt; i++) { if ((change = *new - *old) < 0) { /* this only happens when the counter wraps */ - change = ((unsigned int)*new - (unsigned int)*old); + change = (*new - *old); } total_change += (*dp++ = change); *old++ = *new++; diff --git a/usr.bin/top/utils.h b/usr.bin/top/utils.h index 4d0261da47d..e38e4b2f593 100644 --- a/usr.bin/top/utils.h +++ b/usr.bin/top/utils.h @@ -1,4 +1,4 @@ -/* $OpenBSD: utils.h,v 1.7 2004/10/07 06:26:12 otto Exp $ */ +/* $OpenBSD: utils.h,v 1.8 2005/06/08 22:36:43 millert Exp $ */ /* * Top users/processes display for Unix @@ -36,7 +36,7 @@ char *format_uid(uid_t); int digits(int); int string_index(char *, char **); char **argparse(char *, int *); -int percentages(int, int *, long *, long *, long *); +int percentages(int, int64_t *, int64_t *, int64_t *, int64_t *); char *format_time(time_t); char *format_k(int); int find_pid(pid_t); |