]> git.saurik.com Git - apple/system_cmds.git/blob - fs_usage.tproj/fs_usage.c
62ffde951b44dbde6ed7c039325a6d42e87db96c
[apple/system_cmds.git] / fs_usage.tproj / fs_usage.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 /*
26 cc -I. -DKERNEL_PRIVATE -O -o fs_usage fs_usage.c
27 */
28
29 #define Default_DELAY 1 /* default delay interval */
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <signal.h>
34 #include <strings.h>
35 #include <nlist.h>
36 #include <fcntl.h>
37 #include <string.h>
38 #include <dirent.h>
39
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/time.h>
43
44 #include <libc.h>
45 #include <termios.h>
46 #include <sys/ioctl.h>
47
48 #ifndef KERNEL_PRIVATE
49 #define KERNEL_PRIVATE
50 #include <sys/kdebug.h>
51 #undef KERNEL_PRIVATE
52 #else
53 #include <sys/kdebug.h>
54 #endif /*KERNEL_PRIVATE*/
55
56 #include <sys/sysctl.h>
57 #include <errno.h>
58 #import <mach/clock_types.h>
59 #include <err.h>
60
61 extern int errno;
62
63
64
65 #define MAXINDEX 2048
66
67 typedef struct LibraryInfo {
68 unsigned long address;
69 char *name;
70 } LibraryInfo;
71
72 LibraryInfo frameworkInfo[MAXINDEX];
73 int numFrameworks = 0;
74
75 char seg_addr_table[256]="/AppleInternal/Developer/seg_addr_table";
76
77 char *lookup_name();
78
79
80 /*
81 MAXCOLS controls when extra data kicks in.
82 MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path.
83 If NUMPARMS changes to match the kernel, it will automatically
84 get reflected in the -w mode output.
85 */
86 #define NUMPARMS 23
87 #define PATHLENGTH (NUMPARMS*sizeof(long))
88 #define MAXCOLS 131
89 #define MAX_WIDE_MODE_COLS (PATHLENGTH + 80)
90
91 struct th_info {
92 int in_filemgr;
93 int thread;
94 int pid;
95 int type;
96 int arg1;
97 int arg2;
98 int arg3;
99 int arg4;
100 int child_thread;
101 int waited;
102 double stime;
103 long *pathptr;
104 char pathname[PATHLENGTH + 1]; /* add room for null terminator */
105 };
106
107 #define MAX_THREADS 512
108 struct th_info th_state[MAX_THREADS];
109
110
111 int cur_max = 0;
112 int need_new_map = 1;
113 int bias_secs;
114 int wideflag = 0;
115 int columns = 0;
116 int select_pid_mode = 0; /* Flag set indicates that output is restricted
117 to selected pids or commands */
118
119 int one_good_pid = 0; /* Used to fail gracefully when bad pids given */
120
121 char *arguments = 0;
122 int argmax = 0;
123
124 /*
125 * Network only or filesystem only output filter
126 * Default of zero means report all activity - no filtering
127 */
128 #define FILESYS_FILTER 0x01
129 #define NETWORK_FILTER 0x02
130 #define DEFAULT_DO_NOT_FILTER 0x0
131 int filter_mode = DEFAULT_DO_NOT_FILTER;
132
133 #define NFS_DEV -1
134
135 struct diskrec {
136 struct diskrec *next;
137 char *diskname;
138 int dev;
139 };
140
141 struct diskio {
142 struct diskio *next;
143 struct diskio *prev;
144 int type;
145 int bp;
146 int dev;
147 int blkno;
148 int iosize;
149 int io_errno;
150 int issuing_thread;
151 int completion_thread;
152 char issuing_command[MAXCOMLEN];
153 double issued_time;
154 double completed_time;
155 };
156
157 struct diskrec *disk_list = NULL;
158 struct diskio *free_diskios = NULL;
159 struct diskio *busy_diskios = NULL;
160
161 struct diskio *insert_diskio();
162 struct diskio *complete_diskio();
163 void free_diskio();
164 void print_diskio();
165 void format_print();
166 char *find_disk_name();
167 void cache_disk_names();
168 int ReadSegAddrTable();
169 void mark_thread_waited(int);
170 int check_filter_mode(struct th_info *, int, int, int);
171 void fs_usage_fd_set(unsigned int, unsigned int);
172 int fs_usage_fd_isset(unsigned int, unsigned int);
173 void fs_usage_fd_clear(unsigned int, unsigned int);
174 void init_arguments_buffer();
175 int get_real_command_name(int, char *, int);
176 void create_map_entry(int, int, char *);
177
178 #define DBG_ZERO_FILL_FAULT 1
179 #define DBG_PAGEIN_FAULT 2
180 #define DBG_COW_FAULT 3
181 #define DBG_CACHE_HIT_FAULT 4
182
183 #define TRACE_DATA_NEWTHREAD 0x07000004
184 #define TRACE_DATA_EXEC 0x07000008
185 #define TRACE_STRING_NEWTHREAD 0x07010004
186 #define TRACE_STRING_EXEC 0x07010008
187
188 #define MACH_vmfault 0x01300000
189 #define MACH_pageout 0x01300004
190 #define MACH_sched 0x01400000
191 #define MACH_stkhandoff 0x01400008
192 #define VFS_LOOKUP 0x03010090
193 #define BSC_exit 0x040C0004
194
195 #define P_WrData 0x03020000
196 #define P_RdData 0x03020008
197 #define P_WrMeta 0x03020020
198 #define P_RdMeta 0x03020028
199 #define P_PgOut 0x03020040
200 #define P_PgIn 0x03020048
201 #define P_WrDataAsync 0x03020010
202 #define P_RdDataAsync 0x03020018
203 #define P_WrMetaAsync 0x03020030
204 #define P_RdMetaAsync 0x03020038
205 #define P_PgOutAsync 0x03020050
206 #define P_PgInAsync 0x03020058
207
208 #define P_WrDataDone 0x03020004
209 #define P_RdDataDone 0x0302000C
210 #define P_WrMetaDone 0x03020024
211 #define P_RdMetaDone 0x0302002C
212 #define P_PgOutDone 0x03020044
213 #define P_PgInDone 0x0302004C
214 #define P_WrDataAsyncDone 0x03020014
215 #define P_RdDataAsyncDone 0x0302001C
216 #define P_WrMetaAsyncDone 0x03020034
217 #define P_RdMetaAsyncDone 0x0302003C
218 #define P_PgOutAsyncDone 0x03020054
219 #define P_PgInAsyncDone 0x0302005C
220
221
222 #define MSC_map_fd 0x010c00ac
223
224 // Network related codes
225 #define BSC_recvmsg 0x040C006C
226 #define BSC_sendmsg 0x040C0070
227 #define BSC_recvfrom 0x040C0074
228 #define BSC_accept 0x040C0078
229 #define BSC_select 0x040C0174
230 #define BSC_socket 0x040C0184
231 #define BSC_connect 0x040C0188
232 #define BSC_bind 0x040C01A0
233 #define BSC_listen 0x040C01A8
234 #define BSC_sendto 0x040C0214
235 #define BSC_socketpair 0x040C021C
236
237 #define BSC_read 0x040C000C
238 #define BSC_write 0x040C0010
239 #define BSC_open 0x040C0014
240 #define BSC_close 0x040C0018
241 #define BSC_link 0x040C0024
242 #define BSC_unlink 0x040C0028
243 #define BSC_chdir 0x040c0030
244 #define BSC_fchdir 0x040c0034
245 #define BSC_mknod 0x040C0038
246 #define BSC_chmod 0x040C003C
247 #define BSC_chown 0x040C0040
248 #define BSC_access 0x040C0084
249 #define BSC_chflags 0x040C0088
250 #define BSC_fchflags 0x040C008C
251 #define BSC_sync 0x040C0090
252 #define BSC_dup 0x040C00A4
253 #define BSC_revoke 0x040C00E0
254 #define BSC_symlink 0x040C00E4
255 #define BSC_readlink 0x040C00E8
256 #define BSC_chroot 0x040C00F4
257 #define BSC_dup2 0x040C0168
258 #define BSC_fsync 0x040C017C
259 #define BSC_readv 0x040C01E0
260 #define BSC_writev 0x040C01E4
261 #define BSC_fchown 0x040C01EC
262 #define BSC_fchmod 0x040C01F0
263 #define BSC_rename 0x040C0200
264 #define BSC_mkfifo 0x040c0210
265 #define BSC_mkdir 0x040C0220
266 #define BSC_rmdir 0x040C0224
267 #define BSC_utimes 0x040C0228
268 #define BSC_futimes 0x040C022C
269 #define BSC_statfs 0x040C0274
270 #define BSC_fstatfs 0x040C0278
271 #define BSC_stat 0x040C02F0
272 #define BSC_fstat 0x040C02F4
273 #define BSC_lstat 0x040C02F8
274 #define BSC_pathconf 0x040C02FC
275 #define BSC_fpathconf 0x040C0300
276 #define BSC_getdirentries 0x040C0310
277 #define BSC_mmap 0x040c0314
278 #define BSC_lseek 0x040c031c
279 #define BSC_truncate 0x040C0320
280 #define BSC_ftruncate 0x040C0324
281 #define BSC_undelete 0x040C0334
282 #define BSC_statv 0x040C0364
283 #define BSC_lstatv 0x040C0368
284 #define BSC_fstatv 0x040C036C
285 #define BSC_mkcomplex 0x040C0360
286 #define BSC_getattrlist 0x040C0370
287 #define BSC_setattrlist 0x040C0374
288 #define BSC_getdirentriesattr 0x040C0378
289 #define BSC_exchangedata 0x040C037C
290 #define BSC_checkuseraccess 0x040C0380
291 #define BSC_searchfs 0x040C0384
292 #define BSC_delete 0x040C0388
293 #define BSC_copyfile 0x040C038C
294 #define BSC_fsctl 0x040C03C8
295 #define BSC_load_shared_file 0x040C04A0
296
297 // Carbon File Manager support
298 #define FILEMGR_PBGETCATALOGINFO 0x1e000020
299 #define FILEMGR_PBGETCATALOGINFOBULK 0x1e000024
300 #define FILEMGR_PBCREATEFILEUNICODE 0x1e000028
301 #define FILEMGR_PBCREATEDIRECTORYUNICODE 0x1e00002c
302 #define FILEMGR_PBCREATEFORK 0x1e000030
303 #define FILEMGR_PBDELETEFORK 0x1e000034
304 #define FILEMGR_PBITERATEFORK 0x1e000038
305 #define FILEMGR_PBOPENFORK 0x1e00003c
306 #define FILEMGR_PBREADFORK 0x1e000040
307 #define FILEMGR_PBWRITEFORK 0x1e000044
308 #define FILEMGR_PBALLOCATEFORK 0x1e000048
309 #define FILEMGR_PBDELETEOBJECT 0x1e00004c
310 #define FILEMGR_PBEXCHANGEOBJECT 0x1e000050
311 #define FILEMGR_PBGETFORKCBINFO 0x1e000054
312 #define FILEMGR_PBGETVOLUMEINFO 0x1e000058
313 #define FILEMGR_PBMAKEFSREF 0x1e00005c
314 #define FILEMGR_PBMAKEFSREFUNICODE 0x1e000060
315 #define FILEMGR_PBMOVEOBJECT 0x1e000064
316 #define FILEMGR_PBOPENITERATOR 0x1e000068
317 #define FILEMGR_PBRENAMEUNICODE 0x1e00006c
318 #define FILEMGR_PBSETCATALOGINFO 0x1e000070
319 #define FILEMGR_PBSETVOLUMEINFO 0x1e000074
320 #define FILEMGR_FSREFMAKEPATH 0x1e000078
321 #define FILEMGR_FSPATHMAKEREF 0x1e00007c
322
323 #define FILEMGR_PBGETCATINFO 0x1e010000
324 #define FILEMGR_PBGETCATINFOLITE 0x1e010004
325 #define FILEMGR_PBHGETFINFO 0x1e010008
326 #define FILEMGR_PBXGETVOLINFO 0x1e01000c
327 #define FILEMGR_PBHCREATE 0x1e010010
328 #define FILEMGR_PBHOPENDF 0x1e010014
329 #define FILEMGR_PBHOPENRF 0x1e010018
330 #define FILEMGR_PBHGETDIRACCESS 0x1e01001c
331 #define FILEMGR_PBHSETDIRACCESS 0x1e010020
332 #define FILEMGR_PBHMAPID 0x1e010024
333 #define FILEMGR_PBHMAPNAME 0x1e010028
334 #define FILEMGR_PBCLOSE 0x1e01002c
335 #define FILEMGR_PBFLUSHFILE 0x1e010030
336 #define FILEMGR_PBGETEOF 0x1e010034
337 #define FILEMGR_PBSETEOF 0x1e010038
338 #define FILEMGR_PBGETFPOS 0x1e01003c
339 #define FILEMGR_PBREAD 0x1e010040
340 #define FILEMGR_PBWRITE 0x1e010044
341 #define FILEMGR_PBGETFCBINFO 0x1e010048
342 #define FILEMGR_PBSETFINFO 0x1e01004c
343 #define FILEMGR_PBALLOCATE 0x1e010050
344 #define FILEMGR_PBALLOCCONTIG 0x1e010054
345 #define FILEMGR_PBSETFPOS 0x1e010058
346 #define FILEMGR_PBSETCATINFO 0x1e01005c
347 #define FILEMGR_PBGETVOLPARMS 0x1e010060
348 #define FILEMGR_PBSETVINFO 0x1e010064
349 #define FILEMGR_PBMAKEFSSPEC 0x1e010068
350 #define FILEMGR_PBHGETVINFO 0x1e01006c
351 #define FILEMGR_PBCREATEFILEIDREF 0x1e010070
352 #define FILEMGR_PBDELETEFILEIDREF 0x1e010074
353 #define FILEMGR_PBRESOLVEFILEIDREF 0x1e010078
354 #define FILEMGR_PBFLUSHVOL 0x1e01007c
355 #define FILEMGR_PBHRENAME 0x1e010080
356 #define FILEMGR_PBCATMOVE 0x1e010084
357 #define FILEMGR_PBEXCHANGEFILES 0x1e010088
358 #define FILEMGR_PBHDELETE 0x1e01008c
359 #define FILEMGR_PBDIRCREATE 0x1e010090
360 #define FILEMGR_PBCATSEARCH 0x1e010094
361 #define FILEMGR_PBHSETFLOCK 0x1e010098
362 #define FILEMGR_PBHRSTFLOCK 0x1e01009c
363 #define FILEMGR_PBLOCKRANGE 0x1e0100a0
364 #define FILEMGR_PBUNLOCKRANGE 0x1e0100a4
365
366
367 #define FILEMGR_CLASS 0x1e
368
369 #define MAX_PIDS 32
370 int pids[MAX_PIDS];
371
372 int num_of_pids = 0;
373 int exclude_pids = 0;
374 int exclude_default_pids = 1;
375
376 struct kinfo_proc *kp_buffer = 0;
377 int kp_nentries = 0;
378
379 #define SAMPLE_SIZE 60000
380
381 #define DBG_ZERO_FILL_FAULT 1
382 #define DBG_PAGEIN_FAULT 2
383 #define DBG_COW_FAULT 3
384 #define DBG_CACHE_HIT_FAULT 4
385
386 #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END)
387 #define DBG_FUNC_MASK 0xfffffffc
388
389 double divisor = 0.0; /* Trace divisor converts to microseconds */
390
391 int mib[6];
392 size_t needed;
393 char *my_buffer;
394
395 kbufinfo_t bufinfo = {0, 0, 0, 0, 0};
396
397 int total_threads = 0;
398 kd_threadmap *mapptr = 0; /* pointer to list of threads */
399
400 /* defines for tracking file descriptor state */
401 #define FS_USAGE_FD_SETSIZE 256 /* Initial number of file descriptors per
402 thread that we will track */
403
404 #define FS_USAGE_NFDBITS (sizeof (unsigned long) * 8)
405 #define FS_USAGE_NFDBYTES(n) (((n) / FS_USAGE_NFDBITS) * sizeof (unsigned long))
406
407 typedef struct {
408 unsigned int fd_valid; /* set if this is a valid entry */
409 unsigned int fd_thread;
410 unsigned int fd_setsize; /* this is a bit count */
411 unsigned long *fd_setptr; /* file descripter bitmap */
412 } fd_threadmap;
413
414 fd_threadmap *fdmapptr = 0; /* pointer to list of threads for fd tracking */
415
416 int trace_enabled = 0;
417 int set_remove_flag = 1;
418
419 void set_numbufs();
420 void set_init();
421 void set_enable();
422 void sample_sc();
423 int quit();
424
425 /*
426 * signal handlers
427 */
428
429 void leave() /* exit under normal conditions -- INT handler */
430 {
431 int i;
432 void set_enable();
433 void set_pidcheck();
434 void set_pidexclude();
435 void set_remove();
436
437 set_enable(0);
438
439 if (exclude_pids == 0) {
440 for (i = 0; i < num_of_pids; i++)
441 set_pidcheck(pids[i], 0);
442 }
443 else {
444 for (i = 0; i < num_of_pids; i++)
445 set_pidexclude(pids[i], 0);
446 }
447 set_remove();
448 exit(0);
449 }
450
451
452 void get_screenwidth()
453 {
454 struct winsize size;
455
456 columns = MAXCOLS;
457
458 if (isatty(1)) {
459 if (ioctl(1, TIOCGWINSZ, &size) != -1)
460 columns = size.ws_col;
461 }
462 }
463
464
465 void sigwinch()
466 {
467 if (!wideflag)
468 get_screenwidth();
469 }
470
471 int
472 exit_usage(char *myname) {
473
474 fprintf(stderr, "Usage: %s [-e] [-w] [-f mode] [pid | cmd [pid | cmd]....]\n", myname);
475 fprintf(stderr, " -e exclude the specified list of pids from the sample\n");
476 fprintf(stderr, " and exclude fs_usage by default\n");
477 fprintf(stderr, " -w force wider, detailed, output\n");
478 fprintf(stderr, " -f Output is filtered based on the mode provided\n");
479 fprintf(stderr, " mode = \"network\" Show only network related output\n");
480 fprintf(stderr, " mode = \"filesys\" Show only file system related output\n");
481 fprintf(stderr, " pid selects process(s) to sample\n");
482 fprintf(stderr, " cmd selects process(s) matching command string to sample\n");
483 fprintf(stderr, "\n%s will handle a maximum list of %d pids.\n\n", myname, MAX_PIDS);
484 fprintf(stderr, "By default (no options) the following processes are excluded from the output:\n");
485 fprintf(stderr, "fs_usage, Terminal, telnetd, sshd, rlogind, tcsh, csh, sh\n\n");
486
487 exit(1);
488 }
489
490 int
491 main(argc, argv)
492 int argc;
493 char *argv[];
494 {
495 char *myname = "fs_usage";
496 int i;
497 char ch;
498 void getdivisor();
499 void argtopid();
500 void set_remove();
501 void set_pidcheck();
502 void set_pidexclude();
503 int quit();
504
505 if ( geteuid() != 0 ) {
506 printf("'fs_usage' must be run as root...\n");
507 exit(1);
508 }
509 get_screenwidth();
510
511 /* get our name */
512 if (argc > 0) {
513 if ((myname = rindex(argv[0], '/')) == 0) {
514 myname = argv[0];
515 }
516 else {
517 myname++;
518 }
519 }
520
521
522 while ((ch = getopt(argc, argv, "ewf:")) != EOF) {
523 switch(ch) {
524 case 'e':
525 exclude_pids = 1;
526 exclude_default_pids = 0;
527 break;
528 case 'w':
529 wideflag = 1;
530 if ((uint)columns < MAX_WIDE_MODE_COLS)
531 columns = MAX_WIDE_MODE_COLS;
532 break;
533 case 'f':
534 if (!strcmp(optarg, "network"))
535 filter_mode |= NETWORK_FILTER;
536 else if (!strcmp(optarg, "filesys"))
537 filter_mode |= FILESYS_FILTER;
538 break;
539
540 default:
541 exit_usage(myname);
542 }
543 }
544
545 argc -= optind;
546 argv += optind;
547
548 /* If we process any list of pids/cmds, then turn off the defaults */
549 if (argc > 0)
550 exclude_default_pids = 0;
551
552 while (argc > 0 && num_of_pids < (MAX_PIDS - 1)) {
553 select_pid_mode++;
554 argtopid(argv[0]);
555 argc--;
556 argv++;
557 }
558
559 /* Exclude a set of default pids */
560 if (exclude_default_pids)
561 {
562 argtopid("Terminal");
563 argtopid("telnetd");
564 argtopid("telnet");
565 argtopid("sshd");
566 argtopid("rlogind");
567 argtopid("tcsh");
568 argtopid("csh");
569 argtopid("sh");
570 exclude_pids = 1;
571 }
572
573 if (exclude_pids)
574 {
575 if (num_of_pids < (MAX_PIDS - 1))
576 pids[num_of_pids++] = getpid();
577 else
578 exit_usage(myname);
579 }
580
581 #if 0
582 for (i = 0; i < num_of_pids; i++)
583 {
584 if (exclude_pids)
585 printf("exclude pid %d\n", pids[i]);
586 else
587 printf("pid %d\n", pids[i]);
588 }
589 #endif
590
591 /* set up signal handlers */
592 signal(SIGINT, leave);
593 signal(SIGQUIT, leave);
594 signal(SIGHUP, leave);
595 signal(SIGTERM, leave);
596 signal(SIGWINCH, sigwinch);
597
598 if ((my_buffer = malloc(SAMPLE_SIZE * sizeof(kd_buf))) == (char *)0)
599 quit("can't allocate memory for tracing info\n");
600
601 ReadSegAddrTable();
602 cache_disk_names();
603
604 set_remove();
605 set_numbufs(SAMPLE_SIZE);
606 set_init();
607
608 if (exclude_pids == 0) {
609 for (i = 0; i < num_of_pids; i++)
610 set_pidcheck(pids[i], 1);
611 } else {
612 for (i = 0; i < num_of_pids; i++)
613 set_pidexclude(pids[i], 1);
614 }
615
616 if (select_pid_mode && !one_good_pid)
617 {
618 /*
619 An attempt to restrict output to a given
620 pid or command has failed. Exit gracefully
621 */
622 set_remove();
623 exit_usage(myname);
624 }
625
626 set_enable(1);
627 getdivisor();
628 init_arguments_buffer();
629
630
631 /* main loop */
632
633 while (1) {
634 usleep(1000 * 25);
635
636 sample_sc();
637 }
638 }
639
640 void
641 find_proc_names()
642 {
643 size_t bufSize = 0;
644 struct kinfo_proc *kp;
645 int quit();
646
647 mib[0] = CTL_KERN;
648 mib[1] = KERN_PROC;
649 mib[2] = KERN_PROC_ALL;
650 mib[3] = 0;
651
652 if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0)
653 quit("trace facility failure, KERN_PROC_ALL\n");
654
655 if((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0)
656 quit("can't allocate memory for proc buffer\n");
657
658 if (sysctl(mib, 4, kp, &bufSize, NULL, 0) < 0)
659 quit("trace facility failure, KERN_PROC_ALL\n");
660
661 kp_nentries = bufSize/ sizeof(struct kinfo_proc);
662 kp_buffer = kp;
663 }
664
665
666 struct th_info *find_thread(int thread, int type) {
667 struct th_info *ti;
668
669 for (ti = th_state; ti < &th_state[cur_max]; ti++) {
670 if (ti->thread == thread) {
671 if (type == ti->type)
672 return(ti);
673 if (ti->in_filemgr) {
674 if (type == -1)
675 return(ti);
676 continue;
677 }
678 if (type == 0)
679 return(ti);
680 }
681 }
682 return ((struct th_info *)0);
683 }
684
685
686 void
687 mark_thread_waited(int thread) {
688 struct th_info *ti;
689
690 for (ti = th_state; ti < &th_state[cur_max]; ti++) {
691 if (ti->thread == thread) {
692 ti->waited = 1;
693 }
694 }
695 }
696
697
698 void
699 set_enable(int val)
700 {
701 mib[0] = CTL_KERN;
702 mib[1] = KERN_KDEBUG;
703 mib[2] = KERN_KDENABLE; /* protocol */
704 mib[3] = val;
705 mib[4] = 0;
706 mib[5] = 0; /* no flags */
707 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
708 quit("trace facility failure, KERN_KDENABLE\n");
709
710 if (val)
711 trace_enabled = 1;
712 else
713 trace_enabled = 0;
714 }
715
716 void
717 set_numbufs(int nbufs)
718 {
719 mib[0] = CTL_KERN;
720 mib[1] = KERN_KDEBUG;
721 mib[2] = KERN_KDSETBUF;
722 mib[3] = nbufs;
723 mib[4] = 0;
724 mib[5] = 0; /* no flags */
725 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
726 quit("trace facility failure, KERN_KDSETBUF\n");
727
728 mib[0] = CTL_KERN;
729 mib[1] = KERN_KDEBUG;
730 mib[2] = KERN_KDSETUP;
731 mib[3] = 0;
732 mib[4] = 0;
733 mib[5] = 0; /* no flags */
734 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
735 quit("trace facility failure, KERN_KDSETUP\n");
736 }
737
738 void
739 set_pidcheck(int pid, int on_off)
740 {
741 kd_regtype kr;
742
743 kr.type = KDBG_TYPENONE;
744 kr.value1 = pid;
745 kr.value2 = on_off;
746 needed = sizeof(kd_regtype);
747 mib[0] = CTL_KERN;
748 mib[1] = KERN_KDEBUG;
749 mib[2] = KERN_KDPIDTR;
750 mib[3] = 0;
751 mib[4] = 0;
752 mib[5] = 0;
753
754 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
755 if (on_off == 1)
756 printf("pid %d does not exist\n", pid);
757 }
758 else {
759 one_good_pid++;
760 }
761 }
762
763 /*
764 on_off == 0 turns off pid exclusion
765 on_off == 1 turns on pid exclusion
766 */
767 void
768 set_pidexclude(int pid, int on_off)
769 {
770 kd_regtype kr;
771
772 one_good_pid++;
773
774 kr.type = KDBG_TYPENONE;
775 kr.value1 = pid;
776 kr.value2 = on_off;
777 needed = sizeof(kd_regtype);
778 mib[0] = CTL_KERN;
779 mib[1] = KERN_KDEBUG;
780 mib[2] = KERN_KDPIDEX;
781 mib[3] = 0;
782 mib[4] = 0;
783 mib[5] = 0;
784
785 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
786 if (on_off == 1)
787 printf("pid %d does not exist\n", pid);
788 }
789 }
790
791 void
792 get_bufinfo(kbufinfo_t *val)
793 {
794 needed = sizeof (*val);
795 mib[0] = CTL_KERN;
796 mib[1] = KERN_KDEBUG;
797 mib[2] = KERN_KDGETBUF;
798 mib[3] = 0;
799 mib[4] = 0;
800 mib[5] = 0; /* no flags */
801
802 if (sysctl(mib, 3, val, &needed, 0, 0) < 0)
803 quit("trace facility failure, KERN_KDGETBUF\n");
804
805 }
806
807 void
808 set_remove()
809 {
810 errno = 0;
811
812 mib[0] = CTL_KERN;
813 mib[1] = KERN_KDEBUG;
814 mib[2] = KERN_KDREMOVE; /* protocol */
815 mib[3] = 0;
816 mib[4] = 0;
817 mib[5] = 0; /* no flags */
818 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
819 {
820 set_remove_flag = 0;
821
822 if (errno == EBUSY)
823 quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n");
824 else
825 quit("trace facility failure, KERN_KDREMOVE\n");
826 }
827 }
828
829 void
830 set_init()
831 { kd_regtype kr;
832
833 kr.type = KDBG_RANGETYPE;
834 kr.value1 = 0;
835 kr.value2 = -1;
836 needed = sizeof(kd_regtype);
837 mib[0] = CTL_KERN;
838 mib[1] = KERN_KDEBUG;
839 mib[2] = KERN_KDSETREG;
840 mib[3] = 0;
841 mib[4] = 0;
842 mib[5] = 0; /* no flags */
843
844 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
845 quit("trace facility failure, KERN_KDSETREG\n");
846
847 mib[0] = CTL_KERN;
848 mib[1] = KERN_KDEBUG;
849 mib[2] = KERN_KDSETUP;
850 mib[3] = 0;
851 mib[4] = 0;
852 mib[5] = 0; /* no flags */
853
854 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
855 quit("trace facility failure, KERN_KDSETUP\n");
856 }
857
858 void
859 sample_sc()
860 {
861 kd_buf *kd;
862 int i, count;
863 size_t needed;
864 void read_command_map();
865 void create_map_entry();
866
867 /* Get kernel buffer information */
868 get_bufinfo(&bufinfo);
869
870 if (need_new_map) {
871 read_command_map();
872 need_new_map = 0;
873 }
874 needed = bufinfo.nkdbufs * sizeof(kd_buf);
875 mib[0] = CTL_KERN;
876 mib[1] = KERN_KDEBUG;
877 mib[2] = KERN_KDREADTR;
878 mib[3] = 0;
879 mib[4] = 0;
880 mib[5] = 0; /* no flags */
881
882 if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0)
883 quit("trace facility failure, KERN_KDREADTR\n");
884 count = needed;
885
886 if (bufinfo.flags & KDBG_WRAPPED) {
887 printf("buffer wrapped count = %d\n", count);
888
889 for (i = 0; i < cur_max; i++) {
890 th_state[i].thread = 0;
891 th_state[i].pid = 0;
892 th_state[i].pathptr = (long *)0;
893 th_state[i].pathname[0] = 0;
894 }
895 cur_max = 0;
896 need_new_map = 1;
897
898 set_enable(0);
899 set_enable(1);
900 }
901 kd = (kd_buf *)my_buffer;
902 #if 0
903 printf("READTR returned %d items\n", count);
904 #endif
905 for (i = 0; i < count; i++) {
906 int debugid, thread;
907 int type, n;
908 long *sargptr;
909 uint64_t now;
910 long long l_usecs;
911 int secs;
912 long curr_time;
913 struct th_info *ti;
914 struct diskio *dio;
915 void enter_syscall();
916 void exit_syscall();
917 void kill_thread_map();
918
919 thread = kd[i].arg5 & KDBG_THREAD_MASK;
920 debugid = kd[i].debugid;
921 type = kd[i].debugid & DBG_FUNC_MASK;
922
923 now = kd[i].timestamp;
924
925 if (i == 0)
926 {
927 /*
928 * Compute bias seconds after each trace buffer read.
929 * This helps resync timestamps with the system clock
930 * in the event of a system sleep.
931 */
932 l_usecs = (long long)(now / divisor);
933 secs = l_usecs / 1000000;
934 curr_time = time((long *)0);
935 bias_secs = curr_time - secs;
936 }
937
938
939 switch (type) {
940
941 case P_RdMeta:
942 case P_WrMeta:
943 case P_RdData:
944 case P_WrData:
945 case P_PgIn:
946 case P_PgOut:
947 case P_RdMetaAsync:
948 case P_WrMetaAsync:
949 case P_RdDataAsync:
950 case P_WrDataAsync:
951 case P_PgInAsync:
952 case P_PgOutAsync:
953 insert_diskio(type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, thread, (double)now);
954 continue;
955
956 case P_RdMetaDone:
957 case P_WrMetaDone:
958 case P_RdDataDone:
959 case P_WrDataDone:
960 case P_PgInDone:
961 case P_PgOutDone:
962 case P_RdMetaAsyncDone:
963 case P_WrMetaAsyncDone:
964 case P_RdDataAsyncDone:
965 case P_WrDataAsyncDone:
966 case P_PgInAsyncDone:
967 case P_PgOutAsyncDone:
968 if ((dio = complete_diskio(kd[i].arg1, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
969 print_diskio(dio);
970 free_diskio(dio);
971 }
972 continue;
973
974
975 case TRACE_DATA_NEWTHREAD:
976
977 for (n = 0, ti = th_state; ti < &th_state[MAX_THREADS]; ti++, n++) {
978 if (ti->thread == 0)
979 break;
980 }
981 if (ti == &th_state[MAX_THREADS])
982 continue;
983 if (n >= cur_max)
984 cur_max = n + 1;
985
986 ti->thread = thread;
987 ti->child_thread = kd[i].arg1;
988 ti->pid = kd[i].arg2;
989 continue;
990
991 case TRACE_STRING_NEWTHREAD:
992 if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
993 continue;
994 if (ti->child_thread == 0)
995 continue;
996 create_map_entry(ti->child_thread, ti->pid, (char *)&kd[i].arg1);
997
998 if (ti == &th_state[cur_max - 1])
999 cur_max--;
1000 ti->child_thread = 0;
1001 ti->thread = 0;
1002 ti->pid = 0;
1003 continue;
1004
1005 case TRACE_DATA_EXEC:
1006
1007 for (n = 0, ti = th_state; ti < &th_state[MAX_THREADS]; ti++, n++) {
1008 if (ti->thread == 0)
1009 break;
1010 }
1011 if (ti == &th_state[MAX_THREADS])
1012 continue;
1013 if (n >= cur_max)
1014 cur_max = n + 1;
1015
1016 ti->thread = thread;
1017 ti->pid = kd[i].arg1;
1018 continue;
1019
1020 case TRACE_STRING_EXEC:
1021 if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
1022 {
1023 /* this is for backwards compatibility */
1024 create_map_entry(thread, 0, (char *)&kd[i].arg1);
1025 }
1026 else
1027 {
1028 create_map_entry(thread, ti->pid, (char *)&kd[i].arg1);
1029 if (ti == &th_state[cur_max - 1])
1030 cur_max--;
1031 ti->thread = 0;
1032 ti->pid = 0;
1033 }
1034 continue;
1035
1036 case BSC_exit:
1037 kill_thread_map(thread);
1038 continue;
1039
1040 case MACH_sched:
1041 case MACH_stkhandoff:
1042 mark_thread_waited(thread);
1043 continue;
1044
1045 case VFS_LOOKUP:
1046 if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
1047 continue;
1048
1049 if (!ti->pathptr) {
1050 sargptr = (long *)&ti->pathname[0];
1051 memset(&ti->pathname[0], 0, (PATHLENGTH + 1));
1052 *sargptr++ = kd[i].arg2;
1053 *sargptr++ = kd[i].arg3;
1054 *sargptr++ = kd[i].arg4;
1055 ti->pathptr = sargptr;
1056 } else {
1057 sargptr = ti->pathptr;
1058
1059 /*
1060 We don't want to overrun our pathname buffer if the
1061 kernel sends us more VFS_LOOKUP entries than we can
1062 handle.
1063 */
1064
1065 if ((long *)sargptr >= (long *)&ti->pathname[PATHLENGTH])
1066 continue;
1067
1068 /*
1069 We need to detect consecutive vfslookup entries.
1070 So, if we get here and find a START entry,
1071 fake the pathptr so we can bypass all further
1072 vfslookup entries.
1073 */
1074
1075 if (debugid & DBG_FUNC_START)
1076 {
1077 (long *)ti->pathptr = (long *)&ti->pathname[PATHLENGTH];
1078 continue;
1079 }
1080
1081 *sargptr++ = kd[i].arg1;
1082 *sargptr++ = kd[i].arg2;
1083 *sargptr++ = kd[i].arg3;
1084 *sargptr++ = kd[i].arg4;
1085 ti->pathptr = sargptr;
1086 }
1087 continue;
1088 }
1089
1090 if (debugid & DBG_FUNC_START) {
1091 char *p;
1092
1093 switch (type) {
1094 case FILEMGR_PBGETCATALOGINFO:
1095 p = "GetCatalogInfo";
1096 break;
1097 case FILEMGR_PBGETCATALOGINFOBULK:
1098 p = "GetCatalogInfoBulk";
1099 break;
1100 case FILEMGR_PBCREATEFILEUNICODE:
1101 p = "CreateFileUnicode";
1102 break;
1103 case FILEMGR_PBCREATEDIRECTORYUNICODE:
1104 p = "CreateDirectoryUnicode";
1105 break;
1106 case FILEMGR_PBCREATEFORK:
1107 p = "PBCreateFork";
1108 break;
1109 case FILEMGR_PBDELETEFORK:
1110 p = "PBDeleteFork";
1111 break;
1112 case FILEMGR_PBITERATEFORK:
1113 p = "PBIterateFork";
1114 break;
1115 case FILEMGR_PBOPENFORK:
1116 p = "PBOpenFork";
1117 break;
1118 case FILEMGR_PBREADFORK:
1119 p = "PBReadFork";
1120 break;
1121 case FILEMGR_PBWRITEFORK:
1122 p = "PBWriteFork";
1123 break;
1124 case FILEMGR_PBALLOCATEFORK:
1125 p = "PBAllocateFork";
1126 break;
1127 case FILEMGR_PBDELETEOBJECT:
1128 p = "PBDeleteObject";
1129 break;
1130 case FILEMGR_PBEXCHANGEOBJECT:
1131 p = "PBExchangeObject";
1132 break;
1133 case FILEMGR_PBGETFORKCBINFO:
1134 p = "PBGetForkCBInfo";
1135 break;
1136 case FILEMGR_PBGETVOLUMEINFO:
1137 p = "PBGetVolumeInfo";
1138 break;
1139 case FILEMGR_PBMAKEFSREF:
1140 p = "PBMakeFSRef";
1141 break;
1142 case FILEMGR_PBMAKEFSREFUNICODE:
1143 p = "PBMakeFSRefUnicode";
1144 break;
1145 case FILEMGR_PBMOVEOBJECT:
1146 p = "PBMoveObject";
1147 break;
1148 case FILEMGR_PBOPENITERATOR:
1149 p = "PBOpenIterator";
1150 break;
1151 case FILEMGR_PBRENAMEUNICODE:
1152 p = "PBRenameUnicode";
1153 break;
1154 case FILEMGR_PBSETCATALOGINFO:
1155 p = "SetCatalogInfo";
1156 break;
1157 case FILEMGR_PBSETVOLUMEINFO:
1158 p = "SetVolumeInfo";
1159 break;
1160 case FILEMGR_FSREFMAKEPATH:
1161 p = "FSRefMakePath";
1162 break;
1163 case FILEMGR_FSPATHMAKEREF:
1164 p = "FSPathMakeRef";
1165 break;
1166 // SPEC based calls
1167 case FILEMGR_PBGETCATINFO:
1168 p = "GetCatInfo";
1169 break;
1170 case FILEMGR_PBGETCATINFOLITE:
1171 p = "GetCatInfoLite";
1172 break;
1173 case FILEMGR_PBHGETFINFO:
1174 p = "PBHGetFInfo";
1175 break;
1176 case FILEMGR_PBXGETVOLINFO:
1177 p = "PBXGetVolInfo";
1178 break;
1179 case FILEMGR_PBHCREATE:
1180 p = "PBHCreate";
1181 break;
1182 case FILEMGR_PBHOPENDF:
1183 p = "PBHOpenDF";
1184 break;
1185 case FILEMGR_PBHOPENRF:
1186 p = "PBHOpenRF";
1187 break;
1188 case FILEMGR_PBHGETDIRACCESS:
1189 p = "PBHGetDirAccess";
1190 break;
1191 case FILEMGR_PBHSETDIRACCESS:
1192 p = "PBHSetDirAccess";
1193 break;
1194 case FILEMGR_PBHMAPID:
1195 p = "PBHMapID";
1196 break;
1197 case FILEMGR_PBHMAPNAME:
1198 p = "PBHMapName";
1199 break;
1200 case FILEMGR_PBCLOSE:
1201 p = "PBClose";
1202 break;
1203 case FILEMGR_PBFLUSHFILE:
1204 p = "PBFlushFile";
1205 break;
1206 case FILEMGR_PBGETEOF:
1207 p = "PBGetEOF";
1208 break;
1209 case FILEMGR_PBSETEOF:
1210 p = "PBSetEOF";
1211 break;
1212 case FILEMGR_PBGETFPOS:
1213 p = "PBGetFPos";
1214 break;
1215 case FILEMGR_PBREAD:
1216 p = "PBRead";
1217 break;
1218 case FILEMGR_PBWRITE:
1219 p = "PBWrite";
1220 break;
1221 case FILEMGR_PBGETFCBINFO:
1222 p = "PBGetFCBInfo";
1223 break;
1224 case FILEMGR_PBSETFINFO:
1225 p = "PBSetFInfo";
1226 break;
1227 case FILEMGR_PBALLOCATE:
1228 p = "PBAllocate";
1229 break;
1230 case FILEMGR_PBALLOCCONTIG:
1231 p = "PBAllocContig";
1232 break;
1233 case FILEMGR_PBSETFPOS:
1234 p = "PBSetFPos";
1235 break;
1236 case FILEMGR_PBSETCATINFO:
1237 p = "PBSetCatInfo";
1238 break;
1239 case FILEMGR_PBGETVOLPARMS:
1240 p = "PBGetVolParms";
1241 break;
1242 case FILEMGR_PBSETVINFO:
1243 p = "PBSetVInfo";
1244 break;
1245 case FILEMGR_PBMAKEFSSPEC:
1246 p = "PBMakeFSSpec";
1247 break;
1248 case FILEMGR_PBHGETVINFO:
1249 p = "PBHGetVInfo";
1250 break;
1251 case FILEMGR_PBCREATEFILEIDREF:
1252 p = "PBCreateFileIDRef";
1253 break;
1254 case FILEMGR_PBDELETEFILEIDREF:
1255 p = "PBDeleteFileIDRef";
1256 break;
1257 case FILEMGR_PBRESOLVEFILEIDREF:
1258 p = "PBResolveFileIDRef";
1259 break;
1260 case FILEMGR_PBFLUSHVOL:
1261 p = "PBFlushVol";
1262 break;
1263 case FILEMGR_PBHRENAME:
1264 p = "PBHRename";
1265 break;
1266 case FILEMGR_PBCATMOVE:
1267 p = "PBCatMove";
1268 break;
1269 case FILEMGR_PBEXCHANGEFILES:
1270 p = "PBExchangeFiles";
1271 break;
1272 case FILEMGR_PBHDELETE:
1273 p = "PBHDelete";
1274 break;
1275 case FILEMGR_PBDIRCREATE:
1276 p = "PBDirCreate";
1277 break;
1278 case FILEMGR_PBCATSEARCH:
1279 p = "PBCatSearch";
1280 break;
1281 case FILEMGR_PBHSETFLOCK:
1282 p = "PBHSetFlock";
1283 break;
1284 case FILEMGR_PBHRSTFLOCK:
1285 p = "PBHRstFLock";
1286 break;
1287 case FILEMGR_PBLOCKRANGE:
1288 p = "PBLockRange";
1289 break;
1290 case FILEMGR_PBUNLOCKRANGE:
1291 p = "PBUnlockRange";
1292 break;
1293 default:
1294 p = (char *)0;
1295 break;
1296 }
1297 enter_syscall(thread, type, &kd[i], p, (double)now);
1298 continue;
1299 }
1300 switch (type) {
1301
1302 case MACH_pageout:
1303 if (kd[i].arg2)
1304 exit_syscall("PAGE_OUT_D", thread, type, 0, kd[i].arg1, 0, 4, (double)now);
1305 else
1306 exit_syscall("PAGE_OUT_V", thread, type, 0, kd[i].arg1, 0, 4, (double)now);
1307 break;
1308
1309 case MACH_vmfault:
1310 if (kd[i].arg2 == DBG_PAGEIN_FAULT)
1311 exit_syscall("PAGE_IN", thread, type, kd[i].arg4, kd[i].arg1, 0, 6, (double)now);
1312 else if (kd[i].arg2 == DBG_CACHE_HIT_FAULT)
1313 exit_syscall("CACHE_HIT", thread, type, 0, kd[i].arg1, 0, 2, (double)now);
1314 else {
1315 if ((ti = find_thread(thread, type))) {
1316 if (ti == &th_state[cur_max - 1])
1317 cur_max--;
1318 ti->thread = 0;
1319 }
1320 }
1321 break;
1322
1323 case MSC_map_fd:
1324 exit_syscall("map_fd", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1325 break;
1326
1327 case BSC_mmap:
1328 exit_syscall("mmap", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1329 break;
1330
1331 case BSC_recvmsg:
1332 exit_syscall("recvmsg", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
1333 break;
1334
1335 case BSC_sendmsg:
1336 exit_syscall("sendmsg", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
1337 break;
1338
1339 case BSC_recvfrom:
1340 exit_syscall("recvfrom", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
1341 break;
1342
1343 case BSC_accept:
1344 exit_syscall("accept", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
1345 break;
1346
1347 case BSC_select:
1348 exit_syscall("select", thread, type, kd[i].arg1, kd[i].arg2, 0, 8, (double)now);
1349 break;
1350
1351 case BSC_socket:
1352 exit_syscall("socket", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
1353 break;
1354
1355 case BSC_connect:
1356 exit_syscall("connect", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1357 break;
1358
1359 case BSC_bind:
1360 exit_syscall("bind", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1361 break;
1362
1363 case BSC_listen:
1364 exit_syscall("listen", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1365 break;
1366
1367 case BSC_sendto:
1368 exit_syscall("sendto", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
1369 break;
1370
1371 case BSC_socketpair:
1372 exit_syscall("socketpair", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1373 break;
1374
1375 case BSC_stat:
1376 exit_syscall("stat", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1377 break;
1378
1379 case BSC_load_shared_file:
1380 exit_syscall("load_sf", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1381 break;
1382
1383 case BSC_open:
1384 exit_syscall("open", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
1385 break;
1386
1387 case BSC_dup:
1388 exit_syscall("dup", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
1389 break;
1390
1391 case BSC_dup2:
1392 exit_syscall("dup2", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
1393 break;
1394
1395 case BSC_close:
1396 exit_syscall("close", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1397 break;
1398
1399 case BSC_read:
1400 exit_syscall("read", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
1401 break;
1402
1403 case BSC_write:
1404 exit_syscall("write", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
1405 break;
1406
1407 case BSC_fstat:
1408 exit_syscall("fstat", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1409 break;
1410
1411 case BSC_lstat:
1412 exit_syscall("lstat", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1413 break;
1414
1415 case BSC_link:
1416 exit_syscall("link", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1417 break;
1418
1419 case BSC_unlink:
1420 exit_syscall("unlink", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1421 break;
1422
1423 case BSC_mknod:
1424 exit_syscall("mknod", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1425 break;
1426
1427 case BSC_chmod:
1428 exit_syscall("chmod", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1429 break;
1430
1431 case BSC_chown:
1432 exit_syscall("chown", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1433 break;
1434
1435 case BSC_access:
1436 exit_syscall("access", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1437 break;
1438
1439 case BSC_chdir:
1440 exit_syscall("chdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1441 break;
1442
1443 case BSC_chroot:
1444 exit_syscall("chroot", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1445 break;
1446
1447 case BSC_utimes:
1448 exit_syscall("utimes", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1449 break;
1450
1451 case BSC_delete:
1452 exit_syscall("delete", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1453 break;
1454
1455 case BSC_undelete:
1456 exit_syscall("undelete", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1457 break;
1458
1459 case BSC_revoke:
1460 exit_syscall("revoke", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1461 break;
1462
1463 case BSC_fsctl:
1464 exit_syscall("fsctl", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1465 break;
1466
1467 case BSC_chflags:
1468 exit_syscall("chflags", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1469 break;
1470
1471 case BSC_fchflags:
1472 exit_syscall("fchflags", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1473 break;
1474
1475 case BSC_fchdir:
1476 exit_syscall("fchdir", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1477 break;
1478
1479 case BSC_futimes:
1480 exit_syscall("futimes", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1481 break;
1482
1483 case BSC_sync:
1484 exit_syscall("sync", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1485 break;
1486
1487 case BSC_symlink:
1488 exit_syscall("symlink", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1489 break;
1490
1491 case BSC_readlink:
1492 exit_syscall("readlink", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1493 break;
1494
1495 case BSC_fsync:
1496 exit_syscall("fsync", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1497 break;
1498
1499 case BSC_readv:
1500 exit_syscall("readv", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
1501 break;
1502
1503 case BSC_writev:
1504 exit_syscall("writev", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
1505 break;
1506
1507 case BSC_fchown:
1508 exit_syscall("fchown", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1509 break;
1510
1511 case BSC_fchmod:
1512 exit_syscall("fchmod", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1513 break;
1514
1515 case BSC_mkdir:
1516 exit_syscall("mkdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1517 break;
1518
1519 case BSC_mkfifo:
1520 exit_syscall("mkfifo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1521 break;
1522
1523 case BSC_rmdir:
1524 exit_syscall("rmdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1525 break;
1526
1527 case BSC_statfs:
1528 exit_syscall("statfs", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1529 break;
1530
1531 case BSC_fstatfs:
1532 exit_syscall("fstatfs", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1533 break;
1534
1535 case BSC_pathconf:
1536 exit_syscall("pathconf", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1537 break;
1538
1539 case BSC_fpathconf:
1540 exit_syscall("fpathconf", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1541 break;
1542
1543 case BSC_getdirentries:
1544 exit_syscall("getdirentries", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
1545 break;
1546
1547 case BSC_lseek:
1548 exit_syscall("lseek", thread, type, kd[i].arg1, kd[i].arg3, 1, 5, (double)now);
1549 break;
1550
1551 case BSC_truncate:
1552 exit_syscall("truncate", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1553 break;
1554
1555 case BSC_ftruncate:
1556 exit_syscall("ftruncate", thread, type, kd[i].arg1, kd[i].arg2, 1, 3, (double)now);
1557 break;
1558
1559 case BSC_statv:
1560 exit_syscall("statv", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1561 break;
1562
1563 case BSC_lstatv:
1564 exit_syscall("lstatv", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1565 break;
1566
1567 case BSC_fstatv:
1568 exit_syscall("fstatv", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
1569 break;
1570
1571 case BSC_mkcomplex:
1572 exit_syscall("mkcomplex", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1573 break;
1574
1575 case BSC_getattrlist:
1576 exit_syscall("getattrlist", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1577 break;
1578
1579 case BSC_setattrlist:
1580 exit_syscall("setattrlist", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1581 break;
1582
1583 case BSC_getdirentriesattr:
1584 exit_syscall("getdirentriesattr", thread, type, kd[i].arg1, kd[i].arg2, 0, 1, (double)now);
1585 break;
1586
1587
1588 case BSC_exchangedata:
1589 exit_syscall("exchangedata", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1590 break;
1591
1592 case BSC_rename:
1593 exit_syscall("rename", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1594 break;
1595
1596 case BSC_copyfile:
1597 exit_syscall("copyfile", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1598 break;
1599
1600
1601 case BSC_checkuseraccess:
1602 exit_syscall("checkuseraccess", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1603 break;
1604
1605 case BSC_searchfs:
1606 exit_syscall("searchfs", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1607 break;
1608
1609 case FILEMGR_PBGETCATALOGINFO:
1610 exit_syscall("GetCatalogInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1611 break;
1612 case FILEMGR_PBGETCATALOGINFOBULK:
1613 exit_syscall("GetCatalogInfoBulk", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1614 break;
1615 case FILEMGR_PBCREATEFILEUNICODE:
1616 exit_syscall("CreateFileUnicode", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1617 break;
1618 case FILEMGR_PBCREATEDIRECTORYUNICODE:
1619 exit_syscall("CreateDirectoryUnicode", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1620 break;
1621 case FILEMGR_PBCREATEFORK:
1622 exit_syscall("PBCreateFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1623 break;
1624 case FILEMGR_PBDELETEFORK:
1625 exit_syscall("PBDeleteFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1626 break;
1627 case FILEMGR_PBITERATEFORK:
1628 exit_syscall("PBIterateFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1629 break;
1630 case FILEMGR_PBOPENFORK:
1631 exit_syscall("PBOpenFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1632 break;
1633 case FILEMGR_PBREADFORK:
1634 exit_syscall("PBReadFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1635 break;
1636 case FILEMGR_PBWRITEFORK:
1637 exit_syscall("PBWriteFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1638 break;
1639 case FILEMGR_PBALLOCATEFORK:
1640 exit_syscall("PBAllocateFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1641 break;
1642 case FILEMGR_PBDELETEOBJECT:
1643 exit_syscall("PBDeleteObject", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1644 break;
1645 case FILEMGR_PBEXCHANGEOBJECT:
1646 exit_syscall("PBExchangeObject", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1647 break;
1648 case FILEMGR_PBGETFORKCBINFO:
1649 exit_syscall("PBGetForkCBInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1650 break;
1651 case FILEMGR_PBGETVOLUMEINFO:
1652 exit_syscall("PBGetVolumeInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1653 break;
1654 case FILEMGR_PBMAKEFSREF:
1655 exit_syscall("PBMakeFSRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1656 break;
1657 case FILEMGR_PBMAKEFSREFUNICODE:
1658 exit_syscall("PBMakeFSRefUnicode", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1659 break;
1660 case FILEMGR_PBMOVEOBJECT:
1661 exit_syscall("PBMoveObject", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1662 break;
1663 case FILEMGR_PBOPENITERATOR:
1664 exit_syscall("PBOpenIterator", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1665 break;
1666 case FILEMGR_PBRENAMEUNICODE:
1667 exit_syscall("PBRenameUnicode", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1668 break;
1669 case FILEMGR_PBSETCATALOGINFO:
1670 exit_syscall("PBSetCatalogInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1671 break;
1672 case FILEMGR_PBSETVOLUMEINFO:
1673 exit_syscall("PBSetVolumeInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1674 break;
1675 case FILEMGR_FSREFMAKEPATH:
1676 exit_syscall("FSRefMakePath", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1677 break;
1678 case FILEMGR_FSPATHMAKEREF:
1679 exit_syscall("FSPathMakeRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1680 break;
1681 case FILEMGR_PBGETCATINFO:
1682 exit_syscall("GetCatInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1683 break;
1684 case FILEMGR_PBGETCATINFOLITE:
1685 exit_syscall("GetCatInfoLite", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1686 break;
1687 case FILEMGR_PBHGETFINFO:
1688 exit_syscall("PBHGetFInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1689 break;
1690 case FILEMGR_PBXGETVOLINFO:
1691 exit_syscall("PBXGetVolInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1692 break;
1693 case FILEMGR_PBHCREATE:
1694 exit_syscall("PBHCreate", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1695 break;
1696 case FILEMGR_PBHOPENDF:
1697 exit_syscall("PBHOpenDF", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1698 break;
1699 case FILEMGR_PBHOPENRF:
1700 exit_syscall("PBHOpenRF", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1701 break;
1702 case FILEMGR_PBHGETDIRACCESS:
1703 exit_syscall("PBHGetDirAccess", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1704 break;
1705 case FILEMGR_PBHSETDIRACCESS:
1706 exit_syscall("PBHSetDirAccess", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1707 break;
1708 case FILEMGR_PBHMAPID:
1709 exit_syscall("PBHMapID", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1710 break;
1711 case FILEMGR_PBHMAPNAME:
1712 exit_syscall("PBHMapName", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1713 break;
1714 case FILEMGR_PBCLOSE:
1715 exit_syscall("PBClose", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1716 break;
1717 case FILEMGR_PBFLUSHFILE:
1718 exit_syscall("PBFlushFile", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1719 break;
1720 case FILEMGR_PBGETEOF:
1721 exit_syscall("PBGetEOF", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1722 break;
1723 case FILEMGR_PBSETEOF:
1724 exit_syscall("PBSetEOF", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1725 break;
1726 case FILEMGR_PBGETFPOS:
1727 exit_syscall("PBGetFPos", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1728 break;
1729 case FILEMGR_PBREAD:
1730 exit_syscall("PBRead", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1731 break;
1732 case FILEMGR_PBWRITE:
1733 exit_syscall("PBWrite", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1734 break;
1735 case FILEMGR_PBGETFCBINFO:
1736 exit_syscall("PBGetFCBInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1737 break;
1738 case FILEMGR_PBSETFINFO:
1739 exit_syscall("PBSetFInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1740 break;
1741 case FILEMGR_PBALLOCATE:
1742 exit_syscall("PBAllocate", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1743 break;
1744 case FILEMGR_PBALLOCCONTIG:
1745 exit_syscall("PBAllocContig", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1746 break;
1747 case FILEMGR_PBSETFPOS:
1748 exit_syscall("PBSetFPos", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1749 break;
1750 case FILEMGR_PBSETCATINFO:
1751 exit_syscall("PBSetCatInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1752 break;
1753 case FILEMGR_PBGETVOLPARMS:
1754 exit_syscall("PBGetVolParms", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1755 break;
1756 case FILEMGR_PBSETVINFO:
1757 exit_syscall("PBSetVInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1758 break;
1759 case FILEMGR_PBMAKEFSSPEC:
1760 exit_syscall("PBMakeFSSpec", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1761 break;
1762 case FILEMGR_PBHGETVINFO:
1763 exit_syscall("PBHGetVInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1764 break;
1765 case FILEMGR_PBCREATEFILEIDREF:
1766 exit_syscall("PBCreateFileIDRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1767 break;
1768 case FILEMGR_PBDELETEFILEIDREF:
1769 exit_syscall("PBDeleteFileIDRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1770 break;
1771 case FILEMGR_PBRESOLVEFILEIDREF:
1772 exit_syscall("PBResolveFileIDRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1773 break;
1774 case FILEMGR_PBFLUSHVOL:
1775 exit_syscall("PBFlushVol", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1776 break;
1777 case FILEMGR_PBHRENAME:
1778 exit_syscall("PBHRename", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1779 break;
1780 case FILEMGR_PBCATMOVE:
1781 exit_syscall("PBCatMove", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1782 break;
1783 case FILEMGR_PBEXCHANGEFILES:
1784 exit_syscall("PBExchangeFiles", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1785 break;
1786 case FILEMGR_PBHDELETE:
1787 exit_syscall("PBHDelete", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1788 break;
1789 case FILEMGR_PBDIRCREATE:
1790 exit_syscall("PBDirCreate", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1791 break;
1792 case FILEMGR_PBCATSEARCH:
1793 exit_syscall("PBCatSearch", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1794 break;
1795 case FILEMGR_PBHSETFLOCK:
1796 exit_syscall("PBHSetFLock", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1797 break;
1798 case FILEMGR_PBHRSTFLOCK:
1799 exit_syscall("PBHRstFLock", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1800 break;
1801 case FILEMGR_PBLOCKRANGE:
1802 exit_syscall("PBLockRange", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1803 break;
1804 case FILEMGR_PBUNLOCKRANGE:
1805 exit_syscall("PBUnlockRange", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
1806 break;
1807 default:
1808 break;
1809 }
1810 }
1811 fflush(0);
1812 }
1813
1814 void
1815 enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
1816 {
1817 struct th_info *ti;
1818 int i;
1819 int secs;
1820 int usecs;
1821 long long l_usecs;
1822 long curr_time;
1823 kd_threadmap *map;
1824 kd_threadmap *find_thread_map();
1825 int clen = 0;
1826 int tsclen = 0;
1827 int nmclen = 0;
1828 int argsclen = 0;
1829 char buf[MAXCOLS];
1830
1831 switch (type) {
1832
1833 case MACH_pageout:
1834 case MACH_vmfault:
1835 case MSC_map_fd:
1836 case BSC_mmap:
1837 case BSC_recvmsg:
1838 case BSC_sendmsg:
1839 case BSC_recvfrom:
1840 case BSC_accept:
1841 case BSC_select:
1842 case BSC_socket:
1843 case BSC_connect:
1844 case BSC_bind:
1845 case BSC_listen:
1846 case BSC_sendto:
1847 case BSC_socketpair:
1848 case BSC_stat:
1849 case BSC_load_shared_file:
1850 case BSC_open:
1851 case BSC_dup:
1852 case BSC_dup2:
1853 case BSC_close:
1854 case BSC_read:
1855 case BSC_write:
1856 case BSC_fstat:
1857 case BSC_lstat:
1858 case BSC_link:
1859 case BSC_unlink:
1860 case BSC_mknod:
1861 case BSC_chmod:
1862 case BSC_chown:
1863 case BSC_access:
1864 case BSC_chflags:
1865 case BSC_fchflags:
1866 case BSC_fchdir:
1867 case BSC_futimes:
1868 case BSC_chdir:
1869 case BSC_utimes:
1870 case BSC_chroot:
1871 case BSC_undelete:
1872 case BSC_delete:
1873 case BSC_revoke:
1874 case BSC_fsctl:
1875 case BSC_copyfile:
1876 case BSC_sync:
1877 case BSC_symlink:
1878 case BSC_readlink:
1879 case BSC_fsync:
1880 case BSC_readv:
1881 case BSC_writev:
1882 case BSC_fchown:
1883 case BSC_fchmod:
1884 case BSC_rename:
1885 case BSC_mkdir:
1886 case BSC_mkfifo:
1887 case BSC_rmdir:
1888 case BSC_statfs:
1889 case BSC_fstatfs:
1890 case BSC_pathconf:
1891 case BSC_fpathconf:
1892 case BSC_getdirentries:
1893 case BSC_lseek:
1894 case BSC_truncate:
1895 case BSC_ftruncate:
1896 case BSC_statv:
1897 case BSC_lstatv:
1898 case BSC_fstatv:
1899 case BSC_mkcomplex:
1900 case BSC_getattrlist:
1901 case BSC_setattrlist:
1902 case BSC_getdirentriesattr:
1903 case BSC_exchangedata:
1904 case BSC_checkuseraccess:
1905 case BSC_searchfs:
1906 case FILEMGR_PBGETCATALOGINFO:
1907 case FILEMGR_PBGETCATALOGINFOBULK:
1908 case FILEMGR_PBCREATEFILEUNICODE:
1909 case FILEMGR_PBCREATEDIRECTORYUNICODE:
1910 case FILEMGR_PBCREATEFORK:
1911 case FILEMGR_PBDELETEFORK:
1912 case FILEMGR_PBITERATEFORK:
1913 case FILEMGR_PBOPENFORK:
1914 case FILEMGR_PBREADFORK:
1915 case FILEMGR_PBWRITEFORK:
1916 case FILEMGR_PBALLOCATEFORK:
1917 case FILEMGR_PBDELETEOBJECT:
1918 case FILEMGR_PBEXCHANGEOBJECT:
1919 case FILEMGR_PBGETFORKCBINFO:
1920 case FILEMGR_PBGETVOLUMEINFO:
1921 case FILEMGR_PBMAKEFSREF:
1922 case FILEMGR_PBMAKEFSREFUNICODE:
1923 case FILEMGR_PBMOVEOBJECT:
1924 case FILEMGR_PBOPENITERATOR:
1925 case FILEMGR_PBRENAMEUNICODE:
1926 case FILEMGR_PBSETCATALOGINFO:
1927 case FILEMGR_PBSETVOLUMEINFO:
1928 case FILEMGR_FSREFMAKEPATH:
1929 case FILEMGR_FSPATHMAKEREF:
1930
1931 case FILEMGR_PBGETCATINFO:
1932 case FILEMGR_PBGETCATINFOLITE:
1933 case FILEMGR_PBHGETFINFO:
1934 case FILEMGR_PBXGETVOLINFO:
1935 case FILEMGR_PBHCREATE:
1936 case FILEMGR_PBHOPENDF:
1937 case FILEMGR_PBHOPENRF:
1938 case FILEMGR_PBHGETDIRACCESS:
1939 case FILEMGR_PBHSETDIRACCESS:
1940 case FILEMGR_PBHMAPID:
1941 case FILEMGR_PBHMAPNAME:
1942 case FILEMGR_PBCLOSE:
1943 case FILEMGR_PBFLUSHFILE:
1944 case FILEMGR_PBGETEOF:
1945 case FILEMGR_PBSETEOF:
1946 case FILEMGR_PBGETFPOS:
1947 case FILEMGR_PBREAD:
1948 case FILEMGR_PBWRITE:
1949 case FILEMGR_PBGETFCBINFO:
1950 case FILEMGR_PBSETFINFO:
1951 case FILEMGR_PBALLOCATE:
1952 case FILEMGR_PBALLOCCONTIG:
1953 case FILEMGR_PBSETFPOS:
1954 case FILEMGR_PBSETCATINFO:
1955 case FILEMGR_PBGETVOLPARMS:
1956 case FILEMGR_PBSETVINFO:
1957 case FILEMGR_PBMAKEFSSPEC:
1958 case FILEMGR_PBHGETVINFO:
1959 case FILEMGR_PBCREATEFILEIDREF:
1960 case FILEMGR_PBDELETEFILEIDREF:
1961 case FILEMGR_PBRESOLVEFILEIDREF:
1962 case FILEMGR_PBFLUSHVOL:
1963 case FILEMGR_PBHRENAME:
1964 case FILEMGR_PBCATMOVE:
1965 case FILEMGR_PBEXCHANGEFILES:
1966 case FILEMGR_PBHDELETE:
1967 case FILEMGR_PBDIRCREATE:
1968 case FILEMGR_PBCATSEARCH:
1969 case FILEMGR_PBHSETFLOCK:
1970 case FILEMGR_PBHRSTFLOCK:
1971 case FILEMGR_PBLOCKRANGE:
1972 case FILEMGR_PBUNLOCKRANGE:
1973
1974
1975 for (i = 0, ti = th_state; ti < &th_state[MAX_THREADS]; ti++, i++) {
1976 if (ti->thread == 0)
1977 break;
1978 }
1979 if (ti == &th_state[MAX_THREADS])
1980 return;
1981 if (i >= cur_max)
1982 cur_max = i + 1;
1983
1984
1985 if ((type >> 24) == FILEMGR_CLASS) {
1986 ti->in_filemgr = 1;
1987
1988 l_usecs = (long long)(now / divisor);
1989 secs = l_usecs / 1000000;
1990 curr_time = bias_secs + secs;
1991
1992 sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
1993 tsclen = strlen(buf);
1994
1995 if (columns > MAXCOLS || wideflag) {
1996 usecs = l_usecs - (long long)((long long)secs * 1000000);
1997 sprintf(&buf[tsclen], ".%03ld", (long)usecs / 1000);
1998 tsclen = strlen(buf);
1999 }
2000
2001 /* Print timestamp column */
2002 printf(buf);
2003
2004 map = find_thread_map(thread);
2005 if (map) {
2006 sprintf(buf, " %-25.25s ", name);
2007 nmclen = strlen(buf);
2008 printf(buf);
2009
2010 sprintf(buf, "(%d, 0x%x, 0x%x, 0x%x)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
2011 argsclen = strlen(buf);
2012
2013 /*
2014 Calculate white space out to command
2015 */
2016 if (columns > MAXCOLS || wideflag)
2017 {
2018 clen = columns - (tsclen + nmclen + argsclen + 20);
2019 }
2020 else
2021 clen = columns - (tsclen + nmclen + argsclen + 12);
2022
2023 if(clen > 0)
2024 {
2025 printf(buf); /* print the kdargs */
2026 memset(buf, ' ', clen);
2027 buf[clen] = '\0';
2028 printf(buf);
2029 }
2030 else if ((argsclen + clen) > 0)
2031 {
2032 /* no room so wipe out the kdargs */
2033 memset(buf, ' ', (argsclen + clen));
2034 buf[argsclen + clen] = '\0';
2035 printf(buf);
2036 }
2037
2038 if (columns > MAXCOLS || wideflag)
2039 printf("%-20.20s\n", map->command);
2040 else
2041 printf("%-12.12s\n", map->command);
2042 } else
2043 printf(" %-24.24s (%5d, %#x, 0x%x, 0x%x)\n", name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
2044 } else {
2045 ti->in_filemgr = 0;
2046 }
2047 ti->thread = thread;
2048 ti->waited = 0;
2049 ti->type = type;
2050 ti->stime = now;
2051 ti->arg1 = kd->arg1;
2052 ti->arg2 = kd->arg2;
2053 ti->arg3 = kd->arg3;
2054 ti->arg4 = kd->arg4;
2055 ti->pathptr = (long *)0;
2056 ti->pathname[0] = 0;
2057 break;
2058
2059 default:
2060 break;
2061 }
2062 fflush (0);
2063 }
2064
2065
2066 void
2067 exit_syscall(char *sc_name, int thread, int type, int error, int retval,
2068 int has_fd, int has_ret, double now)
2069 {
2070 struct th_info *ti;
2071
2072 if ((ti = find_thread(thread, type)) == (struct th_info *)0)
2073 return;
2074
2075 if (check_filter_mode(ti, type, error, retval))
2076 format_print(ti, sc_name, thread, type, error, retval, has_fd, has_ret, now, ti->stime, ti->waited, ti->pathname, NULL);
2077
2078 if (ti == &th_state[cur_max - 1])
2079 cur_max--;
2080 ti->thread = 0;
2081 }
2082
2083
2084
2085 void
2086 format_print(struct th_info *ti, char *sc_name, int thread, int type, int error, int retval,
2087 int has_fd, int has_ret, double now, double stime, int waited, char *pathname, struct diskio *dio)
2088 {
2089 int secs;
2090 int usecs;
2091 int nopadding;
2092 long long l_usecs;
2093 long curr_time;
2094 char *command_name;
2095 kd_threadmap *map;
2096 kd_threadmap *find_thread_map();
2097 int len = 0;
2098 int clen = 0;
2099 char *framework_name;
2100 char buf[MAXCOLS];
2101
2102 command_name = "";
2103
2104 if (dio)
2105 command_name = dio->issuing_command;
2106 else {
2107 if ((map = find_thread_map(thread)))
2108 command_name = map->command;
2109 }
2110
2111 l_usecs = (long long)(now / divisor);
2112 secs = l_usecs / 1000000;
2113 curr_time = bias_secs + secs;
2114 sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
2115 clen = strlen(buf);
2116
2117 if (columns > MAXCOLS || wideflag) {
2118 nopadding = 0;
2119 usecs = l_usecs - (long long)((long long)secs * 1000000);
2120 sprintf(&buf[clen], ".%03ld", (long)usecs / 1000);
2121 clen = strlen(buf);
2122
2123 if ((type >> 24) != FILEMGR_CLASS) {
2124 if (find_thread(thread, -1)) {
2125 sprintf(&buf[clen], " ");
2126 clen = strlen(buf);
2127 nopadding = 1;
2128 }
2129 }
2130 } else
2131 nopadding = 1;
2132
2133 if (((type >> 24) == FILEMGR_CLASS) && (columns > MAXCOLS || wideflag))
2134 sprintf(&buf[clen], " %-18.18s", sc_name);
2135 else
2136 sprintf(&buf[clen], " %-15.15s", sc_name);
2137
2138 clen = strlen(buf);
2139
2140 framework_name = (char *)0;
2141
2142 if (columns > MAXCOLS || wideflag) {
2143 if (has_ret == 7) {
2144 sprintf(&buf[clen], " D=0x%8.8x", dio->blkno);
2145
2146 clen = strlen(buf);
2147
2148 if (dio->io_errno)
2149 sprintf(&buf[clen], " [%3d] ", dio->io_errno);
2150 else
2151 sprintf(&buf[clen], " B=0x%-6x /dev/%s", dio->iosize, find_disk_name(dio->dev));
2152 } else {
2153
2154 if (has_fd == 2 && error == 0)
2155 sprintf(&buf[clen], " F=%-3d", retval);
2156 else if (has_fd == 1)
2157 sprintf(&buf[clen], " F=%-3d", ti->arg1);
2158 else if (has_ret != 2 && has_ret != 6)
2159 sprintf(&buf[clen], " ");
2160
2161 clen = strlen(buf);
2162
2163 if (has_ret == 2 || has_ret == 6)
2164 framework_name = lookup_name(retval);
2165
2166 if (error && has_ret != 6)
2167 sprintf(&buf[clen], "[%3d] ", error);
2168 else if (has_ret == 3)
2169 sprintf(&buf[clen], "O=0x%8.8x", ti->arg3);
2170 else if (has_ret == 5)
2171 sprintf(&buf[clen], "O=0x%8.8x", retval);
2172 else if (has_ret == 2)
2173 sprintf(&buf[clen], " A=0x%8.8x ", retval);
2174 else if (has_ret == 6)
2175 sprintf(&buf[clen], " A=0x%8.8x B=0x%-8x", retval, error);
2176 else if (has_ret == 1)
2177 sprintf(&buf[clen], " B=0x%-6x", retval);
2178 else if (has_ret == 4)
2179 sprintf(&buf[clen], "B=0x%-8x", retval);
2180 else if (has_ret == 8) /* BSC_select */
2181 sprintf(&buf[clen], " S=%-3d ", retval);
2182 else
2183 sprintf(&buf[clen], " ");
2184 }
2185 clen = strlen(buf);
2186 }
2187 printf(buf);
2188
2189 /*
2190 Calculate space available to print pathname
2191 */
2192 if (columns > MAXCOLS || wideflag)
2193 clen = columns - (clen + 13 + 20);
2194 else
2195 clen = columns - (clen + 13 + 12);
2196
2197 if ((type >> 24) != FILEMGR_CLASS && !nopadding)
2198 clen -= 3;
2199
2200 if (framework_name)
2201 sprintf(&buf[0], " %s ", framework_name);
2202 else
2203 sprintf(&buf[0], " %s ", pathname);
2204 len = strlen(buf);
2205
2206 if (clen > len)
2207 {
2208 /*
2209 Add null padding if column length
2210 is wider than the pathname length.
2211 */
2212 memset(&buf[len], ' ', clen - len);
2213 buf[clen] = '\0';
2214 printf(buf);
2215 }
2216 else if (clen == len)
2217 {
2218 printf(buf);
2219 }
2220 else if ((clen > 0) && (clen < len))
2221 {
2222 /* This prints the tail end of the pathname */
2223 buf[len-clen] = ' ';
2224 printf(&buf[len - clen]);
2225 }
2226
2227 usecs = (unsigned long)((now - stime) / divisor);
2228 secs = usecs / 1000000;
2229 usecs -= secs * 1000000;
2230
2231 if ((type >> 24) != FILEMGR_CLASS && !nopadding)
2232 printf(" ");
2233
2234 printf(" %2ld.%06ld", (unsigned long)secs, (unsigned long)usecs);
2235
2236 if (waited)
2237 printf(" W");
2238 else
2239 printf(" ");
2240
2241 if (columns > MAXCOLS || wideflag)
2242 printf(" %-20.20s", command_name);
2243 else
2244 printf(" %-12.12s", command_name);
2245
2246 printf("\n");
2247 fflush (0);
2248 }
2249
2250 int
2251 quit(s)
2252 char *s;
2253 {
2254 if (trace_enabled)
2255 set_enable(0);
2256
2257 /*
2258 This flag is turned off when calling
2259 quit() due to a set_remove() failure.
2260 */
2261 if (set_remove_flag)
2262 set_remove();
2263
2264 printf("fs_usage: ");
2265 if (s)
2266 printf("%s", s);
2267
2268 exit(1);
2269 }
2270
2271
2272 void getdivisor()
2273 {
2274
2275 unsigned int delta;
2276 unsigned int abs_to_ns_num;
2277 unsigned int abs_to_ns_denom;
2278 unsigned int proc_to_abs_num;
2279 unsigned int proc_to_abs_denom;
2280
2281 extern void MKGetTimeBaseInfo(unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *);
2282
2283 MKGetTimeBaseInfo (&delta, &abs_to_ns_num, &abs_to_ns_denom,
2284 &proc_to_abs_num, &proc_to_abs_denom);
2285
2286 divisor = ((double)abs_to_ns_denom / (double)abs_to_ns_num) * 1000;
2287 }
2288
2289
2290 void read_command_map()
2291 {
2292 size_t size;
2293 int i;
2294 int prev_total_threads;
2295 int mib[6];
2296
2297 if (mapptr) {
2298 free(mapptr);
2299 mapptr = 0;
2300 }
2301
2302 prev_total_threads = total_threads;
2303 total_threads = bufinfo.nkdthreads;
2304 size = bufinfo.nkdthreads * sizeof(kd_threadmap);
2305
2306 if (size)
2307 {
2308 if ((mapptr = (kd_threadmap *) malloc(size)))
2309 {
2310 bzero (mapptr, size);
2311
2312 /* Now read the threadmap */
2313 mib[0] = CTL_KERN;
2314 mib[1] = KERN_KDEBUG;
2315 mib[2] = KERN_KDTHRMAP;
2316 mib[3] = 0;
2317 mib[4] = 0;
2318 mib[5] = 0; /* no flags */
2319 if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0)
2320 {
2321 /* This is not fatal -- just means I cant map command strings */
2322 free(mapptr);
2323 mapptr = 0;
2324 }
2325 }
2326 }
2327
2328 if (mapptr && (filter_mode != DEFAULT_DO_NOT_FILTER))
2329 {
2330 if (fdmapptr)
2331 {
2332 /* We accept the fact that we lose file descriptor state if the
2333 kd_buffer wraps */
2334 for (i = 0; i < prev_total_threads; i++)
2335 {
2336 if (fdmapptr[i].fd_setptr)
2337 free (fdmapptr[i].fd_setptr);
2338 }
2339 free(fdmapptr);
2340 fdmapptr = 0;
2341 }
2342
2343 size = total_threads * sizeof(fd_threadmap);
2344 if ((fdmapptr = (fd_threadmap *) malloc(size)))
2345 {
2346 bzero (fdmapptr, size);
2347 /* reinitialize file descriptor state map */
2348 for (i = 0; i < total_threads; i++)
2349 {
2350 fdmapptr[i].fd_thread = mapptr[i].thread;
2351 fdmapptr[i].fd_valid = mapptr[i].valid;
2352 fdmapptr[i].fd_setsize = 0;
2353 fdmapptr[i].fd_setptr = 0;
2354 }
2355 }
2356 }
2357
2358 /* Resolve any LaunchCFMApp command names */
2359 if (mapptr && arguments)
2360 {
2361 for (i=0; i < total_threads; i++)
2362 {
2363 int pid;
2364
2365 pid = mapptr[i].valid;
2366
2367 if (pid == 0 || pid == 1)
2368 continue;
2369 else if (!strncmp(mapptr[i].command,"LaunchCFMA", 10))
2370 {
2371 (void)get_real_command_name(pid, mapptr[i].command, sizeof(mapptr[i].command));
2372 }
2373 }
2374 }
2375 }
2376
2377
2378 void create_map_entry(int thread, int pid, char *command)
2379 {
2380 int i, n;
2381 kd_threadmap *map;
2382 fd_threadmap *fdmap = 0;
2383
2384 if (!mapptr)
2385 return;
2386
2387 for (i = 0, map = 0; !map && i < total_threads; i++)
2388 {
2389 if ((int)mapptr[i].thread == thread )
2390 {
2391 map = &mapptr[i]; /* Reuse this entry, the thread has been
2392 * reassigned */
2393 if(filter_mode && fdmapptr)
2394 {
2395 fdmap = &fdmapptr[i];
2396 if (fdmap->fd_thread != thread) /* This shouldn't happen */
2397 fdmap = (fd_threadmap *)0;
2398 }
2399 }
2400 }
2401
2402 if (!map) /* look for invalid entries that I can reuse*/
2403 {
2404 for (i = 0, map = 0; !map && i < total_threads; i++)
2405 {
2406 if (mapptr[i].valid == 0 )
2407 map = &mapptr[i]; /* Reuse this invalid entry */
2408 if (filter_mode && fdmapptr)
2409 {
2410 fdmap = &fdmapptr[i];
2411 }
2412 }
2413 }
2414
2415 if (!map)
2416 {
2417 /* If reach here, then this is a new thread and
2418 * there are no invalid entries to reuse
2419 * Double the size of the thread map table.
2420 */
2421
2422 n = total_threads * 2;
2423 mapptr = (kd_threadmap *) realloc(mapptr, n * sizeof(kd_threadmap));
2424 bzero(&mapptr[total_threads], total_threads*sizeof(kd_threadmap));
2425 map = &mapptr[total_threads];
2426
2427 if (filter_mode && fdmapptr)
2428 {
2429 fdmapptr = (fd_threadmap *)realloc(fdmapptr, n * sizeof(fd_threadmap));
2430 bzero(&fdmapptr[total_threads], total_threads*sizeof(fd_threadmap));
2431 fdmap = &fdmapptr[total_threads];
2432 }
2433
2434 total_threads = n;
2435 }
2436
2437 map->valid = 1;
2438 map->thread = thread;
2439 /*
2440 The trace entry that returns the command name will hold
2441 at most, MAXCOMLEN chars, and in that case, is not
2442 guaranteed to be null terminated.
2443 */
2444 (void)strncpy (map->command, command, MAXCOMLEN);
2445 map->command[MAXCOMLEN] = '\0';
2446
2447 if (fdmap)
2448 {
2449 fdmap->fd_valid = 1;
2450 fdmap->fd_thread = thread;
2451 if (fdmap->fd_setptr)
2452 {
2453 free(fdmap->fd_setptr);
2454 fdmap->fd_setptr = (unsigned long *)0;
2455 }
2456 fdmap->fd_setsize = 0;
2457 }
2458
2459 if (pid == 0 || pid == 1)
2460 return;
2461 else if (!strncmp(map->command, "LaunchCFMA", 10))
2462 (void)get_real_command_name(pid, map->command, sizeof(map->command));
2463 }
2464
2465
2466 kd_threadmap *find_thread_map(int thread)
2467 {
2468 int i;
2469 kd_threadmap *map;
2470
2471 if (!mapptr)
2472 return((kd_threadmap *)0);
2473
2474 for (i = 0; i < total_threads; i++)
2475 {
2476 map = &mapptr[i];
2477 if (map->valid && ((int)map->thread == thread))
2478 {
2479 return(map);
2480 }
2481 }
2482 return ((kd_threadmap *)0);
2483 }
2484
2485 fd_threadmap *find_fd_thread_map(int thread)
2486 {
2487 int i;
2488 fd_threadmap *fdmap = 0;
2489
2490 if (!fdmapptr)
2491 return((fd_threadmap *)0);
2492
2493 for (i = 0; i < total_threads; i++)
2494 {
2495 fdmap = &fdmapptr[i];
2496 if (fdmap->fd_valid && ((int)fdmap->fd_thread == thread))
2497 {
2498 return(fdmap);
2499 }
2500 }
2501 return ((fd_threadmap *)0);
2502 }
2503
2504
2505 void
2506 kill_thread_map(int thread)
2507 {
2508 kd_threadmap *map;
2509 fd_threadmap *fdmap;
2510
2511 if ((map = find_thread_map(thread))) {
2512 map->valid = 0;
2513 map->thread = 0;
2514 map->command[0] = '\0';
2515 }
2516
2517 if (filter_mode)
2518 {
2519 if ((fdmap = find_fd_thread_map(thread)))
2520 {
2521 fdmap->fd_valid = 0;
2522 fdmap->fd_thread = 0;
2523 if (fdmap->fd_setptr)
2524 {
2525 free (fdmap->fd_setptr);
2526 fdmap->fd_setptr = (unsigned long *)0;
2527 }
2528 fdmap->fd_setsize = 0;
2529 }
2530 }
2531 }
2532
2533 void
2534 argtopid(str)
2535 char *str;
2536 {
2537 char *cp;
2538 int ret;
2539 int i;
2540
2541 ret = (int)strtol(str, &cp, 10);
2542 if (cp == str || *cp) {
2543 /* Assume this is a command string and find matching pids */
2544 if (!kp_buffer)
2545 find_proc_names();
2546
2547 for (i=0; i < kp_nentries && num_of_pids < (MAX_PIDS - 1); i++) {
2548 if(kp_buffer[i].kp_proc.p_stat == 0)
2549 continue;
2550 else {
2551 if(!strcmp(str, kp_buffer[i].kp_proc.p_comm))
2552 pids[num_of_pids++] = kp_buffer[i].kp_proc.p_pid;
2553 }
2554 }
2555 }
2556 else if (num_of_pids < (MAX_PIDS - 1))
2557 pids[num_of_pids++] = ret;
2558
2559 return;
2560 }
2561
2562
2563
2564 char *lookup_name(unsigned long addr)
2565 {
2566 register int i;
2567 register int start, last;
2568
2569
2570 if (numFrameworks == 0 || addr < frameworkInfo[0].address || addr > frameworkInfo[numFrameworks].address)
2571 return (0);
2572
2573 start = 0;
2574 last = numFrameworks;
2575
2576 for (i = numFrameworks / 2; i >= 0 && i < numFrameworks; ) {
2577
2578 if (addr >= frameworkInfo[i].address && addr < frameworkInfo[i+1].address)
2579 return(frameworkInfo[i].name);
2580
2581 if (addr >= frameworkInfo[i].address) {
2582 start = i;
2583 i = start + ((last - i) / 2);
2584 } else {
2585 last = i;
2586 i = start + ((i - start) / 2);
2587 }
2588 }
2589 return (0);
2590 }
2591
2592
2593 /*
2594 * Comparison routines for sorting
2595 */
2596 static int compareFrameworkAddress(const void *aa, const void *bb)
2597 {
2598 LibraryInfo *a = (LibraryInfo *)aa;
2599 LibraryInfo *b = (LibraryInfo *)bb;
2600
2601 if (a->address < b->address) return -1;
2602 if (a->address == b->address) return 0;
2603 return 1;
2604 }
2605
2606
2607 int scanline(char *inputstring,char **argv)
2608 {
2609 int n = 0;
2610 char **ap = argv, *p, *val;
2611
2612 for (p = inputstring; p != NULL; )
2613 {
2614 while ((val = strsep(&p, " \t")) != NULL && *val == '\0');
2615 *ap++ = val;
2616 n++;
2617 }
2618 *ap = 0;
2619 return n;
2620 }
2621
2622
2623 int ReadSegAddrTable()
2624 {
2625 char buf[1024];
2626
2627 FILE *fd;
2628 unsigned long frameworkAddress, frameworkDataAddress, previousFrameworkAddress;
2629 char frameworkName[256];
2630 char *tokens[64];
2631 int ntokens;
2632 char *substring,*ptr;
2633 int founddylib = 0;
2634
2635
2636 bzero(buf, sizeof(buf));
2637 bzero(tokens, sizeof(tokens));
2638
2639 numFrameworks = 0;
2640
2641 if ((fd = fopen(seg_addr_table, "r")) == 0)
2642 {
2643 return 0;
2644 }
2645 fgets(buf, 1023, fd);
2646
2647 if (*buf == '#')
2648 {
2649 founddylib = 0;
2650 frameworkName[0] = 0;
2651 previousFrameworkAddress = 0;
2652
2653 while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2))
2654 {
2655 /*
2656 * Get rid of EOL
2657 */
2658 buf[strlen(buf)-1] = 0;
2659
2660 if (strncmp(buf, "# dyld:", 7) == 0) {
2661 /*
2662 * the next line in the file will contain info about dyld
2663 */
2664 founddylib = 1;
2665 continue;
2666 }
2667 /*
2668 * This is a split library line: parse it into 3 tokens
2669 */
2670 ntokens = scanline(buf, tokens);
2671
2672 if (ntokens < 3)
2673 continue;
2674
2675 frameworkAddress = strtoul(tokens[0], 0, 16);
2676 frameworkDataAddress = strtoul(tokens[1], 0, 16);
2677
2678 if (founddylib) {
2679 /*
2680 * dyld entry is of a different form from the std split library
2681 * it consists of a base address and a size instead of a code
2682 * and data base address
2683 */
2684 frameworkInfo[numFrameworks].address = frameworkAddress;
2685 frameworkInfo[numFrameworks+1].address = frameworkAddress + frameworkDataAddress;
2686
2687 frameworkInfo[numFrameworks].name = (char *)"dylib";
2688 frameworkInfo[numFrameworks+1].name = (char *)0;
2689
2690 numFrameworks += 2;
2691 founddylib = 0;
2692
2693 continue;
2694 }
2695
2696 /*
2697 * Make sure that we have 2 addresses and a path
2698 */
2699 if (!frameworkAddress)
2700 continue;
2701 if (!frameworkDataAddress)
2702 continue;
2703 if (*tokens[2] != '/')
2704 continue;
2705 if (frameworkAddress == previousFrameworkAddress)
2706 continue;
2707 previousFrameworkAddress = frameworkAddress;
2708
2709 /*
2710 * Extract lib name from path name
2711 */
2712 if ((substring = strrchr(tokens[2], '.')))
2713 {
2714 /*
2715 * There is a ".": name is whatever is between the "/" around the "."
2716 */
2717 while ( *substring != '/') { /* find "/" before "." */
2718 substring--;
2719 }
2720 substring++;
2721 strcpy(frameworkName, substring); /* copy path from "/" */
2722 substring = frameworkName;
2723
2724 while ( *substring != '/' && *substring) /* find "/" after "." and stop string there */
2725 substring++;
2726 *substring = 0;
2727 }
2728 else
2729 {
2730 /*
2731 * No ".": take segment after last "/"
2732 */
2733 ptr = tokens[2];
2734 substring = ptr;
2735
2736 while (*ptr)
2737 {
2738 if (*ptr == '/')
2739 substring = ptr + 1;
2740 ptr++;
2741 }
2742 strcpy(frameworkName, substring);
2743 }
2744 frameworkInfo[numFrameworks].address = frameworkAddress;
2745 frameworkInfo[numFrameworks+1].address = frameworkDataAddress;
2746
2747 frameworkInfo[numFrameworks].name = (char *)malloc(strlen(frameworkName) + 1);
2748 strcpy(frameworkInfo[numFrameworks].name, frameworkName);
2749 frameworkInfo[numFrameworks+1].name = frameworkInfo[numFrameworks].name;
2750
2751 numFrameworks += 2;
2752 }
2753 }
2754 frameworkInfo[numFrameworks].address = frameworkInfo[numFrameworks - 1].address + 0x800000;
2755 frameworkInfo[numFrameworks].name = (char *)0;
2756
2757 fclose(fd);
2758
2759 qsort(frameworkInfo, numFrameworks, sizeof(LibraryInfo), compareFrameworkAddress);
2760
2761 return 1;
2762 }
2763
2764
2765 struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, int thread, double curtime)
2766 {
2767 register struct diskio *dio;
2768 register kd_threadmap *map;
2769
2770 if ((dio = free_diskios))
2771 free_diskios = dio->next;
2772 else {
2773 if ((dio = (struct diskio *)malloc(sizeof(struct diskio))) == NULL)
2774 return (NULL);
2775 }
2776 dio->prev = NULL;
2777
2778 dio->type = type;
2779 dio->bp = bp;
2780 dio->dev = dev;
2781 dio->blkno = blkno;
2782 dio->iosize = io_size;
2783 dio->issued_time = curtime;
2784 dio->issuing_thread = thread;
2785
2786 if ((map = find_thread_map(thread)))
2787 {
2788 strncpy(dio->issuing_command, map->command, MAXCOMLEN);
2789 dio->issuing_command[MAXCOMLEN-1] = '\0';
2790 }
2791 else
2792 strcpy(dio->issuing_command, "");
2793
2794 dio->next = busy_diskios;
2795 if (dio->next)
2796 dio->next->prev = dio;
2797 busy_diskios = dio;
2798
2799 return (dio);
2800 }
2801
2802
2803 struct diskio *complete_diskio(int bp, int io_errno, int resid, int thread, double curtime)
2804 {
2805 register struct diskio *dio;
2806
2807 for (dio = busy_diskios; dio; dio = dio->next) {
2808 if (dio->bp == bp) {
2809
2810 if (dio == busy_diskios) {
2811 if ((busy_diskios = dio->next))
2812 dio->next->prev = NULL;
2813 } else {
2814 if (dio->next)
2815 dio->next->prev = dio->prev;
2816 dio->prev->next = dio->next;
2817 }
2818 dio->iosize -= resid;
2819 dio->io_errno = io_errno;
2820 dio->completed_time = curtime;
2821 dio->completion_thread = thread;
2822
2823 return (dio);
2824 }
2825 }
2826 return ((struct diskio *)0);
2827 }
2828
2829
2830 void free_diskio(struct diskio *dio)
2831 {
2832 dio->next = free_diskios;
2833 free_diskios = dio;
2834 }
2835
2836
2837 void print_diskio(struct diskio *dio)
2838 {
2839 register char *p;
2840
2841 switch (dio->type) {
2842
2843 case P_RdMeta:
2844 p = " RdMeta";
2845 break;
2846 case P_WrMeta:
2847 p = " WrMeta";
2848 break;
2849 case P_RdData:
2850 p = " RdData";
2851 break;
2852 case P_WrData:
2853 p = " WrData";
2854 break;
2855 case P_PgIn:
2856 p = " PgIn";
2857 break;
2858 case P_PgOut:
2859 p = " PgOut";
2860 break;
2861 case P_RdMetaAsync:
2862 p = " RdMeta[async]";
2863 break;
2864 case P_WrMetaAsync:
2865 p = " WrMeta[async]";
2866 break;
2867 case P_RdDataAsync:
2868 p = " RdData[async]";
2869 break;
2870 case P_WrDataAsync:
2871 p = " WrData[async]";
2872 break;
2873 case P_PgInAsync:
2874 p = " PgIn[async]";
2875 break;
2876 case P_PgOutAsync:
2877 p = " PgOut[async]";
2878 break;
2879 default:
2880 p = " ";
2881 break;
2882 }
2883 if (check_filter_mode(NULL, dio->type,0, 0))
2884 format_print(NULL, p, dio->issuing_thread, dio->type, 0, 0, 0, 7, dio->completed_time, dio->issued_time, 1, "", dio);
2885 }
2886
2887
2888 void cache_disk_names()
2889 {
2890 struct stat st;
2891 DIR *dirp = NULL;
2892 struct dirent *dir;
2893 struct diskrec *dnp;
2894
2895
2896 if ((dirp = opendir("/dev")) == NULL)
2897 return;
2898
2899 while ((dir = readdir(dirp)) != NULL) {
2900 char nbuf[MAXPATHLEN];
2901
2902 if (dir->d_namlen < 5 || strncmp("disk", dir->d_name, 4))
2903 continue;
2904 sprintf(nbuf, "%s/%s", "/dev", dir->d_name);
2905
2906 if (stat(nbuf, &st) < 0)
2907 continue;
2908
2909 if ((dnp = (struct diskrec *)malloc(sizeof(struct diskrec))) == NULL)
2910 continue;
2911
2912 if ((dnp->diskname = (char *)malloc(dir->d_namlen + 1)) == NULL) {
2913 free(dnp);
2914 continue;
2915 }
2916 strncpy(dnp->diskname, dir->d_name, dir->d_namlen);
2917 dnp->diskname[dir->d_namlen] = 0;
2918 dnp->dev = st.st_rdev;
2919
2920 dnp->next = disk_list;
2921 disk_list = dnp;
2922 }
2923 (void) closedir(dirp);
2924 }
2925
2926
2927 char *find_disk_name(int dev)
2928 {
2929 struct diskrec *dnp;
2930
2931 if (dev == NFS_DEV)
2932 return ("NFS");
2933
2934 for (dnp = disk_list; dnp; dnp = dnp->next) {
2935 if (dnp->dev == dev)
2936 return (dnp->diskname);
2937 }
2938 return ("NOTFOUND");
2939 }
2940
2941 void
2942 fs_usage_fd_set(thread, fd)
2943 unsigned int thread;
2944 unsigned int fd;
2945 {
2946 int n;
2947 fd_threadmap *fdmap;
2948
2949 if(!(fdmap = find_fd_thread_map(thread)))
2950 return;
2951
2952 /* If the map is not allocated, then now is the time */
2953 if (fdmap->fd_setptr == (unsigned long *)0)
2954 {
2955 fdmap->fd_setptr = (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE));
2956 if (fdmap->fd_setptr)
2957 {
2958 fdmap->fd_setsize = FS_USAGE_FD_SETSIZE;
2959 bzero(fdmap->fd_setptr,(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE)));
2960 }
2961 else
2962 return;
2963 }
2964
2965 /* If the map is not big enough, then reallocate it */
2966 while (fdmap->fd_setsize < fd)
2967 {
2968 printf("reallocating bitmap for threadid %d, fd = %d, setsize = %d\n",
2969 thread, fd, fdmap->fd_setsize);
2970 n = fdmap->fd_setsize * 2;
2971 fdmap->fd_setptr = (unsigned long *)realloc(fdmap->fd_setptr, (FS_USAGE_NFDBYTES(n)));
2972 bzero(&fdmap->fd_setptr[(fdmap->fd_setsize/FS_USAGE_NFDBITS)], (FS_USAGE_NFDBYTES(fdmap->fd_setsize)));
2973 fdmap->fd_setsize = n;
2974 }
2975
2976 /* set the bit */
2977 fdmap->fd_setptr[fd/FS_USAGE_NFDBITS] |= (1 << ((fd) % FS_USAGE_NFDBITS));
2978
2979 return;
2980 }
2981
2982 /*
2983 Return values:
2984 0 : File Descriptor bit is not set
2985 1 : File Descriptor bit is set
2986 */
2987
2988 int
2989 fs_usage_fd_isset(thread, fd)
2990 unsigned int thread;
2991 unsigned int fd;
2992 {
2993 int ret = 0;
2994 fd_threadmap *fdmap;
2995
2996 if(!(fdmap = find_fd_thread_map(thread)))
2997 return(ret);
2998
2999 if (fdmap->fd_setptr == (unsigned long *)0)
3000 return (ret);
3001
3002 if (fd < fdmap->fd_setsize)
3003 ret = fdmap->fd_setptr[fd/FS_USAGE_NFDBITS] & (1 << (fd % FS_USAGE_NFDBITS));
3004
3005 return (ret);
3006 }
3007
3008 void
3009 fs_usage_fd_clear(thread, fd)
3010 unsigned int thread;
3011 unsigned int fd;
3012 {
3013 fd_threadmap *map;
3014
3015 if (!(map = find_fd_thread_map(thread)))
3016 return;
3017
3018 if (map->fd_setptr == (unsigned long *)0)
3019 return;
3020
3021 /* clear the bit */
3022 if (fd < map->fd_setsize)
3023 map->fd_setptr[fd/FS_USAGE_NFDBITS] &= ~(1 << (fd % FS_USAGE_NFDBITS));
3024
3025 return;
3026 }
3027
3028
3029 /*
3030 * ret = 1 means print the entry
3031 * ret = 0 means don't print the entry
3032 */
3033 int
3034 check_filter_mode(struct th_info * ti, int type, int error, int retval)
3035 {
3036 int ret = 0;
3037 int network_fd_isset = 0;
3038 unsigned int fd;
3039
3040 if (filter_mode == DEFAULT_DO_NOT_FILTER)
3041 return(1);
3042
3043 if (ti == (struct th_info *)0)
3044 {
3045 if(filter_mode & FILESYS_FILTER)
3046 ret = 1;
3047 else
3048 ret = 0;
3049 return(ret);
3050 }
3051
3052
3053 switch (type) {
3054 case BSC_close:
3055 fd = ti->arg1;
3056 network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
3057 if (error == 0)
3058 {
3059 fs_usage_fd_clear(ti->thread,fd);
3060 }
3061
3062 if (network_fd_isset)
3063 {
3064 if (filter_mode & NETWORK_FILTER)
3065 ret = 1;
3066 }
3067 else if (filter_mode & FILESYS_FILTER)
3068 ret = 1;
3069 break;
3070 case BSC_read:
3071 case BSC_write:
3072 /* we don't care about error in this case */
3073 fd = ti->arg1;
3074 network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
3075 if (network_fd_isset)
3076 {
3077 if (filter_mode & NETWORK_FILTER)
3078 ret = 1;
3079 }
3080 else if (filter_mode & FILESYS_FILTER)
3081 ret = 1;
3082 break;
3083 case BSC_accept:
3084 case BSC_socket:
3085 fd = retval;
3086 if (error == 0)
3087 fs_usage_fd_set(ti->thread, fd);
3088 if (filter_mode & NETWORK_FILTER)
3089 ret = 1;
3090 break;
3091 case BSC_recvfrom:
3092 case BSC_sendto:
3093 case BSC_recvmsg:
3094 case BSC_sendmsg:
3095 case BSC_connect:
3096 case BSC_bind:
3097 case BSC_listen:
3098 fd = ti->arg1;
3099 if (error == 0)
3100 fs_usage_fd_set(ti->thread, fd);
3101 if (filter_mode & NETWORK_FILTER)
3102 ret = 1;
3103 break;
3104 case BSC_select:
3105 case BSC_socketpair:
3106 /* Cannot determine info about file descriptors */
3107 if (filter_mode & NETWORK_FILTER)
3108 ret = 1;
3109 break;
3110 case BSC_dup:
3111 case BSC_dup2:
3112 ret=0; /* We track these cases for fd state only */
3113 fd = ti->arg1; /* oldd */
3114 network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
3115 if (error == 0 && network_fd_isset)
3116 {
3117 /* then we are duping a socket descriptor */
3118 fd = retval; /* the new fd */
3119 fs_usage_fd_set(ti->thread, fd);
3120 }
3121 break;
3122
3123 default:
3124 if (filter_mode & FILESYS_FILTER)
3125 ret = 1;
3126 break;
3127 }
3128
3129 return(ret);
3130 }
3131
3132 /*
3133 * Allocate a buffer that is large enough to hold the maximum arguments
3134 * to execve(). This is used when getting the arguments to programs
3135 * when we see LaunchCFMApps. If this fails, it is not fatal, we will
3136 * simply not resolve the command name.
3137 */
3138
3139 void
3140 init_arguments_buffer()
3141 {
3142
3143 int mib[2];
3144 size_t size;
3145
3146 mib[0] = CTL_KERN;
3147 mib[1] = KERN_ARGMAX;
3148 size = sizeof(argmax);
3149 if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
3150 return;
3151
3152 #if 1
3153 /* Hack to avoid kernel bug. */
3154 if (argmax > 8192) {
3155 argmax = 8192;
3156 }
3157 #endif
3158
3159 arguments = (char *)malloc(argmax);
3160
3161 return;
3162 }
3163
3164
3165 int
3166 get_real_command_name(int pid, char *cbuf, int csize)
3167 {
3168 /*
3169 * Get command and arguments.
3170 */
3171 char *cp;
3172 int mib[4];
3173 char *command_beg, *command, *command_end;
3174
3175 if (cbuf == NULL) {
3176 return(0);
3177 }
3178
3179 if (arguments)
3180 bzero(arguments, argmax);
3181 else
3182 return(0);
3183
3184 /*
3185 * A sysctl() is made to find out the full path that the command
3186 * was called with.
3187 */
3188 mib[0] = CTL_KERN;
3189 mib[1] = KERN_PROCARGS;
3190 mib[2] = pid;
3191 mib[3] = 0;
3192
3193 if (sysctl(mib, 3, arguments, (size_t *)&argmax, NULL, 0) < 0) {
3194 return(0);
3195 }
3196
3197 /* Skip the saved exec_path. */
3198 for (cp = arguments; cp < &arguments[argmax]; cp++) {
3199 if (*cp == '\0') {
3200 /* End of exec_path reached. */
3201 break;
3202 }
3203 }
3204 if (cp == &arguments[argmax]) {
3205 return(0);
3206 }
3207
3208 /* Skip trailing '\0' characters. */
3209 for (; cp < &arguments[argmax]; cp++) {
3210 if (*cp != '\0') {
3211 /* Beginning of first argument reached. */
3212 break;
3213 }
3214 }
3215 if (cp == &arguments[argmax]) {
3216 return(0);
3217 }
3218 command_beg = cp;
3219
3220 /*
3221 * Make sure that the command is '\0'-terminated. This protects
3222 * against malicious programs; under normal operation this never
3223 * ends up being a problem..
3224 */
3225 for (; cp < &arguments[argmax]; cp++) {
3226 if (*cp == '\0') {
3227 /* End of first argument reached. */
3228 break;
3229 }
3230 }
3231 if (cp == &arguments[argmax]) {
3232 return(0);
3233 }
3234 command_end = command = cp;
3235
3236 /* Get the basename of command. */
3237 for (command--; command >= command_beg; command--) {
3238 if (*command == '/') {
3239 command++;
3240 break;
3241 }
3242 }
3243
3244 (void) strncpy(cbuf, (char *)command, csize);
3245 cbuf[csize-1] = '\0';
3246
3247 return(1);
3248 }