2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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
22 * @APPLE_LICENSE_HEADER_END@
26 cc -I. -DKERNEL_PRIVATE -O -o fs_usage fs_usage.c
29 #define Default_DELAY 1 /* default delay interval */
40 #include <sys/types.h>
41 #include <sys/param.h>
46 #include <sys/ioctl.h>
48 #ifndef KERNEL_PRIVATE
49 #define KERNEL_PRIVATE
50 #include <sys/kdebug.h>
53 #include <sys/kdebug.h>
54 #endif /*KERNEL_PRIVATE*/
56 #include <sys/sysctl.h>
58 #import <mach/clock_types.h>
67 typedef struct LibraryInfo
{
68 unsigned long address
;
72 LibraryInfo frameworkInfo
[MAXINDEX
];
73 int numFrameworks
= 0;
75 char seg_addr_table
[256]="/AppleInternal/Developer/seg_addr_table";
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.
87 #define PATHLENGTH (NUMPARMS*sizeof(long))
89 #define MAX_WIDE_MODE_COLS (PATHLENGTH + 80)
104 char pathname
[PATHLENGTH
+ 1]; /* add room for null terminator */
107 #define MAX_THREADS 512
108 struct th_info th_state
[MAX_THREADS
];
112 int need_new_map
= 1;
116 int select_pid_mode
= 0; /* Flag set indicates that output is restricted
117 to selected pids or commands */
119 int one_good_pid
= 0; /* Used to fail gracefully when bad pids given */
125 * Network only or filesystem only output filter
126 * Default of zero means report all activity - no filtering
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
;
136 struct diskrec
*next
;
151 int completion_thread
;
152 char issuing_command
[MAXCOMLEN
];
154 double completed_time
;
157 struct diskrec
*disk_list
= NULL
;
158 struct diskio
*free_diskios
= NULL
;
159 struct diskio
*busy_diskios
= NULL
;
161 struct diskio
*insert_diskio();
162 struct diskio
*complete_diskio();
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 *);
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
183 #define TRACE_DATA_NEWTHREAD 0x07000004
184 #define TRACE_DATA_EXEC 0x07000008
185 #define TRACE_STRING_NEWTHREAD 0x07010004
186 #define TRACE_STRING_EXEC 0x07010008
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
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
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
222 #define MSC_map_fd 0x010c00ac
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
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
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
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
367 #define FILEMGR_CLASS 0x1e
373 int exclude_pids
= 0;
374 int exclude_default_pids
= 1;
376 struct kinfo_proc
*kp_buffer
= 0;
379 #define SAMPLE_SIZE 60000
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
386 #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END)
387 #define DBG_FUNC_MASK 0xfffffffc
389 double divisor
= 0.0; /* Trace divisor converts to microseconds */
395 kbufinfo_t bufinfo
= {0, 0, 0, 0, 0};
397 int total_threads
= 0;
398 kd_threadmap
*mapptr
= 0; /* pointer to list of threads */
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 */
404 #define FS_USAGE_NFDBITS (sizeof (unsigned long) * 8)
405 #define FS_USAGE_NFDBYTES(n) (((n) / FS_USAGE_NFDBITS) * sizeof (unsigned long))
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 */
414 fd_threadmap
*fdmapptr
= 0; /* pointer to list of threads for fd tracking */
416 int trace_enabled
= 0;
417 int set_remove_flag
= 1;
429 void leave() /* exit under normal conditions -- INT handler */
434 void set_pidexclude();
439 if (exclude_pids
== 0) {
440 for (i
= 0; i
< num_of_pids
; i
++)
441 set_pidcheck(pids
[i
], 0);
444 for (i
= 0; i
< num_of_pids
; i
++)
445 set_pidexclude(pids
[i
], 0);
452 void get_screenwidth()
459 if (ioctl(1, TIOCGWINSZ
, &size
) != -1)
460 columns
= size
.ws_col
;
472 exit_usage(char *myname
) {
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");
495 char *myname
= "fs_usage";
502 void set_pidexclude();
505 if ( geteuid() != 0 ) {
506 printf("'fs_usage' must be run as root...\n");
513 if ((myname
= rindex(argv
[0], '/')) == 0) {
522 while ((ch
= getopt(argc
, argv
, "ewf:")) != EOF
) {
526 exclude_default_pids
= 0;
530 if ((uint
)columns
< MAX_WIDE_MODE_COLS
)
531 columns
= MAX_WIDE_MODE_COLS
;
534 if (!strcmp(optarg
, "network"))
535 filter_mode
|= NETWORK_FILTER
;
536 else if (!strcmp(optarg
, "filesys"))
537 filter_mode
|= FILESYS_FILTER
;
548 /* If we process any list of pids/cmds, then turn off the defaults */
550 exclude_default_pids
= 0;
552 while (argc
> 0 && num_of_pids
< (MAX_PIDS
- 1)) {
559 /* Exclude a set of default pids */
560 if (exclude_default_pids
)
562 argtopid("Terminal");
575 if (num_of_pids
< (MAX_PIDS
- 1))
576 pids
[num_of_pids
++] = getpid();
582 for (i
= 0; i
< num_of_pids
; i
++)
585 printf("exclude pid %d\n", pids
[i
]);
587 printf("pid %d\n", pids
[i
]);
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
);
598 if ((my_buffer
= malloc(SAMPLE_SIZE
* sizeof(kd_buf
))) == (char *)0)
599 quit("can't allocate memory for tracing info\n");
605 set_numbufs(SAMPLE_SIZE
);
608 if (exclude_pids
== 0) {
609 for (i
= 0; i
< num_of_pids
; i
++)
610 set_pidcheck(pids
[i
], 1);
612 for (i
= 0; i
< num_of_pids
; i
++)
613 set_pidexclude(pids
[i
], 1);
616 if (select_pid_mode
&& !one_good_pid
)
619 An attempt to restrict output to a given
620 pid or command has failed. Exit gracefully
628 init_arguments_buffer();
644 struct kinfo_proc
*kp
;
649 mib
[2] = KERN_PROC_ALL
;
652 if (sysctl(mib
, 4, NULL
, &bufSize
, NULL
, 0) < 0)
653 quit("trace facility failure, KERN_PROC_ALL\n");
655 if((kp
= (struct kinfo_proc
*)malloc(bufSize
)) == (struct kinfo_proc
*)0)
656 quit("can't allocate memory for proc buffer\n");
658 if (sysctl(mib
, 4, kp
, &bufSize
, NULL
, 0) < 0)
659 quit("trace facility failure, KERN_PROC_ALL\n");
661 kp_nentries
= bufSize
/ sizeof(struct kinfo_proc
);
666 struct th_info
*find_thread(int thread
, int type
) {
669 for (ti
= th_state
; ti
< &th_state
[cur_max
]; ti
++) {
670 if (ti
->thread
== thread
) {
671 if (type
== ti
->type
)
673 if (ti
->in_filemgr
) {
682 return ((struct th_info
*)0);
687 mark_thread_waited(int thread
) {
690 for (ti
= th_state
; ti
< &th_state
[cur_max
]; ti
++) {
691 if (ti
->thread
== thread
) {
702 mib
[1] = KERN_KDEBUG
;
703 mib
[2] = KERN_KDENABLE
; /* protocol */
706 mib
[5] = 0; /* no flags */
707 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
708 quit("trace facility failure, KERN_KDENABLE\n");
717 set_numbufs(int nbufs
)
720 mib
[1] = KERN_KDEBUG
;
721 mib
[2] = KERN_KDSETBUF
;
724 mib
[5] = 0; /* no flags */
725 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
726 quit("trace facility failure, KERN_KDSETBUF\n");
729 mib
[1] = KERN_KDEBUG
;
730 mib
[2] = KERN_KDSETUP
;
733 mib
[5] = 0; /* no flags */
734 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
735 quit("trace facility failure, KERN_KDSETUP\n");
739 set_pidcheck(int pid
, int on_off
)
743 kr
.type
= KDBG_TYPENONE
;
746 needed
= sizeof(kd_regtype
);
748 mib
[1] = KERN_KDEBUG
;
749 mib
[2] = KERN_KDPIDTR
;
754 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0) {
756 printf("pid %d does not exist\n", pid
);
764 on_off == 0 turns off pid exclusion
765 on_off == 1 turns on pid exclusion
768 set_pidexclude(int pid
, int on_off
)
774 kr
.type
= KDBG_TYPENONE
;
777 needed
= sizeof(kd_regtype
);
779 mib
[1] = KERN_KDEBUG
;
780 mib
[2] = KERN_KDPIDEX
;
785 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0) {
787 printf("pid %d does not exist\n", pid
);
792 get_bufinfo(kbufinfo_t
*val
)
794 needed
= sizeof (*val
);
796 mib
[1] = KERN_KDEBUG
;
797 mib
[2] = KERN_KDGETBUF
;
800 mib
[5] = 0; /* no flags */
802 if (sysctl(mib
, 3, val
, &needed
, 0, 0) < 0)
803 quit("trace facility failure, KERN_KDGETBUF\n");
813 mib
[1] = KERN_KDEBUG
;
814 mib
[2] = KERN_KDREMOVE
; /* protocol */
817 mib
[5] = 0; /* no flags */
818 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
823 quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n");
825 quit("trace facility failure, KERN_KDREMOVE\n");
833 kr
.type
= KDBG_RANGETYPE
;
836 needed
= sizeof(kd_regtype
);
838 mib
[1] = KERN_KDEBUG
;
839 mib
[2] = KERN_KDSETREG
;
842 mib
[5] = 0; /* no flags */
844 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0)
845 quit("trace facility failure, KERN_KDSETREG\n");
848 mib
[1] = KERN_KDEBUG
;
849 mib
[2] = KERN_KDSETUP
;
852 mib
[5] = 0; /* no flags */
854 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
855 quit("trace facility failure, KERN_KDSETUP\n");
864 void read_command_map();
865 void create_map_entry();
867 /* Get kernel buffer information */
868 get_bufinfo(&bufinfo
);
874 needed
= bufinfo
.nkdbufs
* sizeof(kd_buf
);
876 mib
[1] = KERN_KDEBUG
;
877 mib
[2] = KERN_KDREADTR
;
880 mib
[5] = 0; /* no flags */
882 if (sysctl(mib
, 3, my_buffer
, &needed
, NULL
, 0) < 0)
883 quit("trace facility failure, KERN_KDREADTR\n");
886 if (bufinfo
.flags
& KDBG_WRAPPED
) {
887 printf("buffer wrapped count = %d\n", count
);
889 for (i
= 0; i
< cur_max
; i
++) {
890 th_state
[i
].thread
= 0;
892 th_state
[i
].pathptr
= (long *)0;
893 th_state
[i
].pathname
[0] = 0;
901 kd
= (kd_buf
*)my_buffer
;
903 printf("READTR returned %d items\n", count
);
905 for (i
= 0; i
< count
; i
++) {
915 void enter_syscall();
917 void kill_thread_map();
919 thread
= kd
[i
].arg5
& KDBG_THREAD_MASK
;
920 debugid
= kd
[i
].debugid
;
921 type
= kd
[i
].debugid
& DBG_FUNC_MASK
;
923 now
= kd
[i
].timestamp
;
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.
932 l_usecs
= (long long)(now
/ divisor
);
933 secs
= l_usecs
/ 1000000;
934 curr_time
= time((long *)0);
935 bias_secs
= curr_time
- secs
;
953 insert_diskio(type
, kd
[i
].arg1
, kd
[i
].arg2
, kd
[i
].arg3
, kd
[i
].arg4
, thread
, (double)now
);
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
))) {
975 case TRACE_DATA_NEWTHREAD
:
977 for (n
= 0, ti
= th_state
; ti
< &th_state
[MAX_THREADS
]; ti
++, n
++) {
981 if (ti
== &th_state
[MAX_THREADS
])
987 ti
->child_thread
= kd
[i
].arg1
;
988 ti
->pid
= kd
[i
].arg2
;
991 case TRACE_STRING_NEWTHREAD
:
992 if ((ti
= find_thread(thread
, 0)) == (struct th_info
*)0)
994 if (ti
->child_thread
== 0)
996 create_map_entry(ti
->child_thread
, ti
->pid
, (char *)&kd
[i
].arg1
);
998 if (ti
== &th_state
[cur_max
- 1])
1000 ti
->child_thread
= 0;
1005 case TRACE_DATA_EXEC
:
1007 for (n
= 0, ti
= th_state
; ti
< &th_state
[MAX_THREADS
]; ti
++, n
++) {
1008 if (ti
->thread
== 0)
1011 if (ti
== &th_state
[MAX_THREADS
])
1016 ti
->thread
= thread
;
1017 ti
->pid
= kd
[i
].arg1
;
1020 case TRACE_STRING_EXEC
:
1021 if ((ti
= find_thread(thread
, 0)) == (struct th_info
*)0)
1023 /* this is for backwards compatibility */
1024 create_map_entry(thread
, 0, (char *)&kd
[i
].arg1
);
1028 create_map_entry(thread
, ti
->pid
, (char *)&kd
[i
].arg1
);
1029 if (ti
== &th_state
[cur_max
- 1])
1037 kill_thread_map(thread
);
1041 case MACH_stkhandoff
:
1042 mark_thread_waited(thread
);
1046 if ((ti
= find_thread(thread
, 0)) == (struct th_info
*)0)
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
;
1057 sargptr
= ti
->pathptr
;
1060 We don't want to overrun our pathname buffer if the
1061 kernel sends us more VFS_LOOKUP entries than we can
1065 if ((long *)sargptr
>= (long *)&ti
->pathname
[PATHLENGTH
])
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
1075 if (debugid
& DBG_FUNC_START
)
1077 (long *)ti
->pathptr
= (long *)&ti
->pathname
[PATHLENGTH
];
1081 *sargptr
++ = kd
[i
].arg1
;
1082 *sargptr
++ = kd
[i
].arg2
;
1083 *sargptr
++ = kd
[i
].arg3
;
1084 *sargptr
++ = kd
[i
].arg4
;
1085 ti
->pathptr
= sargptr
;
1090 if (debugid
& DBG_FUNC_START
) {
1094 case FILEMGR_PBGETCATALOGINFO
:
1095 p
= "GetCatalogInfo";
1097 case FILEMGR_PBGETCATALOGINFOBULK
:
1098 p
= "GetCatalogInfoBulk";
1100 case FILEMGR_PBCREATEFILEUNICODE
:
1101 p
= "CreateFileUnicode";
1103 case FILEMGR_PBCREATEDIRECTORYUNICODE
:
1104 p
= "CreateDirectoryUnicode";
1106 case FILEMGR_PBCREATEFORK
:
1109 case FILEMGR_PBDELETEFORK
:
1112 case FILEMGR_PBITERATEFORK
:
1113 p
= "PBIterateFork";
1115 case FILEMGR_PBOPENFORK
:
1118 case FILEMGR_PBREADFORK
:
1121 case FILEMGR_PBWRITEFORK
:
1124 case FILEMGR_PBALLOCATEFORK
:
1125 p
= "PBAllocateFork";
1127 case FILEMGR_PBDELETEOBJECT
:
1128 p
= "PBDeleteObject";
1130 case FILEMGR_PBEXCHANGEOBJECT
:
1131 p
= "PBExchangeObject";
1133 case FILEMGR_PBGETFORKCBINFO
:
1134 p
= "PBGetForkCBInfo";
1136 case FILEMGR_PBGETVOLUMEINFO
:
1137 p
= "PBGetVolumeInfo";
1139 case FILEMGR_PBMAKEFSREF
:
1142 case FILEMGR_PBMAKEFSREFUNICODE
:
1143 p
= "PBMakeFSRefUnicode";
1145 case FILEMGR_PBMOVEOBJECT
:
1148 case FILEMGR_PBOPENITERATOR
:
1149 p
= "PBOpenIterator";
1151 case FILEMGR_PBRENAMEUNICODE
:
1152 p
= "PBRenameUnicode";
1154 case FILEMGR_PBSETCATALOGINFO
:
1155 p
= "SetCatalogInfo";
1157 case FILEMGR_PBSETVOLUMEINFO
:
1158 p
= "SetVolumeInfo";
1160 case FILEMGR_FSREFMAKEPATH
:
1161 p
= "FSRefMakePath";
1163 case FILEMGR_FSPATHMAKEREF
:
1164 p
= "FSPathMakeRef";
1167 case FILEMGR_PBGETCATINFO
:
1170 case FILEMGR_PBGETCATINFOLITE
:
1171 p
= "GetCatInfoLite";
1173 case FILEMGR_PBHGETFINFO
:
1176 case FILEMGR_PBXGETVOLINFO
:
1177 p
= "PBXGetVolInfo";
1179 case FILEMGR_PBHCREATE
:
1182 case FILEMGR_PBHOPENDF
:
1185 case FILEMGR_PBHOPENRF
:
1188 case FILEMGR_PBHGETDIRACCESS
:
1189 p
= "PBHGetDirAccess";
1191 case FILEMGR_PBHSETDIRACCESS
:
1192 p
= "PBHSetDirAccess";
1194 case FILEMGR_PBHMAPID
:
1197 case FILEMGR_PBHMAPNAME
:
1200 case FILEMGR_PBCLOSE
:
1203 case FILEMGR_PBFLUSHFILE
:
1206 case FILEMGR_PBGETEOF
:
1209 case FILEMGR_PBSETEOF
:
1212 case FILEMGR_PBGETFPOS
:
1215 case FILEMGR_PBREAD
:
1218 case FILEMGR_PBWRITE
:
1221 case FILEMGR_PBGETFCBINFO
:
1224 case FILEMGR_PBSETFINFO
:
1227 case FILEMGR_PBALLOCATE
:
1230 case FILEMGR_PBALLOCCONTIG
:
1231 p
= "PBAllocContig";
1233 case FILEMGR_PBSETFPOS
:
1236 case FILEMGR_PBSETCATINFO
:
1239 case FILEMGR_PBGETVOLPARMS
:
1240 p
= "PBGetVolParms";
1242 case FILEMGR_PBSETVINFO
:
1245 case FILEMGR_PBMAKEFSSPEC
:
1248 case FILEMGR_PBHGETVINFO
:
1251 case FILEMGR_PBCREATEFILEIDREF
:
1252 p
= "PBCreateFileIDRef";
1254 case FILEMGR_PBDELETEFILEIDREF
:
1255 p
= "PBDeleteFileIDRef";
1257 case FILEMGR_PBRESOLVEFILEIDREF
:
1258 p
= "PBResolveFileIDRef";
1260 case FILEMGR_PBFLUSHVOL
:
1263 case FILEMGR_PBHRENAME
:
1266 case FILEMGR_PBCATMOVE
:
1269 case FILEMGR_PBEXCHANGEFILES
:
1270 p
= "PBExchangeFiles";
1272 case FILEMGR_PBHDELETE
:
1275 case FILEMGR_PBDIRCREATE
:
1278 case FILEMGR_PBCATSEARCH
:
1281 case FILEMGR_PBHSETFLOCK
:
1284 case FILEMGR_PBHRSTFLOCK
:
1287 case FILEMGR_PBLOCKRANGE
:
1290 case FILEMGR_PBUNLOCKRANGE
:
1291 p
= "PBUnlockRange";
1297 enter_syscall(thread
, type
, &kd
[i
], p
, (double)now
);
1304 exit_syscall("PAGE_OUT_D", thread
, type
, 0, kd
[i
].arg1
, 0, 4, (double)now
);
1306 exit_syscall("PAGE_OUT_V", thread
, type
, 0, kd
[i
].arg1
, 0, 4, (double)now
);
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
);
1315 if ((ti
= find_thread(thread
, type
))) {
1316 if (ti
== &th_state
[cur_max
- 1])
1324 exit_syscall("map_fd", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1328 exit_syscall("mmap", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1332 exit_syscall("recvmsg", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1336 exit_syscall("sendmsg", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1340 exit_syscall("recvfrom", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1344 exit_syscall("accept", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 2, 0, (double)now
);
1348 exit_syscall("select", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 8, (double)now
);
1352 exit_syscall("socket", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 2, 0, (double)now
);
1356 exit_syscall("connect", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1360 exit_syscall("bind", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1364 exit_syscall("listen", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1368 exit_syscall("sendto", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1371 case BSC_socketpair
:
1372 exit_syscall("socketpair", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1376 exit_syscall("stat", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1379 case BSC_load_shared_file
:
1380 exit_syscall("load_sf", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1384 exit_syscall("open", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 2, 0, (double)now
);
1388 exit_syscall("dup", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 2, 0, (double)now
);
1392 exit_syscall("dup2", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 2, 0, (double)now
);
1396 exit_syscall("close", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1400 exit_syscall("read", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1404 exit_syscall("write", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1408 exit_syscall("fstat", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1412 exit_syscall("lstat", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1416 exit_syscall("link", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1420 exit_syscall("unlink", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1424 exit_syscall("mknod", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1428 exit_syscall("chmod", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1432 exit_syscall("chown", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1436 exit_syscall("access", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1440 exit_syscall("chdir", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1444 exit_syscall("chroot", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1448 exit_syscall("utimes", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1452 exit_syscall("delete", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1456 exit_syscall("undelete", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1460 exit_syscall("revoke", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1464 exit_syscall("fsctl", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1468 exit_syscall("chflags", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1472 exit_syscall("fchflags", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1476 exit_syscall("fchdir", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1480 exit_syscall("futimes", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1484 exit_syscall("sync", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1488 exit_syscall("symlink", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1492 exit_syscall("readlink", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1496 exit_syscall("fsync", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1500 exit_syscall("readv", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1504 exit_syscall("writev", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1508 exit_syscall("fchown", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1512 exit_syscall("fchmod", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1516 exit_syscall("mkdir", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1520 exit_syscall("mkfifo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1524 exit_syscall("rmdir", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1528 exit_syscall("statfs", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1532 exit_syscall("fstatfs", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1536 exit_syscall("pathconf", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1540 exit_syscall("fpathconf", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1543 case BSC_getdirentries
:
1544 exit_syscall("getdirentries", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1548 exit_syscall("lseek", thread
, type
, kd
[i
].arg1
, kd
[i
].arg3
, 1, 5, (double)now
);
1552 exit_syscall("truncate", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1556 exit_syscall("ftruncate", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 3, (double)now
);
1560 exit_syscall("statv", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1564 exit_syscall("lstatv", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1568 exit_syscall("fstatv", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1572 exit_syscall("mkcomplex", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1575 case BSC_getattrlist
:
1576 exit_syscall("getattrlist", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1579 case BSC_setattrlist
:
1580 exit_syscall("setattrlist", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1583 case BSC_getdirentriesattr
:
1584 exit_syscall("getdirentriesattr", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 1, (double)now
);
1588 case BSC_exchangedata
:
1589 exit_syscall("exchangedata", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1593 exit_syscall("rename", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1597 exit_syscall("copyfile", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1601 case BSC_checkuseraccess
:
1602 exit_syscall("checkuseraccess", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1606 exit_syscall("searchfs", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1609 case FILEMGR_PBGETCATALOGINFO
:
1610 exit_syscall("GetCatalogInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1612 case FILEMGR_PBGETCATALOGINFOBULK
:
1613 exit_syscall("GetCatalogInfoBulk", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1615 case FILEMGR_PBCREATEFILEUNICODE
:
1616 exit_syscall("CreateFileUnicode", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1618 case FILEMGR_PBCREATEDIRECTORYUNICODE
:
1619 exit_syscall("CreateDirectoryUnicode", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1621 case FILEMGR_PBCREATEFORK
:
1622 exit_syscall("PBCreateFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1624 case FILEMGR_PBDELETEFORK
:
1625 exit_syscall("PBDeleteFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1627 case FILEMGR_PBITERATEFORK
:
1628 exit_syscall("PBIterateFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1630 case FILEMGR_PBOPENFORK
:
1631 exit_syscall("PBOpenFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1633 case FILEMGR_PBREADFORK
:
1634 exit_syscall("PBReadFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1636 case FILEMGR_PBWRITEFORK
:
1637 exit_syscall("PBWriteFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1639 case FILEMGR_PBALLOCATEFORK
:
1640 exit_syscall("PBAllocateFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1642 case FILEMGR_PBDELETEOBJECT
:
1643 exit_syscall("PBDeleteObject", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1645 case FILEMGR_PBEXCHANGEOBJECT
:
1646 exit_syscall("PBExchangeObject", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1648 case FILEMGR_PBGETFORKCBINFO
:
1649 exit_syscall("PBGetForkCBInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1651 case FILEMGR_PBGETVOLUMEINFO
:
1652 exit_syscall("PBGetVolumeInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1654 case FILEMGR_PBMAKEFSREF
:
1655 exit_syscall("PBMakeFSRef", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1657 case FILEMGR_PBMAKEFSREFUNICODE
:
1658 exit_syscall("PBMakeFSRefUnicode", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1660 case FILEMGR_PBMOVEOBJECT
:
1661 exit_syscall("PBMoveObject", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1663 case FILEMGR_PBOPENITERATOR
:
1664 exit_syscall("PBOpenIterator", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1666 case FILEMGR_PBRENAMEUNICODE
:
1667 exit_syscall("PBRenameUnicode", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1669 case FILEMGR_PBSETCATALOGINFO
:
1670 exit_syscall("PBSetCatalogInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1672 case FILEMGR_PBSETVOLUMEINFO
:
1673 exit_syscall("PBSetVolumeInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1675 case FILEMGR_FSREFMAKEPATH
:
1676 exit_syscall("FSRefMakePath", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1678 case FILEMGR_FSPATHMAKEREF
:
1679 exit_syscall("FSPathMakeRef", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1681 case FILEMGR_PBGETCATINFO
:
1682 exit_syscall("GetCatInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1684 case FILEMGR_PBGETCATINFOLITE
:
1685 exit_syscall("GetCatInfoLite", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1687 case FILEMGR_PBHGETFINFO
:
1688 exit_syscall("PBHGetFInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1690 case FILEMGR_PBXGETVOLINFO
:
1691 exit_syscall("PBXGetVolInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1693 case FILEMGR_PBHCREATE
:
1694 exit_syscall("PBHCreate", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1696 case FILEMGR_PBHOPENDF
:
1697 exit_syscall("PBHOpenDF", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1699 case FILEMGR_PBHOPENRF
:
1700 exit_syscall("PBHOpenRF", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1702 case FILEMGR_PBHGETDIRACCESS
:
1703 exit_syscall("PBHGetDirAccess", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1705 case FILEMGR_PBHSETDIRACCESS
:
1706 exit_syscall("PBHSetDirAccess", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1708 case FILEMGR_PBHMAPID
:
1709 exit_syscall("PBHMapID", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1711 case FILEMGR_PBHMAPNAME
:
1712 exit_syscall("PBHMapName", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1714 case FILEMGR_PBCLOSE
:
1715 exit_syscall("PBClose", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1717 case FILEMGR_PBFLUSHFILE
:
1718 exit_syscall("PBFlushFile", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1720 case FILEMGR_PBGETEOF
:
1721 exit_syscall("PBGetEOF", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1723 case FILEMGR_PBSETEOF
:
1724 exit_syscall("PBSetEOF", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1726 case FILEMGR_PBGETFPOS
:
1727 exit_syscall("PBGetFPos", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1729 case FILEMGR_PBREAD
:
1730 exit_syscall("PBRead", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1732 case FILEMGR_PBWRITE
:
1733 exit_syscall("PBWrite", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1735 case FILEMGR_PBGETFCBINFO
:
1736 exit_syscall("PBGetFCBInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1738 case FILEMGR_PBSETFINFO
:
1739 exit_syscall("PBSetFInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1741 case FILEMGR_PBALLOCATE
:
1742 exit_syscall("PBAllocate", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1744 case FILEMGR_PBALLOCCONTIG
:
1745 exit_syscall("PBAllocContig", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1747 case FILEMGR_PBSETFPOS
:
1748 exit_syscall("PBSetFPos", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1750 case FILEMGR_PBSETCATINFO
:
1751 exit_syscall("PBSetCatInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1753 case FILEMGR_PBGETVOLPARMS
:
1754 exit_syscall("PBGetVolParms", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1756 case FILEMGR_PBSETVINFO
:
1757 exit_syscall("PBSetVInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1759 case FILEMGR_PBMAKEFSSPEC
:
1760 exit_syscall("PBMakeFSSpec", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1762 case FILEMGR_PBHGETVINFO
:
1763 exit_syscall("PBHGetVInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1765 case FILEMGR_PBCREATEFILEIDREF
:
1766 exit_syscall("PBCreateFileIDRef", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1768 case FILEMGR_PBDELETEFILEIDREF
:
1769 exit_syscall("PBDeleteFileIDRef", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1771 case FILEMGR_PBRESOLVEFILEIDREF
:
1772 exit_syscall("PBResolveFileIDRef", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1774 case FILEMGR_PBFLUSHVOL
:
1775 exit_syscall("PBFlushVol", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1777 case FILEMGR_PBHRENAME
:
1778 exit_syscall("PBHRename", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1780 case FILEMGR_PBCATMOVE
:
1781 exit_syscall("PBCatMove", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1783 case FILEMGR_PBEXCHANGEFILES
:
1784 exit_syscall("PBExchangeFiles", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1786 case FILEMGR_PBHDELETE
:
1787 exit_syscall("PBHDelete", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1789 case FILEMGR_PBDIRCREATE
:
1790 exit_syscall("PBDirCreate", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1792 case FILEMGR_PBCATSEARCH
:
1793 exit_syscall("PBCatSearch", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1795 case FILEMGR_PBHSETFLOCK
:
1796 exit_syscall("PBHSetFLock", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1798 case FILEMGR_PBHRSTFLOCK
:
1799 exit_syscall("PBHRstFLock", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1801 case FILEMGR_PBLOCKRANGE
:
1802 exit_syscall("PBLockRange", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1804 case FILEMGR_PBUNLOCKRANGE
:
1805 exit_syscall("PBUnlockRange", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1815 enter_syscall(int thread
, int type
, kd_buf
*kd
, char *name
, double now
)
1824 kd_threadmap
*find_thread_map();
1847 case BSC_socketpair
:
1849 case BSC_load_shared_file
:
1892 case BSC_getdirentries
:
1900 case BSC_getattrlist
:
1901 case BSC_setattrlist
:
1902 case BSC_getdirentriesattr
:
1903 case BSC_exchangedata
:
1904 case BSC_checkuseraccess
:
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
:
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
:
1975 for (i
= 0, ti
= th_state
; ti
< &th_state
[MAX_THREADS
]; ti
++, i
++) {
1976 if (ti
->thread
== 0)
1979 if (ti
== &th_state
[MAX_THREADS
])
1985 if ((type
>> 24) == FILEMGR_CLASS
) {
1988 l_usecs
= (long long)(now
/ divisor
);
1989 secs
= l_usecs
/ 1000000;
1990 curr_time
= bias_secs
+ secs
;
1992 sprintf(buf
, "%-8.8s", &(ctime(&curr_time
)[11]));
1993 tsclen
= strlen(buf
);
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
);
2001 /* Print timestamp column */
2004 map
= find_thread_map(thread
);
2006 sprintf(buf
, " %-25.25s ", name
);
2007 nmclen
= strlen(buf
);
2010 sprintf(buf
, "(%d, 0x%x, 0x%x, 0x%x)", (short)kd
->arg1
, kd
->arg2
, kd
->arg3
, kd
->arg4
);
2011 argsclen
= strlen(buf
);
2014 Calculate white space out to command
2016 if (columns
> MAXCOLS
|| wideflag
)
2018 clen
= columns
- (tsclen
+ nmclen
+ argsclen
+ 20);
2021 clen
= columns
- (tsclen
+ nmclen
+ argsclen
+ 12);
2025 printf(buf
); /* print the kdargs */
2026 memset(buf
, ' ', clen
);
2030 else if ((argsclen
+ clen
) > 0)
2032 /* no room so wipe out the kdargs */
2033 memset(buf
, ' ', (argsclen
+ clen
));
2034 buf
[argsclen
+ clen
] = '\0';
2038 if (columns
> MAXCOLS
|| wideflag
)
2039 printf("%-20.20s\n", map
->command
);
2041 printf("%-12.12s\n", map
->command
);
2043 printf(" %-24.24s (%5d, %#x, 0x%x, 0x%x)\n", name
, (short)kd
->arg1
, kd
->arg2
, kd
->arg3
, kd
->arg4
);
2047 ti
->thread
= thread
;
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;
2067 exit_syscall(char *sc_name
, int thread
, int type
, int error
, int retval
,
2068 int has_fd
, int has_ret
, double now
)
2072 if ((ti
= find_thread(thread
, type
)) == (struct th_info
*)0)
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
);
2078 if (ti
== &th_state
[cur_max
- 1])
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
)
2096 kd_threadmap
*find_thread_map();
2099 char *framework_name
;
2105 command_name
= dio
->issuing_command
;
2107 if ((map
= find_thread_map(thread
)))
2108 command_name
= map
->command
;
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]));
2117 if (columns
> MAXCOLS
|| wideflag
) {
2119 usecs
= l_usecs
- (long long)((long long)secs
* 1000000);
2120 sprintf(&buf
[clen
], ".%03ld", (long)usecs
/ 1000);
2123 if ((type
>> 24) != FILEMGR_CLASS
) {
2124 if (find_thread(thread
, -1)) {
2125 sprintf(&buf
[clen
], " ");
2133 if (((type
>> 24) == FILEMGR_CLASS
) && (columns
> MAXCOLS
|| wideflag
))
2134 sprintf(&buf
[clen
], " %-18.18s", sc_name
);
2136 sprintf(&buf
[clen
], " %-15.15s", sc_name
);
2140 framework_name
= (char *)0;
2142 if (columns
> MAXCOLS
|| wideflag
) {
2144 sprintf(&buf
[clen
], " D=0x%8.8x", dio
->blkno
);
2149 sprintf(&buf
[clen
], " [%3d] ", dio
->io_errno
);
2151 sprintf(&buf
[clen
], " B=0x%-6x /dev/%s", dio
->iosize
, find_disk_name(dio
->dev
));
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
], " ");
2163 if (has_ret
== 2 || has_ret
== 6)
2164 framework_name
= lookup_name(retval
);
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
);
2183 sprintf(&buf
[clen
], " ");
2190 Calculate space available to print pathname
2192 if (columns
> MAXCOLS
|| wideflag
)
2193 clen
= columns
- (clen
+ 13 + 20);
2195 clen
= columns
- (clen
+ 13 + 12);
2197 if ((type
>> 24) != FILEMGR_CLASS
&& !nopadding
)
2201 sprintf(&buf
[0], " %s ", framework_name
);
2203 sprintf(&buf
[0], " %s ", pathname
);
2209 Add null padding if column length
2210 is wider than the pathname length.
2212 memset(&buf
[len
], ' ', clen
- len
);
2216 else if (clen
== len
)
2220 else if ((clen
> 0) && (clen
< len
))
2222 /* This prints the tail end of the pathname */
2223 buf
[len
-clen
] = ' ';
2224 printf(&buf
[len
- clen
]);
2227 usecs
= (unsigned long)((now
- stime
) / divisor
);
2228 secs
= usecs
/ 1000000;
2229 usecs
-= secs
* 1000000;
2231 if ((type
>> 24) != FILEMGR_CLASS
&& !nopadding
)
2234 printf(" %2ld.%06ld", (unsigned long)secs
, (unsigned long)usecs
);
2241 if (columns
> MAXCOLS
|| wideflag
)
2242 printf(" %-20.20s", command_name
);
2244 printf(" %-12.12s", command_name
);
2258 This flag is turned off when calling
2259 quit() due to a set_remove() failure.
2261 if (set_remove_flag
)
2264 printf("fs_usage: ");
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
;
2281 extern void MKGetTimeBaseInfo(unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *);
2283 MKGetTimeBaseInfo (&delta
, &abs_to_ns_num
, &abs_to_ns_denom
,
2284 &proc_to_abs_num
, &proc_to_abs_denom
);
2286 divisor
= ((double)abs_to_ns_denom
/ (double)abs_to_ns_num
) * 1000;
2290 void read_command_map()
2294 int prev_total_threads
;
2302 prev_total_threads
= total_threads
;
2303 total_threads
= bufinfo
.nkdthreads
;
2304 size
= bufinfo
.nkdthreads
* sizeof(kd_threadmap
);
2308 if ((mapptr
= (kd_threadmap
*) malloc(size
)))
2310 bzero (mapptr
, size
);
2312 /* Now read the threadmap */
2314 mib
[1] = KERN_KDEBUG
;
2315 mib
[2] = KERN_KDTHRMAP
;
2318 mib
[5] = 0; /* no flags */
2319 if (sysctl(mib
, 3, mapptr
, &size
, NULL
, 0) < 0)
2321 /* This is not fatal -- just means I cant map command strings */
2328 if (mapptr
&& (filter_mode
!= DEFAULT_DO_NOT_FILTER
))
2332 /* We accept the fact that we lose file descriptor state if the
2334 for (i
= 0; i
< prev_total_threads
; i
++)
2336 if (fdmapptr
[i
].fd_setptr
)
2337 free (fdmapptr
[i
].fd_setptr
);
2343 size
= total_threads
* sizeof(fd_threadmap
);
2344 if ((fdmapptr
= (fd_threadmap
*) malloc(size
)))
2346 bzero (fdmapptr
, size
);
2347 /* reinitialize file descriptor state map */
2348 for (i
= 0; i
< total_threads
; i
++)
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;
2358 /* Resolve any LaunchCFMApp command names */
2359 if (mapptr
&& arguments
)
2361 for (i
=0; i
< total_threads
; i
++)
2365 pid
= mapptr
[i
].valid
;
2367 if (pid
== 0 || pid
== 1)
2369 else if (!strncmp(mapptr
[i
].command
,"LaunchCFMA", 10))
2371 (void)get_real_command_name(pid
, mapptr
[i
].command
, sizeof(mapptr
[i
].command
));
2378 void create_map_entry(int thread
, int pid
, char *command
)
2382 fd_threadmap
*fdmap
= 0;
2387 for (i
= 0, map
= 0; !map
&& i
< total_threads
; i
++)
2389 if ((int)mapptr
[i
].thread
== thread
)
2391 map
= &mapptr
[i
]; /* Reuse this entry, the thread has been
2393 if(filter_mode
&& fdmapptr
)
2395 fdmap
= &fdmapptr
[i
];
2396 if (fdmap
->fd_thread
!= thread
) /* This shouldn't happen */
2397 fdmap
= (fd_threadmap
*)0;
2402 if (!map
) /* look for invalid entries that I can reuse*/
2404 for (i
= 0, map
= 0; !map
&& i
< total_threads
; i
++)
2406 if (mapptr
[i
].valid
== 0 )
2407 map
= &mapptr
[i
]; /* Reuse this invalid entry */
2408 if (filter_mode
&& fdmapptr
)
2410 fdmap
= &fdmapptr
[i
];
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.
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
];
2427 if (filter_mode
&& fdmapptr
)
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
];
2438 map
->thread
= thread
;
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.
2444 (void)strncpy (map
->command
, command
, MAXCOMLEN
);
2445 map
->command
[MAXCOMLEN
] = '\0';
2449 fdmap
->fd_valid
= 1;
2450 fdmap
->fd_thread
= thread
;
2451 if (fdmap
->fd_setptr
)
2453 free(fdmap
->fd_setptr
);
2454 fdmap
->fd_setptr
= (unsigned long *)0;
2456 fdmap
->fd_setsize
= 0;
2459 if (pid
== 0 || pid
== 1)
2461 else if (!strncmp(map
->command
, "LaunchCFMA", 10))
2462 (void)get_real_command_name(pid
, map
->command
, sizeof(map
->command
));
2466 kd_threadmap
*find_thread_map(int thread
)
2472 return((kd_threadmap
*)0);
2474 for (i
= 0; i
< total_threads
; i
++)
2477 if (map
->valid
&& ((int)map
->thread
== thread
))
2482 return ((kd_threadmap
*)0);
2485 fd_threadmap
*find_fd_thread_map(int thread
)
2488 fd_threadmap
*fdmap
= 0;
2491 return((fd_threadmap
*)0);
2493 for (i
= 0; i
< total_threads
; i
++)
2495 fdmap
= &fdmapptr
[i
];
2496 if (fdmap
->fd_valid
&& ((int)fdmap
->fd_thread
== thread
))
2501 return ((fd_threadmap
*)0);
2506 kill_thread_map(int thread
)
2509 fd_threadmap
*fdmap
;
2511 if ((map
= find_thread_map(thread
))) {
2514 map
->command
[0] = '\0';
2519 if ((fdmap
= find_fd_thread_map(thread
)))
2521 fdmap
->fd_valid
= 0;
2522 fdmap
->fd_thread
= 0;
2523 if (fdmap
->fd_setptr
)
2525 free (fdmap
->fd_setptr
);
2526 fdmap
->fd_setptr
= (unsigned long *)0;
2528 fdmap
->fd_setsize
= 0;
2541 ret
= (int)strtol(str
, &cp
, 10);
2542 if (cp
== str
|| *cp
) {
2543 /* Assume this is a command string and find matching pids */
2547 for (i
=0; i
< kp_nentries
&& num_of_pids
< (MAX_PIDS
- 1); i
++) {
2548 if(kp_buffer
[i
].kp_proc
.p_stat
== 0)
2551 if(!strcmp(str
, kp_buffer
[i
].kp_proc
.p_comm
))
2552 pids
[num_of_pids
++] = kp_buffer
[i
].kp_proc
.p_pid
;
2556 else if (num_of_pids
< (MAX_PIDS
- 1))
2557 pids
[num_of_pids
++] = ret
;
2564 char *lookup_name(unsigned long addr
)
2567 register int start
, last
;
2570 if (numFrameworks
== 0 || addr
< frameworkInfo
[0].address
|| addr
> frameworkInfo
[numFrameworks
].address
)
2574 last
= numFrameworks
;
2576 for (i
= numFrameworks
/ 2; i
>= 0 && i
< numFrameworks
; ) {
2578 if (addr
>= frameworkInfo
[i
].address
&& addr
< frameworkInfo
[i
+1].address
)
2579 return(frameworkInfo
[i
].name
);
2581 if (addr
>= frameworkInfo
[i
].address
) {
2583 i
= start
+ ((last
- i
) / 2);
2586 i
= start
+ ((i
- start
) / 2);
2594 * Comparison routines for sorting
2596 static int compareFrameworkAddress(const void *aa
, const void *bb
)
2598 LibraryInfo
*a
= (LibraryInfo
*)aa
;
2599 LibraryInfo
*b
= (LibraryInfo
*)bb
;
2601 if (a
->address
< b
->address
) return -1;
2602 if (a
->address
== b
->address
) return 0;
2607 int scanline(char *inputstring
,char **argv
)
2610 char **ap
= argv
, *p
, *val
;
2612 for (p
= inputstring
; p
!= NULL
; )
2614 while ((val
= strsep(&p
, " \t")) != NULL
&& *val
== '\0');
2623 int ReadSegAddrTable()
2628 unsigned long frameworkAddress
, frameworkDataAddress
, previousFrameworkAddress
;
2629 char frameworkName
[256];
2632 char *substring
,*ptr
;
2636 bzero(buf
, sizeof(buf
));
2637 bzero(tokens
, sizeof(tokens
));
2641 if ((fd
= fopen(seg_addr_table
, "r")) == 0)
2645 fgets(buf
, 1023, fd
);
2650 frameworkName
[0] = 0;
2651 previousFrameworkAddress
= 0;
2653 while (fgets(buf
, 1023, fd
) && numFrameworks
< (MAXINDEX
- 2))
2658 buf
[strlen(buf
)-1] = 0;
2660 if (strncmp(buf
, "# dyld:", 7) == 0) {
2662 * the next line in the file will contain info about dyld
2668 * This is a split library line: parse it into 3 tokens
2670 ntokens
= scanline(buf
, tokens
);
2675 frameworkAddress
= strtoul(tokens
[0], 0, 16);
2676 frameworkDataAddress
= strtoul(tokens
[1], 0, 16);
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
2684 frameworkInfo
[numFrameworks
].address
= frameworkAddress
;
2685 frameworkInfo
[numFrameworks
+1].address
= frameworkAddress
+ frameworkDataAddress
;
2687 frameworkInfo
[numFrameworks
].name
= (char *)"dylib";
2688 frameworkInfo
[numFrameworks
+1].name
= (char *)0;
2697 * Make sure that we have 2 addresses and a path
2699 if (!frameworkAddress
)
2701 if (!frameworkDataAddress
)
2703 if (*tokens
[2] != '/')
2705 if (frameworkAddress
== previousFrameworkAddress
)
2707 previousFrameworkAddress
= frameworkAddress
;
2710 * Extract lib name from path name
2712 if ((substring
= strrchr(tokens
[2], '.')))
2715 * There is a ".": name is whatever is between the "/" around the "."
2717 while ( *substring
!= '/') { /* find "/" before "." */
2721 strcpy(frameworkName
, substring
); /* copy path from "/" */
2722 substring
= frameworkName
;
2724 while ( *substring
!= '/' && *substring
) /* find "/" after "." and stop string there */
2731 * No ".": take segment after last "/"
2739 substring
= ptr
+ 1;
2742 strcpy(frameworkName
, substring
);
2744 frameworkInfo
[numFrameworks
].address
= frameworkAddress
;
2745 frameworkInfo
[numFrameworks
+1].address
= frameworkDataAddress
;
2747 frameworkInfo
[numFrameworks
].name
= (char *)malloc(strlen(frameworkName
) + 1);
2748 strcpy(frameworkInfo
[numFrameworks
].name
, frameworkName
);
2749 frameworkInfo
[numFrameworks
+1].name
= frameworkInfo
[numFrameworks
].name
;
2754 frameworkInfo
[numFrameworks
].address
= frameworkInfo
[numFrameworks
- 1].address
+ 0x800000;
2755 frameworkInfo
[numFrameworks
].name
= (char *)0;
2759 qsort(frameworkInfo
, numFrameworks
, sizeof(LibraryInfo
), compareFrameworkAddress
);
2765 struct diskio
*insert_diskio(int type
, int bp
, int dev
, int blkno
, int io_size
, int thread
, double curtime
)
2767 register struct diskio
*dio
;
2768 register kd_threadmap
*map
;
2770 if ((dio
= free_diskios
))
2771 free_diskios
= dio
->next
;
2773 if ((dio
= (struct diskio
*)malloc(sizeof(struct diskio
))) == NULL
)
2782 dio
->iosize
= io_size
;
2783 dio
->issued_time
= curtime
;
2784 dio
->issuing_thread
= thread
;
2786 if ((map
= find_thread_map(thread
)))
2788 strncpy(dio
->issuing_command
, map
->command
, MAXCOMLEN
);
2789 dio
->issuing_command
[MAXCOMLEN
-1] = '\0';
2792 strcpy(dio
->issuing_command
, "");
2794 dio
->next
= busy_diskios
;
2796 dio
->next
->prev
= dio
;
2803 struct diskio
*complete_diskio(int bp
, int io_errno
, int resid
, int thread
, double curtime
)
2805 register struct diskio
*dio
;
2807 for (dio
= busy_diskios
; dio
; dio
= dio
->next
) {
2808 if (dio
->bp
== bp
) {
2810 if (dio
== busy_diskios
) {
2811 if ((busy_diskios
= dio
->next
))
2812 dio
->next
->prev
= NULL
;
2815 dio
->next
->prev
= dio
->prev
;
2816 dio
->prev
->next
= dio
->next
;
2818 dio
->iosize
-= resid
;
2819 dio
->io_errno
= io_errno
;
2820 dio
->completed_time
= curtime
;
2821 dio
->completion_thread
= thread
;
2826 return ((struct diskio
*)0);
2830 void free_diskio(struct diskio
*dio
)
2832 dio
->next
= free_diskios
;
2837 void print_diskio(struct diskio
*dio
)
2841 switch (dio
->type
) {
2862 p
= " RdMeta[async]";
2865 p
= " WrMeta[async]";
2868 p
= " RdData[async]";
2871 p
= " WrData[async]";
2877 p
= " PgOut[async]";
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
);
2888 void cache_disk_names()
2893 struct diskrec
*dnp
;
2896 if ((dirp
= opendir("/dev")) == NULL
)
2899 while ((dir
= readdir(dirp
)) != NULL
) {
2900 char nbuf
[MAXPATHLEN
];
2902 if (dir
->d_namlen
< 5 || strncmp("disk", dir
->d_name
, 4))
2904 sprintf(nbuf
, "%s/%s", "/dev", dir
->d_name
);
2906 if (stat(nbuf
, &st
) < 0)
2909 if ((dnp
= (struct diskrec
*)malloc(sizeof(struct diskrec
))) == NULL
)
2912 if ((dnp
->diskname
= (char *)malloc(dir
->d_namlen
+ 1)) == NULL
) {
2916 strncpy(dnp
->diskname
, dir
->d_name
, dir
->d_namlen
);
2917 dnp
->diskname
[dir
->d_namlen
] = 0;
2918 dnp
->dev
= st
.st_rdev
;
2920 dnp
->next
= disk_list
;
2923 (void) closedir(dirp
);
2927 char *find_disk_name(int dev
)
2929 struct diskrec
*dnp
;
2934 for (dnp
= disk_list
; dnp
; dnp
= dnp
->next
) {
2935 if (dnp
->dev
== dev
)
2936 return (dnp
->diskname
);
2938 return ("NOTFOUND");
2942 fs_usage_fd_set(thread
, fd
)
2943 unsigned int thread
;
2947 fd_threadmap
*fdmap
;
2949 if(!(fdmap
= find_fd_thread_map(thread
)))
2952 /* If the map is not allocated, then now is the time */
2953 if (fdmap
->fd_setptr
== (unsigned long *)0)
2955 fdmap
->fd_setptr
= (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE
));
2956 if (fdmap
->fd_setptr
)
2958 fdmap
->fd_setsize
= FS_USAGE_FD_SETSIZE
;
2959 bzero(fdmap
->fd_setptr
,(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE
)));
2965 /* If the map is not big enough, then reallocate it */
2966 while (fdmap
->fd_setsize
< fd
)
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
;
2977 fdmap
->fd_setptr
[fd
/FS_USAGE_NFDBITS
] |= (1 << ((fd
) % FS_USAGE_NFDBITS
));
2984 0 : File Descriptor bit is not set
2985 1 : File Descriptor bit is set
2989 fs_usage_fd_isset(thread
, fd
)
2990 unsigned int thread
;
2994 fd_threadmap
*fdmap
;
2996 if(!(fdmap
= find_fd_thread_map(thread
)))
2999 if (fdmap
->fd_setptr
== (unsigned long *)0)
3002 if (fd
< fdmap
->fd_setsize
)
3003 ret
= fdmap
->fd_setptr
[fd
/FS_USAGE_NFDBITS
] & (1 << (fd
% FS_USAGE_NFDBITS
));
3009 fs_usage_fd_clear(thread
, fd
)
3010 unsigned int thread
;
3015 if (!(map
= find_fd_thread_map(thread
)))
3018 if (map
->fd_setptr
== (unsigned long *)0)
3022 if (fd
< map
->fd_setsize
)
3023 map
->fd_setptr
[fd
/FS_USAGE_NFDBITS
] &= ~(1 << (fd
% FS_USAGE_NFDBITS
));
3030 * ret = 1 means print the entry
3031 * ret = 0 means don't print the entry
3034 check_filter_mode(struct th_info
* ti
, int type
, int error
, int retval
)
3037 int network_fd_isset
= 0;
3040 if (filter_mode
== DEFAULT_DO_NOT_FILTER
)
3043 if (ti
== (struct th_info
*)0)
3045 if(filter_mode
& FILESYS_FILTER
)
3056 network_fd_isset
= fs_usage_fd_isset(ti
->thread
, fd
);
3059 fs_usage_fd_clear(ti
->thread
,fd
);
3062 if (network_fd_isset
)
3064 if (filter_mode
& NETWORK_FILTER
)
3067 else if (filter_mode
& FILESYS_FILTER
)
3072 /* we don't care about error in this case */
3074 network_fd_isset
= fs_usage_fd_isset(ti
->thread
, fd
);
3075 if (network_fd_isset
)
3077 if (filter_mode
& NETWORK_FILTER
)
3080 else if (filter_mode
& FILESYS_FILTER
)
3087 fs_usage_fd_set(ti
->thread
, fd
);
3088 if (filter_mode
& NETWORK_FILTER
)
3100 fs_usage_fd_set(ti
->thread
, fd
);
3101 if (filter_mode
& NETWORK_FILTER
)
3105 case BSC_socketpair
:
3106 /* Cannot determine info about file descriptors */
3107 if (filter_mode
& NETWORK_FILTER
)
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
)
3117 /* then we are duping a socket descriptor */
3118 fd
= retval
; /* the new fd */
3119 fs_usage_fd_set(ti
->thread
, fd
);
3124 if (filter_mode
& FILESYS_FILTER
)
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.
3140 init_arguments_buffer()
3147 mib
[1] = KERN_ARGMAX
;
3148 size
= sizeof(argmax
);
3149 if (sysctl(mib
, 2, &argmax
, &size
, NULL
, 0) == -1)
3153 /* Hack to avoid kernel bug. */
3154 if (argmax
> 8192) {
3159 arguments
= (char *)malloc(argmax
);
3166 get_real_command_name(int pid
, char *cbuf
, int csize
)
3169 * Get command and arguments.
3173 char *command_beg
, *command
, *command_end
;
3180 bzero(arguments
, argmax
);
3185 * A sysctl() is made to find out the full path that the command
3189 mib
[1] = KERN_PROCARGS
;
3193 if (sysctl(mib
, 3, arguments
, (size_t *)&argmax
, NULL
, 0) < 0) {
3197 /* Skip the saved exec_path. */
3198 for (cp
= arguments
; cp
< &arguments
[argmax
]; cp
++) {
3200 /* End of exec_path reached. */
3204 if (cp
== &arguments
[argmax
]) {
3208 /* Skip trailing '\0' characters. */
3209 for (; cp
< &arguments
[argmax
]; cp
++) {
3211 /* Beginning of first argument reached. */
3215 if (cp
== &arguments
[argmax
]) {
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..
3225 for (; cp
< &arguments
[argmax
]; cp
++) {
3227 /* End of first argument reached. */
3231 if (cp
== &arguments
[argmax
]) {
3234 command_end
= command
= cp
;
3236 /* Get the basename of command. */
3237 for (command
--; command
>= command_beg
; command
--) {
3238 if (*command
== '/') {
3244 (void) strncpy(cbuf
, (char *)command
, csize
);
3245 cbuf
[csize
-1] = '\0';