2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
27 cc -I. -DKERNEL_PRIVATE -O -o fs_usage fs_usage.c
30 #define Default_DELAY 1 /* default delay interval */
41 #include <sys/types.h>
42 #include <sys/param.h>
47 #include <sys/ioctl.h>
49 #ifndef KERNEL_PRIVATE
50 #define KERNEL_PRIVATE
51 #include <sys/kdebug.h>
54 #include <sys/kdebug.h>
55 #endif /*KERNEL_PRIVATE*/
57 #include <sys/sysctl.h>
59 #import <mach/clock_types.h>
68 typedef struct LibraryInfo
{
69 unsigned long address
;
73 LibraryInfo frameworkInfo
[MAXINDEX
];
74 int numFrameworks
= 0;
76 char seg_addr_table
[256]="/AppleInternal/Developer/seg_addr_table";
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.
88 #define PATHLENGTH (NUMPARMS*sizeof(long))
90 #define MAX_WIDE_MODE_COLS (PATHLENGTH + 80)
105 char pathname
[PATHLENGTH
+ 1]; /* add room for null terminator */
108 #define MAX_THREADS 512
109 struct th_info th_state
[MAX_THREADS
];
113 int need_new_map
= 1;
117 int select_pid_mode
= 0; /* Flag set indicates that output is restricted
118 to selected pids or commands */
120 int one_good_pid
= 0; /* Used to fail gracefully when bad pids given */
126 * Network only or filesystem only output filter
127 * Default of zero means report all activity - no filtering
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
;
138 struct diskrec
*next
;
153 int completion_thread
;
154 char issuing_command
[MAXCOMLEN
];
156 double completed_time
;
159 struct diskrec
*disk_list
= NULL
;
160 struct diskio
*free_diskios
= NULL
;
161 struct diskio
*busy_diskios
= NULL
;
163 struct diskio
*insert_diskio();
164 struct diskio
*complete_diskio();
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 *);
180 #define TRACE_DATA_NEWTHREAD 0x07000004
181 #define TRACE_DATA_EXEC 0x07000008
182 #define TRACE_STRING_NEWTHREAD 0x07010004
183 #define TRACE_STRING_EXEC 0x07010008
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
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
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
219 #define MSC_map_fd 0x010c00ac
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
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
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
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
368 #define FILEMGR_CLASS 0x1e
374 int exclude_pids
= 0;
375 int exclude_default_pids
= 1;
377 struct kinfo_proc
*kp_buffer
= 0;
380 #define SAMPLE_SIZE 60000
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
387 #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END)
388 #define DBG_FUNC_MASK 0xfffffffc
390 double divisor
= 0.0; /* Trace divisor converts to microseconds */
396 kbufinfo_t bufinfo
= {0, 0, 0, 0, 0};
398 int total_threads
= 0;
399 kd_threadmap
*mapptr
= 0; /* pointer to list of threads */
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 */
405 #define FS_USAGE_NFDBITS (sizeof (unsigned long) * 8)
406 #define FS_USAGE_NFDBYTES(n) (((n) / FS_USAGE_NFDBITS) * sizeof (unsigned long))
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 */
415 fd_threadmap
*fdmapptr
= 0; /* pointer to list of threads for fd tracking */
417 int trace_enabled
= 0;
418 int set_remove_flag
= 1;
430 void leave() /* exit under normal conditions -- INT handler */
435 void set_pidexclude();
440 if (exclude_pids
== 0) {
441 for (i
= 0; i
< num_of_pids
; i
++)
442 set_pidcheck(pids
[i
], 0);
445 for (i
= 0; i
< num_of_pids
; i
++)
446 set_pidexclude(pids
[i
], 0);
453 void get_screenwidth()
460 if (ioctl(1, TIOCGWINSZ
, &size
) != -1)
461 columns
= size
.ws_col
;
473 exit_usage(char *myname
) {
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");
496 char *myname
= "fs_usage";
503 void set_pidexclude();
506 if ( geteuid() != 0 ) {
507 fprintf(stderr
, "'fs_usage' must be run as root...\n");
514 if ((myname
= rindex(argv
[0], '/')) == 0) {
523 while ((ch
= getopt(argc
, argv
, "ewf:")) != EOF
) {
527 exclude_default_pids
= 0;
531 if ((uint
)columns
< MAX_WIDE_MODE_COLS
)
532 columns
= MAX_WIDE_MODE_COLS
;
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 */
551 /* If we process any list of pids/cmds, then turn off the defaults */
553 exclude_default_pids
= 0;
555 while (argc
> 0 && num_of_pids
< (MAX_PIDS
- 1)) {
562 /* Exclude a set of default pids */
563 if (exclude_default_pids
)
565 argtopid("Terminal");
578 if (num_of_pids
< (MAX_PIDS
- 1))
579 pids
[num_of_pids
++] = getpid();
585 for (i
= 0; i
< num_of_pids
; i
++)
588 fprintf(stderr
, "exclude pid %d\n", pids
[i
]);
590 fprintf(stderr
, "pid %d\n", pids
[i
]);
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
);
601 if ((my_buffer
= malloc(SAMPLE_SIZE
* sizeof(kd_buf
))) == (char *)0)
602 quit("can't allocate memory for tracing info\n");
608 set_numbufs(SAMPLE_SIZE
);
611 if (exclude_pids
== 0) {
612 for (i
= 0; i
< num_of_pids
; i
++)
613 set_pidcheck(pids
[i
], 1);
615 for (i
= 0; i
< num_of_pids
; i
++)
616 set_pidexclude(pids
[i
], 1);
619 if (select_pid_mode
&& !one_good_pid
)
622 An attempt to restrict output to a given
623 pid or command has failed. Exit gracefully
631 init_arguments_buffer();
647 struct kinfo_proc
*kp
;
652 mib
[2] = KERN_PROC_ALL
;
655 if (sysctl(mib
, 4, NULL
, &bufSize
, NULL
, 0) < 0)
656 quit("trace facility failure, KERN_PROC_ALL\n");
658 if((kp
= (struct kinfo_proc
*)malloc(bufSize
)) == (struct kinfo_proc
*)0)
659 quit("can't allocate memory for proc buffer\n");
661 if (sysctl(mib
, 4, kp
, &bufSize
, NULL
, 0) < 0)
662 quit("trace facility failure, KERN_PROC_ALL\n");
664 kp_nentries
= bufSize
/ sizeof(struct kinfo_proc
);
669 struct th_info
*find_thread(int thread
, int type
) {
672 for (ti
= th_state
; ti
< &th_state
[cur_max
]; ti
++) {
673 if (ti
->thread
== thread
) {
674 if (type
== ti
->type
)
676 if (ti
->in_filemgr
) {
685 return ((struct th_info
*)0);
690 mark_thread_waited(int thread
) {
693 for (ti
= th_state
; ti
< &th_state
[cur_max
]; ti
++) {
694 if (ti
->thread
== thread
) {
705 mib
[1] = KERN_KDEBUG
;
706 mib
[2] = KERN_KDENABLE
; /* protocol */
709 mib
[5] = 0; /* no flags */
710 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
711 quit("trace facility failure, KERN_KDENABLE\n");
720 set_numbufs(int nbufs
)
723 mib
[1] = KERN_KDEBUG
;
724 mib
[2] = KERN_KDSETBUF
;
727 mib
[5] = 0; /* no flags */
728 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
729 quit("trace facility failure, KERN_KDSETBUF\n");
732 mib
[1] = KERN_KDEBUG
;
733 mib
[2] = KERN_KDSETUP
;
736 mib
[5] = 0; /* no flags */
737 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
738 quit("trace facility failure, KERN_KDSETUP\n");
742 set_pidcheck(int pid
, int on_off
)
746 kr
.type
= KDBG_TYPENONE
;
749 needed
= sizeof(kd_regtype
);
751 mib
[1] = KERN_KDEBUG
;
752 mib
[2] = KERN_KDPIDTR
;
757 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0) {
759 fprintf(stderr
, "pid %d does not exist\n", pid
);
767 on_off == 0 turns off pid exclusion
768 on_off == 1 turns on pid exclusion
771 set_pidexclude(int pid
, int on_off
)
777 kr
.type
= KDBG_TYPENONE
;
780 needed
= sizeof(kd_regtype
);
782 mib
[1] = KERN_KDEBUG
;
783 mib
[2] = KERN_KDPIDEX
;
788 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0) {
790 fprintf(stderr
, "pid %d does not exist\n", pid
);
795 get_bufinfo(kbufinfo_t
*val
)
797 needed
= sizeof (*val
);
799 mib
[1] = KERN_KDEBUG
;
800 mib
[2] = KERN_KDGETBUF
;
803 mib
[5] = 0; /* no flags */
805 if (sysctl(mib
, 3, val
, &needed
, 0, 0) < 0)
806 quit("trace facility failure, KERN_KDGETBUF\n");
816 mib
[1] = KERN_KDEBUG
;
817 mib
[2] = KERN_KDREMOVE
; /* protocol */
820 mib
[5] = 0; /* no flags */
821 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
826 quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n");
828 quit("trace facility failure, KERN_KDREMOVE\n");
836 kr
.type
= KDBG_RANGETYPE
;
839 needed
= sizeof(kd_regtype
);
841 mib
[1] = KERN_KDEBUG
;
842 mib
[2] = KERN_KDSETREG
;
845 mib
[5] = 0; /* no flags */
847 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0)
848 quit("trace facility failure, KERN_KDSETREG\n");
851 mib
[1] = KERN_KDEBUG
;
852 mib
[2] = KERN_KDSETUP
;
855 mib
[5] = 0; /* no flags */
857 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
858 quit("trace facility failure, KERN_KDSETUP\n");
867 void read_command_map();
868 void create_map_entry();
870 /* Get kernel buffer information */
871 get_bufinfo(&bufinfo
);
877 needed
= bufinfo
.nkdbufs
* sizeof(kd_buf
);
879 mib
[1] = KERN_KDEBUG
;
880 mib
[2] = KERN_KDREADTR
;
883 mib
[5] = 0; /* no flags */
885 if (sysctl(mib
, 3, my_buffer
, &needed
, NULL
, 0) < 0)
886 quit("trace facility failure, KERN_KDREADTR\n");
889 if (bufinfo
.flags
& KDBG_WRAPPED
) {
890 fprintf(stderr
, "buffer wrapped count = %d\n", count
);
892 for (i
= 0; i
< cur_max
; i
++) {
893 th_state
[i
].thread
= 0;
895 th_state
[i
].pathptr
= (long *)0;
896 th_state
[i
].pathname
[0] = 0;
904 kd
= (kd_buf
*)my_buffer
;
906 fprintf(stderr
, "READTR returned %d items\n", count
);
908 for (i
= 0; i
< count
; i
++) {
918 void enter_syscall();
920 void extend_syscall();
921 void kill_thread_map();
924 debugid
= kd
[i
].debugid
;
925 type
= kd
[i
].debugid
& DBG_FUNC_MASK
;
927 now
= kd
[i
].timestamp
& KDBG_TIMESTAMP_MASK
;
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.
936 l_usecs
= (long long)(now
/ divisor
);
937 secs
= l_usecs
/ 1000000;
938 curr_time
= time((long *)0);
939 bias_secs
= curr_time
- secs
;
957 insert_diskio(type
, kd
[i
].arg1
, kd
[i
].arg2
, kd
[i
].arg3
, kd
[i
].arg4
, thread
, (double)now
);
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
))) {
979 case TRACE_DATA_NEWTHREAD
:
981 for (n
= 0, ti
= th_state
; ti
< &th_state
[MAX_THREADS
]; ti
++, n
++) {
985 if (ti
== &th_state
[MAX_THREADS
])
991 ti
->child_thread
= kd
[i
].arg1
;
992 ti
->pid
= kd
[i
].arg2
;
995 case TRACE_STRING_NEWTHREAD
:
996 if ((ti
= find_thread(thread
, 0)) == (struct th_info
*)0)
998 if (ti
->child_thread
== 0)
1000 create_map_entry(ti
->child_thread
, ti
->pid
, (char *)&kd
[i
].arg1
);
1002 if (ti
== &th_state
[cur_max
- 1])
1004 ti
->child_thread
= 0;
1009 case TRACE_DATA_EXEC
:
1011 for (n
= 0, ti
= th_state
; ti
< &th_state
[MAX_THREADS
]; ti
++, n
++) {
1012 if (ti
->thread
== 0)
1015 if (ti
== &th_state
[MAX_THREADS
])
1020 ti
->thread
= thread
;
1021 ti
->pid
= kd
[i
].arg1
;
1024 case TRACE_STRING_EXEC
:
1025 if ((ti
= find_thread(thread
, 0)) == (struct th_info
*)0)
1027 /* this is for backwards compatibility */
1028 create_map_entry(thread
, 0, (char *)&kd
[i
].arg1
);
1032 create_map_entry(thread
, ti
->pid
, (char *)&kd
[i
].arg1
);
1033 if (ti
== &th_state
[cur_max
- 1])
1041 kill_thread_map(thread
);
1045 case MACH_stkhandoff
:
1046 mark_thread_waited(thread
);
1050 if ((ti
= find_thread(thread
, 0)) == (struct th_info
*)0)
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
;
1061 sargptr
= ti
->pathptr
;
1064 We don't want to overrun our pathname buffer if the
1065 kernel sends us more VFS_LOOKUP entries than we can
1069 if ((long *)sargptr
>= (long *)&ti
->pathname
[PATHLENGTH
])
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
1079 if (debugid
& DBG_FUNC_START
)
1081 (long *)ti
->pathptr
= (long *)&ti
->pathname
[PATHLENGTH
];
1085 *sargptr
++ = kd
[i
].arg1
;
1086 *sargptr
++ = kd
[i
].arg2
;
1087 *sargptr
++ = kd
[i
].arg3
;
1088 *sargptr
++ = kd
[i
].arg4
;
1089 ti
->pathptr
= sargptr
;
1094 if (debugid
& DBG_FUNC_START
) {
1098 case FILEMGR_PBGETCATALOGINFO
:
1099 p
= "GetCatalogInfo";
1101 case FILEMGR_PBGETCATALOGINFOBULK
:
1102 p
= "GetCatalogInfoBulk";
1104 case FILEMGR_PBCREATEFILEUNICODE
:
1105 p
= "CreateFileUnicode";
1107 case FILEMGR_PBCREATEDIRECTORYUNICODE
:
1108 p
= "CreateDirectoryUnicode";
1110 case FILEMGR_PBCREATEFORK
:
1113 case FILEMGR_PBDELETEFORK
:
1116 case FILEMGR_PBITERATEFORK
:
1117 p
= "PBIterateFork";
1119 case FILEMGR_PBOPENFORK
:
1122 case FILEMGR_PBREADFORK
:
1125 case FILEMGR_PBWRITEFORK
:
1128 case FILEMGR_PBALLOCATEFORK
:
1129 p
= "PBAllocateFork";
1131 case FILEMGR_PBDELETEOBJECT
:
1132 p
= "PBDeleteObject";
1134 case FILEMGR_PBEXCHANGEOBJECT
:
1135 p
= "PBExchangeObject";
1137 case FILEMGR_PBGETFORKCBINFO
:
1138 p
= "PBGetForkCBInfo";
1140 case FILEMGR_PBGETVOLUMEINFO
:
1141 p
= "PBGetVolumeInfo";
1143 case FILEMGR_PBMAKEFSREF
:
1146 case FILEMGR_PBMAKEFSREFUNICODE
:
1147 p
= "PBMakeFSRefUnicode";
1149 case FILEMGR_PBMOVEOBJECT
:
1152 case FILEMGR_PBOPENITERATOR
:
1153 p
= "PBOpenIterator";
1155 case FILEMGR_PBRENAMEUNICODE
:
1156 p
= "PBRenameUnicode";
1158 case FILEMGR_PBSETCATALOGINFO
:
1159 p
= "SetCatalogInfo";
1161 case FILEMGR_PBSETVOLUMEINFO
:
1162 p
= "SetVolumeInfo";
1164 case FILEMGR_FSREFMAKEPATH
:
1165 p
= "FSRefMakePath";
1167 case FILEMGR_FSPATHMAKEREF
:
1168 p
= "FSPathMakeRef";
1171 case FILEMGR_PBGETCATINFO
:
1174 case FILEMGR_PBGETCATINFOLITE
:
1175 p
= "GetCatInfoLite";
1177 case FILEMGR_PBHGETFINFO
:
1180 case FILEMGR_PBXGETVOLINFO
:
1181 p
= "PBXGetVolInfo";
1183 case FILEMGR_PBHCREATE
:
1186 case FILEMGR_PBHOPENDF
:
1189 case FILEMGR_PBHOPENRF
:
1192 case FILEMGR_PBHGETDIRACCESS
:
1193 p
= "PBHGetDirAccess";
1195 case FILEMGR_PBHSETDIRACCESS
:
1196 p
= "PBHSetDirAccess";
1198 case FILEMGR_PBHMAPID
:
1201 case FILEMGR_PBHMAPNAME
:
1204 case FILEMGR_PBCLOSE
:
1207 case FILEMGR_PBFLUSHFILE
:
1210 case FILEMGR_PBGETEOF
:
1213 case FILEMGR_PBSETEOF
:
1216 case FILEMGR_PBGETFPOS
:
1219 case FILEMGR_PBREAD
:
1222 case FILEMGR_PBWRITE
:
1225 case FILEMGR_PBGETFCBINFO
:
1228 case FILEMGR_PBSETFINFO
:
1231 case FILEMGR_PBALLOCATE
:
1234 case FILEMGR_PBALLOCCONTIG
:
1235 p
= "PBAllocContig";
1237 case FILEMGR_PBSETFPOS
:
1240 case FILEMGR_PBSETCATINFO
:
1243 case FILEMGR_PBGETVOLPARMS
:
1244 p
= "PBGetVolParms";
1246 case FILEMGR_PBSETVINFO
:
1249 case FILEMGR_PBMAKEFSSPEC
:
1252 case FILEMGR_PBHGETVINFO
:
1255 case FILEMGR_PBCREATEFILEIDREF
:
1256 p
= "PBCreateFileIDRef";
1258 case FILEMGR_PBDELETEFILEIDREF
:
1259 p
= "PBDeleteFileIDRef";
1261 case FILEMGR_PBRESOLVEFILEIDREF
:
1262 p
= "PBResolveFileIDRef";
1264 case FILEMGR_PBFLUSHVOL
:
1267 case FILEMGR_PBHRENAME
:
1270 case FILEMGR_PBCATMOVE
:
1273 case FILEMGR_PBEXCHANGEFILES
:
1274 p
= "PBExchangeFiles";
1276 case FILEMGR_PBHDELETE
:
1279 case FILEMGR_PBDIRCREATE
:
1282 case FILEMGR_PBCATSEARCH
:
1285 case FILEMGR_PBHSETFLOCK
:
1288 case FILEMGR_PBHRSTFLOCK
:
1291 case FILEMGR_PBLOCKRANGE
:
1294 case FILEMGR_PBUNLOCKRANGE
:
1295 p
= "PBUnlockRange";
1301 enter_syscall(thread
, type
, &kd
[i
], p
, (double)now
);
1307 case BSC_pread_extended
:
1308 case BSC_pwrite_extended
:
1309 extend_syscall(thread
, type
, &kd
[i
], (double)now
);
1313 exit_syscall("PAGE_OUT_D", thread
, type
, 0, kd
[i
].arg1
, 0, 4, (double)now
);
1315 exit_syscall("PAGE_OUT_V", thread
, type
, 0, kd
[i
].arg1
, 0, 4, (double)now
);
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
);
1324 if ((ti
= find_thread(thread
, type
))) {
1325 if (ti
== &th_state
[cur_max
- 1])
1333 exit_syscall("map_fd", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1337 exit_syscall("mmap", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1341 exit_syscall("recvmsg", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1345 exit_syscall("sendmsg", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1349 exit_syscall("recvfrom", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1353 exit_syscall("accept", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 2, 0, (double)now
);
1357 exit_syscall("select", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 8, (double)now
);
1361 exit_syscall("socket", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 2, 0, (double)now
);
1365 exit_syscall("connect", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1369 exit_syscall("bind", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1373 exit_syscall("listen", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1377 exit_syscall("sendto", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1380 case BSC_socketpair
:
1381 exit_syscall("socketpair", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1385 exit_syscall("stat", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1388 case BSC_load_shared_file
:
1389 exit_syscall("load_sf", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1393 exit_syscall("open", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 2, 0, (double)now
);
1397 exit_syscall("dup", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 2, 0, (double)now
);
1401 exit_syscall("dup2", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 2, 0, (double)now
);
1405 exit_syscall("close", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1409 exit_syscall("read", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1413 exit_syscall("write", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1417 exit_syscall("fstat", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1421 exit_syscall("lstat", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1425 exit_syscall("link", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1429 exit_syscall("unlink", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1433 exit_syscall("mknod", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1437 exit_syscall("chmod", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1441 exit_syscall("chown", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1445 exit_syscall("access", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1449 exit_syscall("chdir", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1453 exit_syscall("chroot", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1457 exit_syscall("utimes", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1461 exit_syscall("delete", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1465 exit_syscall("undelete", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1469 exit_syscall("revoke", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1473 exit_syscall("fsctl", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1477 exit_syscall("chflags", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1481 exit_syscall("fchflags", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1485 exit_syscall("fchdir", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1489 exit_syscall("futimes", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1493 exit_syscall("sync", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1497 exit_syscall("symlink", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1501 exit_syscall("readlink", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1505 exit_syscall("fsync", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1509 exit_syscall("readv", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1513 exit_syscall("writev", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1517 exit_syscall("pread", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 9, (double)now
);
1521 exit_syscall("pwrite", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 9, (double)now
);
1525 exit_syscall("fchown", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1529 exit_syscall("fchmod", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1533 exit_syscall("mkdir", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1537 exit_syscall("mkfifo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1541 exit_syscall("rmdir", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1545 exit_syscall("statfs", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1549 exit_syscall("fstatfs", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1553 exit_syscall("pathconf", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1557 exit_syscall("fpathconf", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1560 case BSC_getdirentries
:
1561 exit_syscall("getdirentries", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 1, (double)now
);
1565 exit_syscall("lseek", thread
, type
, kd
[i
].arg1
, kd
[i
].arg3
, 1, 5, (double)now
);
1569 exit_syscall("truncate", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1573 exit_syscall("ftruncate", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 3, (double)now
);
1577 exit_syscall("statv", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1581 exit_syscall("lstatv", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1585 exit_syscall("fstatv", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 1, 0, (double)now
);
1589 exit_syscall("mkcomplex", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1592 case BSC_getattrlist
:
1593 exit_syscall("getattrlist", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1596 case BSC_setattrlist
:
1597 exit_syscall("setattrlist", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1600 case BSC_getdirentriesattr
:
1601 exit_syscall("getdirentriesattr", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 1, (double)now
);
1605 case BSC_exchangedata
:
1606 exit_syscall("exchangedata", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1610 exit_syscall("rename", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1614 exit_syscall("copyfile", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1618 case BSC_checkuseraccess
:
1619 exit_syscall("checkuseraccess", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1623 exit_syscall("searchfs", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1626 case FILEMGR_PBGETCATALOGINFO
:
1627 exit_syscall("GetCatalogInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1629 case FILEMGR_PBGETCATALOGINFOBULK
:
1630 exit_syscall("GetCatalogInfoBulk", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1632 case FILEMGR_PBCREATEFILEUNICODE
:
1633 exit_syscall("CreateFileUnicode", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1635 case FILEMGR_PBCREATEDIRECTORYUNICODE
:
1636 exit_syscall("CreateDirectoryUnicode", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1638 case FILEMGR_PBCREATEFORK
:
1639 exit_syscall("PBCreateFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1641 case FILEMGR_PBDELETEFORK
:
1642 exit_syscall("PBDeleteFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1644 case FILEMGR_PBITERATEFORK
:
1645 exit_syscall("PBIterateFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1647 case FILEMGR_PBOPENFORK
:
1648 exit_syscall("PBOpenFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1650 case FILEMGR_PBREADFORK
:
1651 exit_syscall("PBReadFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1653 case FILEMGR_PBWRITEFORK
:
1654 exit_syscall("PBWriteFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1656 case FILEMGR_PBALLOCATEFORK
:
1657 exit_syscall("PBAllocateFork", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1659 case FILEMGR_PBDELETEOBJECT
:
1660 exit_syscall("PBDeleteObject", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1662 case FILEMGR_PBEXCHANGEOBJECT
:
1663 exit_syscall("PBExchangeObject", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1665 case FILEMGR_PBGETFORKCBINFO
:
1666 exit_syscall("PBGetForkCBInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1668 case FILEMGR_PBGETVOLUMEINFO
:
1669 exit_syscall("PBGetVolumeInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1671 case FILEMGR_PBMAKEFSREF
:
1672 exit_syscall("PBMakeFSRef", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1674 case FILEMGR_PBMAKEFSREFUNICODE
:
1675 exit_syscall("PBMakeFSRefUnicode", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1677 case FILEMGR_PBMOVEOBJECT
:
1678 exit_syscall("PBMoveObject", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1680 case FILEMGR_PBOPENITERATOR
:
1681 exit_syscall("PBOpenIterator", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1683 case FILEMGR_PBRENAMEUNICODE
:
1684 exit_syscall("PBRenameUnicode", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1686 case FILEMGR_PBSETCATALOGINFO
:
1687 exit_syscall("PBSetCatalogInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1689 case FILEMGR_PBSETVOLUMEINFO
:
1690 exit_syscall("PBSetVolumeInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1692 case FILEMGR_FSREFMAKEPATH
:
1693 exit_syscall("FSRefMakePath", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1695 case FILEMGR_FSPATHMAKEREF
:
1696 exit_syscall("FSPathMakeRef", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1698 case FILEMGR_PBGETCATINFO
:
1699 exit_syscall("GetCatInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1701 case FILEMGR_PBGETCATINFOLITE
:
1702 exit_syscall("GetCatInfoLite", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1704 case FILEMGR_PBHGETFINFO
:
1705 exit_syscall("PBHGetFInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1707 case FILEMGR_PBXGETVOLINFO
:
1708 exit_syscall("PBXGetVolInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1710 case FILEMGR_PBHCREATE
:
1711 exit_syscall("PBHCreate", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1713 case FILEMGR_PBHOPENDF
:
1714 exit_syscall("PBHOpenDF", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1716 case FILEMGR_PBHOPENRF
:
1717 exit_syscall("PBHOpenRF", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1719 case FILEMGR_PBHGETDIRACCESS
:
1720 exit_syscall("PBHGetDirAccess", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1722 case FILEMGR_PBHSETDIRACCESS
:
1723 exit_syscall("PBHSetDirAccess", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1725 case FILEMGR_PBHMAPID
:
1726 exit_syscall("PBHMapID", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1728 case FILEMGR_PBHMAPNAME
:
1729 exit_syscall("PBHMapName", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1731 case FILEMGR_PBCLOSE
:
1732 exit_syscall("PBClose", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1734 case FILEMGR_PBFLUSHFILE
:
1735 exit_syscall("PBFlushFile", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1737 case FILEMGR_PBGETEOF
:
1738 exit_syscall("PBGetEOF", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1740 case FILEMGR_PBSETEOF
:
1741 exit_syscall("PBSetEOF", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1743 case FILEMGR_PBGETFPOS
:
1744 exit_syscall("PBGetFPos", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1746 case FILEMGR_PBREAD
:
1747 exit_syscall("PBRead", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1749 case FILEMGR_PBWRITE
:
1750 exit_syscall("PBWrite", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1752 case FILEMGR_PBGETFCBINFO
:
1753 exit_syscall("PBGetFCBInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1755 case FILEMGR_PBSETFINFO
:
1756 exit_syscall("PBSetFInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1758 case FILEMGR_PBALLOCATE
:
1759 exit_syscall("PBAllocate", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1761 case FILEMGR_PBALLOCCONTIG
:
1762 exit_syscall("PBAllocContig", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1764 case FILEMGR_PBSETFPOS
:
1765 exit_syscall("PBSetFPos", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1767 case FILEMGR_PBSETCATINFO
:
1768 exit_syscall("PBSetCatInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1770 case FILEMGR_PBGETVOLPARMS
:
1771 exit_syscall("PBGetVolParms", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1773 case FILEMGR_PBSETVINFO
:
1774 exit_syscall("PBSetVInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1776 case FILEMGR_PBMAKEFSSPEC
:
1777 exit_syscall("PBMakeFSSpec", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1779 case FILEMGR_PBHGETVINFO
:
1780 exit_syscall("PBHGetVInfo", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1782 case FILEMGR_PBCREATEFILEIDREF
:
1783 exit_syscall("PBCreateFileIDRef", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1785 case FILEMGR_PBDELETEFILEIDREF
:
1786 exit_syscall("PBDeleteFileIDRef", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1788 case FILEMGR_PBRESOLVEFILEIDREF
:
1789 exit_syscall("PBResolveFileIDRef", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1791 case FILEMGR_PBFLUSHVOL
:
1792 exit_syscall("PBFlushVol", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1794 case FILEMGR_PBHRENAME
:
1795 exit_syscall("PBHRename", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1797 case FILEMGR_PBCATMOVE
:
1798 exit_syscall("PBCatMove", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1800 case FILEMGR_PBEXCHANGEFILES
:
1801 exit_syscall("PBExchangeFiles", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1803 case FILEMGR_PBHDELETE
:
1804 exit_syscall("PBHDelete", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1806 case FILEMGR_PBDIRCREATE
:
1807 exit_syscall("PBDirCreate", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1809 case FILEMGR_PBCATSEARCH
:
1810 exit_syscall("PBCatSearch", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1812 case FILEMGR_PBHSETFLOCK
:
1813 exit_syscall("PBHSetFLock", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1815 case FILEMGR_PBHRSTFLOCK
:
1816 exit_syscall("PBHRstFLock", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1818 case FILEMGR_PBLOCKRANGE
:
1819 exit_syscall("PBLockRange", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1821 case FILEMGR_PBUNLOCKRANGE
:
1822 exit_syscall("PBUnlockRange", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, (double)now
);
1832 enter_syscall(int thread
, int type
, kd_buf
*kd
, char *name
, double now
)
1841 kd_threadmap
*find_thread_map();
1864 case BSC_socketpair
:
1866 case BSC_load_shared_file
:
1911 case BSC_getdirentries
:
1919 case BSC_getattrlist
:
1920 case BSC_setattrlist
:
1921 case BSC_getdirentriesattr
:
1922 case BSC_exchangedata
:
1923 case BSC_checkuseraccess
:
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
:
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
:
1994 for (i
= 0, ti
= th_state
; ti
< &th_state
[MAX_THREADS
]; ti
++, i
++) {
1995 if (ti
->thread
== 0)
1998 if (ti
== &th_state
[MAX_THREADS
])
2004 if ((type
>> 24) == FILEMGR_CLASS
) {
2007 l_usecs
= (long long)(now
/ divisor
);
2008 secs
= l_usecs
/ 1000000;
2009 curr_time
= bias_secs
+ secs
;
2011 sprintf(buf
, "%-8.8s", &(ctime(&curr_time
)[11]));
2012 tsclen
= strlen(buf
);
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
);
2020 /* Print timestamp column */
2023 map
= find_thread_map(thread
);
2025 sprintf(buf
, " %-25.25s ", name
);
2026 nmclen
= strlen(buf
);
2029 sprintf(buf
, "(%d, 0x%x, 0x%x, 0x%x)", (short)kd
->arg1
, kd
->arg2
, kd
->arg3
, kd
->arg4
);
2030 argsclen
= strlen(buf
);
2033 Calculate white space out to command
2035 if (columns
> MAXCOLS
|| wideflag
)
2037 clen
= columns
- (tsclen
+ nmclen
+ argsclen
+ 20);
2040 clen
= columns
- (tsclen
+ nmclen
+ argsclen
+ 12);
2044 printf("%s", buf
); /* print the kdargs */
2045 memset(buf
, ' ', clen
);
2049 else if ((argsclen
+ clen
) > 0)
2051 /* no room so wipe out the kdargs */
2052 memset(buf
, ' ', (argsclen
+ clen
));
2053 buf
[argsclen
+ clen
] = '\0';
2057 if (columns
> MAXCOLS
|| wideflag
)
2058 printf("%-20.20s\n", map
->command
);
2060 printf("%-12.12s\n", map
->command
);
2062 printf(" %-24.24s (%5d, %#x, 0x%x, 0x%x)\n", name
, (short)kd
->arg1
, kd
->arg2
, kd
->arg3
, kd
->arg4
);
2066 ti
->thread
= thread
;
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;
2085 * Handle system call extended trace data.
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.
2093 extend_syscall(int thread
, int type
, kd_buf
*kd
, char *name
, double now
)
2098 case BSC_pread_extended
:
2099 if ((ti
= find_thread(thread
, BSC_pread
)) == (struct th_info
*)0)
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 */
2106 case BSC_pwrite_extended
:
2107 if ((ti
= find_thread(thread
, BSC_pwrite
)) == (struct th_info
*)0)
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 */
2120 exit_syscall(char *sc_name
, int thread
, int type
, int error
, int retval
,
2121 int has_fd
, int has_ret
, double now
)
2125 if ((ti
= find_thread(thread
, type
)) == (struct th_info
*)0)
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
);
2131 if (ti
== &th_state
[cur_max
- 1])
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
)
2149 kd_threadmap
*find_thread_map();
2152 char *framework_name
;
2158 command_name
= dio
->issuing_command
;
2160 if ((map
= find_thread_map(thread
)))
2161 command_name
= map
->command
;
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]));
2170 if (columns
> MAXCOLS
|| wideflag
) {
2172 usecs
= l_usecs
- (long long)((long long)secs
* 1000000);
2173 sprintf(&buf
[clen
], ".%03ld", (long)usecs
/ 1000);
2176 if ((type
>> 24) != FILEMGR_CLASS
) {
2177 if (find_thread(thread
, -1)) {
2178 sprintf(&buf
[clen
], " ");
2186 if (((type
>> 24) == FILEMGR_CLASS
) && (columns
> MAXCOLS
|| wideflag
))
2187 sprintf(&buf
[clen
], " %-18.18s", sc_name
);
2189 sprintf(&buf
[clen
], " %-15.15s", sc_name
);
2193 framework_name
= (char *)0;
2195 if (columns
> MAXCOLS
|| wideflag
) {
2197 sprintf(&buf
[clen
], " D=0x%8.8x", dio
->blkno
);
2202 sprintf(&buf
[clen
], " [%3d] ", dio
->io_errno
);
2204 sprintf(&buf
[clen
], " B=0x%-6x /dev/%s", dio
->iosize
, find_disk_name(dio
->dev
));
2207 off_t offset_reassembled
= 0LL;
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
], " ");
2218 if (has_ret
== 2 || has_ret
== 6)
2219 framework_name
= lookup_name(retval
);
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 */
2239 sprintf(&buf
[clen
], "B=0x%-8x", retval
);
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
);
2245 sprintf(&buf
[clen
], "O=0x%8.8qx", (off_t
)offset_reassembled
);
2248 sprintf(&buf
[clen
], " ");
2255 Calculate space available to print pathname
2257 if (columns
> MAXCOLS
|| wideflag
)
2258 clen
= columns
- (clen
+ 13 + 20);
2260 clen
= columns
- (clen
+ 13 + 12);
2262 if ((type
>> 24) != FILEMGR_CLASS
&& !nopadding
)
2266 sprintf(&buf
[0], " %s ", framework_name
);
2268 sprintf(&buf
[0], " %s ", pathname
);
2274 Add null padding if column length
2275 is wider than the pathname length.
2277 memset(&buf
[len
], ' ', clen
- len
);
2281 else if (clen
== len
)
2285 else if ((clen
> 0) && (clen
< len
))
2287 /* This prints the tail end of the pathname */
2288 buf
[len
-clen
] = ' ';
2289 printf("%s", &buf
[len
- clen
]);
2292 usecs
= (unsigned long)((now
- stime
) / divisor
);
2293 secs
= usecs
/ 1000000;
2294 usecs
-= secs
* 1000000;
2296 if ((type
>> 24) != FILEMGR_CLASS
&& !nopadding
)
2299 printf(" %2ld.%06ld", (unsigned long)secs
, (unsigned long)usecs
);
2306 if (columns
> MAXCOLS
|| wideflag
)
2307 printf(" %-20.20s", command_name
);
2309 printf(" %-12.12s", command_name
);
2323 This flag is turned off when calling
2324 quit() due to a set_remove() failure.
2326 if (set_remove_flag
)
2329 fprintf(stderr
, "fs_usage: ");
2331 fprintf(stderr
, "%s", s
);
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
;
2346 extern void MKGetTimeBaseInfo(unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *);
2348 MKGetTimeBaseInfo (&delta
, &abs_to_ns_num
, &abs_to_ns_denom
,
2349 &proc_to_abs_num
, &proc_to_abs_denom
);
2351 divisor
= ((double)abs_to_ns_denom
/ (double)abs_to_ns_num
) * 1000;
2355 void read_command_map()
2359 int prev_total_threads
;
2367 prev_total_threads
= total_threads
;
2368 total_threads
= bufinfo
.nkdthreads
;
2369 size
= bufinfo
.nkdthreads
* sizeof(kd_threadmap
);
2373 if ((mapptr
= (kd_threadmap
*) malloc(size
)))
2375 bzero (mapptr
, size
);
2377 /* Now read the threadmap */
2379 mib
[1] = KERN_KDEBUG
;
2380 mib
[2] = KERN_KDTHRMAP
;
2383 mib
[5] = 0; /* no flags */
2384 if (sysctl(mib
, 3, mapptr
, &size
, NULL
, 0) < 0)
2386 /* This is not fatal -- just means I cant map command strings */
2393 if (mapptr
&& (filter_mode
!= DEFAULT_DO_NOT_FILTER
))
2397 /* We accept the fact that we lose file descriptor state if the
2399 for (i
= 0; i
< prev_total_threads
; i
++)
2401 if (fdmapptr
[i
].fd_setptr
)
2402 free (fdmapptr
[i
].fd_setptr
);
2408 size
= total_threads
* sizeof(fd_threadmap
);
2409 if ((fdmapptr
= (fd_threadmap
*) malloc(size
)))
2411 bzero (fdmapptr
, size
);
2412 /* reinitialize file descriptor state map */
2413 for (i
= 0; i
< total_threads
; i
++)
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;
2423 /* Resolve any LaunchCFMApp command names */
2424 if (mapptr
&& arguments
)
2426 for (i
=0; i
< total_threads
; i
++)
2430 pid
= mapptr
[i
].valid
;
2432 if (pid
== 0 || pid
== 1)
2434 else if (!strncmp(mapptr
[i
].command
,"LaunchCFMA", 10))
2436 (void)get_real_command_name(pid
, mapptr
[i
].command
, sizeof(mapptr
[i
].command
));
2443 void create_map_entry(int thread
, int pid
, char *command
)
2447 fd_threadmap
*fdmap
= 0;
2452 for (i
= 0, map
= 0; !map
&& i
< total_threads
; i
++)
2454 if ((int)mapptr
[i
].thread
== thread
)
2456 map
= &mapptr
[i
]; /* Reuse this entry, the thread has been
2458 if(filter_mode
&& fdmapptr
)
2460 fdmap
= &fdmapptr
[i
];
2461 if (fdmap
->fd_thread
!= thread
) /* This shouldn't happen */
2462 fdmap
= (fd_threadmap
*)0;
2467 if (!map
) /* look for invalid entries that I can reuse*/
2469 for (i
= 0, map
= 0; !map
&& i
< total_threads
; i
++)
2471 if (mapptr
[i
].valid
== 0 )
2472 map
= &mapptr
[i
]; /* Reuse this invalid entry */
2473 if (filter_mode
&& fdmapptr
)
2475 fdmap
= &fdmapptr
[i
];
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.
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
];
2492 if (filter_mode
&& fdmapptr
)
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
];
2503 map
->thread
= thread
;
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.
2509 (void)strncpy (map
->command
, command
, MAXCOMLEN
);
2510 map
->command
[MAXCOMLEN
] = '\0';
2514 fdmap
->fd_valid
= 1;
2515 fdmap
->fd_thread
= thread
;
2516 if (fdmap
->fd_setptr
)
2518 free(fdmap
->fd_setptr
);
2519 fdmap
->fd_setptr
= (unsigned long *)0;
2521 fdmap
->fd_setsize
= 0;
2524 if (pid
== 0 || pid
== 1)
2526 else if (!strncmp(map
->command
, "LaunchCFMA", 10))
2527 (void)get_real_command_name(pid
, map
->command
, sizeof(map
->command
));
2531 kd_threadmap
*find_thread_map(int thread
)
2537 return((kd_threadmap
*)0);
2539 for (i
= 0; i
< total_threads
; i
++)
2542 if (map
->valid
&& ((int)map
->thread
== thread
))
2547 return ((kd_threadmap
*)0);
2550 fd_threadmap
*find_fd_thread_map(int thread
)
2553 fd_threadmap
*fdmap
= 0;
2556 return((fd_threadmap
*)0);
2558 for (i
= 0; i
< total_threads
; i
++)
2560 fdmap
= &fdmapptr
[i
];
2561 if (fdmap
->fd_valid
&& ((int)fdmap
->fd_thread
== thread
))
2566 return ((fd_threadmap
*)0);
2571 kill_thread_map(int thread
)
2574 fd_threadmap
*fdmap
;
2576 if ((map
= find_thread_map(thread
))) {
2579 map
->command
[0] = '\0';
2584 if ((fdmap
= find_fd_thread_map(thread
)))
2586 fdmap
->fd_valid
= 0;
2587 fdmap
->fd_thread
= 0;
2588 if (fdmap
->fd_setptr
)
2590 free (fdmap
->fd_setptr
);
2591 fdmap
->fd_setptr
= (unsigned long *)0;
2593 fdmap
->fd_setsize
= 0;
2606 ret
= (int)strtol(str
, &cp
, 10);
2607 if (cp
== str
|| *cp
) {
2608 /* Assume this is a command string and find matching pids */
2612 for (i
=0; i
< kp_nentries
&& num_of_pids
< (MAX_PIDS
- 1); i
++) {
2613 if(kp_buffer
[i
].kp_proc
.p_stat
== 0)
2616 if(!strcmp(str
, kp_buffer
[i
].kp_proc
.p_comm
))
2617 pids
[num_of_pids
++] = kp_buffer
[i
].kp_proc
.p_pid
;
2621 else if (num_of_pids
< (MAX_PIDS
- 1))
2622 pids
[num_of_pids
++] = ret
;
2629 char *lookup_name(unsigned long addr
)
2632 register int start
, last
;
2635 if (numFrameworks
== 0 || addr
< frameworkInfo
[0].address
|| addr
> frameworkInfo
[numFrameworks
].address
)
2639 last
= numFrameworks
;
2641 for (i
= numFrameworks
/ 2; i
>= 0 && i
< numFrameworks
; ) {
2643 if (addr
>= frameworkInfo
[i
].address
&& addr
< frameworkInfo
[i
+1].address
)
2644 return(frameworkInfo
[i
].name
);
2646 if (addr
>= frameworkInfo
[i
].address
) {
2648 i
= start
+ ((last
- i
) / 2);
2651 i
= start
+ ((i
- start
) / 2);
2659 * Comparison routines for sorting
2661 static int compareFrameworkAddress(const void *aa
, const void *bb
)
2663 LibraryInfo
*a
= (LibraryInfo
*)aa
;
2664 LibraryInfo
*b
= (LibraryInfo
*)bb
;
2666 if (a
->address
< b
->address
) return -1;
2667 if (a
->address
== b
->address
) return 0;
2672 int scanline(char *inputstring
,char **argv
)
2675 char **ap
= argv
, *p
, *val
;
2677 for (p
= inputstring
; p
!= NULL
; )
2679 while ((val
= strsep(&p
, " \t")) != NULL
&& *val
== '\0');
2688 int ReadSegAddrTable()
2693 unsigned long frameworkAddress
, frameworkDataAddress
, previousFrameworkAddress
;
2694 char frameworkName
[256];
2697 char *substring
,*ptr
;
2701 bzero(buf
, sizeof(buf
));
2702 bzero(tokens
, sizeof(tokens
));
2706 if ((fd
= fopen(seg_addr_table
, "r")) == 0)
2710 fgets(buf
, 1023, fd
);
2715 frameworkName
[0] = 0;
2716 previousFrameworkAddress
= 0;
2718 while (fgets(buf
, 1023, fd
) && numFrameworks
< (MAXINDEX
- 2))
2723 buf
[strlen(buf
)-1] = 0;
2725 if (strncmp(buf
, "# dyld:", 7) == 0) {
2727 * the next line in the file will contain info about dyld
2733 * This is a split library line: parse it into 3 tokens
2735 ntokens
= scanline(buf
, tokens
);
2740 frameworkAddress
= strtoul(tokens
[0], 0, 16);
2741 frameworkDataAddress
= strtoul(tokens
[1], 0, 16);
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
2749 frameworkInfo
[numFrameworks
].address
= frameworkAddress
;
2750 frameworkInfo
[numFrameworks
+1].address
= frameworkAddress
+ frameworkDataAddress
;
2752 frameworkInfo
[numFrameworks
].name
= (char *)"dylib";
2753 frameworkInfo
[numFrameworks
+1].name
= (char *)0;
2762 * Make sure that we have 2 addresses and a path
2764 if (!frameworkAddress
)
2766 if (!frameworkDataAddress
)
2768 if (*tokens
[2] != '/')
2770 if (frameworkAddress
== previousFrameworkAddress
)
2772 previousFrameworkAddress
= frameworkAddress
;
2775 * Extract lib name from path name
2777 if ((substring
= strrchr(tokens
[2], '.')))
2780 * There is a ".": name is whatever is between the "/" around the "."
2782 while ( *substring
!= '/') { /* find "/" before "." */
2786 strcpy(frameworkName
, substring
); /* copy path from "/" */
2787 substring
= frameworkName
;
2789 while ( *substring
!= '/' && *substring
) /* find "/" after "." and stop string there */
2796 * No ".": take segment after last "/"
2804 substring
= ptr
+ 1;
2807 strcpy(frameworkName
, substring
);
2809 frameworkInfo
[numFrameworks
].address
= frameworkAddress
;
2810 frameworkInfo
[numFrameworks
+1].address
= frameworkDataAddress
;
2812 frameworkInfo
[numFrameworks
].name
= (char *)malloc(strlen(frameworkName
) + 1);
2813 strcpy(frameworkInfo
[numFrameworks
].name
, frameworkName
);
2814 frameworkInfo
[numFrameworks
+1].name
= frameworkInfo
[numFrameworks
].name
;
2819 frameworkInfo
[numFrameworks
].address
= frameworkInfo
[numFrameworks
- 1].address
+ 0x800000;
2820 frameworkInfo
[numFrameworks
].name
= (char *)0;
2824 qsort(frameworkInfo
, numFrameworks
, sizeof(LibraryInfo
), compareFrameworkAddress
);
2830 struct diskio
*insert_diskio(int type
, int bp
, int dev
, int blkno
, int io_size
, int thread
, double curtime
)
2832 register struct diskio
*dio
;
2833 register kd_threadmap
*map
;
2835 if ((dio
= free_diskios
))
2836 free_diskios
= dio
->next
;
2838 if ((dio
= (struct diskio
*)malloc(sizeof(struct diskio
))) == NULL
)
2847 dio
->iosize
= io_size
;
2848 dio
->issued_time
= curtime
;
2849 dio
->issuing_thread
= thread
;
2851 if ((map
= find_thread_map(thread
)))
2853 strncpy(dio
->issuing_command
, map
->command
, MAXCOMLEN
);
2854 dio
->issuing_command
[MAXCOMLEN
-1] = '\0';
2857 strcpy(dio
->issuing_command
, "");
2859 dio
->next
= busy_diskios
;
2861 dio
->next
->prev
= dio
;
2868 struct diskio
*complete_diskio(int bp
, int io_errno
, int resid
, int thread
, double curtime
)
2870 register struct diskio
*dio
;
2872 for (dio
= busy_diskios
; dio
; dio
= dio
->next
) {
2873 if (dio
->bp
== bp
) {
2875 if (dio
== busy_diskios
) {
2876 if ((busy_diskios
= dio
->next
))
2877 dio
->next
->prev
= NULL
;
2880 dio
->next
->prev
= dio
->prev
;
2881 dio
->prev
->next
= dio
->next
;
2883 dio
->iosize
-= resid
;
2884 dio
->io_errno
= io_errno
;
2885 dio
->completed_time
= curtime
;
2886 dio
->completion_thread
= thread
;
2891 return ((struct diskio
*)0);
2895 void free_diskio(struct diskio
*dio
)
2897 dio
->next
= free_diskios
;
2902 void print_diskio(struct diskio
*dio
)
2906 switch (dio
->type
) {
2927 p
= " RdMeta[async]";
2930 p
= " WrMeta[async]";
2933 p
= " RdData[async]";
2936 p
= " WrData[async]";
2942 p
= " PgOut[async]";
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
);
2953 void cache_disk_names()
2958 struct diskrec
*dnp
;
2961 if ((dirp
= opendir("/dev")) == NULL
)
2964 while ((dir
= readdir(dirp
)) != NULL
) {
2965 char nbuf
[MAXPATHLEN
];
2967 if (dir
->d_namlen
< 5 || strncmp("disk", dir
->d_name
, 4))
2969 sprintf(nbuf
, "%s/%s", "/dev", dir
->d_name
);
2971 if (stat(nbuf
, &st
) < 0)
2974 if ((dnp
= (struct diskrec
*)malloc(sizeof(struct diskrec
))) == NULL
)
2977 if ((dnp
->diskname
= (char *)malloc(dir
->d_namlen
+ 1)) == NULL
) {
2981 strncpy(dnp
->diskname
, dir
->d_name
, dir
->d_namlen
);
2982 dnp
->diskname
[dir
->d_namlen
] = 0;
2983 dnp
->dev
= st
.st_rdev
;
2985 dnp
->next
= disk_list
;
2988 (void) closedir(dirp
);
2992 char *find_disk_name(int dev
)
2994 struct diskrec
*dnp
;
2999 for (dnp
= disk_list
; dnp
; dnp
= dnp
->next
) {
3000 if (dnp
->dev
== dev
)
3001 return (dnp
->diskname
);
3003 return ("NOTFOUND");
3007 fs_usage_fd_set(thread
, fd
)
3008 unsigned int thread
;
3012 fd_threadmap
*fdmap
;
3014 if(!(fdmap
= find_fd_thread_map(thread
)))
3017 /* If the map is not allocated, then now is the time */
3018 if (fdmap
->fd_setptr
== (unsigned long *)0)
3020 fdmap
->fd_setptr
= (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE
));
3021 if (fdmap
->fd_setptr
)
3023 fdmap
->fd_setsize
= FS_USAGE_FD_SETSIZE
;
3024 bzero(fdmap
->fd_setptr
,(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE
)));
3030 /* If the map is not big enough, then reallocate it */
3031 while (fdmap
->fd_setsize
< fd
)
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
;
3042 fdmap
->fd_setptr
[fd
/FS_USAGE_NFDBITS
] |= (1 << ((fd
) % FS_USAGE_NFDBITS
));
3049 0 : File Descriptor bit is not set
3050 1 : File Descriptor bit is set
3054 fs_usage_fd_isset(thread
, fd
)
3055 unsigned int thread
;
3059 fd_threadmap
*fdmap
;
3061 if(!(fdmap
= find_fd_thread_map(thread
)))
3064 if (fdmap
->fd_setptr
== (unsigned long *)0)
3067 if (fd
< fdmap
->fd_setsize
)
3068 ret
= fdmap
->fd_setptr
[fd
/FS_USAGE_NFDBITS
] & (1 << (fd
% FS_USAGE_NFDBITS
));
3074 fs_usage_fd_clear(thread
, fd
)
3075 unsigned int thread
;
3080 if (!(map
= find_fd_thread_map(thread
)))
3083 if (map
->fd_setptr
== (unsigned long *)0)
3087 if (fd
< map
->fd_setsize
)
3088 map
->fd_setptr
[fd
/FS_USAGE_NFDBITS
] &= ~(1 << (fd
% FS_USAGE_NFDBITS
));
3095 * ret = 1 means print the entry
3096 * ret = 0 means don't print the entry
3099 check_filter_mode(struct th_info
* ti
, int type
, int error
, int retval
, char *sc_name
)
3102 int network_fd_isset
= 0;
3105 if (filter_mode
== DEFAULT_DO_NOT_FILTER
)
3108 if (filter_mode
& CACHEHIT_FILTER
)
3110 /* Do not print if cachehit filter is set */
3111 if (!strcmp (sc_name
, "CACHE_HIT"))
3115 if (ti
== (struct th_info
*)0)
3117 if(filter_mode
& FILESYS_FILTER
)
3127 network_fd_isset
= fs_usage_fd_isset(ti
->thread
, fd
);
3130 fs_usage_fd_clear(ti
->thread
,fd
);
3133 if (network_fd_isset
)
3135 if (filter_mode
& NETWORK_FILTER
)
3138 else if (filter_mode
& FILESYS_FILTER
)
3143 /* we don't care about error in this case */
3145 network_fd_isset
= fs_usage_fd_isset(ti
->thread
, fd
);
3146 if (network_fd_isset
)
3148 if (filter_mode
& NETWORK_FILTER
)
3151 else if (filter_mode
& FILESYS_FILTER
)
3158 fs_usage_fd_set(ti
->thread
, fd
);
3159 if (filter_mode
& NETWORK_FILTER
)
3171 fs_usage_fd_set(ti
->thread
, fd
);
3172 if (filter_mode
& NETWORK_FILTER
)
3176 case BSC_socketpair
:
3177 /* Cannot determine info about file descriptors */
3178 if (filter_mode
& NETWORK_FILTER
)
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
)
3188 /* then we are duping a socket descriptor */
3189 fd
= retval
; /* the new fd */
3190 fs_usage_fd_set(ti
->thread
, fd
);
3195 if (filter_mode
& FILESYS_FILTER
)
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.
3211 init_arguments_buffer()
3218 mib
[1] = KERN_ARGMAX
;
3219 size
= sizeof(argmax
);
3220 if (sysctl(mib
, 2, &argmax
, &size
, NULL
, 0) == -1)
3224 /* Hack to avoid kernel bug. */
3225 if (argmax
> 8192) {
3230 arguments
= (char *)malloc(argmax
);
3237 get_real_command_name(int pid
, char *cbuf
, int csize
)
3240 * Get command and arguments.
3244 char *command_beg
, *command
, *command_end
;
3251 bzero(arguments
, argmax
);
3256 * A sysctl() is made to find out the full path that the command
3260 mib
[1] = KERN_PROCARGS
;
3264 if (sysctl(mib
, 3, arguments
, (size_t *)&argmax
, NULL
, 0) < 0) {
3268 /* Skip the saved exec_path. */
3269 for (cp
= arguments
; cp
< &arguments
[argmax
]; cp
++) {
3271 /* End of exec_path reached. */
3275 if (cp
== &arguments
[argmax
]) {
3279 /* Skip trailing '\0' characters. */
3280 for (; cp
< &arguments
[argmax
]; cp
++) {
3282 /* Beginning of first argument reached. */
3286 if (cp
== &arguments
[argmax
]) {
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..
3296 for (; cp
< &arguments
[argmax
]; cp
++) {
3298 /* End of first argument reached. */
3302 if (cp
== &arguments
[argmax
]) {
3305 command_end
= command
= cp
;
3307 /* Get the basename of command. */
3308 for (command
--; command
>= command_beg
; command
--) {
3309 if (*command
== '/') {
3315 (void) strncpy(cbuf
, (char *)command
, csize
);
3316 cbuf
[csize
-1] = '\0';