/*
- * 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
* 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 */
#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>
#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
#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",
};
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;
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;
#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};
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);
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");
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;
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) {
uid_t uid, euid;
gid_t gid, egid;
-
+
ptr = strrchr(argv[optind], '/');
if (ptr)
ptr++;
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();
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);
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();
}
/* set up signal handlers */
signal(SIGINT, leave);
signal(SIGQUIT, leave);
+ signal(SIGHUP, leave);
+ signal(SIGTERM, leave);
signal(SIGWINCH, sigwinch);
if (no_screen_refresh == 0)
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);
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)
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();
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();
(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();
}
}
-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);
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) {
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]);
}
}
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();
sprintf(tbuf, "%-14.14s", proc_name);
clen = strlen(tbuf);
-
+
if (preempted == 1)
p1 = "preemption ";
else
/*
* Display the current time.
* "ctime" always returns a string that looks like this:
- *
+ *
* Sun Sep 16 01:03:52 1973
* 012345678901234567890123
* 1 2
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
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
- 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
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) {
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
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
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
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;
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
delta_otime_usecs = 0;
}
-void
-reset_counters() {
+static void
+reset_counters(void)
+{
int i;
for (i = 0; i < (MAX_SC + msgcode_cnt) ; i++) {
total_faults = 0;
scalls = 0;
called = 0;
-
+
utime_secs = 0;
utime_usecs = 0;
itime_secs = 0;
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;
}
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;
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;
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");
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;
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");
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++) {
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)
return 1;
}
-
-void
-sort_scalls() {
+static void
+sort_scalls(void)
+{
int i, n, k, cnt, secs;
struct th_info *ti;
struct sc_entry *se;
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--;
}
called++;
}
-void
-set_enable(int val)
+static void
+set_enable(int val)
{
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
trace_enabled = 0;
}
-void
-set_numbufs(int nbufs)
+static void
+set_numbufs(int nbufs)
{
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
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 */
}
-void
-set_pidcheck(int pid, int on_off)
+static void
+set_pidcheck(int pid, int on_off)
{
kd_regtype kr;
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);
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 */
}
-void
-set_remove()
+static void
+set_remove(void)
{
extern int errno;
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;
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 */
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) {
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();
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;
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) {
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;
}
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;
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;
}
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];
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) {
se = &sc_tab[code];
scalls++;
} else {
- se = &faults[kd[i].arg2];
+ se = &faults[kd[i].arg4];
total_faults++;
}
if (se->total_count == 0)
ti->depth--;
if (ti->depth == 0) {
- /*
+ /*
* headed back to user mode
* start the time accumulation
*/
ti->depth--;
if (ti->depth == 0) {
- /*
+ /*
* headed back to user mode
* start the time accumulation
*/
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;
errx(EINVAL, "-%c flag requires a %s", flag, req);
return (ret);
}
-