diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-06 00:05:44 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-06 00:05:44 +0200 |
| commit | 1bd8d714ca1889558b26ab8f29a0f199ffdd2bd9 (patch) | |
| tree | fe09a1dee81f5e44e008181014cc1cc442759cd2 | |
| parent | 23639388838448bb1968de70e84005904b316b93 (diff) | |
| download | busybox-w32-1bd8d714ca1889558b26ab8f29a0f199ffdd2bd9.tar.gz busybox-w32-1bd8d714ca1889558b26ab8f29a0f199ffdd2bd9.tar.bz2 busybox-w32-1bd8d714ca1889558b26ab8f29a0f199ffdd2bd9.zip | |
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>
| -rw-r--r-- | procps/top.c | 180 |
1 files changed, 97 insertions, 83 deletions
diff --git a/procps/top.c b/procps/top.c index 1f1c82b5a..bff9f7c4f 100644 --- a/procps/top.c +++ b/procps/top.c | |||
| @@ -166,12 +166,14 @@ struct globals { | |||
| 166 | top_status_t *top; | 166 | top_status_t *top; |
| 167 | int ntop; | 167 | int ntop; |
| 168 | smallint inverted; | 168 | smallint inverted; |
| 169 | smallint not_first_line; | ||
| 169 | #if ENABLE_FEATURE_TOPMEM | 170 | #if ENABLE_FEATURE_TOPMEM |
| 170 | smallint sort_field; | 171 | smallint sort_field; |
| 171 | #endif | 172 | #endif |
| 172 | #if ENABLE_FEATURE_TOP_SMP_CPU | 173 | #if ENABLE_FEATURE_TOP_SMP_CPU |
| 173 | smallint smp_cpu_info; /* one/many cpu info lines? */ | 174 | smallint smp_cpu_info; /* one/many cpu info lines? */ |
| 174 | #endif | 175 | #endif |
| 176 | int lines_remaining; | ||
| 175 | unsigned lines; /* screen height */ | 177 | unsigned lines; /* screen height */ |
| 176 | unsigned scr_width; /* width, clamped <= LINE_BUF_SIZE-2 */ | 178 | unsigned scr_width; /* width, clamped <= LINE_BUF_SIZE-2 */ |
| 177 | #if ENABLE_FEATURE_TOP_INTERACTIVE | 179 | #if ENABLE_FEATURE_TOP_INTERACTIVE |
| @@ -218,7 +220,6 @@ struct globals { | |||
| 218 | #define cpu_prev_jif (G.cpu_prev_jif ) | 220 | #define cpu_prev_jif (G.cpu_prev_jif ) |
| 219 | #define num_cpus (G.num_cpus ) | 221 | #define num_cpus (G.num_cpus ) |
| 220 | #define total_pcpu (G.total_pcpu ) | 222 | #define total_pcpu (G.total_pcpu ) |
| 221 | #define line_buf (G.line_buf ) | ||
| 222 | #define INIT_G() do { \ | 223 | #define INIT_G() do { \ |
| 223 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 224 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
| 224 | BUILD_BUG_ON(LINE_BUF_SIZE <= 80); \ | 225 | BUILD_BUG_ON(LINE_BUF_SIZE <= 80); \ |
| @@ -289,9 +290,9 @@ static NOINLINE int read_cpu_jiffy(FILE *fp, jiffy_counts_t *p_jif) | |||
| 289 | #endif | 290 | #endif |
| 290 | int ret; | 291 | int ret; |
| 291 | 292 | ||
| 292 | if (!fgets(line_buf, LINE_BUF_SIZE, fp) || line_buf[0] != 'c' /* not "cpu" */) | 293 | if (!fgets(G.line_buf, LINE_BUF_SIZE, fp) || G.line_buf[0] != 'c' /* not "cpu" */) |
| 293 | return 0; | 294 | return 0; |
| 294 | ret = sscanf(line_buf, fmt, | 295 | ret = sscanf(G.line_buf, fmt, |
| 295 | &p_jif->usr, &p_jif->nic, &p_jif->sys, &p_jif->idle, | 296 | &p_jif->usr, &p_jif->nic, &p_jif->sys, &p_jif->idle, |
| 296 | &p_jif->iowait, &p_jif->irq, &p_jif->softirq, | 297 | &p_jif->iowait, &p_jif->irq, &p_jif->softirq, |
| 297 | &p_jif->steal); | 298 | &p_jif->steal); |
| @@ -413,6 +414,38 @@ static void do_stats(void) | |||
| 413 | 414 | ||
| 414 | #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ | 415 | #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ |
| 415 | 416 | ||
| 417 | static void print_line_buf(void) | ||
| 418 | { | ||
| 419 | const char *fmt; | ||
| 420 | |||
| 421 | G.lines_remaining--; | ||
| 422 | fmt = OPT_BATCH_MODE ? "\n""%.*s" : "\n""%.*s"CLREOL; | ||
| 423 | if (!G.not_first_line) { | ||
| 424 | G.not_first_line = 1; | ||
| 425 | /* Go to top */ | ||
| 426 | fmt = OPT_BATCH_MODE ? "%.*s" : HOME"%.*s"CLREOL; | ||
| 427 | } | ||
| 428 | printf(fmt, G.scr_width - 1, G.line_buf); | ||
| 429 | } | ||
| 430 | |||
| 431 | static void print_line_bold(void) | ||
| 432 | { | ||
| 433 | G.lines_remaining--; | ||
| 434 | //we never print first line in bold | ||
| 435 | // if (!G.not_first_line) { | ||
| 436 | // printf(OPT_BATCH_MODE ? "%.*s" : HOME"%.*s"CLREOL, G.scr_width - 1, G.line_buf); | ||
| 437 | // G.not_first_line = 1; | ||
| 438 | // } else { | ||
| 439 | printf(OPT_BATCH_MODE ? "\n""%.*s" : "\n"REVERSE"%.*s"NORMAL CLREOL, G.scr_width - 1, G.line_buf); | ||
| 440 | // } | ||
| 441 | } | ||
| 442 | |||
| 443 | static void print_end(void) | ||
| 444 | { | ||
| 445 | fputs_stdout(OPT_BATCH_MODE ? "\n" : CLREOS"\r"); | ||
| 446 | G.not_first_line = 0; /* next print will be "first line" (will clear the screen) */ | ||
| 447 | } | ||
| 448 | |||
| 416 | #if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS && ENABLE_FEATURE_TOP_DECIMALS | 449 | #if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS && ENABLE_FEATURE_TOP_DECIMALS |
| 417 | /* formats 7 char string (8 with terminating NUL) */ | 450 | /* formats 7 char string (8 with terminating NUL) */ |
| 418 | static char *fmt_100percent_8(char pbuf[8], unsigned value, unsigned total) | 451 | 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) | |||
| 439 | #endif | 472 | #endif |
| 440 | 473 | ||
| 441 | #if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS | 474 | #if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS |
| 442 | static void display_cpus(char *scrbuf, int *lines_rem_p) | 475 | static void display_cpus(void) |
| 443 | { | 476 | { |
| 444 | /* | 477 | /* |
| 445 | * xxx% = (cur_jif.xxx - prev_jif.xxx) / (cur_jif.total - prev_jif.total) * 100% | 478 | * 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) | |||
| 475 | # else | 508 | # else |
| 476 | /* Loop thru CPU(s) */ | 509 | /* Loop thru CPU(s) */ |
| 477 | n_cpu_lines = smp_cpu_info ? num_cpus : 1; | 510 | n_cpu_lines = smp_cpu_info ? num_cpus : 1; |
| 478 | if (n_cpu_lines > *lines_rem_p) | 511 | if (n_cpu_lines > G.lines_remaining) |
| 479 | n_cpu_lines = *lines_rem_p; | 512 | n_cpu_lines = G.lines_remaining; |
| 480 | 513 | ||
| 481 | for (i = 0; i < n_cpu_lines; i++) { | 514 | for (i = 0; i < n_cpu_lines; i++) { |
| 482 | p_jif = &cpu_jif[i]; | 515 | p_jif = &cpu_jif[i]; |
| @@ -494,7 +527,7 @@ static void display_cpus(char *scrbuf, int *lines_rem_p) | |||
| 494 | CALC_STAT(softirq); | 527 | CALC_STAT(softirq); |
| 495 | /*CALC_STAT(steal);*/ | 528 | /*CALC_STAT(steal);*/ |
| 496 | 529 | ||
| 497 | snprintf(scrbuf, G.scr_width, | 530 | sprintf(G.line_buf, |
| 498 | /* Barely fits in 79 chars when in "decimals" mode. */ | 531 | /* Barely fits in 79 chars when in "decimals" mode. */ |
| 499 | # if ENABLE_FEATURE_TOP_SMP_CPU | 532 | # if ENABLE_FEATURE_TOP_SMP_CPU |
| 500 | "CPU%s:"FMT"usr"FMT"sys"FMT"nic"FMT"idle"FMT"io"FMT"irq"FMT"sirq", | 533 | "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) | |||
| 507 | /*, SHOW_STAT(steal) - what is this 'steal' thing? */ | 540 | /*, SHOW_STAT(steal) - what is this 'steal' thing? */ |
| 508 | /* I doubt anyone wants to know it */ | 541 | /* I doubt anyone wants to know it */ |
| 509 | ); | 542 | ); |
| 510 | printf(OPT_BATCH_MODE ? "%s\n" : "%s"CLREOL"\n", scrbuf); | 543 | print_line_buf(); |
| 511 | } | 544 | } |
| 512 | } | 545 | } |
| 513 | # undef SHOW_STAT | 546 | # undef SHOW_STAT |
| 514 | # undef CALC_STAT | 547 | # undef CALC_STAT |
| 515 | # undef FMT | 548 | # undef FMT |
| 516 | *lines_rem_p -= i; | ||
| 517 | } | 549 | } |
| 518 | #else /* !ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS */ | 550 | #else /* !ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS */ |
| 519 | # define display_cpus(scrbuf, lines_rem) ((void)0) | 551 | # define display_cpus() ((void)0) |
| 520 | #endif | 552 | #endif |
| 521 | 553 | ||
| 522 | enum { | 554 | enum { |
| @@ -570,51 +602,46 @@ static void parse_meminfo(unsigned long meminfo[MI_MAX]) | |||
| 570 | fclose(f); | 602 | fclose(f); |
| 571 | } | 603 | } |
| 572 | 604 | ||
| 573 | static unsigned long display_header(int *lines_rem_p) | 605 | static unsigned long display_header(void) |
| 574 | { | 606 | { |
| 575 | char scrbuf[100]; /* [80] was a bit too low on 8Gb ram box */ | ||
| 576 | char *buf; | 607 | char *buf; |
| 577 | unsigned width; | ||
| 578 | unsigned long meminfo[MI_MAX]; | 608 | unsigned long meminfo[MI_MAX]; |
| 579 | 609 | ||
| 580 | parse_meminfo(meminfo); | 610 | parse_meminfo(meminfo); |
| 581 | 611 | ||
| 582 | /* Output memory info */ | 612 | /* Output memory info */ |
| 583 | width = (G.scr_width > sizeof(scrbuf)) ? sizeof(scrbuf) : G.scr_width; | 613 | sprintf(G.line_buf, |
| 584 | snprintf(scrbuf, width, | ||
| 585 | "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached", | 614 | "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached", |
| 586 | meminfo[MI_MEMTOTAL] - meminfo[MI_MEMFREE], | 615 | meminfo[MI_MEMTOTAL] - meminfo[MI_MEMFREE], |
| 587 | meminfo[MI_MEMFREE], | 616 | meminfo[MI_MEMFREE], |
| 588 | meminfo[MI_MEMSHARED] + meminfo[MI_SHMEM], | 617 | meminfo[MI_MEMSHARED] + meminfo[MI_SHMEM], |
| 589 | meminfo[MI_BUFFERS], | 618 | meminfo[MI_BUFFERS], |
| 590 | meminfo[MI_CACHED]); | 619 | meminfo[MI_CACHED]); |
| 591 | /* Go to top & clear to the end of screen */ | 620 | print_line_buf(); |
| 592 | printf(OPT_BATCH_MODE ? "%s\n" : HOME"%s"CLREOL"\n", scrbuf); | ||
| 593 | (*lines_rem_p)--; | ||
| 594 | 621 | ||
| 595 | /* Display CPU time split as percentage of total time. | 622 | /* Display CPU time split as percentage of total time. |
| 596 | * This displays either a cumulative line or one line per CPU. | 623 | * This displays either a cumulative line or one line per CPU. |
| 597 | */ | 624 | */ |
| 598 | display_cpus(scrbuf, lines_rem_p); | 625 | display_cpus(); |
| 599 | 626 | ||
| 600 | /* Read load average as a string */ | 627 | /* Read load average as a string */ |
| 601 | buf = stpcpy(scrbuf, "Load average: "); | 628 | buf = stpcpy(G.line_buf, "Load average: "); |
| 602 | open_read_close("loadavg", buf, sizeof(scrbuf) - sizeof("Load average: ")); | 629 | open_read_close("loadavg", buf, sizeof(G.line_buf) - sizeof("Load average: ")); |
| 630 | G.line_buf[sizeof(G.line_buf) - 1] = '\0'; /* paranoia */ | ||
| 603 | strchrnul(buf, '\n')[0] = '\0'; | 631 | strchrnul(buf, '\n')[0] = '\0'; |
| 604 | printf(OPT_BATCH_MODE ? "%.*s\n" : "%.*s"CLREOL"\n", width - 1, scrbuf); | 632 | print_line_buf(); |
| 605 | (*lines_rem_p)--; | ||
| 606 | 633 | ||
| 607 | return meminfo[MI_MEMTOTAL]; | 634 | return meminfo[MI_MEMTOTAL]; |
| 608 | } | 635 | } |
| 609 | 636 | ||
| 610 | static NOINLINE void display_process_list(int lines_rem) | 637 | static NOINLINE void display_process_list(void) |
| 611 | { | 638 | { |
| 612 | enum { | 639 | enum { |
| 613 | BITS_PER_INT = sizeof(int) * 8 | 640 | BITS_PER_INT = sizeof(int) * 8 |
| 614 | }; | 641 | }; |
| 615 | 642 | ||
| 616 | top_status_t *s; | 643 | top_status_t *s; |
| 617 | unsigned long total_memory = display_header(&lines_rem); /* or use total_memsize? */ | 644 | unsigned long total_memory = display_header(); |
| 618 | /* xxx_shift and xxx_scale variables allow us to replace | 645 | /* xxx_shift and xxx_scale variables allow us to replace |
| 619 | * expensive divides with multiply and shift */ | 646 | * expensive divides with multiply and shift */ |
| 620 | unsigned pmem_shift, pmem_scale, pmem_half; | 647 | unsigned pmem_shift, pmem_scale, pmem_half; |
| @@ -626,7 +653,7 @@ static NOINLINE void display_process_list(int lines_rem) | |||
| 626 | 653 | ||
| 627 | #if ENABLE_FEATURE_TOP_DECIMALS | 654 | #if ENABLE_FEATURE_TOP_DECIMALS |
| 628 | # define UPSCALE 1000 | 655 | # define UPSCALE 1000 |
| 629 | typedef struct { unsigned quot, rem; } bb_div_t; | 656 | typedef struct { unsigned quot, rem; } bb_div_t; |
| 630 | /* Used to have "div_t name = div((val), 10)" here | 657 | /* Used to have "div_t name = div((val), 10)" here |
| 631 | * (IOW: intended to use libc-compatible way to divide and use | 658 | * (IOW: intended to use libc-compatible way to divide and use |
| 632 | * both result and remainder, but musl does not inline div()...) | 659 | * both result and remainder, but musl does not inline div()...) |
| @@ -644,13 +671,11 @@ typedef struct { unsigned quot, rem; } bb_div_t; | |||
| 644 | # define FMT "%4u%%" | 671 | # define FMT "%4u%%" |
| 645 | #endif | 672 | #endif |
| 646 | 673 | ||
| 647 | /* what info of the processes is shown */ | 674 | strcpy(G.line_buf, " PID PPID USER STAT RSS %RSS" |
| 648 | printf(OPT_BATCH_MODE ? "%.*s" : REVERSE"%.*s"NORMAL CLREOL, G.scr_width - 1, | ||
| 649 | " PID PPID USER STAT RSS %RSS" | ||
| 650 | IF_FEATURE_TOP_SMP_PROCESS(" CPU") | 675 | IF_FEATURE_TOP_SMP_PROCESS(" CPU") |
| 651 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(" %CPU") | 676 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(" %CPU") |
| 652 | " COMMAND"); | 677 | " COMMAND"); |
| 653 | lines_rem--; | 678 | print_line_bold(); |
| 654 | 679 | ||
| 655 | /* %RSS = s->memsize / MemTotal * 100% | 680 | /* %RSS = s->memsize / MemTotal * 100% |
| 656 | * Calculate this with multiply and shift. Example: | 681 | * Calculate this with multiply and shift. Example: |
| @@ -702,12 +727,12 @@ typedef struct { unsigned quot, rem; } bb_div_t; | |||
| 702 | pcpu_half = (1U << pcpu_shift) / (ENABLE_FEATURE_TOP_DECIMALS ? 20 : 2); | 727 | pcpu_half = (1U << pcpu_shift) / (ENABLE_FEATURE_TOP_DECIMALS ? 20 : 2); |
| 703 | /* printf(" pmem_scale=%u pcpu_scale=%u ", pmem_scale, pcpu_scale); */ | 728 | /* printf(" pmem_scale=%u pcpu_scale=%u ", pmem_scale, pcpu_scale); */ |
| 704 | #endif | 729 | #endif |
| 705 | if (lines_rem > ntop - G_scroll_ofs) | 730 | if (G.lines_remaining > ntop - G_scroll_ofs) |
| 706 | lines_rem = ntop - G_scroll_ofs; | 731 | G.lines_remaining = ntop - G_scroll_ofs; |
| 707 | 732 | ||
| 708 | /* Ok, all preliminary data is ready, go through the list */ | 733 | /* Ok, all preliminary data is ready, go through the list */ |
| 709 | s = top + G_scroll_ofs; | 734 | s = top + G_scroll_ofs; |
| 710 | while (--lines_rem >= 0) { | 735 | while (G.lines_remaining > 0) { |
| 711 | int n; | 736 | int n; |
| 712 | char *ppu; | 737 | char *ppu; |
| 713 | char ppubuf[sizeof(int)*3 * 2 + 12]; | 738 | char ppubuf[sizeof(int)*3 * 2 + 12]; |
| @@ -753,7 +778,7 @@ typedef struct { unsigned quot, rem; } bb_div_t; | |||
| 753 | ppu[6+6+8] = '\0'; /* truncate USER */ | 778 | ppu[6+6+8] = '\0'; /* truncate USER */ |
| 754 | } | 779 | } |
| 755 | shortened: | 780 | shortened: |
| 756 | col = snprintf(line_buf, G.scr_width, | 781 | col = sprintf(G.line_buf, |
| 757 | "%s %s %.5s" FMT | 782 | "%s %s %.5s" FMT |
| 758 | IF_FEATURE_TOP_SMP_PROCESS(" %3d") | 783 | IF_FEATURE_TOP_SMP_PROCESS(" %3d") |
| 759 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(FMT) | 784 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(FMT) |
| @@ -765,14 +790,13 @@ typedef struct { unsigned quot, rem; } bb_div_t; | |||
| 765 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu)) | 790 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu)) |
| 766 | ); | 791 | ); |
| 767 | if ((int)(G.scr_width - col) > 1) | 792 | if ((int)(G.scr_width - col) > 1) |
| 768 | read_cmdline(line_buf + col, G.scr_width - col, s->pid, s->comm); | 793 | read_cmdline(G.line_buf + col, G.scr_width - col, s->pid, s->comm); |
| 769 | printf(OPT_BATCH_MODE ? "\n""%s" : "\n""%s"CLREOL, line_buf); | 794 | print_line_buf(); |
| 770 | /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, | 795 | /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, |
| 771 | cur_jif.busy - prev_jif.busy, cur_jif.total - prev_jif.total); */ | 796 | cur_jif.busy - prev_jif.busy, cur_jif.total - prev_jif.total); */ |
| 772 | s++; | 797 | s++; |
| 773 | } | 798 | } |
| 774 | /* printf(" %d", hist_iterations); */ | 799 | /* printf(" %d", hist_iterations); */ |
| 775 | fputs_stdout(OPT_BATCH_MODE ? "\n" : CLREOS"\r"); | ||
| 776 | } | 800 | } |
| 777 | #undef UPSCALE | 801 | #undef UPSCALE |
| 778 | #undef SHOW_STAT | 802 | #undef SHOW_STAT |
| @@ -844,36 +868,34 @@ static int topmem_sort(char *a, char *b) | |||
| 844 | } | 868 | } |
| 845 | 869 | ||
| 846 | /* display header info (meminfo / loadavg) */ | 870 | /* display header info (meminfo / loadavg) */ |
| 847 | static void display_topmem_header(int *lines_rem_p) | 871 | static void display_topmem_header(void) |
| 848 | { | 872 | { |
| 849 | unsigned long meminfo[MI_MAX]; | 873 | unsigned long meminfo[MI_MAX]; |
| 850 | 874 | ||
| 851 | parse_meminfo(meminfo); | 875 | parse_meminfo(meminfo); |
| 852 | 876 | ||
| 853 | snprintf(line_buf, LINE_BUF_SIZE, | 877 | sprintf(G.line_buf, |
| 854 | "Mem total:%lu anon:%lu map:%lu free:%lu", | 878 | "Mem total:%lu anon:%lu map:%lu free:%lu", |
| 855 | meminfo[MI_MEMTOTAL], | 879 | meminfo[MI_MEMTOTAL], |
| 856 | meminfo[MI_ANONPAGES], | 880 | meminfo[MI_ANONPAGES], |
| 857 | meminfo[MI_MAPPED], | 881 | meminfo[MI_MAPPED], |
| 858 | meminfo[MI_MEMFREE]); | 882 | meminfo[MI_MEMFREE]); |
| 859 | printf(OPT_BATCH_MODE ? "%.*s\n" : HOME"%.*s"CLREOL"\n", G.scr_width - 1, line_buf); | 883 | print_line_buf(); |
| 860 | 884 | ||
| 861 | snprintf(line_buf, LINE_BUF_SIZE, | 885 | sprintf(G.line_buf, |
| 862 | " slab:%lu buf:%lu cache:%lu dirty:%lu write:%lu", | 886 | " slab:%lu buf:%lu cache:%lu dirty:%lu write:%lu", |
| 863 | meminfo[MI_SLAB], | 887 | meminfo[MI_SLAB], |
| 864 | meminfo[MI_BUFFERS], | 888 | meminfo[MI_BUFFERS], |
| 865 | meminfo[MI_CACHED], | 889 | meminfo[MI_CACHED], |
| 866 | meminfo[MI_DIRTY], | 890 | meminfo[MI_DIRTY], |
| 867 | meminfo[MI_WRITEBACK]); | 891 | meminfo[MI_WRITEBACK]); |
| 868 | printf(OPT_BATCH_MODE ? "%.*s\n" : "%.*s"CLREOL"\n", G.scr_width - 1, line_buf); | 892 | print_line_buf(); |
| 869 | 893 | ||
| 870 | snprintf(line_buf, LINE_BUF_SIZE, | 894 | sprintf(G.line_buf, |
| 871 | "Swap total:%lu free:%lu", // TODO: % used? | 895 | "Swap total:%lu free:%lu", // TODO: % used? |
| 872 | meminfo[MI_SWAPTOTAL], | 896 | meminfo[MI_SWAPTOTAL], |
| 873 | meminfo[MI_SWAPFREE]); | 897 | meminfo[MI_SWAPFREE]); |
| 874 | printf(OPT_BATCH_MODE ? "%.*s\n" : "%.*s"CLREOL"\n", G.scr_width - 1, line_buf); | 898 | print_line_buf(); |
| 875 | |||
| 876 | (*lines_rem_p) -= 3; | ||
| 877 | } | 899 | } |
| 878 | 900 | ||
| 879 | /* see http://en.wikipedia.org/wiki/Tera */ | 901 | /* see http://en.wikipedia.org/wiki/Tera */ |
| @@ -886,67 +908,57 @@ static void ulltoa4_and_space(unsigned long long ul, char buf[5]) | |||
| 886 | smart_ulltoa4(ul, buf, " mgtpezy")[0] = ' '; | 908 | smart_ulltoa4(ul, buf, " mgtpezy")[0] = ' '; |
| 887 | } | 909 | } |
| 888 | 910 | ||
| 889 | static NOINLINE void display_topmem_process_list(int lines_rem) | 911 | static NOINLINE void display_topmem_process_list(void) |
| 890 | { | 912 | { |
| 891 | #define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK" | 913 | #define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK" |
| 892 | #define MIN_WIDTH sizeof(HDR_STR) | 914 | #define MIN_WIDTH sizeof(HDR_STR) |
| 893 | const topmem_status_t *s = topmem + G_scroll_ofs; | 915 | const topmem_status_t *s = topmem + G_scroll_ofs; |
| 894 | char *cp, ch; | 916 | char *cp, ch; |
| 895 | 917 | ||
| 896 | display_topmem_header(&lines_rem); | 918 | display_topmem_header(); |
| 897 | 919 | ||
| 898 | strcpy(line_buf, HDR_STR " COMMAND"); | 920 | strcpy(G.line_buf, HDR_STR " COMMAND"); |
| 899 | /* Mark the ^FIELD^ we sort by */ | 921 | /* Mark the ^FIELD^ we sort by */ |
| 900 | cp = &line_buf[5 + sort_field * 6]; | 922 | cp = &G.line_buf[5 + sort_field * 6]; |
| 901 | ch = "^_"[inverted]; | 923 | ch = "^_"[inverted]; |
| 902 | cp[6] = ch; | 924 | cp[6] = ch; |
| 903 | do *cp++ = ch; while (*cp == ' '); | 925 | do *cp++ = ch; while (*cp == ' '); |
| 926 | print_line_bold(); | ||
| 904 | 927 | ||
| 905 | printf(OPT_BATCH_MODE ? "%.*s" : REVERSE"%.*s"NORMAL CLREOL, G.scr_width - 1, line_buf); | 928 | if (G.lines_remaining > ntop - G_scroll_ofs) |
| 906 | lines_rem--; | 929 | G.lines_remaining = ntop - G_scroll_ofs; |
| 907 | 930 | while (G.lines_remaining > 0) { | |
| 908 | if (lines_rem > ntop - G_scroll_ofs) | ||
| 909 | lines_rem = ntop - G_scroll_ofs; | ||
| 910 | while (--lines_rem >= 0) { | ||
| 911 | /* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */ | 931 | /* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */ |
| 912 | int n = sprintf(line_buf, "%5u ", s->pid); | 932 | int n = sprintf(G.line_buf, "%5u ", s->pid); |
| 913 | if (n > 7) { | 933 | if (n > 7) { |
| 914 | /* PID is 7 chars long (up to 4194304) */ | 934 | /* PID is 7 chars long (up to 4194304) */ |
| 915 | ulltoa4_and_space(s->vsz , &line_buf[8]); | 935 | ulltoa4_and_space(s->vsz , &G.line_buf[8]); |
| 916 | ulltoa4_and_space(s->vszrw, &line_buf[8+5]); | 936 | ulltoa4_and_space(s->vszrw, &G.line_buf[8+5]); |
| 917 | /* the next field (RSS) starts at 8+10 = 3*6 */ | 937 | /* the next field (RSS) starts at 8+10 = 3*6 */ |
| 918 | } else { | 938 | } else { |
| 919 | if (n == 7) /* PID is 6 chars long */ | 939 | if (n == 7) /* PID is 6 chars long */ |
| 920 | ulltoa4_and_space(s->vsz, &line_buf[7]); | 940 | ulltoa4_and_space(s->vsz, &G.line_buf[7]); |
| 921 | /* the next field (VSZRW) starts at 7+5 = 2*6 */ | 941 | /* the next field (VSZRW) starts at 7+5 = 2*6 */ |
| 922 | else /* PID is 5 chars or less */ | 942 | else /* PID is 5 chars or less */ |
| 923 | ulltoa5_and_space(s->vsz, &line_buf[6]); | 943 | ulltoa5_and_space(s->vsz, &G.line_buf[6]); |
| 924 | ulltoa5_and_space(s->vszrw, &line_buf[2*6]); | 944 | ulltoa5_and_space(s->vszrw, &G.line_buf[2*6]); |
| 925 | } | 945 | } |
| 926 | ulltoa5_and_space(s->rss , &line_buf[3*6]); | 946 | ulltoa5_and_space(s->rss , &G.line_buf[3*6]); |
| 927 | ulltoa5_and_space(s->rss_sh , &line_buf[4*6]); | 947 | ulltoa5_and_space(s->rss_sh , &G.line_buf[4*6]); |
| 928 | ulltoa5_and_space(s->dirty , &line_buf[5*6]); | 948 | ulltoa5_and_space(s->dirty , &G.line_buf[5*6]); |
| 929 | ulltoa5_and_space(s->dirty_sh, &line_buf[6*6]); | 949 | ulltoa5_and_space(s->dirty_sh, &G.line_buf[6*6]); |
| 930 | ulltoa5_and_space(s->stack , &line_buf[7*6]); | 950 | ulltoa5_and_space(s->stack , &G.line_buf[7*6]); |
| 931 | line_buf[8*6] = '\0'; | 951 | G.line_buf[8*6] = '\0'; |
| 932 | if ((int)(G.scr_width - MIN_WIDTH) > 1) | 952 | if ((int)(G.scr_width - MIN_WIDTH) > 1) |
| 933 | read_cmdline(&line_buf[8*6], G.scr_width - MIN_WIDTH, s->pid, s->comm); | 953 | read_cmdline(&G.line_buf[8*6], G.scr_width - MIN_WIDTH, s->pid, s->comm); |
| 934 | printf(OPT_BATCH_MODE ? "\n""%.*s" : "\n""%.*s"CLREOL, G.scr_width, line_buf); | 954 | print_line_buf(); |
| 935 | s++; | 955 | s++; |
| 936 | } | 956 | } |
| 937 | fputs_stdout(OPT_BATCH_MODE ? "\n" : CLREOS"\r"); | ||
| 938 | #undef HDR_STR | 957 | #undef HDR_STR |
| 939 | #undef MIN_WIDTH | 958 | #undef MIN_WIDTH |
| 940 | } | 959 | } |
| 941 | 960 | ||
| 942 | #else | 961 | #endif /* end TOPMEM support */ |
| 943 | //void display_topmem_process_list(int lines_rem); | ||
| 944 | //int topmem_sort(char *a, char *b); | ||
| 945 | #endif /* TOPMEM */ | ||
| 946 | |||
| 947 | /* | ||
| 948 | * end TOPMEM support | ||
| 949 | */ | ||
| 950 | 962 | ||
| 951 | enum { | 963 | enum { |
| 952 | TOP_MASK = 0 | 964 | TOP_MASK = 0 |
| @@ -1228,7 +1240,6 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |||
| 1228 | } | 1240 | } |
| 1229 | #endif | 1241 | #endif |
| 1230 | 1242 | ||
| 1231 | /* change to /proc */ | ||
| 1232 | xchdir("/proc"); | 1243 | xchdir("/proc"); |
| 1233 | 1244 | ||
| 1234 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE | 1245 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE |
| @@ -1340,14 +1351,16 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |||
| 1340 | } | 1351 | } |
| 1341 | #endif | 1352 | #endif |
| 1342 | IF_FEATURE_TOP_INTERACTIVE(redraw:) | 1353 | IF_FEATURE_TOP_INTERACTIVE(redraw:) |
| 1354 | G.lines_remaining = G.lines; | ||
| 1343 | IF_FEATURE_TOPMEM(if (scan_mask != TOPMEM_MASK)) { | 1355 | IF_FEATURE_TOPMEM(if (scan_mask != TOPMEM_MASK)) { |
| 1344 | display_process_list(G.lines); | 1356 | display_process_list(); |
| 1345 | } | 1357 | } |
| 1346 | #if ENABLE_FEATURE_TOPMEM | 1358 | #if ENABLE_FEATURE_TOPMEM |
| 1347 | else { /* TOPMEM */ | 1359 | else { /* TOPMEM */ |
| 1348 | display_topmem_process_list(G.lines); | 1360 | display_topmem_process_list(); |
| 1349 | } | 1361 | } |
| 1350 | #endif | 1362 | #endif |
| 1363 | print_end(); | ||
| 1351 | fflush_all(); | 1364 | fflush_all(); |
| 1352 | if (iterations >= 0 && !--iterations) | 1365 | if (iterations >= 0 && !--iterations) |
| 1353 | break; | 1366 | break; |
| @@ -1369,7 +1382,8 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |||
| 1369 | #endif | 1382 | #endif |
| 1370 | } /* end of "while (not Q)" */ | 1383 | } /* end of "while (not Q)" */ |
| 1371 | 1384 | ||
| 1372 | bb_putchar('\n'); | 1385 | if (!OPT_BATCH_MODE) |
| 1386 | bb_putchar('\n'); | ||
| 1373 | #if ENABLE_FEATURE_TOP_INTERACTIVE | 1387 | #if ENABLE_FEATURE_TOP_INTERACTIVE |
| 1374 | reset_term(); | 1388 | reset_term(); |
| 1375 | #endif | 1389 | #endif |
