aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2006-04-24 23:13:46 +0000
committerRob Landley <rob@landley.net>2006-04-24 23:13:46 +0000
commit997650b9720a3e1302114f0aa37b7625cdf31b85 (patch)
tree4a8b6741846f00409eff470ec3a83ba7afe75b5d
parent56fbd21fa77145486afea2307bcc52b9f05e3154 (diff)
downloadbusybox-w32-997650b9720a3e1302114f0aa37b7625cdf31b85.tar.gz
busybox-w32-997650b9720a3e1302114f0aa37b7625cdf31b85.tar.bz2
busybox-w32-997650b9720a3e1302114f0aa37b7625cdf31b85.zip
From Denis Vlasenko:
* CPU% = process[i].ticks/sum(process[i].ticks) * busy_cpu_ticks/total_cpu_ticks * got rid of empty line under "Load average" line   and used last line - +2 visible processes * do not do float conversion of loadavg, just read it as string from /proc * fix display on small screens * dropped unused .stime, .utime fields * a few variables were renamed * style fixes
-rw-r--r--procps/top.c400
1 files changed, 177 insertions, 223 deletions
diff --git a/procps/top.c b/procps/top.c
index d140924d8..a8728df54 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -52,13 +52,13 @@ static procps_status_t *top; /* Hehe */
52static int ntop; 52static int ntop;
53 53
54#ifdef CONFIG_FEATURE_USE_TERMIOS 54#ifdef CONFIG_FEATURE_USE_TERMIOS
55static int pid_sort (procps_status_t *P, procps_status_t *Q) 55static int pid_sort(procps_status_t *P, procps_status_t *Q)
56{ 56{
57 return (Q->pid - P->pid); 57 return (Q->pid - P->pid);
58} 58}
59#endif 59#endif
60 60
61static int mem_sort (procps_status_t *P, procps_status_t *Q) 61static int mem_sort(procps_status_t *P, procps_status_t *Q)
62{ 62{
63 return (int)(Q->rss - P->rss); 63 return (int)(Q->rss - P->rss);
64} 64}
@@ -68,12 +68,12 @@ static int mem_sort (procps_status_t *P, procps_status_t *Q)
68#define sort_depth 3 68#define sort_depth 3
69static cmp_t sort_function[sort_depth]; 69static cmp_t sort_function[sort_depth];
70 70
71static int pcpu_sort (procps_status_t *P, procps_status_t *Q) 71static int pcpu_sort(procps_status_t *P, procps_status_t *Q)
72{ 72{
73 return (Q->pcpu - P->pcpu); 73 return (Q->pcpu - P->pcpu);
74} 74}
75 75
76static int time_sort (procps_status_t *P, procps_status_t *Q) 76static int time_sort(procps_status_t *P, procps_status_t *Q)
77{ 77{
78 return (int)((Q->stime + Q->utime) - (P->stime + P->utime)); 78 return (int)((Q->stime + Q->utime) - (P->stime + P->utime));
79} 79}
@@ -81,7 +81,7 @@ static int time_sort (procps_status_t *P, procps_status_t *Q)
81static int mult_lvl_cmp(void* a, void* b) { 81static int mult_lvl_cmp(void* a, void* b) {
82 int i, cmp_val; 82 int i, cmp_val;
83 83
84 for(i = 0; i < sort_depth; i++) { 84 for (i = 0; i < sort_depth; i++) {
85 cmp_val = (*sort_function[i])(a, b); 85 cmp_val = (*sort_function[i])(a, b);
86 if (cmp_val != 0) 86 if (cmp_val != 0)
87 return cmp_val; 87 return cmp_val;
@@ -94,199 +94,105 @@ static int mult_lvl_cmp(void* a, void* b) {
94struct save_hist { 94struct save_hist {
95 int ticks; 95 int ticks;
96 int pid; 96 int pid;
97 int utime;
98 int stime;
99}; 97};
100 98
101/* 99/*
102 * Calculates percent cpu usage for each task. 100 * Calculates percent cpu usage for each task.
103 */ 101 */
104 102
105static struct save_hist *save_history; 103static struct save_hist *prev_hist;
104static int prev_hist_count;
105/* static int hist_iterations; */
106 106
107static unsigned long Hertz;
108 107
109/*********************************************************************** 108static unsigned total_pcpu;
110 * Some values in /proc are expressed in units of 1/HZ seconds, where HZ 109/* static unsigned long total_rss; */
111 * is the kernel clock tick rate. One of these units is called a jiffy.
112 * The HZ value used in the kernel may vary according to hacker desire.
113 * According to Linus Torvalds, this is not true. He considers the values
114 * in /proc as being in architecture-dependent units that have no relation
115 * to the kernel clock tick rate. Examination of the kernel source code
116 * reveals that opinion as wishful thinking.
117 *
118 * In any case, we need the HZ constant as used in /proc. (the real HZ value
119 * may differ, but we don't care) There are several ways we could get HZ:
120 *
121 * 1. Include the kernel header file. If it changes, recompile this library.
122 * 2. Use the sysconf() function. When HZ changes, recompile the C library!
123 * 3. Ask the kernel. This is obviously correct...
124 *
125 * Linus Torvalds won't let us ask the kernel, because he thinks we should
126 * not know the HZ value. Oh well, we don't have to listen to him.
127 * Someone smuggled out the HZ value. :-)
128 *
129 * This code should work fine, even if Linus fixes the kernel to match his
130 * stated behavior. The code only fails in case of a partial conversion.
131 *
132 */
133
134#define file_to_buf_bufsize 80
135static inline int file_to_buf(char *buf, const char *filename, int fd)
136{
137 int sz;
138 110
139 if (fd == -1) { 111struct jiffy_counts {
140 fd = open(filename, O_RDONLY); 112 unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal;
141 if(fd == -1) 113 unsigned long long total;
142 bb_perror_msg_and_die("is /proc mounted?"); 114 unsigned long long busy;
143 } else { 115};
144 lseek(fd, 0L, SEEK_SET); 116static struct jiffy_counts jif, prev_jif;
145 }
146 sz = read(fd, buf, file_to_buf_bufsize - 1);
147 if (sz < 0) {
148 bb_perror_msg_and_die("%s", filename);
149 }
150 buf[sz] = '\0';
151 return fd;
152}
153 117
154static void init_Hertz_value(void) 118static void get_jiffy_counts(void)
155{ 119{
156 unsigned long user_j, nice_j, sys_j, other_j; /* jiffies (clock ticks) */ 120 FILE* fp = bb_xfopen("stat", "r");
157 double up_1, up_2, seconds; 121 prev_jif = jif;
158 unsigned long jiffies, h; 122 if (fscanf(fp, "cpu %lld %lld %lld %lld %lld %lld %lld %lld",
159 char buf[80]; 123 &jif.usr,&jif.nic,&jif.sys,&jif.idle,
160 int uptime_fd = -1; 124 &jif.iowait,&jif.irq,&jif.softirq,&jif.steal) < 4) {
161 int stat_fd = -1; 125 bb_error_msg_and_die("failed to read 'stat'");
162
163 long smp_num_cpus = sysconf(_SC_NPROCESSORS_CONF);
164
165 if(smp_num_cpus<1) smp_num_cpus=1;
166
167 do {
168 uptime_fd = file_to_buf(buf, "uptime", uptime_fd);
169 up_1 = strtod(buf, 0);
170 stat_fd = file_to_buf(buf, "stat", stat_fd);
171 sscanf(buf, "cpu %lu %lu %lu %lu", &user_j, &nice_j, &sys_j, &other_j);
172 uptime_fd = file_to_buf(buf, "uptime", uptime_fd);
173 up_2 = strtod(buf, 0);
174 } while((long)( (up_2-up_1)*1000.0/up_1 )); /* want under 0.1% error */
175 close(uptime_fd);
176 close(stat_fd);
177
178 jiffies = user_j + nice_j + sys_j + other_j;
179 seconds = (up_1 + up_2) / 2;
180 h = (unsigned long)( (double)jiffies/seconds/smp_num_cpus );
181 /* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */
182 switch(h) {
183 case 30 ... 34 : Hertz = 32; break; /* ia64 emulator */
184 case 48 ... 52 : Hertz = 50; break;
185 case 58 ... 62 : Hertz = 60; break;
186 case 63 ... 65 : Hertz = 64; break; /* StrongARM /Shark */
187 case 95 ... 105 : Hertz = 100; break; /* normal Linux */
188 case 124 ... 132 : Hertz = 128; break; /* MIPS, ARM */
189 case 195 ... 204 : Hertz = 200; break; /* normal << 1 */
190 case 253 ... 260 : Hertz = 256; break;
191 case 295 ... 304 : Hertz = 300; break; /* 3 cpus */
192 case 393 ... 408 : Hertz = 400; break; /* normal << 2 */
193 case 495 ... 504 : Hertz = 500; break; /* 5 cpus */
194 case 595 ... 604 : Hertz = 600; break; /* 6 cpus */
195 case 695 ... 704 : Hertz = 700; break; /* 7 cpus */
196 case 790 ... 808 : Hertz = 800; break; /* normal << 3 */
197 case 895 ... 904 : Hertz = 900; break; /* 9 cpus */
198 case 990 ... 1010 : Hertz = 1000; break; /* ARM */
199 case 1015 ... 1035 : Hertz = 1024; break; /* Alpha, ia64 */
200 case 1095 ... 1104 : Hertz = 1100; break; /* 11 cpus */
201 case 1180 ... 1220 : Hertz = 1200; break; /* Alpha */
202 default:
203 /* If 32-bit or big-endian (not Alpha or ia64), assume HZ is 100. */
204 Hertz = (sizeof(long)==sizeof(int) || htons(999)==999) ? 100UL : 1024UL;
205 } 126 }
127 fclose(fp);
128 jif.total = jif.usr + jif.nic + jif.sys + jif.idle
129 + jif.iowait + jif.irq + jif.softirq + jif.steal;
130 /* procps 2.x does not count iowait as busy time */
131 jif.busy = jif.total - jif.idle - jif.iowait;
206} 132}
207 133
208static void do_stats(void) 134static void do_stats(void)
209{ 135{
210 struct timeval t;
211 static struct timeval oldtime;
212 struct timezone timez;
213 float elapsed_time;
214
215 procps_status_t *cur; 136 procps_status_t *cur;
216 int total_time, i, n; 137 int pid, total_time, i, last_i, n;
217 static int prev_count; 138 struct save_hist *new_hist;
218 int systime, usrtime, pid;
219
220 struct save_hist *New_save_hist;
221 139
222 /* 140 get_jiffy_counts();
223 * Finds the current time (in microseconds) and calculates the time 141 total_pcpu = 0;
224 * elapsed since the last update. 142 /* total_rss = 0; */
225 */ 143 new_hist = xmalloc(sizeof(struct save_hist)*ntop);
226 gettimeofday(&t, &timez);
227 elapsed_time = (t.tv_sec - oldtime.tv_sec)
228 + (float) (t.tv_usec - oldtime.tv_usec) / 1000000.0;
229 oldtime.tv_sec = t.tv_sec;
230 oldtime.tv_usec = t.tv_usec;
231
232 New_save_hist = alloca(sizeof(struct save_hist)*ntop);
233 /* 144 /*
234 * Make a pass through the data to get stats. 145 * Make a pass through the data to get stats.
235 */ 146 */
236 for(n = 0; n < ntop; n++) { 147 /* hist_iterations = 0; */
148 i = 0;
149 for (n = 0; n < ntop; n++) {
237 cur = top + n; 150 cur = top + n;
238 151
239 /* 152 /*
240 * Calculate time in cur process. Time is sum of user time 153 * Calculate time in cur process. Time is sum of user time
241 * (usrtime) plus system time (systime). 154 * and system time
242 */ 155 */
243 systime = cur->stime;
244 usrtime = cur->utime;
245 pid = cur->pid; 156 pid = cur->pid;
246 total_time = systime + usrtime; 157 total_time = cur->stime + cur->utime;
247 New_save_hist[n].ticks = total_time; 158 new_hist[n].ticks = total_time;
248 New_save_hist[n].pid = pid; 159 new_hist[n].pid = pid;
249 New_save_hist[n].stime = systime;
250 New_save_hist[n].utime = usrtime;
251 160
252 /* find matching entry from previous pass */ 161 /* find matching entry from previous pass */
253 for (i = 0; i < prev_count; i++) { 162 cur->pcpu = 0;
254 if (save_history[i].pid == pid) { 163 /* do not start at index 0, continue at last used one
255 total_time -= save_history[i].ticks; 164 * (brought hist_iterations from ~14000 down to 172) */
256 systime -= save_history[i].stime; 165 last_i = i;
257 usrtime -= save_history[i].utime; 166 if (prev_hist_count) do {
167 if (prev_hist[i].pid == pid) {
168 cur->pcpu = total_time - prev_hist[i].ticks;
258 break; 169 break;
259 } 170 }
260 } 171 i = (i+1) % prev_hist_count;
261 172 /* hist_iterations++; */
262 /* 173 } while (i != last_i);
263 * Calculate percent cpu time for cur task. 174 total_pcpu += cur->pcpu;
264 */ 175 /* total_rss += cur->rss; */
265 i = (total_time * 10 * 100/Hertz) / elapsed_time;
266 if (i > 999)
267 i = 999;
268 cur->pcpu = i;
269 } 176 }
270 177
271 /* 178 /*
272 * Save cur frame's information. 179 * Save cur frame's information.
273 */ 180 */
274 free(save_history); 181 free(prev_hist);
275 save_history = memcpy(xmalloc(sizeof(struct save_hist)*n), New_save_hist, 182 prev_hist = new_hist;
276 sizeof(struct save_hist)*n); 183 prev_hist_count = ntop;
277 prev_count = n;
278 qsort(top, n, sizeof(procps_status_t), (void*)mult_lvl_cmp);
279} 184}
280#else 185#else
281static cmp_t sort_function; 186static cmp_t sort_function;
282#endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */ 187#endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */
283 188
284/* display generic info (meminfo / loadavg) */ 189/* display generic info (meminfo / loadavg) */
285static unsigned long display_generic(void) 190static unsigned long display_generic(int scr_width)
286{ 191{
287 FILE *fp; 192 FILE *fp;
288 char buf[80]; 193 char buf[80];
289 float avg1, avg2, avg3; 194 char scrbuf[80];
195 char *end;
290 unsigned long total, used, mfree, shared, buffers, cached; 196 unsigned long total, used, mfree, shared, buffers, cached;
291 unsigned int needs_conversion = 1; 197 unsigned int needs_conversion = 1;
292 198
@@ -332,11 +238,14 @@ static unsigned long display_generic(void)
332 } 238 }
333 fclose(fp); 239 fclose(fp);
334 240
335 /* read load average */ 241 /* read load average as a string */
336 fp = bb_xfopen("loadavg", "r"); 242 fp = bb_xfopen("loadavg", "r");
337 if (fscanf(fp, "%f %f %f", &avg1, &avg2, &avg3) != 3) { 243 buf[0] = '\0';
338 bb_error_msg_and_die("failed to read 'loadavg'"); 244 fgets(buf, sizeof(buf), fp);
339 } 245 end = strchr(buf, ' ');
246 if (end) end = strchr(end+1, ' ');
247 if (end) end = strchr(end+1, ' ');
248 if (end) *end = '\0';
340 fclose(fp); 249 fclose(fp);
341 250
342 if (needs_conversion) { 251 if (needs_conversion) {
@@ -351,59 +260,110 @@ static unsigned long display_generic(void)
351 260
352 /* output memory info and load average */ 261 /* output memory info and load average */
353 /* clear screen & go to top */ 262 /* clear screen & go to top */
354 printf("\e[H\e[J" "Mem: " 263 if (scr_width > sizeof(scrbuf))
355 "%ldK used, %ldK free, %ldK shrd, %ldK buff, %ldK cached\n", 264 scr_width = sizeof(scrbuf);
265 snprintf(scrbuf, scr_width,
266 "Mem: %ldK used, %ldK free, %ldK shrd, %ldK buff, %ldK cached",
356 used, mfree, shared, buffers, cached); 267 used, mfree, shared, buffers, cached);
357 printf("Load average: %.2f, %.2f, %.2f " 268 printf("\e[H\e[J%s\n", scrbuf);
358 "(State: S=sleeping R=running, W=waiting)\n", 269 snprintf(scrbuf, scr_width,
359 avg1, avg2, avg3); 270 "Load average: %s (Status: S=sleeping R=running, W=waiting)", buf);
271 printf("%s\n", scrbuf);
272
360 return total; 273 return total;
361} 274}
362 275
363 276
364/* display process statuses */ 277/* display process statuses */
365static void display_status(int count, int col) 278static void display_status(int count, int scr_width)
366{ 279{
280 enum {
281 bits_per_int = sizeof(int)*8
282 };
283
367 procps_status_t *s = top; 284 procps_status_t *s = top;
368 char rss_str_buf[8]; 285 char rss_str_buf[8];
369 unsigned long total_memory = display_generic(); 286 unsigned long total_memory = display_generic(scr_width); /* or use total_rss? */
287 unsigned pmem_shift, pmem_scale;
370 288
371#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 289#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
290 unsigned pcpu_shift, pcpu_scale;
291
372 /* what info of the processes is shown */ 292 /* what info of the processes is shown */
373 printf("\n\e[7m PID USER STATUS RSS PPID %%CPU %%MEM COMMAND\e[0m\n"); 293 printf("\e[7m%.*s\e[0m", scr_width,
294 " PID USER STATUS RSS PPID %CPU %MEM COMMAND");
295#define MIN_WIDTH \
296 sizeof( " PID USER STATUS RSS PPID %CPU %MEM C")
374#else 297#else
375 printf("\n\e[7m PID USER STATUS RSS PPID %%MEM COMMAND\e[0m\n"); 298 printf("\e[7m%.*s\e[0m", scr_width,
299 " PID USER STATUS RSS PPID %MEM COMMAND");
300#define MIN_WIDTH \
301 sizeof( " PID USER STATUS RSS PPID %MEM C")
376#endif 302#endif
377 303
378 while (count--) { 304 /*
379 char *namecmd = s->short_cmd; 305 * MEM% = s->rss/MemTotal
380 int pmem; 306 */
307 pmem_shift = bits_per_int-11;
308 pmem_scale = 1000*(1U<<(bits_per_int-11)) / total_memory;
309 /* s->rss is in kb. we want (s->rss * pmem_scale) to never overflow */
310 while (pmem_scale >= 512) {
311 pmem_scale /= 4;
312 pmem_shift -= 2;
313 }
314#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
315 /*
316 * CPU% = s->pcpu/sum(s->pcpu) * busy_cpu_ticks/total_cpu_ticks
317 * (pcpu is delta of sys+user time between samples)
318 */
319 /* (jif.xxx - prev_jif.xxx) and s->pcpu are
320 * in 0..~64000 range (HZ*update_interval).
321 * we assume that unsigned is at least 32-bit.
322 */
323 pcpu_shift = 6;
324 pcpu_scale = (1000*64*(uint16_t)(jif.busy-prev_jif.busy) ? : 1);
325 while (pcpu_scale < (1U<<(bits_per_int-2))) {
326 pcpu_scale *= 4;
327 pcpu_shift += 2;
328 }
329 pcpu_scale /= ( (uint16_t)(jif.total-prev_jif.total)*total_pcpu ? : 1);
330 /* we want (s->pcpu * pcpu_scale) to never overflow */
331 while (pcpu_scale >= 1024) {
332 pcpu_scale /= 4;
333 pcpu_shift -= 2;
334 }
335 /* printf(" pmem_scale=%u pcpu_scale=%u ", pmem_scale, pcpu_scale); */
336#endif
381 337
382 pmem = 1000.0 * s->rss / total_memory; 338 while (count--) {
383 if (pmem > 999) pmem = 999; 339 div_t pmem = div( (s->rss*pmem_scale) >> pmem_shift, 10);
340 int col = scr_width+1;
384 341
385 if(s->rss > 10*1024) 342 if (s->rss >= 100*1024)
386 sprintf(rss_str_buf, "%6ldM", s->rss/1024); 343 sprintf(rss_str_buf, "%6ldM", s->rss/1024);
387 else 344 else
388 sprintf(rss_str_buf, "%7ld", s->rss); 345 sprintf(rss_str_buf, "%7ld", s->rss);
389#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 346#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
390 printf("%5d %-8s %s %s %5d %2d.%d %2u.%u ", 347 {
391 s->pid, s->user, s->state, rss_str_buf, s->ppid, 348 div_t pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10);
392 s->pcpu/10, s->pcpu%10, pmem/10, pmem%10); 349 col -= printf("\n%5d %-8s %s %s%6d%3u.%c%3u.%c ",
350 s->pid, s->user, s->state, rss_str_buf, s->ppid,
351 pcpu.quot, '0'+pcpu.rem, pmem.quot, '0'+pmem.rem);
352 }
393#else 353#else
394 printf("%5d %-8s %s %s %5d %2u.%u ", 354 col -= printf("\n%5d %-8s %s %s%6d%3u.%c ",
395 s->pid, s->user, s->state, rss_str_buf, s->ppid, 355 s->pid, s->user, s->state, rss_str_buf, s->ppid,
396 pmem/10, pmem%10); 356 pmem.quot, '0'+pmem.rem););
397#endif 357#endif
398 if((int)strlen(namecmd) > col) 358 if (col>0)
399 namecmd[col] = 0; 359 printf("%.*s", col, s->short_cmd);
400 printf("%s", namecmd); 360 /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu,
401 if(count) 361 jif.busy - prev_jif.busy, jif.total - prev_jif.total); */
402 putchar('\n');
403 else
404 fflush(stdout);
405 s++; 362 s++;
406 } 363 }
364 /* printf(" %d", hist_iterations); */
365 putchar('\r');
366 fflush(stdout);
407} 367}
408 368
409static void clearmems(void) 369static void clearmems(void)
@@ -427,7 +387,7 @@ static void reset_term(void)
427#ifdef CONFIG_FEATURE_CLEAN_UP 387#ifdef CONFIG_FEATURE_CLEAN_UP
428 clearmems(); 388 clearmems();
429#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 389#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
430 free(save_history); 390 free(prev_hist);
431#endif 391#endif
432#endif /* CONFIG_FEATURE_CLEAN_UP */ 392#endif /* CONFIG_FEATURE_CLEAN_UP */
433} 393}
@@ -453,21 +413,13 @@ int top_main(int argc, char **argv)
453 413
454 /* do normal option parsing */ 414 /* do normal option parsing */
455 opt = bb_getopt_ulflags(argc, argv, "d:", &sinterval); 415 opt = bb_getopt_ulflags(argc, argv, "d:", &sinterval);
456 if((opt & 1)) { 416 if ((opt & 1)) {
457 interval = atoi(sinterval); 417 interval = atoi(sinterval);
458 } else { 418 } else {
459 /* Default update rate is 5 seconds */ 419 /* Default update rate is 5 seconds */
460 interval = 5; 420 interval = 5;
461 } 421 }
462 422
463 /* Default to 25 lines - 5 lines for status */
464 lines = 25 - 5;
465 /* Default CMD format size */
466#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
467 col = 35 - 6;
468#else
469 col = 35;
470#endif
471 /* change to /proc */ 423 /* change to /proc */
472 bb_xchdir("/proc"); 424 bb_xchdir("/proc");
473#ifdef CONFIG_FEATURE_USE_TERMIOS 425#ifdef CONFIG_FEATURE_USE_TERMIOS
@@ -477,24 +429,14 @@ int top_main(int argc, char **argv)
477 /* Turn off echoing */ 429 /* Turn off echoing */
478 new_settings.c_lflag &= ~(ECHO | ECHONL); 430 new_settings.c_lflag &= ~(ECHO | ECHONL);
479 431
480 signal (SIGTERM, sig_catcher); 432 signal(SIGTERM, sig_catcher);
481 sigaction (SIGTERM, (struct sigaction *) 0, &sa); 433 sigaction(SIGTERM, (struct sigaction *) 0, &sa);
482 sa.sa_flags |= SA_RESTART; 434 sa.sa_flags |= SA_RESTART;
483 sa.sa_flags &= ~SA_INTERRUPT; 435 sa.sa_flags &= ~SA_INTERRUPT;
484 sigaction (SIGTERM, &sa, (struct sigaction *) 0); 436 sigaction(SIGTERM, &sa, (struct sigaction *) 0);
485 sigaction (SIGINT, &sa, (struct sigaction *) 0); 437 sigaction(SIGINT, &sa, (struct sigaction *) 0);
486 tcsetattr(0, TCSANOW, (void *) &new_settings); 438 tcsetattr(0, TCSANOW, (void *) &new_settings);
487 atexit(reset_term); 439 atexit(reset_term);
488
489 get_terminal_width_height(0, &col, &lines);
490 if (lines > 4) {
491 lines -= 4;
492#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
493 col = col - 80 + 35 - 6;
494#else
495 col = col - 80 + 35;
496#endif
497 }
498#endif /* CONFIG_FEATURE_USE_TERMIOS */ 440#endif /* CONFIG_FEATURE_USE_TERMIOS */
499 441
500#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 442#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
@@ -506,9 +448,21 @@ int top_main(int argc, char **argv)
506#endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */ 448#endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */
507 449
508 while (1) { 450 while (1) {
509 /* read process IDs & status for all the processes */ 451 procps_status_t *p;
510 procps_status_t * p;
511 452
453 /* Default to 25 lines - 5 lines for status */
454 lines = 24 - 3;
455 col = 79;
456#ifdef CONFIG_FEATURE_USE_TERMIOS
457 get_terminal_width_height(0, &col, &lines);
458 if (lines < 5 || col < MIN_WIDTH) {
459 sleep(interval);
460 continue;
461 }
462 lines -= 3;
463#endif /* CONFIG_FEATURE_USE_TERMIOS */
464
465 /* read process IDs & status for all the processes */
512 while ((p = procps_scan(0)) != 0) { 466 while ((p = procps_scan(0)) != 0) {
513 int n = ntop; 467 int n = ntop;
514 468
@@ -519,14 +473,14 @@ int top_main(int argc, char **argv)
519 bb_error_msg_and_die("Can't find process info in /proc"); 473 bb_error_msg_and_die("Can't find process info in /proc");
520 } 474 }
521#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 475#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
522 if(!Hertz) { 476 if (!prev_hist_count) {
523 init_Hertz_value();
524 do_stats(); 477 do_stats();
525 sleep(1); 478 sleep(1);
526 clearmems(); 479 clearmems();
527 continue; 480 continue;
528 } 481 }
529 do_stats(); 482 do_stats();
483 qsort(top, ntop, sizeof(procps_status_t), (void*)mult_lvl_cmp);
530#else 484#else
531 qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function); 485 qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function);
532#endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */ 486#endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */
@@ -539,16 +493,16 @@ int top_main(int argc, char **argv)
539#ifdef CONFIG_FEATURE_USE_TERMIOS 493#ifdef CONFIG_FEATURE_USE_TERMIOS
540 tv.tv_sec = interval; 494 tv.tv_sec = interval;
541 tv.tv_usec = 0; 495 tv.tv_usec = 0;
542 FD_ZERO (&readfds); 496 FD_ZERO(&readfds);
543 FD_SET (0, &readfds); 497 FD_SET(0, &readfds);
544 select (1, &readfds, NULL, NULL, &tv); 498 select(1, &readfds, NULL, NULL, &tv);
545 if (FD_ISSET (0, &readfds)) { 499 if (FD_ISSET(0, &readfds)) {
546 if (read (0, &c, 1) <= 0) { /* signal */ 500 if (read(0, &c, 1) <= 0) { /* signal */
547 return EXIT_FAILURE; 501 return EXIT_FAILURE;
548 } 502 }
549 if(c == 'q' || c == initial_settings.c_cc[VINTR]) 503 if (c == 'q' || c == initial_settings.c_cc[VINTR])
550 break; 504 break;
551 if(c == 'M') { 505 if (c == 'M') {
552#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 506#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
553 sort_function[0] = mem_sort; 507 sort_function[0] = mem_sort;
554 sort_function[1] = pcpu_sort; 508 sort_function[1] = pcpu_sort;
@@ -558,18 +512,18 @@ int top_main(int argc, char **argv)
558#endif 512#endif
559 } 513 }
560#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 514#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
561 if(c == 'P') { 515 if (c == 'P') {
562 sort_function[0] = pcpu_sort; 516 sort_function[0] = pcpu_sort;
563 sort_function[1] = mem_sort; 517 sort_function[1] = mem_sort;
564 sort_function[2] = time_sort; 518 sort_function[2] = time_sort;
565 } 519 }
566 if(c == 'T') { 520 if (c == 'T') {
567 sort_function[0] = time_sort; 521 sort_function[0] = time_sort;
568 sort_function[1] = mem_sort; 522 sort_function[1] = mem_sort;
569 sort_function[2] = pcpu_sort; 523 sort_function[2] = pcpu_sort;
570 } 524 }
571#endif 525#endif
572 if(c == 'N') { 526 if (c == 'N') {
573#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 527#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
574 sort_function[0] = pid_sort; 528 sort_function[0] = pid_sort;
575#else 529#else
@@ -582,7 +536,7 @@ int top_main(int argc, char **argv)
582#endif /* CONFIG_FEATURE_USE_TERMIOS */ 536#endif /* CONFIG_FEATURE_USE_TERMIOS */
583 clearmems(); 537 clearmems();
584 } 538 }
585 if(ENABLE_FEATURE_CLEAN_UP) 539 if (ENABLE_FEATURE_CLEAN_UP)
586 clearmems(); 540 clearmems();
587 putchar('\n'); 541 putchar('\n');
588 return EXIT_SUCCESS; 542 return EXIT_SUCCESS;