aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2006-02-13 22:04:27 +0000
committerRob Landley <rob@landley.net>2006-02-13 22:04:27 +0000
commitb2804551a0fafa83d0c5d602761e787f40821519 (patch)
tree9ca7e94ed410676810005e9d95ceaee6a70c6518
parent90632d021cecfb9db88f047ad195f91803b66c4a (diff)
downloadbusybox-w32-b2804551a0fafa83d0c5d602761e787f40821519.tar.gz
busybox-w32-b2804551a0fafa83d0c5d602761e787f40821519.tar.bz2
busybox-w32-b2804551a0fafa83d0c5d602761e787f40821519.zip
Cleanups from Denis Vlasenko.
-rw-r--r--libbb/procps.c37
-rw-r--r--procps/top.c324
2 files changed, 185 insertions, 176 deletions
diff --git a/libbb/procps.c b/libbb/procps.c
index 3e863b0de..09561b533 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -13,9 +13,24 @@
13#include <stdlib.h> 13#include <stdlib.h>
14#include <unistd.h> 14#include <unistd.h>
15#include <asm/page.h> 15#include <asm/page.h>
16#include <fcntl.h>
16 17
17#include "libbb.h" 18#include "libbb.h"
18 19
20
21static int read_to_buf(char *filename, void *buf, int bufsize)
22{
23 int fd;
24
25 fd = open(filename, O_RDONLY);
26 if(fd < 0)
27 return -1;
28 bufsize = read(fd, buf, bufsize);
29 close(fd);
30 return bufsize;
31}
32
33
19extern procps_status_t * procps_scan(int save_user_arg0) 34extern procps_status_t * procps_scan(int save_user_arg0)
20{ 35{
21 static DIR *dir; 36 static DIR *dir;
@@ -24,8 +39,8 @@ extern procps_status_t * procps_scan(int save_user_arg0)
24 char *name; 39 char *name;
25 int n; 40 int n;
26 char status[32]; 41 char status[32];
42 char *status_tail;
27 char buf[1024]; 43 char buf[1024];
28 FILE *fp;
29 procps_status_t curstatus; 44 procps_status_t curstatus;
30 int pid; 45 int pid;
31 long tasknice; 46 long tasknice;
@@ -50,18 +65,14 @@ extern procps_status_t * procps_scan(int save_user_arg0)
50 pid = atoi(name); 65 pid = atoi(name);
51 curstatus.pid = pid; 66 curstatus.pid = pid;
52 67
53 sprintf(status, "/proc/%d", pid); 68 status_tail = status + sprintf(status, "/proc/%d", pid);
54 if(stat(status, &sb)) 69 if(stat(status, &sb))
55 continue; 70 continue;
56 bb_getpwuid(curstatus.user, sb.st_uid, sizeof(curstatus.user)); 71 bb_getpwuid(curstatus.user, sb.st_uid, sizeof(curstatus.user));
57 72
58 sprintf(status, "/proc/%d/stat", pid); 73 strcpy(status_tail, "/stat");
59 74 n = read_to_buf(status, buf, sizeof(buf));
60 if((fp = fopen(status, "r")) == NULL) 75 if(n < 0)
61 continue;
62 name = fgets(buf, sizeof(buf), fp);
63 fclose(fp);
64 if(name == NULL)
65 continue; 76 continue;
66 name = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */ 77 name = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */
67 if(name == 0 || name[1] != ' ') 78 if(name == 0 || name[1] != ' ')
@@ -113,10 +124,9 @@ extern procps_status_t * procps_scan(int save_user_arg0)
113#endif 124#endif
114 125
115 if(save_user_arg0) { 126 if(save_user_arg0) {
116 sprintf(status, "/proc/%d/cmdline", pid); 127 strcpy(status_tail, "/cmdline");
117 if((fp = fopen(status, "r")) == NULL) 128 n = read_to_buf(status, buf, sizeof(buf));
118 continue; 129 if(n > 0) {
119 if((n=fread(buf, 1, sizeof(buf)-1, fp)) > 0) {
120 if(buf[n-1]=='\n') 130 if(buf[n-1]=='\n')
121 buf[--n] = 0; 131 buf[--n] = 0;
122 name = buf; 132 name = buf;
@@ -131,7 +141,6 @@ extern procps_status_t * procps_scan(int save_user_arg0)
131 curstatus.cmd = strdup(buf); 141 curstatus.cmd = strdup(buf);
132 /* if NULL it work true also */ 142 /* if NULL it work true also */
133 } 143 }
134 fclose(fp);
135 } 144 }
136 return memcpy(&ret_status, &curstatus, sizeof(procps_status_t)); 145 return memcpy(&ret_status, &curstatus, sizeof(procps_status_t));
137 } 146 }
diff --git a/procps/top.c b/procps/top.c
index fbe060dfe..17addd0f5 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -53,13 +53,13 @@ static int ntop;
53#ifdef CONFIG_FEATURE_USE_TERMIOS 53#ifdef CONFIG_FEATURE_USE_TERMIOS
54static int pid_sort (procps_status_t *P, procps_status_t *Q) 54static int pid_sort (procps_status_t *P, procps_status_t *Q)
55{ 55{
56 return (Q->pid - P->pid); 56 return (Q->pid - P->pid);
57} 57}
58#endif 58#endif
59 59
60static int mem_sort (procps_status_t *P, procps_status_t *Q) 60static int mem_sort (procps_status_t *P, procps_status_t *Q)
61{ 61{
62 return (int)(Q->rss - P->rss); 62 return (int)(Q->rss - P->rss);
63} 63}
64 64
65#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 65#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
@@ -69,32 +69,32 @@ static cmp_t sort_function[sort_depth];
69 69
70static int pcpu_sort (procps_status_t *P, procps_status_t *Q) 70static int pcpu_sort (procps_status_t *P, procps_status_t *Q)
71{ 71{
72 return (Q->pcpu - P->pcpu); 72 return (Q->pcpu - P->pcpu);
73} 73}
74 74
75static int time_sort (procps_status_t *P, procps_status_t *Q) 75static int time_sort (procps_status_t *P, procps_status_t *Q)
76{ 76{
77 return (int)((Q->stime + Q->utime) - (P->stime + P->utime)); 77 return (int)((Q->stime + Q->utime) - (P->stime + P->utime));
78} 78}
79 79
80static int mult_lvl_cmp(void* a, void* b) { 80static int mult_lvl_cmp(void* a, void* b) {
81 int i, cmp_val; 81 int i, cmp_val;
82 82
83 for(i = 0; i < sort_depth; i++) { 83 for(i = 0; i < sort_depth; i++) {
84 cmp_val = (*sort_function[i])(a, b); 84 cmp_val = (*sort_function[i])(a, b);
85 if (cmp_val != 0) 85 if (cmp_val != 0)
86 return cmp_val; 86 return cmp_val;
87 } 87 }
88 return 0; 88 return 0;
89} 89}
90 90
91/* This structure stores some critical information from one frame to 91/* This structure stores some critical information from one frame to
92 the next. mostly used for sorting. Added cumulative and resident fields. */ 92 the next. mostly used for sorting. Added cumulative and resident fields. */
93struct save_hist { 93struct save_hist {
94 int ticks; 94 int ticks;
95 int pid; 95 int pid;
96 int utime; 96 int utime;
97 int stime; 97 int stime;
98}; 98};
99 99
100/* 100/*
@@ -130,152 +130,152 @@ static unsigned long Hertz;
130 * 130 *
131 */ 131 */
132 132
133#define FILE_TO_BUF(filename, fd) do{ \ 133static int file_to_buf(char *buf, int bufsize, char *filename, int *d)
134 if (fd == -1 && (fd = open(filename, O_RDONLY)) == -1) { \ 134{
135 bb_perror_msg_and_die("/proc not be mounted?"); \ 135 int fd = *d;
136 } \ 136 int sz;
137 lseek(fd, 0L, SEEK_SET); \ 137
138 if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) { \ 138 if (fd == -1) {
139 bb_perror_msg_and_die("%s", filename); \ 139 fd = open(filename, O_RDONLY);
140 } \ 140 if(fd == -1)
141 buf[local_n] = '\0'; \ 141 bb_perror_msg_and_die("is /proc mounted?");
142}while(0) 142 } else {
143 143 lseek(fd, 0L, SEEK_SET);
144#define FILE_TO_BUF2(filename, fd) do{ \ 144 }
145 lseek(fd, 0L, SEEK_SET); \ 145 sz = read(fd, buf, bufsize - 1);
146 if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) { \ 146 if (sz < 0) {
147 bb_perror_msg_and_die("%s", filename); \ 147 bb_perror_msg_and_die("%s", filename);
148 } \ 148 }
149 buf[local_n] = '\0'; \ 149 buf[sz] = '\0';
150}while(0) 150 *d = fd;
151 151 return sz;
152static void init_Hertz_value(void) { 152}
153 unsigned long user_j, nice_j, sys_j, other_j; /* jiffies (clock ticks) */ 153
154 double up_1, up_2, seconds; 154static void init_Hertz_value(void)
155 unsigned long jiffies, h; 155{
156 char buf[80]; 156 unsigned long user_j, nice_j, sys_j, other_j; /* jiffies (clock ticks) */
157 int uptime_fd = -1; 157 double up_1, up_2, seconds;
158 int stat_fd = -1; 158 unsigned long jiffies, h;
159 159 char buf[80];
160 long smp_num_cpus = sysconf(_SC_NPROCESSORS_CONF); 160 int uptime_fd = -1;
161 161 int stat_fd = -1;
162 if(smp_num_cpus<1) smp_num_cpus=1; 162
163 do { 163 long smp_num_cpus = sysconf(_SC_NPROCESSORS_CONF);
164 int local_n; 164
165 165 if(smp_num_cpus<1) smp_num_cpus=1;
166 FILE_TO_BUF("uptime", uptime_fd); 166
167 up_1 = strtod(buf, 0); 167 do {
168 FILE_TO_BUF("stat", stat_fd); 168 file_to_buf(buf, sizeof(buf), "uptime", &uptime_fd);
169 sscanf(buf, "cpu %lu %lu %lu %lu", &user_j, &nice_j, &sys_j, &other_j); 169 up_1 = strtod(buf, 0);
170 FILE_TO_BUF2("uptime", uptime_fd); 170 file_to_buf(buf, sizeof(buf), "stat", &stat_fd);
171 up_2 = strtod(buf, 0); 171 sscanf(buf, "cpu %lu %lu %lu %lu", &user_j, &nice_j, &sys_j, &other_j);
172 } while((long)( (up_2-up_1)*1000.0/up_1 )); /* want under 0.1% error */ 172 file_to_buf(buf, sizeof(buf), "uptime", &uptime_fd);
173 173 up_2 = strtod(buf, 0);
174 close(uptime_fd); 174 } while((long)( (up_2-up_1)*1000.0/up_1 )); /* want under 0.1% error */
175 close(stat_fd); 175 close(uptime_fd);
176 176 close(stat_fd);
177 jiffies = user_j + nice_j + sys_j + other_j; 177
178 seconds = (up_1 + up_2) / 2; 178 jiffies = user_j + nice_j + sys_j + other_j;
179 h = (unsigned long)( (double)jiffies/seconds/smp_num_cpus ); 179 seconds = (up_1 + up_2) / 2;
180 /* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */ 180 h = (unsigned long)( (double)jiffies/seconds/smp_num_cpus );
181 switch(h){ 181 /* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */
182 case 30 ... 34 : Hertz = 32; break; /* ia64 emulator */ 182 switch(h) {
183 case 48 ... 52 : Hertz = 50; break; 183 case 30 ... 34 : Hertz = 32; break; /* ia64 emulator */
184 case 58 ... 62 : Hertz = 60; break; 184 case 48 ... 52 : Hertz = 50; break;
185 case 63 ... 65 : Hertz = 64; break; /* StrongARM /Shark */ 185 case 58 ... 62 : Hertz = 60; break;
186 case 95 ... 105 : Hertz = 100; break; /* normal Linux */ 186 case 63 ... 65 : Hertz = 64; break; /* StrongARM /Shark */
187 case 124 ... 132 : Hertz = 128; break; /* MIPS, ARM */ 187 case 95 ... 105 : Hertz = 100; break; /* normal Linux */
188 case 195 ... 204 : Hertz = 200; break; /* normal << 1 */ 188 case 124 ... 132 : Hertz = 128; break; /* MIPS, ARM */
189 case 253 ... 260 : Hertz = 256; break; 189 case 195 ... 204 : Hertz = 200; break; /* normal << 1 */
190 case 295 ... 304 : Hertz = 300; break; /* 3 cpus */ 190 case 253 ... 260 : Hertz = 256; break;
191 case 393 ... 408 : Hertz = 400; break; /* normal << 2 */ 191 case 295 ... 304 : Hertz = 300; break; /* 3 cpus */
192 case 495 ... 504 : Hertz = 500; break; /* 5 cpus */ 192 case 393 ... 408 : Hertz = 400; break; /* normal << 2 */
193 case 595 ... 604 : Hertz = 600; break; /* 6 cpus */ 193 case 495 ... 504 : Hertz = 500; break; /* 5 cpus */
194 case 695 ... 704 : Hertz = 700; break; /* 7 cpus */ 194 case 595 ... 604 : Hertz = 600; break; /* 6 cpus */
195 case 790 ... 808 : Hertz = 800; break; /* normal << 3 */ 195 case 695 ... 704 : Hertz = 700; break; /* 7 cpus */
196 case 895 ... 904 : Hertz = 900; break; /* 9 cpus */ 196 case 790 ... 808 : Hertz = 800; break; /* normal << 3 */
197 case 990 ... 1010 : Hertz = 1000; break; /* ARM */ 197 case 895 ... 904 : Hertz = 900; break; /* 9 cpus */
198 case 1015 ... 1035 : Hertz = 1024; break; /* Alpha, ia64 */ 198 case 990 ... 1010 : Hertz = 1000; break; /* ARM */
199 case 1095 ... 1104 : Hertz = 1100; break; /* 11 cpus */ 199 case 1015 ... 1035 : Hertz = 1024; break; /* Alpha, ia64 */
200 case 1180 ... 1220 : Hertz = 1200; break; /* Alpha */ 200 case 1095 ... 1104 : Hertz = 1100; break; /* 11 cpus */
201 default: 201 case 1180 ... 1220 : Hertz = 1200; break; /* Alpha */
202 /* If 32-bit or big-endian (not Alpha or ia64), assume HZ is 100. */ 202 default:
203 Hertz = (sizeof(long)==sizeof(int) || htons(999)==999) ? 100UL : 1024UL; 203 /* If 32-bit or big-endian (not Alpha or ia64), assume HZ is 100. */
204 } 204 Hertz = (sizeof(long)==sizeof(int) || htons(999)==999) ? 100UL : 1024UL;
205 }
205} 206}
206 207
207static void do_stats(void) 208static void do_stats(void)
208{ 209{
209 struct timeval t; 210 struct timeval t;
210 static struct timeval oldtime; 211 static struct timeval oldtime;
211 struct timezone timez; 212 struct timezone timez;
212 float elapsed_time; 213 float elapsed_time;
213 214
214 procps_status_t *cur; 215 procps_status_t *cur;
215 int total_time, i, n; 216 int total_time, i, n;
216 static int prev_count; 217 static int prev_count;
217 int systime, usrtime, pid; 218 int systime, usrtime, pid;
218 219
219 struct save_hist *New_save_hist; 220 struct save_hist *New_save_hist;
220 221
221 /* 222 /*
222 * Finds the current time (in microseconds) and calculates the time 223 * Finds the current time (in microseconds) and calculates the time
223 * elapsed since the last update. 224 * elapsed since the last update.
224 */ 225 */
225 gettimeofday(&t, &timez); 226 gettimeofday(&t, &timez);
226 elapsed_time = (t.tv_sec - oldtime.tv_sec) 227 elapsed_time = (t.tv_sec - oldtime.tv_sec)
227 + (float) (t.tv_usec - oldtime.tv_usec) / 1000000.0; 228 + (float) (t.tv_usec - oldtime.tv_usec) / 1000000.0;
228 oldtime.tv_sec = t.tv_sec; 229 oldtime.tv_sec = t.tv_sec;
229 oldtime.tv_usec = t.tv_usec; 230 oldtime.tv_usec = t.tv_usec;
230
231 New_save_hist = alloca(sizeof(struct save_hist)*ntop);
232 /*
233 * Make a pass through the data to get stats.
234 */
235 for(n = 0; n < ntop; n++) {
236 cur = top + n;
237 231
232 New_save_hist = alloca(sizeof(struct save_hist)*ntop);
238 /* 233 /*
239 * Calculate time in cur process. Time is sum of user time 234 * Make a pass through the data to get stats.
240 * (usrtime) plus system time (systime).
241 */ 235 */
242 systime = cur->stime; 236 for(n = 0; n < ntop; n++) {
243 usrtime = cur->utime; 237 cur = top + n;
244 pid = cur->pid; 238
245 total_time = systime + usrtime; 239 /*
246 New_save_hist[n].ticks = total_time; 240 * Calculate time in cur process. Time is sum of user time
247 New_save_hist[n].pid = pid; 241 * (usrtime) plus system time (systime).
248 New_save_hist[n].stime = systime; 242 */
249 New_save_hist[n].utime = usrtime; 243 systime = cur->stime;
250 244 usrtime = cur->utime;
251 /* find matching entry from previous pass */ 245 pid = cur->pid;
252 for (i = 0; i < prev_count; i++) { 246 total_time = systime + usrtime;
253 if (save_history[i].pid == pid) { 247 New_save_hist[n].ticks = total_time;
254 total_time -= save_history[i].ticks; 248 New_save_hist[n].pid = pid;
255 systime -= save_history[i].stime; 249 New_save_hist[n].stime = systime;
256 usrtime -= save_history[i].utime; 250 New_save_hist[n].utime = usrtime;
257 break; 251
258 } 252 /* find matching entry from previous pass */
253 for (i = 0; i < prev_count; i++) {
254 if (save_history[i].pid == pid) {
255 total_time -= save_history[i].ticks;
256 systime -= save_history[i].stime;
257 usrtime -= save_history[i].utime;
258 break;
259 }
260 }
261
262 /*
263 * Calculate percent cpu time for cur task.
264 */
265 i = (total_time * 10 * 100/Hertz) / elapsed_time;
266 if (i > 999)
267 i = 999;
268 cur->pcpu = i;
259 } 269 }
260 270
261 /* 271 /*
262 * Calculate percent cpu time for cur task. 272 * Save cur frame's information.
263 */ 273 */
264 i = (total_time * 10 * 100/Hertz) / elapsed_time; 274 free(save_history);
265 if (i > 999) 275 save_history = memcpy(xmalloc(sizeof(struct save_hist)*n), New_save_hist,
266 i = 999;
267 cur->pcpu = i;
268
269 }
270
271 /*
272 * Save cur frame's information.
273 */
274 free(save_history);
275 save_history = memcpy(xmalloc(sizeof(struct save_hist)*n), New_save_hist,
276 sizeof(struct save_hist)*n); 276 sizeof(struct save_hist)*n);
277 prev_count = n; 277 prev_count = n;
278 qsort(top, n, sizeof(procps_status_t), (void*)mult_lvl_cmp); 278 qsort(top, n, sizeof(procps_status_t), (void*)mult_lvl_cmp);
279} 279}
280#else 280#else
281static cmp_t sort_function; 281static cmp_t sort_function;
@@ -335,7 +335,7 @@ static unsigned long display_generic(void)
335 /* read load average */ 335 /* read load average */
336 fp = bb_xfopen("loadavg", "r"); 336 fp = bb_xfopen("loadavg", "r");
337 if (fscanf(fp, "%f %f %f", &avg1, &avg2, &avg3) != 3) { 337 if (fscanf(fp, "%f %f %f", &avg1, &avg2, &avg3) != 3) {
338 bb_error_msg_and_die("failed to read '%s'", "loadavg"); 338 bb_error_msg_and_die("failed to read 'loadavg'");
339 } 339 }
340 fclose(fp); 340 fclose(fp);
341 341
@@ -352,11 +352,11 @@ static unsigned long display_generic(void)
352 /* output memory info and load average */ 352 /* output memory info and load average */
353 /* clear screen & go to top */ 353 /* clear screen & go to top */
354 printf("\e[H\e[J" "Mem: " 354 printf("\e[H\e[J" "Mem: "
355 "%ldK used, %ldK free, %ldK shrd, %ldK buff, %ldK cached\n", 355 "%ldK used, %ldK free, %ldK shrd, %ldK buff, %ldK cached\n",
356 used, mfree, shared, buffers, cached); 356 used, mfree, shared, buffers, cached);
357 printf("Load average: %.2f, %.2f, %.2f " 357 printf("Load average: %.2f, %.2f, %.2f "
358 "(State: S=sleeping R=running, W=waiting)\n", 358 "(State: S=sleeping R=running, W=waiting)\n",
359 avg1, avg2, avg3); 359 avg1, avg2, avg3);
360 return total; 360 return total;
361} 361}
362 362
@@ -428,7 +428,7 @@ static void reset_term(void)
428#endif /* CONFIG_FEATURE_CLEAN_UP */ 428#endif /* CONFIG_FEATURE_CLEAN_UP */
429} 429}
430 430
431static void sig_catcher (int sig ATTRIBUTE_UNUSED) 431static void sig_catcher(int sig ATTRIBUTE_UNUSED)
432{ 432{
433 reset_term(); 433 reset_term();
434} 434}
@@ -486,11 +486,11 @@ int top_main(int argc, char **argv)
486 486
487 get_terminal_width_height(0, &col, &lines); 487 get_terminal_width_height(0, &col, &lines);
488 if (lines > 4) { 488 if (lines > 4) {
489 lines -= 5; 489 lines -= 5;
490#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 490#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
491 col = col - 80 + 35 - 6; 491 col = col - 80 + 35 - 6;
492#else 492#else
493 col = col - 80 + 35; 493 col = col - 80 + 35;
494#endif 494#endif
495 } 495 }
496#endif /* CONFIG_FEATURE_USE_TERMIOS */ 496#endif /* CONFIG_FEATURE_USE_TERMIOS */
@@ -514,8 +514,8 @@ int top_main(int argc, char **argv)
514 memcpy(top + n, p, sizeof(procps_status_t)); 514 memcpy(top + n, p, sizeof(procps_status_t));
515 } 515 }
516 if (ntop == 0) { 516 if (ntop == 0) {
517 bb_perror_msg_and_die("scandir('/proc')"); 517 bb_error_msg_and_die("Can't find process info in /proc");
518 } 518 }
519#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 519#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
520 if(!Hertz) { 520 if(!Hertz) {
521 init_Hertz_value(); 521 init_Hertz_value();
@@ -523,7 +523,7 @@ int top_main(int argc, char **argv)
523 sleep(1); 523 sleep(1);
524 clearmems(); 524 clearmems();
525 continue; 525 continue;
526 } 526 }
527 do_stats(); 527 do_stats();
528#else 528#else
529 qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function); 529 qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function);