]> git.saurik.com Git - apple/system_cmds.git/blobdiff - sc_usage.tproj/sc_usage.c
system_cmds-735.20.1.tar.gz
[apple/system_cmds.git] / sc_usage.tproj / sc_usage.c
index 5198d9aeadbba17d4bda465472d4a51f951a5070..d39e8efe62dde5f8c3666fffc1fb72d65db32930 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
  * Reserved.  This file contains Original Code and/or Modifications of
  * Original Code as defined in and that are subject to the Apple Public
@@ -10,7 +10,7 @@
  * except in compliance with the License.  Please obtain a copy of the
  * License at http://www.apple.com/publicsource and read it before using
  * this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
  * License for the specific language governing rights and limitations
  * under the License."
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 
 /*
-cc -I. -DKERNEL_PRIVATE -O -o sc_usage sc_usage.c
+cc -I. -DPRIVATE -D__APPLE_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 <sys/types.h>
 #include <sys/param.h>
 #include <sys/time.h>
+#include <sys/ptrace.h>
 
 #include <libc.h>
 #include <termios.h>
-#include <bsd/curses.h>
+#include <curses.h>
 
 #include <sys/ioctl.h>
 
@@ -58,7 +59,7 @@ cc -I. -DKERNEL_PRIVATE -O -o sc_usage sc_usage.c
 #include <errno.h>
 #include <mach/mach_time.h>
 #include <err.h>
-
+#include <libutil.h>
 
 /* Number of lines of header information on the standard screen */
 #define        HEADER_LINES    5
@@ -89,9 +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",
@@ -118,17 +119,17 @@ struct entry {
 };
 
 struct th_info {
-        int  thread;
+        uintptr_t  thread;
         int  depth;
         int  vfslookup;
         int  curpri;
         long *pathptr;
-        char pathname[PATHLENGTH + 1];
+        long pathname[NUMPARMS + 1];
         struct entry th_entry[MAX_NESTED];
 };
 
 struct sc_entry {
-        char name[32];
+        char name[64];
         int  delta_count;
         int  total_count;
         int  waiting;
@@ -170,6 +171,7 @@ double       other_start;
 int    max_sc = 0;
 int    bsc_base = 0;
 int    msc_base = 0;
+int       mach_idle = 0;
 int    mach_sched = 0;
 int    mach_stkhandoff = 0;
 int    vfs_lookup = 0;
@@ -192,11 +194,9 @@ int    scalls;
 #define DIVISOR 16.6666        /* Trace divisor converts to microseconds */
 double divisor = DIVISOR;
 
-struct termios tmode, omode;
-
 int mib[6];
 size_t needed;
-char  *my_buffer;
+void  *my_buffer;
 
 kbufinfo_t bufinfo = {0, 0, 0, 0};
 
@@ -204,30 +204,40 @@ int trace_enabled = 0;
 int set_remove_flag = 1;
 
 struct kinfo_proc *kp_buffer = 0;
-int kp_nentries = 0;
+size_t kp_nentries = 0;
 
 extern char **environ;
 
-void set_enable();
-void set_pidcheck();
-void set_remove();
-void set_numbufs();
-void set_init();
-
+static void set_enable(int);
+static void set_pidcheck(int, int);
+static void set_remove(void);
+static void set_numbufs(int);
+static void set_init(void);
+void quit(char *);
+int argtopid(char *);
+int argtoi(int, char*, char*, int);
+
+void get_bufinfo(kbufinfo_t *);
+static void reset_counters(void);
+static void getdivisor(void);
+static void screen_update(void);
+static void sc_tab_init(char *);
+static void sort_scalls(void);
+static void sample_sc(void);
+static int find_msgcode(int);
 
 /*
  *  signal handlers
  */
 
-void leave()                   /* exit under normal conditions -- INT handler */
+/* exit under normal conditions -- INT handler */
+static void
+leave(__unused int unused)
 {
-
         if (no_screen_refresh == 0) {
                move(LINES - 1, 0);
                refresh();
                endwin();
-
-               tcsetattr(0, TCSANOW, &omode);
        }
        set_enable(0);
        set_pidcheck(pid, 0);
@@ -235,38 +245,16 @@ void leave()                      /* exit under normal conditions -- INT handler */
        exit(0);
 }
 
-void err_leave(s)      /* exit under error conditions */
-char *s;
-{
-
-        if (no_screen_refresh == 0) {
-               move(LINES - 1, 0);
-               refresh();
-               endwin();
-
-               tcsetattr(0, TCSANOW, &omode);
-       }
-
-        printf("sc_usage: ");
-       if (s)
-               printf("%s ", s);
-
-       set_enable(0);
-       set_pidcheck(pid, 0);
-       set_remove();
-
-       exit(1);
-}
-
-void sigwinch()
+static void
+sigwinch(__unused int unused)
 {
         if (no_screen_refresh == 0)
                newLINES = 1;
 }
 
-int
-exit_usage(myname) {
-
+static int
+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");
        fprintf(stderr, "             Default is /usr/share/misc/trace.codes\n");
@@ -280,10 +268,10 @@ exit_usage(myname) {
        exit(1);
 }
 
-
 #define usec_to_1000ths(t)       ((t) / 1000)
 
-void print_time(char *p, unsigned int useconds, unsigned int seconds)
+static void
+print_time(char *p, unsigned int useconds, unsigned int seconds)
 {
        long    minutes, hours;
 
@@ -291,43 +279,37 @@ 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, "%02ld:%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, "%02ld:%02ld:%02ld ", hours, (minutes % 60),
+                               (unsigned long)(seconds % 60));
        }
        else {
                sprintf(p, "%4ld hrs ", hours);
        }
 }
 
-
-main(argc, argv)
-       int     argc;
-       char    *argv[];
+int
+main(int argc, char *argv[])
 {
        char    *myname   = "sc_usage";
        char    *codefile = "/usr/share/misc/trace.codes";
        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");
              exit(1);
        }
 
+        if (0 != reexec_to_match_kernel()) {
+               fprintf(stderr, "Could not re-execute: %d\n", errno);
+               exit(1);
+       }
+
        /* get our name */
        if (argc > 0) {
                if ((myname = rindex(argv[0], '/')) == 0) {
@@ -378,7 +360,7 @@ main(argc, argv)
 
                uid_t uid, euid;
                gid_t gid, egid;
-               
+
                ptr = strrchr(argv[optind], '/');
                if (ptr)
                  ptr++;
@@ -388,7 +370,7 @@ main(argc, argv)
                strncpy(proc_name, ptr, sizeof(proc_name)-1);
                proc_name[sizeof(proc_name)-1] = '\0';
 
-               uid= getuid();
+               uid= getuid();
                gid= getgid();
                euid= geteuid();
                egid= getegid();
@@ -406,7 +388,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);
@@ -423,22 +405,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();
        }
@@ -447,6 +424,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)
@@ -455,8 +434,6 @@ main(argc, argv)
                topn = 1024;
                COLS = 80;
        }
-       if ((my_buffer = malloc(SAMPLE_SIZE * sizeof(kd_buf))) == (char *)0)
-           quit("can't allocate memory for tracing info\n");
 
        set_remove();
        set_numbufs(SAMPLE_SIZE);
@@ -464,7 +441,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)
@@ -472,6 +449,12 @@ main(argc, argv)
        if ((sort_now = 10 / delay) < 2)
                sort_now = 2;
 
+       get_bufinfo(&bufinfo);
+
+       my_buffer = malloc(bufinfo.nkdbufs * sizeof(kd_buf));
+       if(my_buffer == (char *) 0)
+               quit("can't allocate memory for tracing info\n");
+
        (void)sort_scalls();
        (void)screen_update();
 
@@ -479,22 +462,15 @@ main(argc, argv)
 
        while (1) {
                int     i;
-               int     cnt;
-               char    ibuf[128];
-               void    sample_sc();
-               
+               char    c;
+
                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(0);
+                               if (c != ERR)
+                                       reset_counters();
                        } else
                                usleep(100000);
                        sample_sc();
@@ -502,7 +478,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();
 
@@ -513,10 +493,11 @@ main(argc, argv)
        }
 }
 
-void
-print_row(struct sc_entry *se, int no_wtime) {
+static void
+print_row(struct sc_entry *se, int no_wtime)
+{
        char    tbuf[256];
-       int     clen;
+       size_t     clen;
 
        if (se->delta_count)
                sprintf(tbuf, "%-23.23s    %8d(%d)", se->name, se->total_count, se->delta_count);
@@ -526,14 +507,14 @@ print_row(struct sc_entry *se, int no_wtime) {
 
        memset(&tbuf[clen], ' ', 45 - clen);
 
-       print_time(&tbuf[45], (unsigned long)(se->stime_usecs), se->stime_secs);
+       print_time(&tbuf[45], (unsigned int)(se->stime_usecs), se->stime_secs);
        clen = strlen(tbuf);
 
        if (no_wtime == 0 && (se->wtime_usecs || se->wtime_secs)) {
                sprintf(&tbuf[clen], "  ");
                clen += strlen(&tbuf[clen]);
 
-               print_time(&tbuf[clen], (unsigned long)(se->wtime_usecs), se->wtime_secs);
+               print_time(&tbuf[clen], (unsigned int)(se->wtime_usecs), se->wtime_secs);
                clen += strlen(&tbuf[clen]);
 
                if (se->waiting || se->delta_wtime_usecs || se->delta_wtime_secs) {
@@ -541,7 +522,7 @@ print_row(struct sc_entry *se, int no_wtime) {
                        sprintf(&tbuf[clen], "(");
                        clen += strlen(&tbuf[clen]);
 
-                       print_time(&tbuf[clen], (unsigned long)(se->delta_wtime_usecs),
+                       print_time(&tbuf[clen], (unsigned int)(se->delta_wtime_usecs),
                                                                se->delta_wtime_secs);
                        clen += strlen(&tbuf[clen]);
 
@@ -558,34 +539,29 @@ print_row(struct sc_entry *se, int no_wtime) {
                }
        }
        sprintf(&tbuf[clen], "\n");
-
-       if (tbuf[COLS-2] != '\n') {
-               tbuf[COLS-1] = '\n';
-               tbuf[COLS] = 0;
-       }
        if (no_screen_refresh)
                printf("%s", tbuf);
        else
                printw(tbuf);
 }
 
-
-void screen_update()
+static void
+screen_update(void)
 {
         char    *p1, *p2, *p3;
        char    tbuf[256];
-       int     clen;
-       int     plen;
+       size_t  clen;
+       size_t  plen;
        int     n, i, rows;
        long    curr_time;
        long    elapsed_secs;
-       int     hours;
-       int     minutes;
+       long    hours;
+       long    minutes;
        struct  sc_entry *se;
        int     output_lf;
        int     max_rows;
        struct th_info *ti;
-       
+
        if (no_screen_refresh == 0) {
                /* clear for new display */
                erase();
@@ -595,7 +571,7 @@ void screen_update()
 
        sprintf(tbuf, "%-14.14s", proc_name);
        clen = strlen(tbuf);
-       
+
        if (preempted == 1)
                p1 = "preemption ";
        else
@@ -616,7 +592,7 @@ void screen_update()
        /*
         *  Display the current time.
         *  "ctime" always returns a string that looks like this:
-        *  
+        *
         *      Sun Sep 16 01:03:52 1973
         *      012345678901234567890123
         *                1         2
@@ -637,11 +613,6 @@ void screen_update()
        clen = 78 - 8;
 
        sprintf(&tbuf[clen], "%-8.8s\n", &(ctime(&curr_time)[11]));
-
-       if (tbuf[COLS-2] != '\n') {
-               tbuf[COLS-1] = '\n';
-               tbuf[COLS] = 0;
-       }
        if (no_screen_refresh)
                printf("%s", tbuf);
        else
@@ -661,11 +632,6 @@ void screen_update()
        clen = strlen(tbuf);
        sprintf(&tbuf[clen], "                    %3ld:%02ld:%02ld\n", 
                hours, minutes % 60, elapsed_secs % 60);
-
-       if (tbuf[COLS-2] != '\n') {
-               tbuf[COLS-1] = '\n';
-               tbuf[COLS] = 0;
-       }
        if (no_screen_refresh)
                printf("%s", tbuf);
        else
@@ -673,22 +639,13 @@ void screen_update()
 
 
 
-       sprintf(tbuf, "\nTYPE                            NUMBER        CPU_TIME   WAIT_TIME\n");
-
-       if (tbuf[COLS-2] != '\n') {
-               tbuf[COLS-1] = '\n';
-               tbuf[COLS] = 0;
-       }
+       sprintf(tbuf, "\nTYPE                           NUMBER        CPU_TIME   WAIT_TIME\n");
        if (no_screen_refresh)
                printf("%s", tbuf);
        else
                printw(tbuf);
 
        sprintf(tbuf, "------------------------------------------------------------------------------\n");
-       if (tbuf[COLS-2] != '\n') {
-               tbuf[COLS-1] = '\n';
-               tbuf[COLS] = 0;
-       }
        if (no_screen_refresh)
                printf("%s", tbuf);
        else
@@ -700,7 +657,7 @@ void screen_update()
        sprintf(tbuf, "System         Idle                                     ");
        clen = strlen(tbuf);
 
-       print_time(&tbuf[clen], (unsigned long)(itime_usecs), itime_secs);
+       print_time(&tbuf[clen], itime_usecs, itime_secs);
        clen += strlen(&tbuf[clen]);
 
        if (delta_itime_usecs || delta_itime_secs) {
@@ -708,18 +665,13 @@ void screen_update()
                sprintf(&tbuf[clen], "(");
                clen += strlen(&tbuf[clen]);
 
-               print_time(&tbuf[clen], (unsigned long)(delta_itime_usecs), delta_itime_secs);
+               print_time(&tbuf[clen], delta_itime_usecs, delta_itime_secs);
                clen += strlen(&tbuf[clen]);
 
                sprintf(&tbuf[clen], ")");
                clen += strlen(&tbuf[clen]);
        }
         sprintf(&tbuf[clen], "\n");
-
-       if (tbuf[COLS-2] != '\n') {
-               tbuf[COLS-1] = '\n';
-               tbuf[COLS] = 0;
-       }
        if (no_screen_refresh)
                printf("%s", tbuf);
        else
@@ -731,26 +683,21 @@ void screen_update()
        sprintf(tbuf, "System         Busy                                     ");
        clen = strlen(tbuf);
 
-       print_time(&tbuf[clen], (unsigned long)(otime_usecs), otime_secs);
+       print_time(&tbuf[clen], otime_usecs, otime_secs);
        clen += strlen(&tbuf[clen]);
 
        if (delta_otime_usecs || delta_otime_secs) {
 
-               sprintf(&tbuf[clen], "(");      
+               sprintf(&tbuf[clen], "(");
        clen += strlen(&tbuf[clen]);
 
-               print_time(&tbuf[clen], (unsigned long)(delta_otime_usecs), delta_otime_secs);
+               print_time(&tbuf[clen], delta_otime_usecs, delta_otime_secs);
                clen += strlen(&tbuf[clen]);
 
                sprintf(&tbuf[clen], ")");
                clen += strlen(&tbuf[clen]);
        }
         sprintf(&tbuf[clen], "\n");
-
-       if (tbuf[COLS-2] != '\n') {
-               tbuf[COLS-1] = '\n';
-               tbuf[COLS] = 0;
-       }
        if (no_screen_refresh)
                printf("%s", tbuf);
        else
@@ -761,14 +708,10 @@ void screen_update()
        sprintf(tbuf, "%-14.14s Usermode                      ", proc_name);
        clen = strlen(tbuf);
 
-       print_time(&tbuf[clen], (unsigned long)(utime_usecs), utime_secs);
+       print_time(&tbuf[clen], utime_usecs, utime_secs);
        clen += strlen(&tbuf[clen]);
-        sprintf(&tbuf[clen], "\n");
 
-       if (tbuf[COLS-2] != '\n') {
-               tbuf[COLS-1] = '\n';
-               tbuf[COLS] = 0;
-       }
+       sprintf(&tbuf[clen], "\n");
        if (no_screen_refresh)
                printf("%s", tbuf);
        else
@@ -818,40 +761,34 @@ void screen_update()
                print_row(&sc_tab[n], 0);
                rows++;
        }
-       if (no_screen_refresh == 0) {
-               sprintf(tbuf, "\n");
 
+
+       sprintf(tbuf, "\n");
+       if (no_screen_refresh == 0) {
                while (rows++ < max_rows)
                        printw(tbuf);
        } else
-               printf("\n");
+               printf("%s", tbuf);
 
        if (num_of_threads) {
                sprintf(tbuf, "\nCURRENT_TYPE              LAST_PATHNAME_WAITED_FOR     CUR_WAIT_TIME THRD# PRI\n");
 
-               if (tbuf[COLS-2] != '\n') {
-                       tbuf[COLS-1] = '\n';
-                       tbuf[COLS] = 0;
-               }
                if (no_screen_refresh)
                        printf("%s", tbuf);
                else
                        printw(tbuf);
 
                sprintf(tbuf, "------------------------------------------------------------------------------\n");
-               if (tbuf[COLS-2] != '\n') {
-                       tbuf[COLS-1] = '\n';
-                       tbuf[COLS] = 0;
-               }
                if (no_screen_refresh)
                        printf("%s", tbuf);
                else
                        printw(tbuf);
        }
        ti = &th_state[0];
-               
+
        for (i = 0; i < num_of_threads; i++, ti++) {
                struct entry *te;
+               char    *p;
                uint64_t now;
                int      secs, time_secs, time_usecs;
 
@@ -870,37 +807,34 @@ void screen_update()
                                        sprintf(tbuf, "%-23.23s", sc_tab[te->code].name);
                                else
                                        sprintf(tbuf, "%-23.23s", "vm_fault");
-                       } else 
+                       } else
                                sprintf(tbuf, "%-23.23s", state_name[te->sc_state]);
                } else {
                        te = &ti->th_entry[0];
                        sprintf(tbuf, "%-23.23s", state_name[te->sc_state]);
                }
                clen = strlen(tbuf);
-               
+
                /* print the tail end of the pathname */
-               plen = strlen(ti->pathname);
-               if (plen > 34)
-                 plen -= 34;
+               p = (char *)ti->pathname;
+
+               plen = strlen(p);
+               if (plen > 26)
+                 plen -= 26;
                else
                  plen = 0;
-               sprintf(&tbuf[clen], "   %-34.34s ", &ti->pathname[plen]);
+               sprintf(&tbuf[clen], "   %-26.26s   ", &p[plen]);
 
                clen += strlen(&tbuf[clen]);
 
-               time_usecs = (unsigned long)(((double)now - te->otime) / divisor);
+               time_usecs = (((double)now - te->otime) / divisor);
                secs = time_usecs / 1000000;
                time_usecs -= secs * 1000000;
                time_secs = secs;
 
                print_time(&tbuf[clen], time_usecs, time_secs);
                clen += strlen(&tbuf[clen]);
-               sprintf(&tbuf[clen], "  %2d %3d\n", i, ti->curpri);
-
-               if (tbuf[COLS-2] != '\n') {
-                       tbuf[COLS-1] = '\n';
-                       tbuf[COLS] = 0;
-               }
+               sprintf(&tbuf[clen], "    %2d    %3d\n", i, ti->curpri);
                if (no_screen_refresh)
                        printf("%s", tbuf);
                else
@@ -938,8 +872,9 @@ void screen_update()
        delta_otime_usecs = 0;
 }
 
-void
-reset_counters() {
+static void
+reset_counters(void)
+{
         int   i;
 
        for (i = 0; i < (MAX_SC + msgcode_cnt) ; i++) {
@@ -969,7 +904,7 @@ reset_counters() {
        total_faults = 0;
        scalls = 0;
        called = 0;
-       
+
        utime_secs = 0;
        utime_usecs = 0;
        itime_secs = 0;
@@ -982,32 +917,28 @@ reset_counters() {
        delta_otime_usecs = 0;
 }
 
-void
-sc_tab_init(char *codefile) {
+static void
+sc_tab_init(char *codefile)
+{
         int  code;
-       int  n, cnt;
+       int  n;
        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);
                exit(1);
        }
 
-       n = fscanf(fp, "%d\n", &cnt);
-       if (n != 1)
-               return;
-
        /* Count Mach message MSG_ codes */
        for (msgcode_cnt=0;;) {
-               n = fscanf(fp, "%x%s\n", &code, &name[0]);
+               n = fscanf(fp, "%x%55s\n", &code, &name[0]);
                if (n != 2)
                  break;
                if (strncmp ("MSG_", &name[0], 4) == 0)
                  msgcode_cnt++;
-               if (strcmp("USER_TEST", &name[0]) == 0)
+               if (strcmp("TRACE_LAST_WRAPPER", &name[0]) == 0)
                        break;
        }
 
@@ -1034,13 +965,8 @@ sc_tab_init(char *codefile) {
 
        rewind(fp);
 
-       n = fscanf(fp, "%d\n", &cnt);
-
-       if (n != 1)
-               return;
-
        for (;;) {
-               n = fscanf(fp, "%x%s\n", &code, &name[0]);
+               n = fscanf(fp, "%x%55s\n", &code, &name[0]);
 
                if (n != 2)
                        break;
@@ -1057,6 +983,10 @@ sc_tab_init(char *codefile) {
                        mach_stkhandoff = code;
                        continue;
                }
+               if (strcmp("MACH_IDLE", &name[0]) == 0) {
+                       mach_idle = code;
+                       continue;
+               }
                if (strcmp("VFS_LOOKUP", &name[0]) == 0) {
                        vfs_lookup = code;
                        continue;
@@ -1090,7 +1020,7 @@ sc_tab_init(char *codefile) {
                        strcpy(&sc_tab[n].name[0], &name[4]);
                        continue;
                }
-               if (strcmp("USER_TEST", &name[0]) == 0)
+               if (strcmp("TRACE_LAST_WRAPPER", &name[0]) == 0)
                        break;
        }
        strcpy(&faults[1].name[0], "zero_fill");
@@ -1099,8 +1029,8 @@ sc_tab_init(char *codefile) {
        strcpy(&faults[4].name[0], "cache_hit");
 }
 
-void
-find_proc_names()
+static void
+find_proc_names(void)
 {
        size_t                  bufSize = 0;
        struct kinfo_proc       *kp;
@@ -1115,7 +1045,7 @@ find_proc_names()
 
        if((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0)
            quit("can't allocate memory for proc buffer\n");
-       
+
        if (sysctl(mib, 4, kp, &bufSize, NULL, 0) < 0)
                quit("trace facility failure, KERN_PROC_ALL\n");
 
@@ -1123,7 +1053,9 @@ find_proc_names()
        kp_buffer = kp;
 }
 
-struct th_info *find_thread(int thread) {
+static struct th_info *
+find_thread(uintptr_t thread)
+{
        struct th_info *ti;
 
        for (ti = th_state; ti < &th_state[MAX_THREADS]; ti++) {
@@ -1133,10 +1065,9 @@ struct th_info *find_thread(int thread) {
        return ((struct th_info *)0);
 }
 
-
-int
-cmp_wtime(struct sc_entry *s1, struct sc_entry *s2) {
-
+static int
+cmp_wtime(struct sc_entry *s1, struct sc_entry *s2)
+{
         if (s1->wtime_secs < s2->wtime_secs)
                return 0;
         if (s1->wtime_secs > s2->wtime_secs)
@@ -1146,9 +1077,9 @@ cmp_wtime(struct sc_entry *s1, struct sc_entry *s2) {
        return 1;
 }
 
-
-void
-sort_scalls() {
+static void
+sort_scalls(void)
+{
         int  i, n, k, cnt, secs;
        struct th_info *ti;
        struct sc_entry *se;
@@ -1189,7 +1120,7 @@ sort_scalls() {
                                if ((unsigned long)(((double)now - te->otime) / divisor) > 5000000) {
                                        ti->thread = 0;
                                        ti->vfslookup = 0;
-                                       ti->pathptr = (long *)0;
+                                       ti->pathptr = (long *)NULL;
                                        ti->pathname[0] = 0;
                                        num_of_threads--;
                                }
@@ -1230,8 +1161,8 @@ sort_scalls() {
        called++;
 }
 
-void
-set_enable(int val) 
+static void
+set_enable(int val)
 {
        mib[0] = CTL_KERN;
        mib[1] = KERN_KDEBUG;
@@ -1248,8 +1179,8 @@ set_enable(int val)
          trace_enabled = 0;
 }
 
-void
-set_numbufs(int nbufs) 
+static void
+set_numbufs(int nbufs)
 {
        mib[0] = CTL_KERN;
        mib[1] = KERN_KDEBUG;
@@ -1262,7 +1193,7 @@ set_numbufs(int nbufs)
 
        mib[0] = CTL_KERN;
        mib[1] = KERN_KDEBUG;
-       mib[2] = KERN_KDSETUP;          
+       mib[2] = KERN_KDSETUP;
        mib[3] = 0;
        mib[4] = 0;
        mib[5] = 0;                     /* no flags */
@@ -1271,8 +1202,8 @@ set_numbufs(int nbufs)
 
 }
 
-void
-set_pidcheck(int pid, int on_off) 
+static void
+set_pidcheck(int pid, int on_off)
 {
         kd_regtype kr;
 
@@ -1287,7 +1218,7 @@ set_pidcheck(int pid, int on_off)
        mib[4] = 0;
        mib[5] = 0;
        if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
-               if (on_off == 1) { 
+               if (on_off == 1) {
                        printf("pid %d does not exist\n", pid);
                        set_remove();
                        exit(2);
@@ -1301,7 +1232,7 @@ get_bufinfo(kbufinfo_t *val)
         needed = sizeof (*val);
        mib[0] = CTL_KERN;
        mib[1] = KERN_KDEBUG;
-       mib[2] = KERN_KDGETBUF;         
+       mib[2] = KERN_KDGETBUF;
        mib[3] = 0;
        mib[4] = 0;
        mib[5] = 0;             /* no flags */
@@ -1310,8 +1241,8 @@ get_bufinfo(kbufinfo_t *val)
 
 }
 
-void
-set_remove(
+static void
+set_remove(void)
 {
         extern int errno;
 
@@ -1329,15 +1260,16 @@ set_remove()
            set_remove_flag = 0;
 
            if (errno == EBUSY)
-               quit("the trace facility is currently in use...\n          fs_usage, sc_usage, and latency use this feature.\n\n");
+               quit("The trace facility is currently in use...\n          Note: fs_usage, sc_usage, and latency use this feature.\n\n");
            else
                quit("trace facility failure, KERN_KDREMOVE\n");
          }
 }
 
-void
-set_init() 
-{       kd_regtype kr;
+static void
+set_init(void)
+{
+       kd_regtype kr;
 
        kr.type = KDBG_RANGETYPE;
        kr.value1 = 0;
@@ -1345,7 +1277,7 @@ set_init()
        needed = sizeof(kd_regtype);
        mib[0] = CTL_KERN;
        mib[1] = KERN_KDEBUG;
-       mib[2] = KERN_KDSETREG;         
+       mib[2] = KERN_KDSETREG;
        mib[3] = 0;
        mib[4] = 0;
        mib[5] = 0;             /* no flags */
@@ -1354,37 +1286,38 @@ set_init()
 
        mib[0] = CTL_KERN;
        mib[1] = KERN_KDEBUG;
-       mib[2] = KERN_KDSETUP;          
+       mib[2] = KERN_KDSETUP;
        mib[3] = 0;
        mib[4] = 0;
        mib[5] = 0;             /* no flags */
        if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
                quit("trace facility failure, KERN_KDSETUP\n");
-
 }
 
-void
-sample_sc()
+static void
+sample_sc(void)
 {
        kd_buf *kd;
-       int i, count;
+       int i;
+       size_t count;
        int secs;
-       int find_msgcode();
-       
-        /* Get kernel buffer information */
-       get_bufinfo(&bufinfo);
+
 #ifdef OLD_KDEBUG
        set_enable(0);
 #endif
+       get_bufinfo(&bufinfo);
+
        needed = bufinfo.nkdbufs * sizeof(kd_buf);
        mib[0] = CTL_KERN;
        mib[1] = KERN_KDEBUG;
-       mib[2] = KERN_KDREADTR;         
+       mib[2] = KERN_KDREADTR;
        mib[3] = 0;
        mib[4] = 0;
-       mib[5] = 0;             /* no flags */
+       mib[5] = 0;
+
        if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0)
-               quit("trace facility failure, KERN_KDREADTR\n");
+               quit("trace facility failure, KERN_KDREADTR\n");
+
        count = needed;
 
        if (bufinfo.flags & KDBG_WRAPPED) {
@@ -1392,11 +1325,12 @@ 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].pathptr = (long *)NULL;
                        th_state[i].pathname[0] = 0;
                }
                num_of_threads = 0;
        }
+
 #ifdef OLD_KDEBUG
        set_remove();
        set_init();
@@ -1406,14 +1340,15 @@ sample_sc()
        kd = (kd_buf *)my_buffer;
 
        for (i = 0; i < count; i++) {
-               int debugid, baseid, thread;
+               int debugid, baseid;
+               uintptr_t thread;
                int type, code;
                uint64_t now;
                struct th_info *ti, *switched_out, *switched_in;
                struct sc_entry *se;
                struct entry *te;
 
-               thread  = kd[i].arg5 & KDBG_THREAD_MASK;
+               thread  = kd[i].arg5;
                debugid = kd[i].debugid;
                type    = kd[i].debugid & DBG_FUNC_MASK;
 
@@ -1421,23 +1356,28 @@ sample_sc()
                switched_out = (struct th_info *)0;
                switched_in  = (struct th_info *)0;
 
-               now = (((uint64_t)kd[i].timestamp.tv_sec) << 32) |
-                       (uint64_t)((unsigned int)(kd[i].timestamp.tv_nsec));
+               now = kd[i].timestamp & KDBG_TIMESTAMP_MASK;
+
                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++;
-                               memset(&ti->pathname[0], 0, (PATHLENGTH + 1));
-                               sargptr = (long *)&ti->pathname[0];
+                               sargptr = ti->pathname;
 
                                *sargptr++ = kd[i].arg2;
                                *sargptr++ = kd[i].arg3;
                                *sargptr++ = kd[i].arg4;
+                               /*
+                                * NULL terminate the 'string'
+                                */
+                               *sargptr = 0;
+
                                ti->pathptr = sargptr;
 
                        } else if (ti->vfslookup > 1) {
@@ -1450,23 +1390,49 @@ sample_sc()
                                  handle.
                                */
 
-                               if ((long *)sargptr >= (long *)&ti->pathname[PATHLENGTH])
-                                 continue;
+                               if (sargptr >= &ti->pathname[NUMPARMS])
+                                       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)
+                                 {
+                                   ti->pathptr = &ti->pathname[NUMPARMS];
+                                   continue;
+                                 }
+
                                *sargptr++ = kd[i].arg1;
                                *sargptr++ = kd[i].arg2;
                                *sargptr++ = kd[i].arg3;
                                *sargptr++ = kd[i].arg4;
+                               /*
+                                * NULL terminate the 'string'
+                                */
+                               *sargptr = 0;
+
                                ti->pathptr = sargptr;
                        }
                        continue;
 
                } else if (baseid == bsc_base)
                        code = (debugid >> 2) & 0x1ff;
-               else if (baseid == msc_base)
+               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);
-                       switched_in  = find_thread(kd[i].arg2);
+               else if (type == mach_idle) {
+                       if (debugid & DBG_FUNC_START) {
+                               switched_out = find_thread(kd[i].arg5);
+                               switched_in = 0;
+                       }
+                       else
+                       if (debugid & DBG_FUNC_END) {
+                               switched_in = find_thread(kd[i].arg5);
+                               switched_out = 0;
+                       }
 
                        if (in_idle) {
                                itime_usecs += ((double)now - idle_start) / divisor;
@@ -1479,17 +1445,45 @@ sample_sc()
                        }
                        if ( !switched_in) {
                                /*
-                                * not one of the target proc's threads
-                                */
+                                        * not one of the target proc's threads
+                                        */
                                if (now_collect_cpu_time) {
-                                       if (kd[i].arg4 == 0) {
                                                in_idle = 1;
-                                               idle_start = (double)now;
-                                       } else {
+                                                       idle_start = (double)now;
+                                       }
+                       }
+                       else {
+                               if (now_collect_cpu_time) {
+                                                       in_idle = 0;
+                                                       in_other = 1;
+                                                       other_start = (double)now;
+                                       }
+                       }
+                       if ( !switched_in && !switched_out)
+                               continue;
+
+               }
+               else if (type == mach_sched || type == mach_stkhandoff) {
+                       switched_out = find_thread(kd[i].arg5);
+                       switched_in  = find_thread(kd[i].arg2);
+
+                       if (in_idle) {
+                               itime_usecs += ((double)now - idle_start) / divisor;
+                               delta_itime_usecs += ((double)now - idle_start) / divisor;
+                               in_idle = 0;
+                       } else if (in_other) {
+                               otime_usecs += ((double)now - other_start) / divisor;
+                               delta_otime_usecs += ((double)now - other_start) / divisor;
+                               in_other = 0;
+                       }
+                       if ( !switched_in) {
+                               /*
+                                        * not one of the target proc's threads
+                                        */
+                               if (now_collect_cpu_time) {
                                                in_other = 1;
-                                               other_start = (double)now;
+                                                       other_start = (double)now;
                                        }
-                               }
                        }
                        if ( !switched_in && !switched_out)
                                continue;
@@ -1505,14 +1499,14 @@ sample_sc()
                if (switched_out || switched_in) {
                        if (switched_out) {
                                ti = switched_out;
-                               ti->curpri = kd[i].arg3;
+                               ti->curpri = (int)kd[i].arg3;
 
                                if (ti->depth) {
                                        te = &ti->th_entry[ti->depth-1];
 
                                        if (te->sc_state == KERNEL_MODE)
                                                te->ctime += (double)now - te->stime;
-                                       te->sc_state = WAITING; 
+                                       te->sc_state = WAITING;
 
                                        ti->vfslookup = 1;
 
@@ -1531,14 +1525,14 @@ sample_sc()
                        }
                        if (switched_in) {
                                ti = switched_in;
-                               ti->curpri = kd[i].arg4;
+                               ti->curpri = (int)kd[i].arg4;
 
                                if (ti->depth) {
                                        te = &ti->th_entry[ti->depth-1];
 
                                        if (te->sc_state == WAITING)
                                                te->wtime += (double)now - te->stime;
-                                       te->sc_state = KERNEL_MODE; 
+                                       te->sc_state = KERNEL_MODE;
                                } else {
                                        te = &ti->th_entry[0];
 
@@ -1548,7 +1542,7 @@ sample_sc()
                                te->otime = (double)now;
                        }
                        continue;
-               } 
+               }
                if ((ti = find_thread(thread)) == (struct th_info *)0) {
                        for (ti = &th_state[0]; ti < &th_state[MAX_THREADS]; ti++) {
                                if (ti->thread == 0) {
@@ -1595,7 +1589,7 @@ sample_sc()
                                se = &sc_tab[code];
                                scalls++;
                        } else {
-                               se = &faults[kd[i].arg2];
+                               se = &faults[kd[i].arg4];
                                total_faults++;
                        }
                        if (se->total_count == 0)
@@ -1628,7 +1622,7 @@ sample_sc()
                                        ti->depth--;
 
                                        if (ti->depth == 0) {
-                                               /* 
+                                               /*
                                                 * headed back to user mode
                                                 * start the time accumulation
                                                 */
@@ -1645,7 +1639,7 @@ sample_sc()
                                ti->depth--;
 
                                if (ti->depth == 0) {
-                                       /* 
+                                       /*
                                         * headed back to user mode
                                         * start the time accumulation
                                         */
@@ -1678,100 +1672,101 @@ sample_sc()
        delta_otime_secs += secs;
 }
 
-
-quit(s)
-char *s;
+void
+quit(char *s)
 {
         if (trace_enabled)
                set_enable(0);
 
-       /* 
+       /*
           This flag is turned off when calling
           quit() due to a set_remove() failure.
        */
        if (set_remove_flag)
                set_remove();
 
+       if (no_screen_refresh == 0) {
+               /* clear for new display */
+               erase();
+               move(0, 0);
+               refresh();
+               endwin();
+       }
+
         printf("sc_usage: ");
        if (s)
-               printf("%s ", s);
+               printf("%s", s);
 
        exit(1);
 }
 
-void getdivisor()
+static void
+getdivisor(void)
 {
-  mach_timebase_info_data_t info;
-
-  (void) mach_timebase_info (&info);
+       mach_timebase_info_data_t info;
 
-  divisor = ( (double)info.denom / (double)info.numer) * 1000;
+       (void) mach_timebase_info (&info);
 
+       divisor = ( (double)info.denom / (double)info.numer) * 1000;
 }
 
-
-argtopid(str)
-        char *str;
+int
+argtopid(char *str)
 {
-        char *cp;
-        int ret;
+       char *cp;
+       int ret;
        int i;
 
        if (!kp_buffer)
-               find_proc_names();
-
-        ret = (int)strtol(str, &cp, 10);
-        if (cp == str || *cp) {
-         /* Assume this is a command string and find first matching pid */
-               for (i=0; i < kp_nentries; i++) {
-                     if(kp_buffer[i].kp_proc.p_stat == 0)
-                         continue;
-                     else {
-                         if(!strcmp(str, kp_buffer[i].kp_proc.p_comm))
-                           {
-                             strncpy(proc_name, kp_buffer[i].kp_proc.p_comm, sizeof(proc_name)-1);
-                             proc_name[sizeof(proc_name)-1] = '\0';
-                             return(kp_buffer[i].kp_proc.p_pid);
-                           }
-                     }
+               find_proc_names();
+
+       ret = (int)strtol(str, &cp, 10);
+       if (cp == str || *cp) {
+               /* Assume this is a command string and find first matching pid */
+               for (i=0; i < kp_nentries; i++) {
+                       if (kp_buffer[i].kp_proc.p_stat == 0)
+                               continue;
+                       else {
+                               if (!strcmp(str, kp_buffer[i].kp_proc.p_comm)) {
+                                       strncpy(proc_name,
+                                               kp_buffer[i].kp_proc.p_comm,
+                                               sizeof(proc_name)-1);
+                                       proc_name[sizeof(proc_name)-1] = '\0';
+                                       return (kp_buffer[i].kp_proc.p_pid);
+                               }
+                       }
                }
-       }
-       else
-         {
-           for (i=0; i < kp_nentries; i++)
-             {
-               if(kp_buffer[i].kp_proc.p_stat == 0)
-                 continue;
-               else if (kp_buffer[i].kp_proc.p_pid == ret) {
-                   strncpy(proc_name, kp_buffer[i].kp_proc.p_comm, sizeof(proc_name)-1);
-                   proc_name[sizeof(proc_name)-1] = '\0';
-                   return(kp_buffer[i].kp_proc.p_pid);               
+       } else {
+               for (i=0; i < kp_nentries; i++) {
+                       if (kp_buffer[i].kp_proc.p_stat == 0)
+                               continue;
+                       else if (kp_buffer[i].kp_proc.p_pid == ret) {
+                               strncpy(proc_name,
+                                       kp_buffer[i].kp_proc.p_comm,
+                                       sizeof(proc_name)-1);
+                               proc_name[sizeof(proc_name)-1] = '\0';
+                               return (kp_buffer[i].kp_proc.p_pid);
+                       }
                }
-             }
-         }
-        return(-1);
+       }
+       return (-1);
 }
 
-
 /* Returns index into sc_tab for a mach msg entry */
-int
+static int
 find_msgcode(int debugid)
 {
+       int indx;
 
-  int indx;
-
-  for (indx=0; indx< msgcode_cnt; indx++)
-    {
-      if (msgcode_tab[indx] == ((debugid & 0x00ffffff) >>2))
-         return (MAX_SC+indx);
-    }
-  return (0);
+       for (indx=0; indx< msgcode_cnt; indx++) {
+               if (msgcode_tab[indx] == ((debugid & 0x00ffffff) >>2))
+                       return (MAX_SC+indx);
+       }
+       return (0);
 }
-  
-argtoi(flag, req, str, base)
-       int flag;
-       char *req, *str;
-       int base;
+
+int
+argtoi(int flag, char *req, char *str, int base)
 {
        char *cp;
        int ret;
@@ -1781,4 +1776,3 @@ argtoi(flag, req, str, base)
                errx(EINVAL, "-%c flag requires a %s", flag, req);
        return (ret);
 }
-