mirror of
https://git.busybox.net/busybox
synced 2026-02-07 20:50:26 +00:00
top: disentangle printing logic
function old new delta print_line_buf - 78 +78 print_line_bold - 50 +50 top_main 1043 1091 +48 handle_input 708 714 +6 do_stats 186 192 +6 .rodata 115543 115526 -17 display_topmem_process_list 748 523 -225 display_process_list 1432 1186 -246 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 3/3 up/down: 188/-488) Total: -300 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
2363938883
commit
1bd8d714ca
1 changed files with 97 additions and 83 deletions
180
procps/top.c
180
procps/top.c
|
|
@ -166,12 +166,14 @@ struct globals {
|
|||
top_status_t *top;
|
||||
int ntop;
|
||||
smallint inverted;
|
||||
smallint not_first_line;
|
||||
#if ENABLE_FEATURE_TOPMEM
|
||||
smallint sort_field;
|
||||
#endif
|
||||
#if ENABLE_FEATURE_TOP_SMP_CPU
|
||||
smallint smp_cpu_info; /* one/many cpu info lines? */
|
||||
#endif
|
||||
int lines_remaining;
|
||||
unsigned lines; /* screen height */
|
||||
unsigned scr_width; /* width, clamped <= LINE_BUF_SIZE-2 */
|
||||
#if ENABLE_FEATURE_TOP_INTERACTIVE
|
||||
|
|
@ -218,7 +220,6 @@ struct globals {
|
|||
#define cpu_prev_jif (G.cpu_prev_jif )
|
||||
#define num_cpus (G.num_cpus )
|
||||
#define total_pcpu (G.total_pcpu )
|
||||
#define line_buf (G.line_buf )
|
||||
#define INIT_G() do { \
|
||||
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
|
||||
BUILD_BUG_ON(LINE_BUF_SIZE <= 80); \
|
||||
|
|
@ -289,9 +290,9 @@ static NOINLINE int read_cpu_jiffy(FILE *fp, jiffy_counts_t *p_jif)
|
|||
#endif
|
||||
int ret;
|
||||
|
||||
if (!fgets(line_buf, LINE_BUF_SIZE, fp) || line_buf[0] != 'c' /* not "cpu" */)
|
||||
if (!fgets(G.line_buf, LINE_BUF_SIZE, fp) || G.line_buf[0] != 'c' /* not "cpu" */)
|
||||
return 0;
|
||||
ret = sscanf(line_buf, fmt,
|
||||
ret = sscanf(G.line_buf, fmt,
|
||||
&p_jif->usr, &p_jif->nic, &p_jif->sys, &p_jif->idle,
|
||||
&p_jif->iowait, &p_jif->irq, &p_jif->softirq,
|
||||
&p_jif->steal);
|
||||
|
|
@ -413,6 +414,38 @@ static void do_stats(void)
|
|||
|
||||
#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
|
||||
|
||||
static void print_line_buf(void)
|
||||
{
|
||||
const char *fmt;
|
||||
|
||||
G.lines_remaining--;
|
||||
fmt = OPT_BATCH_MODE ? "\n""%.*s" : "\n""%.*s"CLREOL;
|
||||
if (!G.not_first_line) {
|
||||
G.not_first_line = 1;
|
||||
/* Go to top */
|
||||
fmt = OPT_BATCH_MODE ? "%.*s" : HOME"%.*s"CLREOL;
|
||||
}
|
||||
printf(fmt, G.scr_width - 1, G.line_buf);
|
||||
}
|
||||
|
||||
static void print_line_bold(void)
|
||||
{
|
||||
G.lines_remaining--;
|
||||
//we never print first line in bold
|
||||
// if (!G.not_first_line) {
|
||||
// printf(OPT_BATCH_MODE ? "%.*s" : HOME"%.*s"CLREOL, G.scr_width - 1, G.line_buf);
|
||||
// G.not_first_line = 1;
|
||||
// } else {
|
||||
printf(OPT_BATCH_MODE ? "\n""%.*s" : "\n"REVERSE"%.*s"NORMAL CLREOL, G.scr_width - 1, G.line_buf);
|
||||
// }
|
||||
}
|
||||
|
||||
static void print_end(void)
|
||||
{
|
||||
fputs_stdout(OPT_BATCH_MODE ? "\n" : CLREOS"\r");
|
||||
G.not_first_line = 0; /* next print will be "first line" (will clear the screen) */
|
||||
}
|
||||
|
||||
#if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS && ENABLE_FEATURE_TOP_DECIMALS
|
||||
/* formats 7 char string (8 with terminating NUL) */
|
||||
static char *fmt_100percent_8(char pbuf[8], unsigned value, unsigned total)
|
||||
|
|
@ -439,7 +472,7 @@ static char *fmt_100percent_8(char pbuf[8], unsigned value, unsigned total)
|
|||
#endif
|
||||
|
||||
#if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS
|
||||
static void display_cpus(char *scrbuf, int *lines_rem_p)
|
||||
static void display_cpus(void)
|
||||
{
|
||||
/*
|
||||
* xxx% = (cur_jif.xxx - prev_jif.xxx) / (cur_jif.total - prev_jif.total) * 100%
|
||||
|
|
@ -475,8 +508,8 @@ static void display_cpus(char *scrbuf, int *lines_rem_p)
|
|||
# else
|
||||
/* Loop thru CPU(s) */
|
||||
n_cpu_lines = smp_cpu_info ? num_cpus : 1;
|
||||
if (n_cpu_lines > *lines_rem_p)
|
||||
n_cpu_lines = *lines_rem_p;
|
||||
if (n_cpu_lines > G.lines_remaining)
|
||||
n_cpu_lines = G.lines_remaining;
|
||||
|
||||
for (i = 0; i < n_cpu_lines; i++) {
|
||||
p_jif = &cpu_jif[i];
|
||||
|
|
@ -494,7 +527,7 @@ static void display_cpus(char *scrbuf, int *lines_rem_p)
|
|||
CALC_STAT(softirq);
|
||||
/*CALC_STAT(steal);*/
|
||||
|
||||
snprintf(scrbuf, G.scr_width,
|
||||
sprintf(G.line_buf,
|
||||
/* Barely fits in 79 chars when in "decimals" mode. */
|
||||
# if ENABLE_FEATURE_TOP_SMP_CPU
|
||||
"CPU%s:"FMT"usr"FMT"sys"FMT"nic"FMT"idle"FMT"io"FMT"irq"FMT"sirq",
|
||||
|
|
@ -507,16 +540,15 @@ static void display_cpus(char *scrbuf, int *lines_rem_p)
|
|||
/*, SHOW_STAT(steal) - what is this 'steal' thing? */
|
||||
/* I doubt anyone wants to know it */
|
||||
);
|
||||
printf(OPT_BATCH_MODE ? "%s\n" : "%s"CLREOL"\n", scrbuf);
|
||||
print_line_buf();
|
||||
}
|
||||
}
|
||||
# undef SHOW_STAT
|
||||
# undef CALC_STAT
|
||||
# undef FMT
|
||||
*lines_rem_p -= i;
|
||||
}
|
||||
#else /* !ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS */
|
||||
# define display_cpus(scrbuf, lines_rem) ((void)0)
|
||||
# define display_cpus() ((void)0)
|
||||
#endif
|
||||
|
||||
enum {
|
||||
|
|
@ -570,51 +602,46 @@ static void parse_meminfo(unsigned long meminfo[MI_MAX])
|
|||
fclose(f);
|
||||
}
|
||||
|
||||
static unsigned long display_header(int *lines_rem_p)
|
||||
static unsigned long display_header(void)
|
||||
{
|
||||
char scrbuf[100]; /* [80] was a bit too low on 8Gb ram box */
|
||||
char *buf;
|
||||
unsigned width;
|
||||
unsigned long meminfo[MI_MAX];
|
||||
|
||||
parse_meminfo(meminfo);
|
||||
|
||||
/* Output memory info */
|
||||
width = (G.scr_width > sizeof(scrbuf)) ? sizeof(scrbuf) : G.scr_width;
|
||||
snprintf(scrbuf, width,
|
||||
sprintf(G.line_buf,
|
||||
"Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached",
|
||||
meminfo[MI_MEMTOTAL] - meminfo[MI_MEMFREE],
|
||||
meminfo[MI_MEMFREE],
|
||||
meminfo[MI_MEMSHARED] + meminfo[MI_SHMEM],
|
||||
meminfo[MI_BUFFERS],
|
||||
meminfo[MI_CACHED]);
|
||||
/* Go to top & clear to the end of screen */
|
||||
printf(OPT_BATCH_MODE ? "%s\n" : HOME"%s"CLREOL"\n", scrbuf);
|
||||
(*lines_rem_p)--;
|
||||
print_line_buf();
|
||||
|
||||
/* Display CPU time split as percentage of total time.
|
||||
* This displays either a cumulative line or one line per CPU.
|
||||
*/
|
||||
display_cpus(scrbuf, lines_rem_p);
|
||||
display_cpus();
|
||||
|
||||
/* Read load average as a string */
|
||||
buf = stpcpy(scrbuf, "Load average: ");
|
||||
open_read_close("loadavg", buf, sizeof(scrbuf) - sizeof("Load average: "));
|
||||
buf = stpcpy(G.line_buf, "Load average: ");
|
||||
open_read_close("loadavg", buf, sizeof(G.line_buf) - sizeof("Load average: "));
|
||||
G.line_buf[sizeof(G.line_buf) - 1] = '\0'; /* paranoia */
|
||||
strchrnul(buf, '\n')[0] = '\0';
|
||||
printf(OPT_BATCH_MODE ? "%.*s\n" : "%.*s"CLREOL"\n", width - 1, scrbuf);
|
||||
(*lines_rem_p)--;
|
||||
print_line_buf();
|
||||
|
||||
return meminfo[MI_MEMTOTAL];
|
||||
}
|
||||
|
||||
static NOINLINE void display_process_list(int lines_rem)
|
||||
static NOINLINE void display_process_list(void)
|
||||
{
|
||||
enum {
|
||||
BITS_PER_INT = sizeof(int) * 8
|
||||
};
|
||||
|
||||
top_status_t *s;
|
||||
unsigned long total_memory = display_header(&lines_rem); /* or use total_memsize? */
|
||||
unsigned long total_memory = display_header();
|
||||
/* xxx_shift and xxx_scale variables allow us to replace
|
||||
* expensive divides with multiply and shift */
|
||||
unsigned pmem_shift, pmem_scale, pmem_half;
|
||||
|
|
@ -626,7 +653,7 @@ static NOINLINE void display_process_list(int lines_rem)
|
|||
|
||||
#if ENABLE_FEATURE_TOP_DECIMALS
|
||||
# define UPSCALE 1000
|
||||
typedef struct { unsigned quot, rem; } bb_div_t;
|
||||
typedef struct { unsigned quot, rem; } bb_div_t;
|
||||
/* Used to have "div_t name = div((val), 10)" here
|
||||
* (IOW: intended to use libc-compatible way to divide and use
|
||||
* both result and remainder, but musl does not inline div()...)
|
||||
|
|
@ -644,13 +671,11 @@ typedef struct { unsigned quot, rem; } bb_div_t;
|
|||
# define FMT "%4u%%"
|
||||
#endif
|
||||
|
||||
/* what info of the processes is shown */
|
||||
printf(OPT_BATCH_MODE ? "%.*s" : REVERSE"%.*s"NORMAL CLREOL, G.scr_width - 1,
|
||||
" PID PPID USER STAT RSS %RSS"
|
||||
strcpy(G.line_buf, " PID PPID USER STAT RSS %RSS"
|
||||
IF_FEATURE_TOP_SMP_PROCESS(" CPU")
|
||||
IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(" %CPU")
|
||||
" COMMAND");
|
||||
lines_rem--;
|
||||
print_line_bold();
|
||||
|
||||
/* %RSS = s->memsize / MemTotal * 100%
|
||||
* Calculate this with multiply and shift. Example:
|
||||
|
|
@ -702,12 +727,12 @@ typedef struct { unsigned quot, rem; } bb_div_t;
|
|||
pcpu_half = (1U << pcpu_shift) / (ENABLE_FEATURE_TOP_DECIMALS ? 20 : 2);
|
||||
/* printf(" pmem_scale=%u pcpu_scale=%u ", pmem_scale, pcpu_scale); */
|
||||
#endif
|
||||
if (lines_rem > ntop - G_scroll_ofs)
|
||||
lines_rem = ntop - G_scroll_ofs;
|
||||
if (G.lines_remaining > ntop - G_scroll_ofs)
|
||||
G.lines_remaining = ntop - G_scroll_ofs;
|
||||
|
||||
/* Ok, all preliminary data is ready, go through the list */
|
||||
s = top + G_scroll_ofs;
|
||||
while (--lines_rem >= 0) {
|
||||
while (G.lines_remaining > 0) {
|
||||
int n;
|
||||
char *ppu;
|
||||
char ppubuf[sizeof(int)*3 * 2 + 12];
|
||||
|
|
@ -753,7 +778,7 @@ typedef struct { unsigned quot, rem; } bb_div_t;
|
|||
ppu[6+6+8] = '\0'; /* truncate USER */
|
||||
}
|
||||
shortened:
|
||||
col = snprintf(line_buf, G.scr_width,
|
||||
col = sprintf(G.line_buf,
|
||||
"%s %s %.5s" FMT
|
||||
IF_FEATURE_TOP_SMP_PROCESS(" %3d")
|
||||
IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(FMT)
|
||||
|
|
@ -765,14 +790,13 @@ typedef struct { unsigned quot, rem; } bb_div_t;
|
|||
IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu))
|
||||
);
|
||||
if ((int)(G.scr_width - col) > 1)
|
||||
read_cmdline(line_buf + col, G.scr_width - col, s->pid, s->comm);
|
||||
printf(OPT_BATCH_MODE ? "\n""%s" : "\n""%s"CLREOL, line_buf);
|
||||
read_cmdline(G.line_buf + col, G.scr_width - col, s->pid, s->comm);
|
||||
print_line_buf();
|
||||
/* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu,
|
||||
cur_jif.busy - prev_jif.busy, cur_jif.total - prev_jif.total); */
|
||||
s++;
|
||||
}
|
||||
/* printf(" %d", hist_iterations); */
|
||||
fputs_stdout(OPT_BATCH_MODE ? "\n" : CLREOS"\r");
|
||||
}
|
||||
#undef UPSCALE
|
||||
#undef SHOW_STAT
|
||||
|
|
@ -844,36 +868,34 @@ static int topmem_sort(char *a, char *b)
|
|||
}
|
||||
|
||||
/* display header info (meminfo / loadavg) */
|
||||
static void display_topmem_header(int *lines_rem_p)
|
||||
static void display_topmem_header(void)
|
||||
{
|
||||
unsigned long meminfo[MI_MAX];
|
||||
|
||||
parse_meminfo(meminfo);
|
||||
|
||||
snprintf(line_buf, LINE_BUF_SIZE,
|
||||
sprintf(G.line_buf,
|
||||
"Mem total:%lu anon:%lu map:%lu free:%lu",
|
||||
meminfo[MI_MEMTOTAL],
|
||||
meminfo[MI_ANONPAGES],
|
||||
meminfo[MI_MAPPED],
|
||||
meminfo[MI_MEMFREE]);
|
||||
printf(OPT_BATCH_MODE ? "%.*s\n" : HOME"%.*s"CLREOL"\n", G.scr_width - 1, line_buf);
|
||||
print_line_buf();
|
||||
|
||||
snprintf(line_buf, LINE_BUF_SIZE,
|
||||
sprintf(G.line_buf,
|
||||
" slab:%lu buf:%lu cache:%lu dirty:%lu write:%lu",
|
||||
meminfo[MI_SLAB],
|
||||
meminfo[MI_BUFFERS],
|
||||
meminfo[MI_CACHED],
|
||||
meminfo[MI_DIRTY],
|
||||
meminfo[MI_WRITEBACK]);
|
||||
printf(OPT_BATCH_MODE ? "%.*s\n" : "%.*s"CLREOL"\n", G.scr_width - 1, line_buf);
|
||||
print_line_buf();
|
||||
|
||||
snprintf(line_buf, LINE_BUF_SIZE,
|
||||
sprintf(G.line_buf,
|
||||
"Swap total:%lu free:%lu", // TODO: % used?
|
||||
meminfo[MI_SWAPTOTAL],
|
||||
meminfo[MI_SWAPFREE]);
|
||||
printf(OPT_BATCH_MODE ? "%.*s\n" : "%.*s"CLREOL"\n", G.scr_width - 1, line_buf);
|
||||
|
||||
(*lines_rem_p) -= 3;
|
||||
print_line_buf();
|
||||
}
|
||||
|
||||
/* see http://en.wikipedia.org/wiki/Tera */
|
||||
|
|
@ -886,67 +908,57 @@ static void ulltoa4_and_space(unsigned long long ul, char buf[5])
|
|||
smart_ulltoa4(ul, buf, " mgtpezy")[0] = ' ';
|
||||
}
|
||||
|
||||
static NOINLINE void display_topmem_process_list(int lines_rem)
|
||||
static NOINLINE void display_topmem_process_list(void)
|
||||
{
|
||||
#define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK"
|
||||
#define MIN_WIDTH sizeof(HDR_STR)
|
||||
const topmem_status_t *s = topmem + G_scroll_ofs;
|
||||
char *cp, ch;
|
||||
|
||||
display_topmem_header(&lines_rem);
|
||||
display_topmem_header();
|
||||
|
||||
strcpy(line_buf, HDR_STR " COMMAND");
|
||||
strcpy(G.line_buf, HDR_STR " COMMAND");
|
||||
/* Mark the ^FIELD^ we sort by */
|
||||
cp = &line_buf[5 + sort_field * 6];
|
||||
cp = &G.line_buf[5 + sort_field * 6];
|
||||
ch = "^_"[inverted];
|
||||
cp[6] = ch;
|
||||
do *cp++ = ch; while (*cp == ' ');
|
||||
print_line_bold();
|
||||
|
||||
printf(OPT_BATCH_MODE ? "%.*s" : REVERSE"%.*s"NORMAL CLREOL, G.scr_width - 1, line_buf);
|
||||
lines_rem--;
|
||||
|
||||
if (lines_rem > ntop - G_scroll_ofs)
|
||||
lines_rem = ntop - G_scroll_ofs;
|
||||
while (--lines_rem >= 0) {
|
||||
if (G.lines_remaining > ntop - G_scroll_ofs)
|
||||
G.lines_remaining = ntop - G_scroll_ofs;
|
||||
while (G.lines_remaining > 0) {
|
||||
/* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */
|
||||
int n = sprintf(line_buf, "%5u ", s->pid);
|
||||
int n = sprintf(G.line_buf, "%5u ", s->pid);
|
||||
if (n > 7) {
|
||||
/* PID is 7 chars long (up to 4194304) */
|
||||
ulltoa4_and_space(s->vsz , &line_buf[8]);
|
||||
ulltoa4_and_space(s->vszrw, &line_buf[8+5]);
|
||||
ulltoa4_and_space(s->vsz , &G.line_buf[8]);
|
||||
ulltoa4_and_space(s->vszrw, &G.line_buf[8+5]);
|
||||
/* the next field (RSS) starts at 8+10 = 3*6 */
|
||||
} else {
|
||||
if (n == 7) /* PID is 6 chars long */
|
||||
ulltoa4_and_space(s->vsz, &line_buf[7]);
|
||||
ulltoa4_and_space(s->vsz, &G.line_buf[7]);
|
||||
/* the next field (VSZRW) starts at 7+5 = 2*6 */
|
||||
else /* PID is 5 chars or less */
|
||||
ulltoa5_and_space(s->vsz, &line_buf[6]);
|
||||
ulltoa5_and_space(s->vszrw, &line_buf[2*6]);
|
||||
ulltoa5_and_space(s->vsz, &G.line_buf[6]);
|
||||
ulltoa5_and_space(s->vszrw, &G.line_buf[2*6]);
|
||||
}
|
||||
ulltoa5_and_space(s->rss , &line_buf[3*6]);
|
||||
ulltoa5_and_space(s->rss_sh , &line_buf[4*6]);
|
||||
ulltoa5_and_space(s->dirty , &line_buf[5*6]);
|
||||
ulltoa5_and_space(s->dirty_sh, &line_buf[6*6]);
|
||||
ulltoa5_and_space(s->stack , &line_buf[7*6]);
|
||||
line_buf[8*6] = '\0';
|
||||
ulltoa5_and_space(s->rss , &G.line_buf[3*6]);
|
||||
ulltoa5_and_space(s->rss_sh , &G.line_buf[4*6]);
|
||||
ulltoa5_and_space(s->dirty , &G.line_buf[5*6]);
|
||||
ulltoa5_and_space(s->dirty_sh, &G.line_buf[6*6]);
|
||||
ulltoa5_and_space(s->stack , &G.line_buf[7*6]);
|
||||
G.line_buf[8*6] = '\0';
|
||||
if ((int)(G.scr_width - MIN_WIDTH) > 1)
|
||||
read_cmdline(&line_buf[8*6], G.scr_width - MIN_WIDTH, s->pid, s->comm);
|
||||
printf(OPT_BATCH_MODE ? "\n""%.*s" : "\n""%.*s"CLREOL, G.scr_width, line_buf);
|
||||
read_cmdline(&G.line_buf[8*6], G.scr_width - MIN_WIDTH, s->pid, s->comm);
|
||||
print_line_buf();
|
||||
s++;
|
||||
}
|
||||
fputs_stdout(OPT_BATCH_MODE ? "\n" : CLREOS"\r");
|
||||
#undef HDR_STR
|
||||
#undef MIN_WIDTH
|
||||
}
|
||||
|
||||
#else
|
||||
//void display_topmem_process_list(int lines_rem);
|
||||
//int topmem_sort(char *a, char *b);
|
||||
#endif /* TOPMEM */
|
||||
|
||||
/*
|
||||
* end TOPMEM support
|
||||
*/
|
||||
#endif /* end TOPMEM support */
|
||||
|
||||
enum {
|
||||
TOP_MASK = 0
|
||||
|
|
@ -1228,7 +1240,6 @@ int top_main(int argc UNUSED_PARAM, char **argv)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* change to /proc */
|
||||
xchdir("/proc");
|
||||
|
||||
#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
|
||||
|
|
@ -1340,14 +1351,16 @@ int top_main(int argc UNUSED_PARAM, char **argv)
|
|||
}
|
||||
#endif
|
||||
IF_FEATURE_TOP_INTERACTIVE(redraw:)
|
||||
G.lines_remaining = G.lines;
|
||||
IF_FEATURE_TOPMEM(if (scan_mask != TOPMEM_MASK)) {
|
||||
display_process_list(G.lines);
|
||||
display_process_list();
|
||||
}
|
||||
#if ENABLE_FEATURE_TOPMEM
|
||||
else { /* TOPMEM */
|
||||
display_topmem_process_list(G.lines);
|
||||
display_topmem_process_list();
|
||||
}
|
||||
#endif
|
||||
print_end();
|
||||
fflush_all();
|
||||
if (iterations >= 0 && !--iterations)
|
||||
break;
|
||||
|
|
@ -1369,7 +1382,8 @@ int top_main(int argc UNUSED_PARAM, char **argv)
|
|||
#endif
|
||||
} /* end of "while (not Q)" */
|
||||
|
||||
bb_putchar('\n');
|
||||
if (!OPT_BATCH_MODE)
|
||||
bb_putchar('\n');
|
||||
#if ENABLE_FEATURE_TOP_INTERACTIVE
|
||||
reset_term();
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue