aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2012-09-21 13:04:37 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2012-09-21 13:04:37 +0200
commit2fb8d0dee974622c52e446a02d066cccc4768bbf (patch)
tree1158413d0b22e62a8ffb8bfc5a85df568af82a00
parent3c62bbae94642e6d05bc9f900bbdb5173d26cc51 (diff)
downloadbusybox-w32-2fb8d0dee974622c52e446a02d066cccc4768bbf.tar.gz
busybox-w32-2fb8d0dee974622c52e446a02d066cccc4768bbf.tar.bz2
busybox-w32-2fb8d0dee974622c52e446a02d066cccc4768bbf.zip
top: implement scrolling up/down (_very_ useful)
function old new delta handle_input 494 564 +70 top_main 928 947 +19 display_topmem_process_list 363 381 +18 display_process_list 1442 1453 +11 clearmems 38 28 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/1 up/down: 118/-10) Total: 108 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--procps/Config.src54
-rw-r--r--procps/top.c130
2 files changed, 110 insertions, 74 deletions
diff --git a/procps/Config.src b/procps/Config.src
index 5cd47c84f..527d9ee0c 100644
--- a/procps/Config.src
+++ b/procps/Config.src
@@ -140,60 +140,6 @@ config BB_SYSCTL
140 help 140 help
141 Configure kernel parameters at runtime. 141 Configure kernel parameters at runtime.
142 142
143config TOP
144 bool "top"
145 default y
146 help
147 The top program provides a dynamic real-time view of a running
148 system.
149
150config FEATURE_TOP_CPU_USAGE_PERCENTAGE
151 bool "Show CPU per-process usage percentage"
152 default y
153 depends on TOP
154 help
155 Make top display CPU usage for each process.
156 This adds about 2k.
157
158config FEATURE_TOP_CPU_GLOBAL_PERCENTS
159 bool "Show CPU global usage percentage"
160 default y
161 depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
162 help
163 Makes top display "CPU: NN% usr NN% sys..." line.
164 This adds about 0.5k.
165
166config FEATURE_TOP_SMP_CPU
167 bool "SMP CPU usage display ('c' key)"
168 default y
169 depends on FEATURE_TOP_CPU_GLOBAL_PERCENTS
170 help
171 Allow 'c' key to switch between individual/cumulative CPU stats
172 This adds about 0.5k.
173
174config FEATURE_TOP_DECIMALS
175 bool "Show 1/10th of a percent in CPU/mem statistics"
176 default y
177 depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
178 help
179 Show 1/10th of a percent in CPU/mem statistics.
180 This adds about 0.3k.
181
182config FEATURE_TOP_SMP_PROCESS
183 bool "Show CPU process runs on ('j' field)"
184 default y
185 depends on TOP
186 help
187 Show CPU where process was last found running on.
188 This is the 'j' field.
189
190config FEATURE_TOPMEM
191 bool "Topmem command ('s' key)"
192 default y
193 depends on TOP
194 help
195 Enable 's' in top (gives lots of memory info).
196
197config FEATURE_SHOW_THREADS 143config FEATURE_SHOW_THREADS
198 bool "Support for showing threads in ps/pstree/top" 144 bool "Support for showing threads in ps/pstree/top"
199 default y 145 default y
diff --git a/procps/top.c b/procps/top.c
index 15eb624cc..00cb44896 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -50,6 +50,60 @@
50 * chroot . ./top -bn1 >top1.out 50 * chroot . ./top -bn1 >top1.out
51 */ 51 */
52 52
53//config:config TOP
54//config: bool "top"
55//config: default y
56//config: help
57//config: The top program provides a dynamic real-time view of a running
58//config: system.
59//config:
60//config:config FEATURE_TOP_CPU_USAGE_PERCENTAGE
61//config: bool "Show CPU per-process usage percentage"
62//config: default y
63//config: depends on TOP
64//config: help
65//config: Make top display CPU usage for each process.
66//config: This adds about 2k.
67//config:
68//config:config FEATURE_TOP_CPU_GLOBAL_PERCENTS
69//config: bool "Show CPU global usage percentage"
70//config: default y
71//config: depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
72//config: help
73//config: Makes top display "CPU: NN% usr NN% sys..." line.
74//config: This adds about 0.5k.
75//config:
76//config:config FEATURE_TOP_SMP_CPU
77//config: bool "SMP CPU usage display ('c' key)"
78//config: default y
79//config: depends on FEATURE_TOP_CPU_GLOBAL_PERCENTS
80//config: help
81//config: Allow 'c' key to switch between individual/cumulative CPU stats
82//config: This adds about 0.5k.
83//config:
84//config:config FEATURE_TOP_DECIMALS
85//config: bool "Show 1/10th of a percent in CPU/mem statistics"
86//config: default y
87//config: depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
88//config: help
89//config: Show 1/10th of a percent in CPU/mem statistics.
90//config: This adds about 0.3k.
91//config:
92//config:config FEATURE_TOP_SMP_PROCESS
93//config: bool "Show CPU process runs on ('j' field)"
94//config: default y
95//config: depends on TOP
96//config: help
97//config: Show CPU where process was last found running on.
98//config: This is the 'j' field.
99//config:
100//config:config FEATURE_TOPMEM
101//config: bool "Topmem command ('s' key)"
102//config: default y
103//config: depends on TOP
104//config: help
105//config: Enable 's' in top (gives lots of memory info).
106
53#include "libbb.h" 107#include "libbb.h"
54 108
55 109
@@ -101,6 +155,8 @@ struct globals {
101#endif 155#endif
102#if ENABLE_FEATURE_USE_TERMIOS 156#if ENABLE_FEATURE_USE_TERMIOS
103 struct termios initial_settings; 157 struct termios initial_settings;
158 unsigned lines; /* screen height */
159 int scroll_ofs;
104#endif 160#endif
105#if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 161#if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
106 cmp_funcp sort_function[1]; 162 cmp_funcp sort_function[1];
@@ -118,6 +174,9 @@ struct globals {
118 jiffy_counts_t *cpu_jif, *cpu_prev_jif; 174 jiffy_counts_t *cpu_jif, *cpu_prev_jif;
119 int num_cpus; 175 int num_cpus;
120#endif 176#endif
177#if ENABLE_FEATURE_USE_TERMIOS
178 char kbd_input[KEYCODE_BUFFER_SIZE];
179#endif
121 char line_buf[80]; 180 char line_buf[80];
122}; //FIX_ALIASING; - large code growth 181}; //FIX_ALIASING; - large code growth
123enum { LINE_BUF_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line_buf) }; 182enum { LINE_BUF_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line_buf) };
@@ -602,9 +661,9 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width)
602 661
603 /* Ok, all preliminary data is ready, go through the list */ 662 /* Ok, all preliminary data is ready, go through the list */
604 scr_width += 2; /* account for leading '\n' and trailing NUL */ 663 scr_width += 2; /* account for leading '\n' and trailing NUL */
605 if (lines_rem > ntop) 664 if (lines_rem > ntop - G.scroll_ofs)
606 lines_rem = ntop; 665 lines_rem = ntop - G.scroll_ofs;
607 s = top; 666 s = top + G.scroll_ofs;
608 while (--lines_rem >= 0) { 667 while (--lines_rem >= 0) {
609 unsigned col; 668 unsigned col;
610 CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); 669 CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift);
@@ -649,7 +708,6 @@ static void clearmems(void)
649 clear_username_cache(); 708 clear_username_cache();
650 free(top); 709 free(top);
651 top = NULL; 710 top = NULL;
652 ntop = 0;
653} 711}
654 712
655#if ENABLE_FEATURE_USE_TERMIOS 713#if ENABLE_FEATURE_USE_TERMIOS
@@ -793,7 +851,7 @@ static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width)
793{ 851{
794#define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK" 852#define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK"
795#define MIN_WIDTH sizeof(HDR_STR) 853#define MIN_WIDTH sizeof(HDR_STR)
796 const topmem_status_t *s = topmem; 854 const topmem_status_t *s = topmem + G.scroll_ofs;
797 855
798 display_topmem_header(scr_width, &lines_rem); 856 display_topmem_header(scr_width, &lines_rem);
799 strcpy(line_buf, HDR_STR " COMMAND"); 857 strcpy(line_buf, HDR_STR " COMMAND");
@@ -801,8 +859,8 @@ static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width)
801 printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, line_buf); 859 printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, line_buf);
802 lines_rem--; 860 lines_rem--;
803 861
804 if (lines_rem > ntop) 862 if (lines_rem > ntop - G.scroll_ofs)
805 lines_rem = ntop; 863 lines_rem = ntop - G.scroll_ofs;
806 while (--lines_rem >= 0) { 864 while (--lines_rem >= 0) {
807 /* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */ 865 /* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */
808 ulltoa6_and_space(s->pid , &line_buf[0*6]); 866 ulltoa6_and_space(s->pid , &line_buf[0*6]);
@@ -856,26 +914,57 @@ enum {
856#if ENABLE_FEATURE_USE_TERMIOS 914#if ENABLE_FEATURE_USE_TERMIOS
857static unsigned handle_input(unsigned scan_mask, unsigned interval) 915static unsigned handle_input(unsigned scan_mask, unsigned interval)
858{ 916{
859 unsigned char c;
860 struct pollfd pfd[1]; 917 struct pollfd pfd[1];
861 918
862 pfd[0].fd = 0; 919 pfd[0].fd = 0;
863 pfd[0].events = POLLIN; 920 pfd[0].events = POLLIN;
864 921
865 while (1) { 922 while (1) {
866 if (safe_poll(pfd, 1, interval * 1000) <= 0) 923 int32_t c;
867 return scan_mask;
868 interval = 0;
869 924
870 if (safe_read(STDIN_FILENO, &c, 1) != 1) { /* error/EOF? */ 925 c = read_key(STDIN_FILENO, G.kbd_input, interval * 1000);
926 if (c == -1 && errno != EAGAIN) {
927 /* error/EOF */
871 option_mask32 |= OPT_EOF; 928 option_mask32 |= OPT_EOF;
872 return scan_mask; 929 break;
873 } 930 }
931 interval = 0;
874 932
875 if (c == initial_settings.c_cc[VINTR]) 933 if (c == initial_settings.c_cc[VINTR])
876 return EXIT_MASK; 934 return EXIT_MASK;
877 if (c == initial_settings.c_cc[VEOF]) 935 if (c == initial_settings.c_cc[VEOF])
878 return EXIT_MASK; 936 return EXIT_MASK;
937
938 if (c == KEYCODE_UP) {
939 G.scroll_ofs--;
940 goto normalize_ofs;
941 }
942 if (c == KEYCODE_DOWN) {
943 G.scroll_ofs++;
944 goto normalize_ofs;
945 }
946 if (c == KEYCODE_HOME) {
947 G.scroll_ofs = 0;
948 break;
949 }
950 if (c == KEYCODE_END) {
951 G.scroll_ofs = ntop - G.lines / 2;
952 goto normalize_ofs;
953 }
954 if (c == KEYCODE_PAGEUP) {
955 G.scroll_ofs -= G.lines / 2;
956 goto normalize_ofs;
957 }
958 if (c == KEYCODE_PAGEDOWN) {
959 G.scroll_ofs += G.lines / 2;
960 normalize_ofs:
961 if (G.scroll_ofs >= ntop)
962 G.scroll_ofs = ntop - 1;
963 if (G.scroll_ofs < 0)
964 G.scroll_ofs = 0;
965 break;
966 }
967
879 c |= 0x20; /* lowercase */ 968 c |= 0x20; /* lowercase */
880 if (c == 'q') 969 if (c == 'q')
881 return EXIT_MASK; 970 return EXIT_MASK;
@@ -1011,7 +1100,7 @@ int top_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1011int top_main(int argc UNUSED_PARAM, char **argv) 1100int top_main(int argc UNUSED_PARAM, char **argv)
1012{ 1101{
1013 int iterations; 1102 int iterations;
1014 unsigned lines, col; 1103 unsigned col;
1015 unsigned interval; 1104 unsigned interval;
1016 char *str_interval, *str_iterations; 1105 char *str_interval, *str_iterations;
1017 unsigned scan_mask = TOP_MASK; 1106 unsigned scan_mask = TOP_MASK;
@@ -1081,15 +1170,15 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1081 procps_status_t *p = NULL; 1170 procps_status_t *p = NULL;
1082 1171
1083 if (OPT_BATCH_MODE) { 1172 if (OPT_BATCH_MODE) {
1084 lines = INT_MAX; 1173 G.lines = INT_MAX;
1085 col = LINE_BUF_SIZE - 2; /* +2 bytes for '\n', NUL */ 1174 col = LINE_BUF_SIZE - 2; /* +2 bytes for '\n', NUL */
1086 } else { 1175 } else {
1087 lines = 24; /* default */ 1176 G.lines = 24; /* default */
1088 col = 79; 1177 col = 79;
1089#if ENABLE_FEATURE_USE_TERMIOS 1178#if ENABLE_FEATURE_USE_TERMIOS
1090 /* We output to stdout, we need size of stdout (not stdin)! */ 1179 /* We output to stdout, we need size of stdout (not stdin)! */
1091 get_terminal_width_height(STDOUT_FILENO, &col, &lines); 1180 get_terminal_width_height(STDOUT_FILENO, &col, &G.lines);
1092 if (lines < 5 || col < 10) { 1181 if (G.lines < 5 || col < 10) {
1093 sleep(interval); 1182 sleep(interval);
1094 continue; 1183 continue;
1095 } 1184 }
@@ -1099,6 +1188,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1099 } 1188 }
1100 1189
1101 /* read process IDs & status for all the processes */ 1190 /* read process IDs & status for all the processes */
1191 ntop = 0;
1102 while ((p = procps_scan(p, scan_mask)) != NULL) { 1192 while ((p = procps_scan(p, scan_mask)) != NULL) {
1103 int n; 1193 int n;
1104#if ENABLE_FEATURE_TOPMEM 1194#if ENABLE_FEATURE_TOPMEM
@@ -1165,10 +1255,10 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1165 } 1255 }
1166#endif 1256#endif
1167 if (scan_mask != TOPMEM_MASK) 1257 if (scan_mask != TOPMEM_MASK)
1168 display_process_list(lines, col); 1258 display_process_list(G.lines, col);
1169#if ENABLE_FEATURE_TOPMEM 1259#if ENABLE_FEATURE_TOPMEM
1170 else 1260 else
1171 display_topmem_process_list(lines, col); 1261 display_topmem_process_list(G.lines, col);
1172#endif 1262#endif
1173 clearmems(); 1263 clearmems();
1174 if (iterations >= 0 && !--iterations) 1264 if (iterations >= 0 && !--iterations)