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