X-Git-Url: https://git.saurik.com/apple/system_cmds.git/blobdiff_plain/1815bff58803503e37009deeb85cfa8c22acf9d9..d904471cf60febf9484bc16c29e58e92baf2b9cc:/sc_usage.tproj/sc_usage.c diff --git a/sc_usage.tproj/sc_usage.c b/sc_usage.tproj/sc_usage.c index 86ed491..adab8fa 100644 --- a/sc_usage.tproj/sc_usage.c +++ b/sc_usage.tproj/sc_usage.c @@ -23,7 +23,7 @@ */ /* -cc -I. -DKERNEL_PRIVATE -O -o sc_usage sc_usage.c +cc -I. -DKERNEL_PRIVATE -O -o sc_usage sc_usage.c -lncurses */ #define Default_DELAY 1 /* default delay interval */ @@ -39,10 +39,11 @@ cc -I. -DKERNEL_PRIVATE -O -o sc_usage sc_usage.c #include #include #include +#include #include #include -#include +#include #include @@ -56,7 +57,7 @@ cc -I. -DKERNEL_PRIVATE -O -o sc_usage sc_usage.c #include #include -#import +#include #include @@ -89,6 +90,9 @@ long start_time = 0; #define MAX_NESTED 8 #define MAX_FAULTS 5 +/* If NUMPARMS from kernel changes, it will be reflected in PATHLENGTH as well */ +#define NUMPARMS 23 +#define PATHLENGTH (NUMPARMS*sizeof(long)) char *state_name[] = { "Dont Know", @@ -104,12 +108,6 @@ char *state_name[] = { #define WAITING 3 #define PREEMPTED 4 -typedef struct { - natural_t hi; - natural_t lo; -} AbsoluteTime; - - struct entry { int sc_state; int type; @@ -125,7 +123,8 @@ struct th_info { int depth; int vfslookup; int curpri; - char pathname[32]; + long *pathptr; + char pathname[PATHLENGTH + 1]; struct entry th_entry[MAX_NESTED]; }; @@ -194,7 +193,6 @@ int scalls; #define DIVISOR 16.6666 /* Trace divisor converts to microseconds */ double divisor = DIVISOR; -struct termios tmode, omode; int mib[6]; size_t needed; @@ -215,6 +213,9 @@ void set_pidcheck(); void set_remove(); void set_numbufs(); void set_init(); +void quit(char *); +int argtopid(char *); +int argtoi(int, char*, char*, int); /* @@ -228,8 +229,6 @@ void leave() /* exit under normal conditions -- INT handler */ move(LINES - 1, 0); refresh(); endwin(); - - tcsetattr(0, TCSANOW, &omode); } set_enable(0); set_pidcheck(pid, 0); @@ -245,8 +244,6 @@ char *s; move(LINES - 1, 0); refresh(); endwin(); - - tcsetattr(0, TCSANOW, &omode); } printf("sc_usage: "); @@ -266,31 +263,8 @@ void sigwinch() newLINES = 1; } - -/* raw read of the timebase register */ -void clock_get_uptime( - AbsoluteTime *result) -{ -#ifdef __ppc__ - - natural_t hi, lo, hic; - - do { - asm volatile(" mftbu %0" : "=r" (hi)); - asm volatile(" mftb %0" : "=r" (lo)); - asm volatile(" mftbu %0" : "=r" (hic)); - } while (hic != hi); - - result->lo = lo; - result->hi = hi; -#else - result->lo = 0; - result->hi = 0; -#endif /* __ppc__ */ -} - int -exit_usage(myname) { +exit_usage(char *myname) { fprintf(stderr, "Usage: %s [-c codefile] [-e] [-l] [-sn] pid | cmd | -E execute path\n", myname); fprintf(stderr, " -c name of codefile containing mappings for syscalls\n"); @@ -316,19 +290,19 @@ void print_time(char *p, unsigned int useconds, unsigned int seconds) hours = minutes / 60; if (minutes < 100) { // up to 100 minutes - sprintf(p, "%2ld:%02ld.%03ld", minutes, seconds % 60, - usec_to_1000ths(useconds)); + sprintf(p, "%2ld:%02ld.%03ld", minutes, (unsigned long)(seconds % 60), + (unsigned long)usec_to_1000ths(useconds)); } else if (hours < 100) { // up to 100 hours - sprintf(p, "%2ld:%02ld:%02ld ", hours, minutes % 60, - seconds % 60); + sprintf(p, "%2ld:%02ld:%02ld ", hours, (minutes % 60), + (unsigned long)(seconds % 60)); } else { sprintf(p, "%4ld hrs ", hours); } } - +int main(argc, argv) int argc; char *argv[]; @@ -338,15 +312,11 @@ main(argc, argv) char ch; char *ptr; int delay = Default_DELAY; - int length; void screen_update(); void sort_scalls(); void sc_tab_init(); void getdivisor(); void reset_counters(); - int argtopid(); - int argtoi(); - int quit(); if ( geteuid() != 0 ) { printf("'sc_usage' must be run as root...\n"); @@ -431,7 +401,7 @@ main(argc, argv) exit(1); case 0: /* child */ setsid(); - ptrace(0,0,0,0); /* PT_TRACE_ME */ + ptrace(0,(pid_t)0,(caddr_t)0,0); /* PT_TRACE_ME */ execve(argv[optind], &argv[optind], environ); perror("execve:"); exit(1); @@ -448,22 +418,17 @@ main(argc, argv) if (no_screen_refresh == 0) { - if (tcgetattr(0, &tmode) < 0) { - printf("can't get terminal attributes\n"); - exit(1); - } - omode = tmode; - - tmode.c_lflag &= ~ICANON; - tmode.c_cc[VMIN] = 0; - tmode.c_cc[VTIME] = 1; - if (tcsetattr(0, TCSANOW, &tmode) < 0) { - printf("can't set terminal attributes\n"); - exit(1); - } /* initializes curses and screen (last) */ - initscr(); + if (initscr() == (WINDOW *) 0) + { + printf("Unrecognized TERM type, try vt100\n"); + exit(1); + } + cbreak(); + timeout(100); + noecho(); + clear(); refresh(); } @@ -472,6 +437,8 @@ main(argc, argv) /* set up signal handlers */ signal(SIGINT, leave); signal(SIGQUIT, leave); + signal(SIGHUP, leave); + signal(SIGTERM, leave); signal(SIGWINCH, sigwinch); if (no_screen_refresh == 0) @@ -489,7 +456,7 @@ main(argc, argv) set_pidcheck(pid, 1); set_enable(1); if (execute_flag) - ptrace(7, pid, 1, 0); /* PT_CONTINUE */ + ptrace(7, pid, (caddr_t)1, 0); /* PT_CONTINUE */ getdivisor(); if (delay == 0) @@ -504,22 +471,16 @@ main(argc, argv) while (1) { int i; - int cnt; - char ibuf[128]; + char c; void sample_sc(); for (i = 0; i < (10 * delay) && newLINES == 0; i++) { if (no_screen_refresh == 0) { - if ((cnt = read(0, &ibuf, 128)) > 0) { - int n; - - for (n = 0; n < cnt; n++) - if (ibuf[n] == 'q') - leave(); - reset_counters(); - break; - } + if ((c = getch()) != ERR && (char)c == 'q') + leave(); + if (c != ERR) + reset_counters(); } else usleep(100000); sample_sc(); @@ -527,7 +488,11 @@ main(argc, argv) (void)sort_scalls(); if (newLINES) { - initscr(); + /* + No need to check for initscr error return. + We won't get here if it fails on the first call. + */ + endwin(); clear(); refresh(); @@ -600,6 +565,7 @@ void screen_update() char *p1, *p2, *p3; char tbuf[256]; int clen; + int plen; int n, i, rows; long curr_time; long elapsed_secs; @@ -684,7 +650,7 @@ void screen_update() clen = strlen(tbuf); sprintf(&tbuf[clen], " %3ld:%02ld:%02ld\n", - hours, minutes % 60, elapsed_secs % 60); + (long)hours, (long)(minutes % 60), (long)(elapsed_secs % 60)); if (tbuf[COLS-2] != '\n') { tbuf[COLS-1] = '\n'; @@ -851,7 +817,7 @@ void screen_update() printf("\n"); if (num_of_threads) { - sprintf(tbuf, "\nCURRENT_TYPE LAST_PATHNAME_WAITED_FOR CUR_WAIT_TIME THRD# PRI\n"); + sprintf(tbuf, "\nCURRENT_TYPE LAST_PATHNAME_WAITED_FOR CUR_WAIT_TIME THRD# PRI\n"); if (tbuf[COLS-2] != '\n') { tbuf[COLS-1] = '\n'; @@ -876,14 +842,10 @@ void screen_update() for (i = 0; i < num_of_threads; i++, ti++) { struct entry *te; - unsigned long long now; - AbsoluteTime timestamp; + uint64_t now; int secs, time_secs, time_usecs; - clock_get_uptime(×tamp); - - now = (((unsigned long long)timestamp.hi) << 32) | - (unsigned long long)((unsigned int)(timestamp.lo)); + now = mach_absolute_time(); while (ti->thread == 0 && ti < &th_state[MAX_THREADS]) ti++; @@ -906,7 +868,13 @@ void screen_update() } clen = strlen(tbuf); - sprintf(&tbuf[clen], " %-28.28s ", ti->pathname); + /* print the tail end of the pathname */ + plen = strlen(ti->pathname); + if (plen > 34) + plen -= 34; + else + plen = 0; + sprintf(&tbuf[clen], " %-34.34s ", &ti->pathname[plen]); clen += strlen(&tbuf[clen]); @@ -917,7 +885,7 @@ void screen_update() print_time(&tbuf[clen], time_usecs, time_secs); clen += strlen(&tbuf[clen]); - sprintf(&tbuf[clen], " %2d %3d\n", i, ti->curpri); + sprintf(&tbuf[clen], " %2d %3d\n", i, ti->curpri); if (tbuf[COLS-2] != '\n') { tbuf[COLS-1] = '\n'; @@ -1011,7 +979,6 @@ sc_tab_init(char *codefile) { int msgcode_indx=0; char name[56]; FILE *fp; - int quit(); if ((fp = fopen(codefile,"r")) == (FILE *)0) { printf("Failed to open code description file %s\n", codefile); @@ -1175,13 +1142,9 @@ sort_scalls() { struct th_info *ti; struct sc_entry *se; struct entry *te; - unsigned long long now; - AbsoluteTime timestamp; + uint64_t now; - clock_get_uptime(×tamp); - - now = (((unsigned long long)timestamp.hi) << 32) | - (unsigned long long)((unsigned int)(timestamp.lo)); + now = mach_absolute_time(); for (ti = th_state; ti < &th_state[MAX_THREADS]; ti++) { if (ti->thread == 0) @@ -1215,6 +1178,7 @@ sort_scalls() { if ((unsigned long)(((double)now - te->otime) / divisor) > 5000000) { ti->thread = 0; ti->vfslookup = 0; + ti->pathptr = (long *)0; ti->pathname[0] = 0; num_of_threads--; } @@ -1417,6 +1381,7 @@ sample_sc() th_state[i].depth = 0; th_state[i].thread = 0; th_state[i].vfslookup = 0; + th_state[i].pathptr = (long *)0; th_state[i].pathname[0] = 0; } num_of_threads = 0; @@ -1432,7 +1397,7 @@ sample_sc() for (i = 0; i < count; i++) { int debugid, baseid, thread; int type, code; - unsigned long long now; + uint64_t now; struct th_info *ti, *switched_out, *switched_in; struct sc_entry *se; struct entry *te; @@ -1445,32 +1410,57 @@ sample_sc() switched_out = (struct th_info *)0; switched_in = (struct th_info *)0; - now = (((unsigned long long)kd[i].timestamp.tv_sec) << 32) | - (unsigned long long)((unsigned int)(kd[i].timestamp.tv_nsec)); + now = kd[i].timestamp; + baseid = debugid & 0xffff0000; - if (debugid == vfs_lookup) { + if (type == vfs_lookup) { long *sargptr; if ((ti = find_thread(thread)) == (struct th_info *)0) continue; + if (ti->vfslookup == 1) { - ti->vfslookup = 2; - memset(&ti->pathname[0], 0, 32); - sargptr = (long *)&ti->pathname[0]; - + ti->vfslookup++; + memset(&ti->pathname[0], 0, (PATHLENGTH + 1)); + sargptr = (long *)&ti->pathname[0]; + *sargptr++ = kd[i].arg2; *sargptr++ = kd[i].arg3; *sargptr++ = kd[i].arg4; + ti->pathptr = sargptr; + + } else if (ti->vfslookup > 1) { + ti->vfslookup++; + sargptr = ti->pathptr; + + /* + We don't want to overrun our pathname buffer if the + kernel sends us more VFS_LOOKUP entries than we can + handle. + */ + + if ((long *)sargptr >= (long *)&ti->pathname[PATHLENGTH]) + continue; + + /* + We need to detect consecutive vfslookup entries. + So, if we get here and find a START entry, + fake the pathptr so we can bypass all further + vfslookup entries. + */ + + if (debugid & DBG_FUNC_START) + { + (long *)ti->pathptr = (long *)&ti->pathname[PATHLENGTH]; + continue; + } - } else if (ti->vfslookup == 2) { - ti->vfslookup = 3; - - sargptr = (long *)&ti->pathname[12]; *sargptr++ = kd[i].arg1; *sargptr++ = kd[i].arg2; *sargptr++ = kd[i].arg3; *sargptr++ = kd[i].arg4; + ti->pathptr = sargptr; } continue; @@ -1478,8 +1468,8 @@ sample_sc() code = (debugid >> 2) & 0x1ff; else if (baseid == msc_base) code = 512 + ((debugid >> 2) & 0x1ff); - else if (baseid == mach_sched || baseid == mach_stkhandoff) { - switched_out = find_thread(kd[i].arg1); + else if (type == mach_sched || type == mach_stkhandoff) { + switched_out = find_thread((kd[i].arg5 & KDBG_THREAD_MASK)); switched_in = find_thread(kd[i].arg2); if (in_idle) { @@ -1617,7 +1607,7 @@ sample_sc() se->delta_count++; se->total_count++; - if (ti->depth) { + while (ti->depth) { te = &ti->th_entry[ti->depth-1]; if (te->type == type) { @@ -1653,6 +1643,20 @@ sample_sc() te->stime = (double)now; te->otime = (double)now; + + break; + } + ti->depth--; + + if (ti->depth == 0) { + /* + * headed back to user mode + * start the time accumulation + */ + te = &ti->th_entry[0]; + te->sc_state = USER_MODE; + te->stime = (double)now; + te->otime = (double)now; } } } @@ -1678,9 +1682,8 @@ sample_sc() delta_otime_secs += secs; } - -quit(s) -char *s; +void +quit(char *s) { if (trace_enabled) set_enable(0); @@ -1699,23 +1702,18 @@ char *s; exit(1); } - void getdivisor() { + mach_timebase_info_data_t info; - unsigned int delta; - unsigned int abs_to_ns_num; - unsigned int abs_to_ns_denom; - unsigned int proc_to_abs_num; - unsigned int proc_to_abs_denom; + (void) mach_timebase_info (&info); - MKGetTimeBaseInfo (&delta, &abs_to_ns_num, &abs_to_ns_denom, - &proc_to_abs_num, &proc_to_abs_denom); + divisor = ( (double)info.denom / (double)info.numer) * 1000; - divisor = ((double)abs_to_ns_denom / (double)abs_to_ns_num) * 1000; } +int argtopid(str) char *str; { @@ -1773,7 +1771,8 @@ find_msgcode(int debugid) } return (0); } - + +int argtoi(flag, req, str, base) int flag; char *req, *str;