]> git.saurik.com Git - apple/system_cmds.git/blobdiff - sc_usage.tproj/sc_usage.c
system_cmds-230.tar.gz
[apple/system_cmds.git] / sc_usage.tproj / sc_usage.c
index 86ed4916c223aafc05510f8158d3cc48836e9602..965d369ed17dac7bfee2e6f56ff90541e0205aca 100644 (file)
@@ -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 */
@@ -42,7 +42,7 @@ cc -I. -DKERNEL_PRIVATE -O -o sc_usage sc_usage.c
 
 #include <libc.h>
 #include <termios.h>
-#include <bsd/curses.h>
+#include <curses.h>
 
 #include <sys/ioctl.h>
 
@@ -56,7 +56,7 @@ cc -I. -DKERNEL_PRIVATE -O -o sc_usage sc_usage.c
 
 #include <sys/sysctl.h>
 #include <errno.h>
-#import <mach/clock_types.h>
+#include <mach/mach_time.h>
 #include <err.h>
 
 
@@ -89,6 +89,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 +107,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 +122,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 +192,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;
@@ -228,8 +225,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 +240,6 @@ char *s;
                move(LINES - 1, 0);
                refresh();
                endwin();
-
-               tcsetattr(0, TCSANOW, &omode);
        }
 
         printf("sc_usage: ");
@@ -266,29 +259,6 @@ 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) {
 
@@ -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)
@@ -505,21 +472,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 +489,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 +566,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;
@@ -851,7 +818,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 +843,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(&timestamp);
-
-               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 +869,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 +886,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';
@@ -1175,13 +1144,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(&timestamp);
-
-       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 +1180,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 +1383,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 +1399,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 +1412,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 = (((uint64_t)kd[i].timestamp.tv_sec) << 32) |
+                       (uint64_t)((unsigned int)(kd[i].timestamp.tv_nsec));
                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;
 
@@ -1617,7 +1609,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 +1645,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;
                                }
                        }
                }
@@ -1699,20 +1705,14 @@ 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;
 }