diff options
Diffstat (limited to 'procps/top.c')
-rw-r--r-- | procps/top.c | 144 |
1 files changed, 93 insertions, 51 deletions
diff --git a/procps/top.c b/procps/top.c index c76fdc312..8d732d4b2 100644 --- a/procps/top.c +++ b/procps/top.c @@ -30,37 +30,76 @@ #include "busybox.h" -typedef int (*cmp_t)(procps_status_t *P, procps_status_t *Q); -static procps_status_t *top; /* Hehe */ +typedef struct { + unsigned long rss; +#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE + unsigned long ticks; + unsigned pcpu; /* delta of ticks */ +#endif + unsigned pid, ppid; + unsigned uid; + char state[4]; + char comm[COMM_LEN]; +} top_status_t; +static top_status_t *top; static int ntop; +/* This structure stores some critical information from one frame to + the next. Used for finding deltas. */ +struct save_hist { + unsigned long ticks; + unsigned pid; +}; +static struct save_hist *prev_hist; +static int prev_hist_count; +/* static int hist_iterations; */ +static unsigned total_pcpu; +/* static unsigned long total_rss; */ + + #define OPT_BATCH_MODE (option_mask32 & 0x4) #if ENABLE_FEATURE_USE_TERMIOS -static int pid_sort(procps_status_t *P, procps_status_t *Q) +static int pid_sort(top_status_t *P, top_status_t *Q) { + /* Buggy wrt pids with high bit set */ + /* (linux pids are in [1..2^15-1]) */ return (Q->pid - P->pid); } #endif -static int mem_sort(procps_status_t *P, procps_status_t *Q) +static int mem_sort(top_status_t *P, top_status_t *Q) { - return (int)(Q->rss - P->rss); + /* We want to avoid unsigned->signed and truncation errors */ + if (Q->rss < P->rss) return -1; + return Q->rss != P->rss; /* 0 if ==, 1 if > */ } -#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE + +typedef int (*cmp_funcp)(top_status_t *P, top_status_t *Q); + +#if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE + +static cmp_funcp sort_function; + +#else enum { SORT_DEPTH = 3 }; -static cmp_t sort_function[SORT_DEPTH]; -static int pcpu_sort(procps_status_t *P, procps_status_t *Q) +static cmp_funcp sort_function[SORT_DEPTH]; + +static int pcpu_sort(top_status_t *P, top_status_t *Q) { - return (Q->pcpu - P->pcpu); + /* Buggy wrt ticks with high bit set */ + /* Affects only processes for which ticks overflow */ + return (int)Q->pcpu - (int)P->pcpu; } -static int time_sort(procps_status_t *P, procps_status_t *Q) +static int time_sort(top_status_t *P, top_status_t *Q) { - return (int)((Q->stime + Q->utime) - (P->stime + P->utime)); + /* We want to avoid unsigned->signed and truncation errors */ + if (Q->ticks < P->ticks) return -1; + return Q->ticks != P->ticks; /* 0 if ==, 1 if > */ } static int mult_lvl_cmp(void* a, void* b) { @@ -74,24 +113,6 @@ static int mult_lvl_cmp(void* a, void* b) { return 0; } -/* This structure stores some critical information from one frame to - the next. Mostly used for sorting. */ -struct save_hist { - int ticks; - pid_t pid; -}; - -/* - * Calculates percent cpu usage for each task. - */ - -static struct save_hist *prev_hist; -static int prev_hist_count; -/* static int hist_iterations; */ - - -static unsigned total_pcpu; -/* static unsigned long total_rss; */ typedef struct { unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal; @@ -115,11 +136,12 @@ static void get_jiffy_counts(void) jif.busy = jif.total - jif.idle - jif.iowait; } + static void do_stats(void) { - procps_status_t *cur; + top_status_t *cur; pid_t pid; - int total_time, i, last_i, n; + int i, last_i, n; struct save_hist *new_hist; get_jiffy_counts(); @@ -139,8 +161,7 @@ static void do_stats(void) * and system time */ pid = cur->pid; - total_time = cur->stime + cur->utime; - new_hist[n].ticks = total_time; + new_hist[n].ticks = cur->ticks; new_hist[n].pid = pid; /* find matching entry from previous pass */ @@ -150,13 +171,13 @@ static void do_stats(void) last_i = i; if (prev_hist_count) do { if (prev_hist[i].pid == pid) { - cur->pcpu = total_time - prev_hist[i].ticks; + cur->pcpu = cur->ticks - prev_hist[i].ticks; + total_pcpu += cur->pcpu; break; } i = (i+1) % prev_hist_count; /* hist_iterations++; */ } while (i != last_i); - total_pcpu += cur->pcpu; /* total_rss += cur->rss; */ } @@ -167,10 +188,9 @@ static void do_stats(void) prev_hist = new_hist; prev_hist_count = ntop; } -#else -static cmp_t sort_function; #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ + /* display generic info (meminfo / loadavg) */ static unsigned long display_generic(int scr_width) { @@ -265,7 +285,7 @@ static void display_status(int count, int scr_width) bits_per_int = sizeof(int)*8 }; - procps_status_t *s = top; + top_status_t *s = top; char rss_str_buf[8]; unsigned long total_memory = display_generic(scr_width); /* or use total_rss? */ unsigned pmem_shift, pmem_scale; @@ -333,14 +353,19 @@ static void display_status(int count, int scr_width) sprintf(rss_str_buf, "%6ldM", s->rss/1024); else sprintf(rss_str_buf, "%7ld", s->rss); - USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10);) - col -= printf("\n%5u %-8s %s %s%6u%3u.%c" \ - USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE("%3u.%c") " ", - (unsigned)s->pid, s->user, s->state, rss_str_buf, (unsigned)s->ppid, + USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE( + pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10); + ) + col -= printf("\n%5u %-8s %s " + "%s%6u" + USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE("%3u.%c") + "%3u.%c ", + s->pid, get_cached_username(s->uid), s->state, + rss_str_buf, s->ppid, USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu.quot, '0'+pcpu.rem,) pmem.quot, '0'+pmem.rem); if (col > 0) - printf("%.*s", col, s->short_cmd); + printf("%.*s", col, s->comm); /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, jif.busy - prev_jif.busy, jif.total - prev_jif.total); */ s++; @@ -350,18 +375,20 @@ static void display_status(int count, int scr_width) fflush(stdout); } + static void clearmems(void) { + clear_username_cache(); free(top); top = 0; ntop = 0; } + #if ENABLE_FEATURE_USE_TERMIOS #include <termios.h> #include <signal.h> - static struct termios initial_settings; static void reset_term(void) @@ -427,7 +454,7 @@ int top_main(int argc, char **argv) #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ while (1) { - procps_status_t *p; + procps_status_t *p = NULL; /* Default to 25 lines - 5 lines for status */ lines = 24 - 3; @@ -442,11 +469,26 @@ int top_main(int argc, char **argv) #endif /* FEATURE_USE_TERMIOS */ /* read process IDs & status for all the processes */ - while ((p = procps_scan(0)) != 0) { + while ((p = procps_scan(p, 0 + | PSSCAN_PID + | PSSCAN_PPID + | PSSCAN_RSS + | PSSCAN_STIME + | PSSCAN_UTIME + | PSSCAN_STATE + | PSSCAN_COMM + | PSSCAN_SID + | PSSCAN_UIDGID + ))) { int n = ntop; - - top = xrealloc(top, (++ntop)*sizeof(procps_status_t)); - memcpy(top + n, p, sizeof(procps_status_t)); + top = xrealloc(top, (++ntop)*sizeof(top_status_t)); + top[n].pid = p->pid; + top[n].ppid = p->ppid; + top[n].rss = p->rss; + top[n].ticks = p->stime + p->utime; + top[n].uid = p->uid; + strcpy(top[n].state, p->state); + strcpy(top[n].comm, p->comm); } if (ntop == 0) { bb_error_msg_and_die("can't find process info in /proc"); @@ -459,9 +501,9 @@ int top_main(int argc, char **argv) continue; } do_stats(); - qsort(top, ntop, sizeof(procps_status_t), (void*)mult_lvl_cmp); + qsort(top, ntop, sizeof(top_status_t), (void*)mult_lvl_cmp); #else - qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function); + qsort(top, ntop, sizeof(top_status_t), (void*)sort_function); #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ count = lines; if (OPT_BATCH_MODE || count > ntop) { |