From dce5e09683580cda2fbbf46378ef513d80d4f7fe Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Tue, 8 Feb 2011 14:00:48 +0000 Subject: [PATCH] top - able to account kernel cpu time to process --- commands/top/top.c | 104 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 85 insertions(+), 19 deletions(-) diff --git a/commands/top/top.c b/commands/top/top.c index be90c07f8..0e6d0d246 100644 --- a/commands/top/top.c +++ b/commands/top/top.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -36,8 +37,17 @@ #include #include +#define TIMECYCLEKEY 't' + u32_t system_hz; +/* name of cpu cycle types, in the order they appear in /psinfo. */ +char *cputimenames[] = { "user", "ipc", "kernelcall" }; + +#define CPUTIMENAMES (sizeof(cputimenames)/sizeof(cputimenames[0])) + +#define CPUTIME(m, i) (m & (1L << (i))) + unsigned int nr_procs, nr_tasks; int nr_total; @@ -59,7 +69,7 @@ struct proc { int p_flags; endpoint_t p_endpoint; pid_t p_pid; - u64_t p_cycles; + u64_t p_cpucycles[CPUTIMENAMES]; int p_priority; endpoint_t p_blocked; time_t p_user_time; @@ -78,6 +88,7 @@ void parse_file(pid_t pid) unsigned long cycles_hi, cycles_lo; FILE *fp; struct proc *p; + int i; sprintf(path, "%d/psinfo", pid); @@ -122,12 +133,13 @@ void parse_file(pid_t pid) if (state != STATE_RUN) p->p_flags |= BLOCKED; - p->p_cycles = make64(cycles_lo, cycles_hi); + p->p_cpucycles[0] = make64(cycles_lo, cycles_hi); p->p_memory = 0L; if (!(p->p_flags & IS_TASK)) { - if (fscanf(fp, " %lu %*u %*u %*c %*d %*u %u %*u %d", - &p->p_memory, &effuid, &p->p_nice) != 3) { + int i; + if ((i=fscanf(fp, " %lu %*u %*u %*c %*d %*u %u %*u %d %*c %*d %*u", + &p->p_memory, &effuid, &p->p_nice)) != 3) { fclose(fp); return; @@ -136,6 +148,15 @@ void parse_file(pid_t pid) p->p_effuid = effuid; } + for(i = 1; i < CPUTIMENAMES; i++) { + if(fscanf(fp, " %lu %lu", + &cycles_hi, &cycles_lo) == 2) { + p->p_cpucycles[i] = make64(cycles_lo, cycles_hi); + } else { + p->p_cpucycles[i] = make64(0, 0); + } + } + p->p_flags |= USED; fclose(fp); @@ -302,6 +323,8 @@ struct tp *lookup(endpoint_t who, struct tp *tptab, int np) */ #define SCALE (1 << 12) +double ktotal = 0; + void print_proc(struct tp *tp, u32_t tcyc) { int euid = 0; @@ -339,8 +362,45 @@ void print_proc(struct tp *tp, u32_t tcyc) printf("%6.2f%% %s", 100.0*pcyc/tcyc, name); } +char *cputimemodename(int cputimemode) +{ + static char name[100]; + int i; + + name[0] = '\0'; + + for(i = 0; i < CPUTIMENAMES; i++) { + if(CPUTIME(cputimemode, i)) { + assert(strlen(name) + + strlen(cputimenames[i]) < sizeof(name)); + strcat(name, cputimenames[i]); + strcat(name, " "); + } + } + + return name; +} + +u64_t cputicks(struct proc *p1, struct proc *p2, int timemode) +{ + int i; + u64_t t = make64(0, 0); + for(i = 0; i < CPUTIMENAMES; i++) { + if(!CPUTIME(timemode, i)) + continue; + if(p1->p_endpoint == p2->p_endpoint) { + t = add64(t, sub64(p2->p_cpucycles[i], + p1->p_cpucycles[i])); + } else { + t = add64(t, p2->p_cpucycles[i]); + } + } + + return t; +} + void print_procs(int maxlines, - struct proc *proc1, struct proc *proc2) + struct proc *proc1, struct proc *proc2, int cputimemode) { int p, nprocs; u64_t idleticks = cvu64(0); @@ -363,24 +423,19 @@ void print_procs(int maxlines, } for(p = nprocs = 0; p < nr_total; p++) { - + u64_t uticks; if(!(proc2[p].p_flags & USED)) continue; tick_procs[nprocs].p = proc2 + p; - if(proc1[p].p_endpoint == proc2[p].p_endpoint) { - tick_procs[nprocs].ticks = - sub64(proc2[p].p_cycles, proc1[p].p_cycles); - } else { - tick_procs[nprocs].ticks = - proc2[p].p_cycles; - } - total_ticks = add64(total_ticks, tick_procs[nprocs].ticks); + tick_procs[nprocs].ticks = cputicks(&proc1[p], &proc2[p], cputimemode); + uticks = cputicks(&proc1[p], &proc2[p], 1); + total_ticks = add64(total_ticks, uticks); if(p-NR_TASKS == IDLE) { - idleticks = tick_procs[nprocs].ticks; + idleticks = uticks; continue; } if(p-NR_TASKS == KERNEL) { - kernelticks = tick_procs[nprocs].ticks; + kernelticks = uticks; continue; } if(!(proc2[p].p_flags & IS_TASK)) { @@ -416,6 +471,11 @@ void print_procs(int maxlines, #define NEWLINE do { printf("\n"); if(--maxlines <= 0) { return; } } while(0) NEWLINE; + + printf("CPU time displayed (press '%c' to cycle): %s", + TIMECYCLEKEY, cputimemodename(cputimemode)); + NEWLINE; + NEWLINE; printf(" PID USERNAME PRI NICE SIZE STATE TIME CPU COMMAND"); @@ -471,7 +531,7 @@ void print_procs(int maxlines, } } -void showtop(int r) +void showtop(int cputimemode, int r) { #define NLOADS 3 double loads[NLOADS]; @@ -502,7 +562,7 @@ void showtop(int r) if(winsize.ws_row > 0) r = winsize.ws_row; - print_procs(r - lines - 2, prev_proc, proc); + print_procs(r - lines - 2, prev_proc, proc, cputimemode); } void init(int *rows) @@ -561,6 +621,7 @@ void getkinfo(void) int main(int argc, char *argv[]) { int r, c, s = 0; + int cputimemode = 1; /* bitmap. */ if (chdir(_PATH_PROC) != 0) { perror("chdir to " _PATH_PROC); @@ -601,7 +662,7 @@ int main(int argc, char *argv[]) fd_set fds; int ns; struct timeval tv; - showtop(r); + showtop(cputimemode, r); tv.tv_sec = s; tv.tv_usec = 0; @@ -621,6 +682,11 @@ int main(int argc, char *argv[]) putchar('\r'); return 0; break; + case TIMECYCLEKEY: + cputimemode++; + if(cputimemode >= (1L << CPUTIMENAMES)) + cputimemode = 1; + break; } } } -- 2.44.0