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. -DPRIVATE -D__APPLE_PRIVATE -O -o fs_usage fs_usage.c
29 #define Default_DELAY 1 /* default delay interval */
41 #include <sys/types.h>
42 #include <sys/param.h>
47 #include <sys/ioctl.h>
48 #include <sys/socket.h>
51 #ifndef KERNEL_PRIVATE
52 #define KERNEL_PRIVATE
53 #include <sys/kdebug.h>
56 #include <sys/kdebug.h>
57 #endif /*KERNEL_PRIVATE*/
59 #include <sys/sysctl.h>
62 #import <mach/clock_types.h>
63 #import <mach/mach_time.h>
67 #define F_OPENFROM 56 /* SPI: open a file relative to fd (must be a dir) */
68 #define F_UNLINKFROM 57 /* SPI: open a file relative to fd (must be a dir) */
69 #define F_CHECK_OPENEVT 58 /* SPI: if a process is marked OPENEVT, or in O_EVTONLY on opens of this vnode */
74 typedef struct LibraryRange
{
79 LibraryRange framework32
;
80 LibraryRange framework64
;
92 char *frameworkType
[] = {
103 typedef struct LibraryInfo
{
110 LibraryInfo frameworkInfo
[MAXINDEX
];
111 int numFrameworks
= 0;
113 void lookup_name(uint64_t user_addr
, char **type
, char **name
);
117 MAXCOLS controls when extra data kicks in.
118 MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path.
119 If NUMPARMS changes to match the kernel, it will automatically
120 get reflected in the -w mode output.
123 #define PATHLENGTH (NUMPARMS*sizeof(uintptr_t))
125 #define MAX_WIDE_MODE_COLS (PATHLENGTH + 80)
126 #define MAXWIDTH MAX_WIDE_MODE_COLS + 64
142 uintptr_t child_thread
;
146 uintptr_t pathname
[NUMPARMS
+ 1]; /* add room for null terminator */
149 #define MAX_THREADS 1024
150 struct th_info th_state
[MAX_THREADS
];
152 kd_threadmap
*last_map
= NULL
;
154 int map_is_the_same
= 0;
156 int filemgr_in_progress
= 0;
157 int execs_in_progress
= 0;
160 int need_new_map
= 1;
165 int select_pid_mode
= 0; /* Flag set indicates that output is restricted
166 to selected pids or commands */
168 int one_good_pid
= 0; /* Used to fail gracefully when bad pids given */
175 #define USLEEP_BEHIND 2
176 #define USLEEP_MAX 32
177 int usleep_ms
= USLEEP_MIN
;
180 * Network only or filesystem only output filter
181 * Default of zero means report all activity - no filtering
183 #define FILESYS_FILTER 0x01
184 #define NETWORK_FILTER 0x02
185 #define CACHEHIT_FILTER 0x04
186 #define EXEC_FILTER 0x08
187 #define PATHNAME_FILTER 0x10
188 #define DEFAULT_DO_NOT_FILTER 0x00
190 int filter_mode
= CACHEHIT_FILTER
;
195 struct diskrec
*next
;
209 uintptr_t issuing_thread
;
210 uintptr_t completion_thread
;
211 char issuing_command
[MAXCOMLEN
];
213 double completed_time
;
216 struct diskrec
*disk_list
= NULL
;
217 struct diskio
*free_diskios
= NULL
;
218 struct diskio
*busy_diskios
= NULL
;
222 struct diskio
*insert_diskio();
223 struct diskio
*complete_diskio();
226 void format_print(struct th_info
*, char *, uintptr_t, int, int, int, int, int, int, double, double, int, char *, struct diskio
*);
227 void enter_syscall_now(uintptr_t, int, kd_buf
*, char *, double);
228 void enter_syscall(uintptr_t, int, kd_buf
*, char *, double);
229 void exit_syscall(char *, uintptr_t, int, int, int, int, int, int, double);
230 void extend_syscall(uintptr_t, int, kd_buf
*);
231 char *find_disk_name();
232 void cache_disk_names();
233 void recache_disk_names();
234 int ReadSharedCacheMap(const char *, LibraryRange
*, char *);
235 void SortFrameworkAddresses();
236 void mark_thread_waited(uintptr_t);
237 int check_filter_mode(struct th_info
*, int, int, int, char *);
238 void fs_usage_fd_set(unsigned int, unsigned int);
239 int fs_usage_fd_isset(unsigned int, unsigned int);
240 void fs_usage_fd_clear(unsigned int, unsigned int);
241 void init_arguments_buffer();
242 int get_real_command_name(int, char *, int);
243 void create_map_entry(uintptr_t, int, char *);
244 void kill_thread_map(uintptr_t);
246 #define CLASS_MASK 0xff000000
247 #define CSC_MASK 0xffff0000
248 #define BSC_INDEX(type) ((type >> 2) & 0x3fff)
251 #define TRACE_DATA_NEWTHREAD 0x07000004
252 #define TRACE_DATA_EXEC 0x07000008
253 #define TRACE_STRING_NEWTHREAD 0x07010004
254 #define TRACE_STRING_EXEC 0x07010008
256 #define MACH_vmfault 0x01300008
257 #define MACH_pageout 0x01300004
258 #define MACH_sched 0x01400000
259 #define MACH_stkhandoff 0x01400008
260 #define MACH_idle 0x01400024
261 #define VFS_LOOKUP 0x03010090
262 #define BSC_exit 0x040C0004
264 #define SPEC_ioctl 0x3060000
266 #define P_DISKIO 0x03020000
267 #define P_DISKIO_DONE 0x03020004
268 #define P_DISKIO_MASK (CSC_MASK | 0x4)
270 #define P_WrData 0x03020000
271 #define P_RdData 0x03020008
272 #define P_WrMeta 0x03020020
273 #define P_RdMeta 0x03020028
274 #define P_PgOut 0x03020040
275 #define P_PgIn 0x03020048
276 #define P_WrDataAsync 0x03020010
277 #define P_RdDataAsync 0x03020018
278 #define P_WrMetaAsync 0x03020030
279 #define P_RdMetaAsync 0x03020038
280 #define P_PgOutAsync 0x03020050
281 #define P_PgInAsync 0x03020058
283 #define P_WrDataDone 0x03020004
284 #define P_RdDataDone 0x0302000C
285 #define P_WrMetaDone 0x03020024
286 #define P_RdMetaDone 0x0302002C
287 #define P_PgOutDone 0x03020044
288 #define P_PgInDone 0x0302004C
289 #define P_WrDataAsyncDone 0x03020014
290 #define P_RdDataAsyncDone 0x0302001C
291 #define P_WrMetaAsyncDone 0x03020034
292 #define P_RdMetaAsyncDone 0x0302003C
293 #define P_PgOutAsyncDone 0x03020054
294 #define P_PgInAsyncDone 0x0302005C
297 #define MSC_map_fd 0x010c00ac
299 #define BSC_BASE 0x040C0000
300 #define MSC_BASE 0x010C0000
302 // Network related codes
303 #define BSC_recvmsg 0x040C006C
304 #define BSC_sendmsg 0x040C0070
305 #define BSC_recvfrom 0x040C0074
306 #define BSC_accept 0x040C0078
307 #define BSC_select 0x040C0174
308 #define BSC_socket 0x040C0184
309 #define BSC_connect 0x040C0188
310 #define BSC_bind 0x040C01A0
311 #define BSC_listen 0x040C01A8
312 #define BSC_sendto 0x040C0214
313 #define BSC_socketpair 0x040C021C
315 #define BSC_read 0x040C000C
316 #define BSC_write 0x040C0010
317 #define BSC_open 0x040C0014
318 #define BSC_close 0x040C0018
319 #define BSC_link 0x040C0024
320 #define BSC_unlink 0x040C0028
321 #define BSC_chdir 0x040c0030
322 #define BSC_fchdir 0x040c0034
323 #define BSC_mknod 0x040C0038
324 #define BSC_chmod 0x040C003C
325 #define BSC_chown 0x040C0040
326 #define BSC_getfsstat 0x040C0048
327 #define BSC_access 0x040C0084
328 #define BSC_chflags 0x040C0088
329 #define BSC_fchflags 0x040C008C
330 #define BSC_sync 0x040C0090
331 #define BSC_dup 0x040C00A4
332 #define BSC_ioctl 0x040C00D8
333 #define BSC_revoke 0x040C00E0
334 #define BSC_symlink 0x040C00E4
335 #define BSC_readlink 0x040C00E8
336 #define BSC_execve 0x040C00EC
337 #define BSC_umask 0x040C00F0
338 #define BSC_chroot 0x040C00F4
339 #define BSC_msync 0x040C0104
340 #define BSC_dup2 0x040C0168
341 #define BSC_fcntl 0x040C0170
342 #define BSC_fsync 0x040C017C
343 #define BSC_readv 0x040C01E0
344 #define BSC_writev 0x040C01E4
345 #define BSC_fchown 0x040C01EC
346 #define BSC_fchmod 0x040C01F0
347 #define BSC_rename 0x040C0200
348 #define BSC_mkfifo 0x040c0210
349 #define BSC_mkdir 0x040C0220
350 #define BSC_rmdir 0x040C0224
351 #define BSC_utimes 0x040C0228
352 #define BSC_futimes 0x040C022C
353 #define BSC_pread 0x040C0264
354 #define BSC_pwrite 0x040C0268
355 #define BSC_statfs 0x040C0274
356 #define BSC_fstatfs 0x040C0278
357 #define BSC_stat 0x040C02F0
358 #define BSC_fstat 0x040C02F4
359 #define BSC_lstat 0x040C02F8
360 #define BSC_pathconf 0x040C02FC
361 #define BSC_fpathconf 0x040C0300
362 #define BSC_getdirentries 0x040C0310
363 #define BSC_mmap 0x040c0314
364 #define BSC_lseek 0x040c031c
365 #define BSC_truncate 0x040C0320
366 #define BSC_ftruncate 0x040C0324
367 #define BSC_undelete 0x040C0334
368 #define BSC_statv 0x040C0364
369 #define BSC_lstatv 0x040C0368
370 #define BSC_fstatv 0x040C036C
371 #define BSC_mkcomplex 0x040C0360
372 #define BSC_getattrlist 0x040C0370
373 #define BSC_setattrlist 0x040C0374
374 #define BSC_getdirentriesattr 0x040C0378
375 #define BSC_exchangedata 0x040C037C
376 #define BSC_checkuseraccess 0x040C0380
377 #define BSC_searchfs 0x040C0384
378 #define BSC_delete 0x040C0388
379 #define BSC_copyfile 0x040C038C
380 #define BSC_getxattr 0x040C03A8
381 #define BSC_fgetxattr 0x040C03AC
382 #define BSC_setxattr 0x040C03B0
383 #define BSC_fsetxattr 0x040C03B4
384 #define BSC_removexattr 0x040C03B8
385 #define BSC_fremovexattr 0x040C03BC
386 #define BSC_listxattr 0x040C03C0
387 #define BSC_flistxattr 0x040C03C4
388 #define BSC_fsctl 0x040C03C8
389 #define BSC_open_extended 0x040C0454
390 #define BSC_stat_extended 0x040C045C
391 #define BSC_lstat_extended 0x040C0460
392 #define BSC_fstat_extended 0x040C0464
393 #define BSC_chmod_extended 0x040C0468
394 #define BSC_fchmod_extended 0x040C046C
395 #define BSC_access_extended 0x040C0470
396 #define BSC_mkfifo_extended 0x040C048C
397 #define BSC_mkdir_extended 0x040C0490
398 #define BSC_load_shared_file 0x040C04A0
399 #define BSC_aio_fsync 0x040C04E4
400 #define BSC_aio_return 0x040C04E8
401 #define BSC_aio_suspend 0x040C04EC
402 #define BSC_aio_cancel 0x040C04F0
403 #define BSC_aio_error 0x040C04F4
404 #define BSC_aio_read 0x040C04F8
405 #define BSC_aio_write 0x040C04FC
406 #define BSC_lio_listio 0x040C0500
407 #define BSC_sendfile 0x040C0544
408 #define BSC_stat64 0x040C0548
409 #define BSC_fstat64 0x040C054C
410 #define BSC_lstat64 0x040C0550
411 #define BSC_stat64_extended 0x040C0554
412 #define BSC_lstat64_extended 0x040C0558
413 #define BSC_fstat64_extended 0x040C055C
414 #define BSC_getdirentries64 0x040C0560
415 #define BSC_statfs64 0x040C0564
416 #define BSC_fstatfs64 0x040C0568
417 #define BSC_getfsstat64 0x040C056C
418 #define BSC_pthread_chdir 0x040C0570
419 #define BSC_pthread_fchdir 0x040C0574
420 #define BSC_lchown 0x040C05B0
422 #define BSC_read_nocancel 0x040c0630
423 #define BSC_write_nocancel 0x040c0634
424 #define BSC_open_nocancel 0x040c0638
425 #define BSC_close_nocancel 0x040c063c
426 #define BSC_recvmsg_nocancel 0x040c0644
427 #define BSC_sendmsg_nocancel 0x040c0648
428 #define BSC_recvfrom_nocancel 0x040c064c
429 #define BSC_accept_nocancel 0x040c0650
430 #define BSC_msync_nocancel 0x040c0654
431 #define BSC_fcntl_nocancel 0x040c0658
432 #define BSC_select_nocancel 0x040c065c
433 #define BSC_fsync_nocancel 0x040c0660
434 #define BSC_connect_nocancel 0x040c0664
435 #define BSC_readv_nocancel 0x040c066c
436 #define BSC_writev_nocancel 0x040c0670
437 #define BSC_sendto_nocancel 0x040c0674
438 #define BSC_pread_nocancel 0x040c0678
439 #define BSC_pwrite_nocancel 0x040c067c
440 #define BSC_aio_suspend_nocancel 0x40c0694
442 #define BSC_msync_extended 0x040e0104
443 #define BSC_pread_extended 0x040e0264
444 #define BSC_pwrite_extended 0x040e0268
445 #define BSC_mmap_extended 0x040e0314
446 #define BSC_mmap_extended2 0x040f0314
448 // Carbon File Manager support
449 #define FILEMGR_PBGETCATALOGINFO 0x1e000020
450 #define FILEMGR_PBGETCATALOGINFOBULK 0x1e000024
451 #define FILEMGR_PBCREATEFILEUNICODE 0x1e000028
452 #define FILEMGR_PBCREATEDIRECTORYUNICODE 0x1e00002c
453 #define FILEMGR_PBCREATEFORK 0x1e000030
454 #define FILEMGR_PBDELETEFORK 0x1e000034
455 #define FILEMGR_PBITERATEFORK 0x1e000038
456 #define FILEMGR_PBOPENFORK 0x1e00003c
457 #define FILEMGR_PBREADFORK 0x1e000040
458 #define FILEMGR_PBWRITEFORK 0x1e000044
459 #define FILEMGR_PBALLOCATEFORK 0x1e000048
460 #define FILEMGR_PBDELETEOBJECT 0x1e00004c
461 #define FILEMGR_PBEXCHANGEOBJECT 0x1e000050
462 #define FILEMGR_PBGETFORKCBINFO 0x1e000054
463 #define FILEMGR_PBGETVOLUMEINFO 0x1e000058
464 #define FILEMGR_PBMAKEFSREF 0x1e00005c
465 #define FILEMGR_PBMAKEFSREFUNICODE 0x1e000060
466 #define FILEMGR_PBMOVEOBJECT 0x1e000064
467 #define FILEMGR_PBOPENITERATOR 0x1e000068
468 #define FILEMGR_PBRENAMEUNICODE 0x1e00006c
469 #define FILEMGR_PBSETCATALOGINFO 0x1e000070
470 #define FILEMGR_PBSETVOLUMEINFO 0x1e000074
471 #define FILEMGR_FSREFMAKEPATH 0x1e000078
472 #define FILEMGR_FSPATHMAKEREF 0x1e00007c
474 #define FILEMGR_PBGETCATINFO 0x1e010000
475 #define FILEMGR_PBGETCATINFOLITE 0x1e010004
476 #define FILEMGR_PBHGETFINFO 0x1e010008
477 #define FILEMGR_PBXGETVOLINFO 0x1e01000c
478 #define FILEMGR_PBHCREATE 0x1e010010
479 #define FILEMGR_PBHOPENDF 0x1e010014
480 #define FILEMGR_PBHOPENRF 0x1e010018
481 #define FILEMGR_PBHGETDIRACCESS 0x1e01001c
482 #define FILEMGR_PBHSETDIRACCESS 0x1e010020
483 #define FILEMGR_PBHMAPID 0x1e010024
484 #define FILEMGR_PBHMAPNAME 0x1e010028
485 #define FILEMGR_PBCLOSE 0x1e01002c
486 #define FILEMGR_PBFLUSHFILE 0x1e010030
487 #define FILEMGR_PBGETEOF 0x1e010034
488 #define FILEMGR_PBSETEOF 0x1e010038
489 #define FILEMGR_PBGETFPOS 0x1e01003c
490 #define FILEMGR_PBREAD 0x1e010040
491 #define FILEMGR_PBWRITE 0x1e010044
492 #define FILEMGR_PBGETFCBINFO 0x1e010048
493 #define FILEMGR_PBSETFINFO 0x1e01004c
494 #define FILEMGR_PBALLOCATE 0x1e010050
495 #define FILEMGR_PBALLOCCONTIG 0x1e010054
496 #define FILEMGR_PBSETFPOS 0x1e010058
497 #define FILEMGR_PBSETCATINFO 0x1e01005c
498 #define FILEMGR_PBGETVOLPARMS 0x1e010060
499 #define FILEMGR_PBSETVINFO 0x1e010064
500 #define FILEMGR_PBMAKEFSSPEC 0x1e010068
501 #define FILEMGR_PBHGETVINFO 0x1e01006c
502 #define FILEMGR_PBCREATEFILEIDREF 0x1e010070
503 #define FILEMGR_PBDELETEFILEIDREF 0x1e010074
504 #define FILEMGR_PBRESOLVEFILEIDREF 0x1e010078
505 #define FILEMGR_PBFLUSHVOL 0x1e01007c
506 #define FILEMGR_PBHRENAME 0x1e010080
507 #define FILEMGR_PBCATMOVE 0x1e010084
508 #define FILEMGR_PBEXCHANGEFILES 0x1e010088
509 #define FILEMGR_PBHDELETE 0x1e01008c
510 #define FILEMGR_PBDIRCREATE 0x1e010090
511 #define FILEMGR_PBCATSEARCH 0x1e010094
512 #define FILEMGR_PBHSETFLOCK 0x1e010098
513 #define FILEMGR_PBHRSTFLOCK 0x1e01009c
514 #define FILEMGR_PBLOCKRANGE 0x1e0100a0
515 #define FILEMGR_PBUNLOCKRANGE 0x1e0100a4
518 #define FILEMGR_CLASS 0x1e
519 #define FILEMGR_BASE 0x1e000000
521 #define FMT_DEFAULT 0
528 #define FMT_CACHEHIT 7
532 #define FMT_FTRUNC 11
534 #define FMT_SELECT 13
536 #define FMT_AIO_FSYNC 15
537 #define FMT_AIO_RETURN 16
538 #define FMT_AIO_SUSPEND 17
539 #define FMT_AIO_CANCEL 18
541 #define FMT_LIO_LISTIO 20
544 #define FMT_ACCESS 23
546 #define FMT_FCHMOD 25
547 #define FMT_CHMOD_EXT 26
548 #define FMT_FCHMOD_EXT 27
549 #define FMT_CHFLAGS 28
550 #define FMT_FCHFLAGS 29
554 #define FMT_SENDFILE 33
555 #define FMT_SPEC_IOCTL 34
557 #define MAX_BSD_SYSCALL 512
562 } bsd_syscalls
[MAX_BSD_SYSCALL
];
565 int bsd_syscall_types
[] = {
567 BSC_recvmsg_nocancel
,
569 BSC_sendmsg_nocancel
,
571 BSC_recvfrom_nocancel
,
578 BSC_connect_nocancel
,
648 BSC_getdirentriesattr
,
672 BSC_load_shared_file
,
676 BSC_aio_suspend_nocancel
,
693 BSC_lstat64_extended
,
694 BSC_fstat64_extended
,
706 #define MAX_FILEMGR 512
708 struct filemgr_call
{
710 } filemgr_calls
[MAX_FILEMGR
];
713 int filemgr_call_types
[] = {
714 FILEMGR_PBGETCATALOGINFO
,
715 FILEMGR_PBGETCATALOGINFOBULK
,
716 FILEMGR_PBCREATEFILEUNICODE
,
717 FILEMGR_PBCREATEDIRECTORYUNICODE
,
718 FILEMGR_PBCREATEFORK
,
719 FILEMGR_PBDELETEFORK
,
720 FILEMGR_PBITERATEFORK
,
724 FILEMGR_PBALLOCATEFORK
,
725 FILEMGR_PBDELETEOBJECT
,
726 FILEMGR_PBEXCHANGEOBJECT
,
727 FILEMGR_PBGETFORKCBINFO
,
728 FILEMGR_PBGETVOLUMEINFO
,
730 FILEMGR_PBMAKEFSREFUNICODE
,
731 FILEMGR_PBMOVEOBJECT
,
732 FILEMGR_PBOPENITERATOR
,
733 FILEMGR_PBRENAMEUNICODE
,
734 FILEMGR_PBSETCATALOGINFO
,
735 FILEMGR_PBSETVOLUMEINFO
,
736 FILEMGR_FSREFMAKEPATH
,
737 FILEMGR_FSPATHMAKEREF
,
739 FILEMGR_PBGETCATINFO
,
740 FILEMGR_PBGETCATINFOLITE
,
742 FILEMGR_PBXGETVOLINFO
,
746 FILEMGR_PBHGETDIRACCESS
,
747 FILEMGR_PBHSETDIRACCESS
,
757 FILEMGR_PBGETFCBINFO
,
760 FILEMGR_PBALLOCCONTIG
,
762 FILEMGR_PBSETCATINFO
,
763 FILEMGR_PBGETVOLPARMS
,
765 FILEMGR_PBMAKEFSSPEC
,
767 FILEMGR_PBCREATEFILEIDREF
,
768 FILEMGR_PBDELETEFILEIDREF
,
769 FILEMGR_PBRESOLVEFILEIDREF
,
773 FILEMGR_PBEXCHANGEFILES
,
780 FILEMGR_PBUNLOCKRANGE
,
790 int exclude_pids
= 0;
791 int exclude_default_pids
= 1;
794 struct kinfo_proc
*kp_buffer
= 0;
799 #define EVENT_BASE 60000
801 int num_events
= EVENT_BASE
;
804 #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END)
805 #define DBG_FUNC_MASK 0xfffffffc
807 double divisor
= 0.0; /* Trace divisor converts to microseconds */
813 kbufinfo_t bufinfo
= {0, 0, 0, 0, 0};
815 int total_threads
= 0;
816 kd_threadmap
*mapptr
= 0; /* pointer to list of threads */
818 /* defines for tracking file descriptor state */
819 #define FS_USAGE_FD_SETSIZE 256 /* Initial number of file descriptors per
820 thread that we will track */
822 #define FS_USAGE_NFDBITS (sizeof (unsigned long) * 8)
823 #define FS_USAGE_NFDBYTES(n) (((n) / FS_USAGE_NFDBITS) * sizeof (unsigned long))
826 unsigned int fd_valid
; /* set if this is a valid entry */
828 unsigned int fd_setsize
; /* this is a bit count */
829 unsigned long *fd_setptr
; /* file descripter bitmap */
832 fd_threadmap
*fdmapptr
= 0; /* pointer to list of threads for fd tracking */
834 int trace_enabled
= 0;
835 int set_remove_flag
= 1;
837 char *RAW_file
= (char *)0;
840 double bias_now
= 0.0;
841 double start_time
= 0.0;
842 double end_time
= 99999999999.9;
855 void leave() /* exit under normal conditions -- INT handler */
860 void set_pidexclude();
867 if (exclude_pids
== 0) {
868 for (i
= 0; i
< num_of_pids
; i
++)
869 set_pidcheck(pids
[i
], 0);
872 for (i
= 0; i
< num_of_pids
; i
++)
873 set_pidexclude(pids
[i
], 0);
880 void get_screenwidth()
887 if (ioctl(1, TIOCGWINSZ
, &size
) != -1) {
888 columns
= size
.ws_col
;
890 if (columns
> MAXWIDTH
)
904 exit_usage(char *myname
) {
906 fprintf(stderr
, "Usage: %s [-e] [-w] [-f mode] [pid | cmd [pid | cmd]....]\n", myname
);
907 fprintf(stderr
, " -e exclude the specified list of pids from the sample\n");
908 fprintf(stderr
, " and exclude fs_usage by default\n");
909 fprintf(stderr
, " -w force wider, detailed, output\n");
910 fprintf(stderr
, " -f Output is based on the mode provided\n");
911 fprintf(stderr
, " mode = \"network\" Show only network related output\n");
912 fprintf(stderr
, " mode = \"filesys\" Show only file system related output\n");
913 fprintf(stderr
, " mode = \"pathname\" Show only pathname related output\n");
914 fprintf(stderr
, " mode = \"exec\" Show only execs\n");
915 fprintf(stderr
, " mode = \"cachehit\" In addition, show cachehits\n");
916 fprintf(stderr
, " pid selects process(s) to sample\n");
917 fprintf(stderr
, " cmd selects process(s) matching command string to sample\n");
918 fprintf(stderr
, "\n%s will handle a maximum list of %d pids.\n\n", myname
, MAX_PIDS
);
919 fprintf(stderr
, "By default (no options) the following processes are excluded from the output:\n");
920 fprintf(stderr
, "fs_usage, Terminal, telnetd, sshd, rlogind, tcsh, csh, sh\n\n");
926 int filemgr_index(type
) {
929 return (((type
>> 2) & 0x3fff) + 256);
931 return (((type
>> 2) & 0x3fff));
935 void init_tables(void)
940 for (i
= 0; i
< MAX_THREADS
; i
++)
941 th_state
[i
].my_index
= i
;
943 for (i
= 0; i
< MAX_BSD_SYSCALL
; i
++) {
944 bsd_syscalls
[i
].sc_name
= NULL
;
945 bsd_syscalls
[i
].sc_format
= FMT_DEFAULT
;
948 for (i
= 0; i
< MAX_FILEMGR
; i
++) {
949 filemgr_calls
[i
].fm_name
= NULL
;
952 for (i
= 0; (type
= bsd_syscall_types
[i
]); i
++) {
954 code
= BSC_INDEX(type
);
956 if (code
>= MAX_BSD_SYSCALL
) {
957 printf("BSD syscall init (%x): type exceeds table size\n", type
);
963 bsd_syscalls
[code
].sc_name
= "sendfile";
964 bsd_syscalls
[code
].sc_format
= FMT_FD
; /* this should be changed to FMT_SENDFILE */
965 break; /* once we add an extended info trace event */
968 case BSC_recvmsg_nocancel
:
969 bsd_syscalls
[code
].sc_name
= "recvmsg";
970 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
974 case BSC_sendmsg_nocancel
:
975 bsd_syscalls
[code
].sc_name
= "sendmsg";
976 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
980 case BSC_recvfrom_nocancel
:
981 bsd_syscalls
[code
].sc_name
= "recvfrom";
982 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
986 case BSC_sendto_nocancel
:
987 bsd_syscalls
[code
].sc_name
= "sendto";
988 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
992 case BSC_select_nocancel
:
993 bsd_syscalls
[code
].sc_name
= "select";
994 bsd_syscalls
[code
].sc_format
= FMT_SELECT
;
998 case BSC_accept_nocancel
:
999 bsd_syscalls
[code
].sc_name
= "accept";
1000 bsd_syscalls
[code
].sc_format
= FMT_FD_2
;
1004 bsd_syscalls
[code
].sc_name
= "socket";
1005 bsd_syscalls
[code
].sc_format
= FMT_SOCKET
;
1009 case BSC_connect_nocancel
:
1010 bsd_syscalls
[code
].sc_name
= "connect";
1011 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1015 bsd_syscalls
[code
].sc_name
= "bind";
1016 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1020 bsd_syscalls
[code
].sc_name
= "listen";
1021 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1025 bsd_syscalls
[code
].sc_name
= "mmap";
1026 bsd_syscalls
[code
].sc_format
= FMT_MMAP
;
1029 case BSC_socketpair
:
1030 bsd_syscalls
[code
].sc_name
= "socketpair";
1034 bsd_syscalls
[code
].sc_name
= "getxattr";
1038 bsd_syscalls
[code
].sc_name
= "setxattr";
1041 case BSC_removexattr
:
1042 bsd_syscalls
[code
].sc_name
= "removexattr";
1046 bsd_syscalls
[code
].sc_name
= "listxattr";
1050 bsd_syscalls
[code
].sc_name
= "stat";
1054 bsd_syscalls
[code
].sc_name
= "stat64";
1057 case BSC_stat_extended
:
1058 bsd_syscalls
[code
].sc_name
= "stat_extended";
1061 case BSC_stat64_extended
:
1062 bsd_syscalls
[code
].sc_name
= "stat_extended64";
1066 bsd_syscalls
[code
].sc_name
= "execve";
1069 case BSC_load_shared_file
:
1070 bsd_syscalls
[code
].sc_name
= "load_sf";
1074 case BSC_open_nocancel
:
1075 bsd_syscalls
[code
].sc_name
= "open";
1076 bsd_syscalls
[code
].sc_format
= FMT_OPEN
;
1079 case BSC_open_extended
:
1080 bsd_syscalls
[code
].sc_name
= "open_extended";
1081 bsd_syscalls
[code
].sc_format
= FMT_OPEN
;
1085 bsd_syscalls
[code
].sc_name
= "dup";
1086 bsd_syscalls
[code
].sc_format
= FMT_FD_2
;
1090 bsd_syscalls
[code
].sc_name
= "dup2";
1091 bsd_syscalls
[code
].sc_format
= FMT_FD_2
;
1095 case BSC_close_nocancel
:
1096 bsd_syscalls
[code
].sc_name
= "close";
1097 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1101 case BSC_read_nocancel
:
1102 bsd_syscalls
[code
].sc_name
= "read";
1103 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1107 case BSC_write_nocancel
:
1108 bsd_syscalls
[code
].sc_name
= "write";
1109 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1113 bsd_syscalls
[code
].sc_name
= "fgetxattr";
1114 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1118 bsd_syscalls
[code
].sc_name
= "fsetxattr";
1119 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1122 case BSC_fremovexattr
:
1123 bsd_syscalls
[code
].sc_name
= "fremovexattr";
1124 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1127 case BSC_flistxattr
:
1128 bsd_syscalls
[code
].sc_name
= "flistxattr";
1129 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1133 bsd_syscalls
[code
].sc_name
= "fstat";
1134 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1138 bsd_syscalls
[code
].sc_name
= "fstat64";
1139 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1142 case BSC_fstat_extended
:
1143 bsd_syscalls
[code
].sc_name
= "fstat_extended";
1144 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1147 case BSC_fstat64_extended
:
1148 bsd_syscalls
[code
].sc_name
= "fstat64_extended";
1149 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1153 bsd_syscalls
[code
].sc_name
= "lstat";
1157 bsd_syscalls
[code
].sc_name
= "lstat64";
1160 case BSC_lstat_extended
:
1161 bsd_syscalls
[code
].sc_name
= "lstat_extended";
1164 case BSC_lstat64_extended
:
1165 bsd_syscalls
[code
].sc_name
= "lstat_extended64";
1169 bsd_syscalls
[code
].sc_name
= "lstatv";
1173 bsd_syscalls
[code
].sc_name
= "link";
1177 bsd_syscalls
[code
].sc_name
= "unlink";
1181 bsd_syscalls
[code
].sc_name
= "mknod";
1185 bsd_syscalls
[code
].sc_name
= "umask";
1186 bsd_syscalls
[code
].sc_format
= FMT_UMASK
;
1190 bsd_syscalls
[code
].sc_name
= "chmod";
1191 bsd_syscalls
[code
].sc_format
= FMT_CHMOD
;
1194 case BSC_chmod_extended
:
1195 bsd_syscalls
[code
].sc_name
= "chmod_extended";
1196 bsd_syscalls
[code
].sc_format
= FMT_CHMOD_EXT
;
1200 bsd_syscalls
[code
].sc_name
= "fchmod";
1201 bsd_syscalls
[code
].sc_format
= FMT_FCHMOD
;
1204 case BSC_fchmod_extended
:
1205 bsd_syscalls
[code
].sc_name
= "fchmod_extended";
1206 bsd_syscalls
[code
].sc_format
= FMT_FCHMOD_EXT
;
1210 bsd_syscalls
[code
].sc_name
= "chown";
1214 bsd_syscalls
[code
].sc_name
= "lchown";
1218 bsd_syscalls
[code
].sc_name
= "fchown";
1219 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1223 bsd_syscalls
[code
].sc_name
= "access";
1224 bsd_syscalls
[code
].sc_format
= FMT_ACCESS
;
1227 case BSC_access_extended
:
1228 bsd_syscalls
[code
].sc_name
= "access_extended";
1232 bsd_syscalls
[code
].sc_name
= "chdir";
1235 case BSC_pthread_chdir
:
1236 bsd_syscalls
[code
].sc_name
= "pthread_chdir";
1240 bsd_syscalls
[code
].sc_name
= "chroot";
1244 bsd_syscalls
[code
].sc_name
= "utimes";
1248 bsd_syscalls
[code
].sc_name
= "delete-Carbon";
1252 bsd_syscalls
[code
].sc_name
= "undelete";
1256 bsd_syscalls
[code
].sc_name
= "revoke";
1260 bsd_syscalls
[code
].sc_name
= "fsctl";
1264 bsd_syscalls
[code
].sc_name
= "chflags";
1265 bsd_syscalls
[code
].sc_format
= FMT_CHFLAGS
;
1269 bsd_syscalls
[code
].sc_name
= "fchflags";
1270 bsd_syscalls
[code
].sc_format
= FMT_FCHFLAGS
;
1274 bsd_syscalls
[code
].sc_name
= "fchdir";
1275 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1278 case BSC_pthread_fchdir
:
1279 bsd_syscalls
[code
].sc_name
= "pthread_fchdir";
1280 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1284 bsd_syscalls
[code
].sc_name
= "futimes";
1285 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1289 bsd_syscalls
[code
].sc_name
= "sync";
1293 bsd_syscalls
[code
].sc_name
= "symlink";
1297 bsd_syscalls
[code
].sc_name
= "readlink";
1301 case BSC_fsync_nocancel
:
1302 bsd_syscalls
[code
].sc_name
= "fsync";
1303 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1307 case BSC_readv_nocancel
:
1308 bsd_syscalls
[code
].sc_name
= "readv";
1309 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1313 case BSC_writev_nocancel
:
1314 bsd_syscalls
[code
].sc_name
= "writev";
1315 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1319 case BSC_pread_nocancel
:
1320 bsd_syscalls
[code
].sc_name
= "pread";
1321 bsd_syscalls
[code
].sc_format
= FMT_PREAD
;
1325 case BSC_pwrite_nocancel
:
1326 bsd_syscalls
[code
].sc_name
= "pwrite";
1327 bsd_syscalls
[code
].sc_format
= FMT_PREAD
;
1331 bsd_syscalls
[code
].sc_name
= "mkdir";
1334 case BSC_mkdir_extended
:
1335 bsd_syscalls
[code
].sc_name
= "mkdir_extended";
1339 bsd_syscalls
[code
].sc_name
= "mkfifo";
1342 case BSC_mkfifo_extended
:
1343 bsd_syscalls
[code
].sc_name
= "mkfifo_extended";
1347 bsd_syscalls
[code
].sc_name
= "rmdir";
1351 bsd_syscalls
[code
].sc_name
= "statfs";
1355 bsd_syscalls
[code
].sc_name
= "statfs64";
1359 bsd_syscalls
[code
].sc_name
= "getfsstat";
1362 case BSC_getfsstat64
:
1363 bsd_syscalls
[code
].sc_name
= "getfsstat64";
1367 bsd_syscalls
[code
].sc_name
= "fstatfs";
1368 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1372 bsd_syscalls
[code
].sc_name
= "fstatfs64";
1373 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1377 bsd_syscalls
[code
].sc_name
= "pathconf";
1381 bsd_syscalls
[code
].sc_name
= "fpathconf";
1382 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1385 case BSC_getdirentries
:
1386 bsd_syscalls
[code
].sc_name
= "getdirentries";
1387 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1390 case BSC_getdirentries64
:
1391 bsd_syscalls
[code
].sc_name
= "getdirentries64";
1392 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1396 bsd_syscalls
[code
].sc_name
= "lseek";
1397 bsd_syscalls
[code
].sc_format
= FMT_LSEEK
;
1401 bsd_syscalls
[code
].sc_name
= "truncate";
1402 bsd_syscalls
[code
].sc_format
= FMT_TRUNC
;
1406 bsd_syscalls
[code
].sc_name
= "ftruncate";
1407 bsd_syscalls
[code
].sc_format
= FMT_FTRUNC
;
1411 bsd_syscalls
[code
].sc_name
= "statv";
1415 bsd_syscalls
[code
].sc_name
= "fstatv";
1416 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1420 bsd_syscalls
[code
].sc_name
= "mkcomplex";
1423 case BSC_getattrlist
:
1424 bsd_syscalls
[code
].sc_name
= "getattrlist";
1427 case BSC_setattrlist
:
1428 bsd_syscalls
[code
].sc_name
= "setattrlist";
1431 case BSC_getdirentriesattr
:
1432 bsd_syscalls
[code
].sc_name
= "getdirentriesattr";
1433 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1436 case BSC_exchangedata
:
1437 bsd_syscalls
[code
].sc_name
= "exchangedata";
1441 bsd_syscalls
[code
].sc_name
= "rename";
1445 bsd_syscalls
[code
].sc_name
= "copyfile";
1448 case BSC_checkuseraccess
:
1449 bsd_syscalls
[code
].sc_name
= "checkuseraccess";
1453 bsd_syscalls
[code
].sc_name
= "searchfs";
1457 bsd_syscalls
[code
].sc_name
= "aio_fsync";
1458 bsd_syscalls
[code
].sc_format
= FMT_AIO_FSYNC
;
1461 case BSC_aio_return
:
1462 bsd_syscalls
[code
].sc_name
= "aio_return";
1463 bsd_syscalls
[code
].sc_format
= FMT_AIO_RETURN
;
1466 case BSC_aio_suspend
:
1467 case BSC_aio_suspend_nocancel
:
1468 bsd_syscalls
[code
].sc_name
= "aio_suspend";
1469 bsd_syscalls
[code
].sc_format
= FMT_AIO_SUSPEND
;
1472 case BSC_aio_cancel
:
1473 bsd_syscalls
[code
].sc_name
= "aio_cancel";
1474 bsd_syscalls
[code
].sc_format
= FMT_AIO_CANCEL
;
1478 bsd_syscalls
[code
].sc_name
= "aio_error";
1479 bsd_syscalls
[code
].sc_format
= FMT_AIO
;
1483 bsd_syscalls
[code
].sc_name
= "aio_read";
1484 bsd_syscalls
[code
].sc_format
= FMT_AIO
;
1488 bsd_syscalls
[code
].sc_name
= "aio_write";
1489 bsd_syscalls
[code
].sc_format
= FMT_AIO
;
1492 case BSC_lio_listio
:
1493 bsd_syscalls
[code
].sc_name
= "lio_listio";
1494 bsd_syscalls
[code
].sc_format
= FMT_LIO_LISTIO
;
1498 case BSC_msync_nocancel
:
1499 bsd_syscalls
[code
].sc_name
= "msync";
1500 bsd_syscalls
[code
].sc_format
= FMT_MSYNC
;
1504 case BSC_fcntl_nocancel
:
1505 bsd_syscalls
[code
].sc_name
= "fcntl";
1506 bsd_syscalls
[code
].sc_format
= FMT_FCNTL
;
1510 bsd_syscalls
[code
].sc_name
= "ioctl";
1511 bsd_syscalls
[code
].sc_format
= FMT_IOCTL
;
1516 for (i
= 0; (type
= filemgr_call_types
[i
]); i
++) {
1519 code
= filemgr_index(type
);
1521 if (code
>= MAX_FILEMGR
) {
1522 printf("FILEMGR call init (%x): type exceeds table size\n", type
);
1527 case FILEMGR_PBGETCATALOGINFO
:
1528 p
= "GetCatalogInfo";
1531 case FILEMGR_PBGETCATALOGINFOBULK
:
1532 p
= "GetCatalogInfoBulk";
1535 case FILEMGR_PBCREATEFILEUNICODE
:
1536 p
= "CreateFileUnicode";
1539 case FILEMGR_PBCREATEDIRECTORYUNICODE
:
1540 p
= "CreateDirectoryUnicode";
1543 case FILEMGR_PBCREATEFORK
:
1547 case FILEMGR_PBDELETEFORK
:
1551 case FILEMGR_PBITERATEFORK
:
1552 p
= "PBIterateFork";
1555 case FILEMGR_PBOPENFORK
:
1559 case FILEMGR_PBREADFORK
:
1563 case FILEMGR_PBWRITEFORK
:
1567 case FILEMGR_PBALLOCATEFORK
:
1568 p
= "PBAllocateFork";
1571 case FILEMGR_PBDELETEOBJECT
:
1572 p
= "PBDeleteObject";
1575 case FILEMGR_PBEXCHANGEOBJECT
:
1576 p
= "PBExchangeObject";
1579 case FILEMGR_PBGETFORKCBINFO
:
1580 p
= "PBGetForkCBInfo";
1583 case FILEMGR_PBGETVOLUMEINFO
:
1584 p
= "PBGetVolumeInfo";
1587 case FILEMGR_PBMAKEFSREF
:
1591 case FILEMGR_PBMAKEFSREFUNICODE
:
1592 p
= "PBMakeFSRefUnicode";
1595 case FILEMGR_PBMOVEOBJECT
:
1599 case FILEMGR_PBOPENITERATOR
:
1600 p
= "PBOpenIterator";
1603 case FILEMGR_PBRENAMEUNICODE
:
1604 p
= "PBRenameUnicode";
1607 case FILEMGR_PBSETCATALOGINFO
:
1608 p
= "SetCatalogInfo";
1611 case FILEMGR_PBSETVOLUMEINFO
:
1612 p
= "SetVolumeInfo";
1615 case FILEMGR_FSREFMAKEPATH
:
1616 p
= "FSRefMakePath";
1619 case FILEMGR_FSPATHMAKEREF
:
1620 p
= "FSPathMakeRef";
1623 case FILEMGR_PBGETCATINFO
:
1627 case FILEMGR_PBGETCATINFOLITE
:
1628 p
= "GetCatInfoLite";
1631 case FILEMGR_PBHGETFINFO
:
1635 case FILEMGR_PBXGETVOLINFO
:
1636 p
= "PBXGetVolInfo";
1639 case FILEMGR_PBHCREATE
:
1643 case FILEMGR_PBHOPENDF
:
1647 case FILEMGR_PBHOPENRF
:
1651 case FILEMGR_PBHGETDIRACCESS
:
1652 p
= "PBHGetDirAccess";
1655 case FILEMGR_PBHSETDIRACCESS
:
1656 p
= "PBHSetDirAccess";
1659 case FILEMGR_PBHMAPID
:
1663 case FILEMGR_PBHMAPNAME
:
1667 case FILEMGR_PBCLOSE
:
1671 case FILEMGR_PBFLUSHFILE
:
1675 case FILEMGR_PBGETEOF
:
1679 case FILEMGR_PBSETEOF
:
1683 case FILEMGR_PBGETFPOS
:
1687 case FILEMGR_PBREAD
:
1691 case FILEMGR_PBWRITE
:
1695 case FILEMGR_PBGETFCBINFO
:
1699 case FILEMGR_PBSETFINFO
:
1703 case FILEMGR_PBALLOCATE
:
1707 case FILEMGR_PBALLOCCONTIG
:
1708 p
= "PBAllocContig";
1711 case FILEMGR_PBSETFPOS
:
1715 case FILEMGR_PBSETCATINFO
:
1719 case FILEMGR_PBGETVOLPARMS
:
1720 p
= "PBGetVolParms";
1723 case FILEMGR_PBSETVINFO
:
1727 case FILEMGR_PBMAKEFSSPEC
:
1731 case FILEMGR_PBHGETVINFO
:
1735 case FILEMGR_PBCREATEFILEIDREF
:
1736 p
= "PBCreateFileIDRef";
1739 case FILEMGR_PBDELETEFILEIDREF
:
1740 p
= "PBDeleteFileIDRef";
1743 case FILEMGR_PBRESOLVEFILEIDREF
:
1744 p
= "PBResolveFileIDRef";
1747 case FILEMGR_PBFLUSHVOL
:
1751 case FILEMGR_PBHRENAME
:
1755 case FILEMGR_PBCATMOVE
:
1759 case FILEMGR_PBEXCHANGEFILES
:
1760 p
= "PBExchangeFiles";
1763 case FILEMGR_PBHDELETE
:
1767 case FILEMGR_PBDIRCREATE
:
1771 case FILEMGR_PBCATSEARCH
:
1775 case FILEMGR_PBHSETFLOCK
:
1779 case FILEMGR_PBHRSTFLOCK
:
1783 case FILEMGR_PBLOCKRANGE
:
1787 case FILEMGR_PBUNLOCKRANGE
:
1788 p
= "PBUnlockRange";
1795 filemgr_calls
[code
].fm_name
= p
;
1806 char *myname
= "fs_usage";
1809 struct sigaction osa
;
1813 void set_pidcheck();
1814 void set_pidexclude();
1817 if (0 != reexec_to_match_kernel()) {
1818 fprintf(stderr
, "Could not re-execute: %d\n", errno
);
1826 if ((myname
= rindex(argv
[0], '/')) == 0) {
1834 while ((ch
= getopt(argc
, argv
, "ewf:R:S:E:")) != EOF
) {
1840 exclude_default_pids
= 0;
1845 if ((uint
)columns
< MAX_WIDE_MODE_COLS
)
1846 columns
= MAX_WIDE_MODE_COLS
;
1850 if (!strcmp(optarg
, "network"))
1851 filter_mode
|= NETWORK_FILTER
;
1852 else if (!strcmp(optarg
, "filesys"))
1853 filter_mode
|= FILESYS_FILTER
;
1854 else if (!strcmp(optarg
, "cachehit"))
1855 filter_mode
&= ~CACHEHIT_FILTER
; /* turns on CACHE_HIT */
1856 else if (!strcmp(optarg
, "exec"))
1857 filter_mode
|= EXEC_FILTER
;
1858 else if (!strcmp(optarg
, "pathname"))
1859 filter_mode
|= PATHNAME_FILTER
;
1868 start_time
= atof(optarg
);
1872 end_time
= atof(optarg
);
1880 if ( geteuid() != 0 ) {
1881 fprintf(stderr
, "'fs_usage' must be run as root...\n");
1889 * when excluding, fs_usage should be the first in line for pids[]
1891 * the !exclude_pids && argc == 0 catches the exclude_default_pids
1892 * case below where exclude_pids is later set and the fs_usage PID
1893 * needs to make it into pids[]
1895 if (exclude_pids
|| (!exclude_pids
&& argc
== 0))
1897 if (num_of_pids
< (MAX_PIDS
- 1))
1898 pids
[num_of_pids
++] = getpid();
1901 /* If we process any list of pids/cmds, then turn off the defaults */
1903 exclude_default_pids
= 0;
1905 while (argc
> 0 && num_of_pids
< (MAX_PIDS
- 1)) {
1912 /* Exclude a set of default pids */
1913 if (exclude_default_pids
)
1915 argtopid("Terminal");
1916 argtopid("telnetd");
1919 argtopid("rlogind");
1927 for (i
= 0; i
< num_of_pids
; i
++)
1930 fprintf(stderr
, "exclude pid %d\n", pids
[i
]);
1932 fprintf(stderr
, "pid %d\n", pids
[i
]);
1937 /* set up signal handlers */
1938 signal(SIGINT
, leave
);
1939 signal(SIGQUIT
, leave
);
1941 sigaction(SIGHUP
, (struct sigaction
*)NULL
, &osa
);
1943 if (osa
.sa_handler
== SIG_DFL
)
1944 signal(SIGHUP
, leave
);
1945 signal(SIGTERM
, leave
);
1947 /* grab the number of cpus */
1952 len
= sizeof(num_cpus
);
1953 sysctl(mib
, 2, &num_cpus
, &len
, NULL
, 0);
1954 num_events
= EVENT_BASE
* num_cpus
;
1956 signal(SIGWINCH
, sigwinch
);
1958 if ((my_buffer
= malloc(num_events
* sizeof(kd_buf
))) == (char *)0)
1959 quit("can't allocate memory for tracing info\n");
1961 if (ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_i386.map", &framework32
, "/var/db/dyld/dyld_shared_cache_i386")) {
1962 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64.map", &framework64
, "/var/db/dyld/dyld_shared_cache_x86_64");
1964 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc.map", &framework32
, "/var/db/dyld/dyld_shared_cache_ppc");
1965 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc64.map", &framework64
, "/var/db/dyld/dyld_shared_cache_ppc64");
1967 SortFrameworkAddresses();
1974 set_numbufs(num_events
);
1977 if (exclude_pids
== 0) {
1978 for (i
= 0; i
< num_of_pids
; i
++)
1979 set_pidcheck(pids
[i
], 1);
1981 for (i
= 0; i
< num_of_pids
; i
++)
1982 set_pidexclude(pids
[i
], 1);
1985 if (select_pid_mode
&& !one_good_pid
)
1988 An attempt to restrict output to a given
1989 pid or command has failed. Exit gracefully
1996 init_arguments_buffer();
2006 usleep(1000 * usleep_ms
);
2010 last_time
= time((long *)0);
2018 struct kinfo_proc
*kp
;
2023 mib
[2] = KERN_PROC_ALL
;
2026 if (sysctl(mib
, 4, NULL
, &bufSize
, NULL
, 0) < 0)
2027 quit("trace facility failure, KERN_PROC_ALL\n");
2029 if((kp
= (struct kinfo_proc
*)malloc(bufSize
)) == (struct kinfo_proc
*)0)
2030 quit("can't allocate memory for proc buffer\n");
2032 if (sysctl(mib
, 4, kp
, &bufSize
, NULL
, 0) < 0)
2033 quit("trace facility failure, KERN_PROC_ALL\n");
2035 kp_nentries
= bufSize
/ sizeof(struct kinfo_proc
);
2040 void destroy_thread(struct th_info
*ti
) {
2042 ti
->child_thread
= 0;
2046 if (ti
->my_index
< cur_start
)
2047 cur_start
= ti
->my_index
;
2049 if (ti
->my_index
== cur_max
) {
2050 while (ti
>= &th_state
[0]) {
2055 cur_max
= ti
->my_index
;
2060 struct th_info
*find_empty(void) {
2063 for (ti
= &th_state
[cur_start
]; ti
< &th_state
[MAX_THREADS
]; ti
++, cur_start
++) {
2064 if (ti
->thread
== 0) {
2065 if (cur_start
> cur_max
)
2066 cur_max
= cur_start
;
2072 return ((struct th_info
*)0);
2077 struct th_info
*find_thread(uintptr_t thread
, int type
) {
2080 for (ti
= &th_state
[0]; ti
<= &th_state
[cur_max
]; ti
++) {
2081 if (ti
->thread
== thread
) {
2082 if (type
== ti
->type
)
2084 if (ti
->in_filemgr
) {
2093 return ((struct th_info
*)0);
2098 mark_thread_waited(uintptr_t thread
) {
2101 for (ti
= th_state
; ti
<= &th_state
[cur_max
]; ti
++) {
2102 if (ti
->thread
== thread
) {
2113 mib
[1] = KERN_KDEBUG
;
2114 mib
[2] = KERN_KDENABLE
; /* protocol */
2117 mib
[5] = 0; /* no flags */
2118 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
2119 quit("trace facility failure, KERN_KDENABLE\n");
2128 set_numbufs(int nbufs
)
2131 mib
[1] = KERN_KDEBUG
;
2132 mib
[2] = KERN_KDSETBUF
;
2135 mib
[5] = 0; /* no flags */
2136 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
2137 quit("trace facility failure, KERN_KDSETBUF\n");
2140 mib
[1] = KERN_KDEBUG
;
2141 mib
[2] = KERN_KDSETUP
;
2144 mib
[5] = 0; /* no flags */
2145 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
2146 quit("trace facility failure, KERN_KDSETUP\n");
2150 set_pidcheck(int pid
, int on_off
)
2154 kr
.type
= KDBG_TYPENONE
;
2157 needed
= sizeof(kd_regtype
);
2159 mib
[1] = KERN_KDEBUG
;
2160 mib
[2] = KERN_KDPIDTR
;
2165 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0) {
2167 fprintf(stderr
, "pid %d does not exist\n", pid
);
2175 on_off == 0 turns off pid exclusion
2176 on_off == 1 turns on pid exclusion
2179 set_pidexclude(int pid
, int on_off
)
2185 kr
.type
= KDBG_TYPENONE
;
2188 needed
= sizeof(kd_regtype
);
2190 mib
[1] = KERN_KDEBUG
;
2191 mib
[2] = KERN_KDPIDEX
;
2196 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0) {
2198 fprintf(stderr
, "pid %d does not exist\n", pid
);
2203 get_bufinfo(kbufinfo_t
*val
)
2205 needed
= sizeof (*val
);
2207 mib
[1] = KERN_KDEBUG
;
2208 mib
[2] = KERN_KDGETBUF
;
2211 mib
[5] = 0; /* no flags */
2213 if (sysctl(mib
, 3, val
, &needed
, 0, 0) < 0)
2214 quit("trace facility failure, KERN_KDGETBUF\n");
2224 mib
[1] = KERN_KDEBUG
;
2225 mib
[2] = KERN_KDREMOVE
; /* protocol */
2228 mib
[5] = 0; /* no flags */
2229 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
2231 set_remove_flag
= 0;
2234 quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n");
2236 quit("trace facility failure, KERN_KDREMOVE\n");
2244 kr
.type
= KDBG_RANGETYPE
;
2247 needed
= sizeof(kd_regtype
);
2249 mib
[1] = KERN_KDEBUG
;
2250 mib
[2] = KERN_KDSETREG
;
2253 mib
[5] = 0; /* no flags */
2255 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0)
2256 quit("trace facility failure, KERN_KDSETREG\n");
2259 mib
[1] = KERN_KDEBUG
;
2260 mib
[2] = KERN_KDSETUP
;
2263 mib
[5] = 0; /* no flags */
2265 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
2266 quit("trace facility failure, KERN_KDSETUP\n");
2275 uint32_t my_buffer_size
= 0;
2276 void read_command_map();
2277 void create_map_entry();
2280 /* Get kernel buffer information */
2281 get_bufinfo(&bufinfo
);
2283 my_buffer_size
= num_events
* sizeof(kd_buf
);
2290 needed
= bufinfo
.nkdbufs
* sizeof(kd_buf
);
2292 mib
[1] = KERN_KDEBUG
;
2293 mib
[2] = KERN_KDREADTR
;
2296 mib
[5] = 0; /* no flags */
2298 if (sysctl(mib
, 3, my_buffer
, &needed
, NULL
, 0) < 0)
2299 quit("trace facility failure, KERN_KDREADTR\n");
2302 if (count
> (num_events
/ 8)) {
2303 if (usleep_ms
> USLEEP_BEHIND
)
2304 usleep_ms
= USLEEP_BEHIND
;
2305 else if (usleep_ms
> USLEEP_MIN
)
2308 } else if (count
< (num_events
/ 16)) {
2309 if (usleep_ms
< USLEEP_MAX
)
2313 if (bufinfo
.flags
& KDBG_WRAPPED
) {
2314 fprintf(stderr
, "fs_usage: buffer overrun, events generated too quickly: %d\n", count
);
2316 for (i
= 0; i
<= cur_max
; i
++) {
2317 th_state
[i
].thread
= 0;
2318 th_state
[i
].pid
= 0;
2319 th_state
[i
].pathptr
= (uintptr_t *)NULL
;
2320 th_state
[i
].pathname
[0] = 0;
2325 map_is_the_same
= 0;
2333 if ((bytes_read
= read(RAW_fd
, my_buffer
, my_buffer_size
)) < sizeof(kd_buf
))
2335 count
= bytes_read
/ sizeof(kd_buf
);
2337 kd
= (kd_buf
*)my_buffer
;
2339 fprintf(stderr
, "READTR returned %d items\n", count
);
2341 for (i
= 0; i
< count
; i
++) {
2355 thread
= kd
[i
].arg5
;
2356 debugid
= kd
[i
].debugid
;
2357 type
= kd
[i
].debugid
& DBG_FUNC_MASK
;
2359 now
= kdbg_get_timestamp(&kd
[i
]);
2361 if (i
== 0 && !RAW_flag
)
2363 curr_time
= time((long *)0);
2365 * Compute bias seconds after each trace buffer read.
2366 * This helps resync timestamps with the system clock
2367 * in the event of a system sleep.
2369 if (bias_secs
== 0 || curr_time
< last_time
|| curr_time
> (last_time
+ 2)) {
2370 l_usecs
= (long long)(now
/ divisor
);
2371 secs
= l_usecs
/ 1000000;
2372 bias_secs
= curr_time
- secs
;
2375 if (RAW_flag
&& bias_now
== 0.0)
2378 if ((type
& P_DISKIO_MASK
) == P_DISKIO
) {
2379 insert_diskio(type
, kd
[i
].arg1
, kd
[i
].arg2
, kd
[i
].arg3
, kd
[i
].arg4
, thread
, (double)now
);
2382 if ((type
& P_DISKIO_MASK
) == P_DISKIO_DONE
) {
2383 if ((dio
= complete_diskio(kd
[i
].arg1
, kd
[i
].arg4
, kd
[i
].arg3
, thread
, (double)now
))) {
2392 case TRACE_DATA_NEWTHREAD
:
2394 if ((ti
= find_empty()) == NULL
)
2397 ti
->thread
= thread
;
2398 ti
->child_thread
= kd
[i
].arg1
;
2399 ti
->pid
= kd
[i
].arg2
;
2402 case TRACE_STRING_NEWTHREAD
:
2403 if ((ti
= find_thread(thread
, 0)) == (struct th_info
*)0)
2405 if (ti
->child_thread
== 0)
2407 create_map_entry(ti
->child_thread
, ti
->pid
, (char *)&kd
[i
].arg1
);
2413 case TRACE_DATA_EXEC
:
2415 if ((ti
= find_empty()) == NULL
)
2418 ti
->thread
= thread
;
2419 ti
->pid
= kd
[i
].arg1
;
2422 case TRACE_STRING_EXEC
:
2423 if ((ti
= find_thread(thread
, 0)) == (struct th_info
*)0)
2425 /* this is for backwards compatibility */
2426 create_map_entry(thread
, 0, (char *)&kd
[i
].arg1
);
2430 create_map_entry(thread
, ti
->pid
, (char *)&kd
[i
].arg1
);
2437 kill_thread_map(thread
);
2441 if (kd
[i
].arg4
& MAP_ANON
)
2447 case MACH_stkhandoff
:
2448 mark_thread_waited(thread
);
2452 if ((ti
= find_thread(thread
, 0)) == (struct th_info
*)0)
2455 if (ti
->pathptr
== NULL
) {
2456 sargptr
= ti
->pathname
;
2457 *sargptr
++ = kd
[i
].arg2
;
2458 *sargptr
++ = kd
[i
].arg3
;
2459 *sargptr
++ = kd
[i
].arg4
;
2461 * NULL terminate the 'string'
2464 ti
->pathptr
= sargptr
;
2466 sargptr
= ti
->pathptr
;
2469 * We don't want to overrun our pathname buffer if the
2470 * kernel sends us more VFS_LOOKUP entries than we can
2473 if ((uintptr_t)sargptr
>= (uintptr_t)&ti
->pathname
[NUMPARMS
]) {
2478 * We need to detect consecutive vfslookup entries.
2479 * So, if we get here and find a START entry,
2480 * fake the pathptr so we can bypass all further
2481 * vfslookup entries.
2483 if (debugid
& DBG_FUNC_START
) {
2484 ti
->pathptr
= &ti
->pathname
[NUMPARMS
];
2487 *sargptr
++ = kd
[i
].arg1
;
2488 *sargptr
++ = kd
[i
].arg2
;
2489 *sargptr
++ = kd
[i
].arg3
;
2490 *sargptr
++ = kd
[i
].arg4
;
2492 * NULL terminate the 'string'
2495 ti
->pathptr
= sargptr
;
2500 if (debugid
& DBG_FUNC_START
) {
2503 if ((type
& CLASS_MASK
) == FILEMGR_BASE
) {
2505 index
= filemgr_index(type
);
2507 if (index
>= MAX_FILEMGR
)
2510 if ((p
= filemgr_calls
[index
].fm_name
) == NULL
)
2515 enter_syscall(thread
, type
, &kd
[i
], p
, (double)now
);
2522 if (kd
[i
].arg2
== DKIOCSYNCHRONIZECACHE
)
2523 exit_syscall("IOCTL", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, FMT_SPEC_IOCTL
, (double)now
);
2525 if ((ti
= find_thread(thread
, type
))) {
2533 exit_syscall("PAGE_OUT_ANON", thread
, type
, 0, kd
[i
].arg1
, 0, 0, FMT_PGOUT
, (double)now
);
2535 exit_syscall("PAGE_OUT_FILE", thread
, type
, 0, kd
[i
].arg1
, 0, 0, FMT_PGOUT
, (double)now
);
2539 if (kd
[i
].arg4
== DBG_PAGEIN_FAULT
)
2540 exit_syscall("PAGE_IN", thread
, type
, 0, kd
[i
].arg1
, kd
[i
].arg2
, 0, FMT_PGIN
, (double)now
);
2541 else if (kd
[i
].arg4
== DBG_PAGEINV_FAULT
)
2542 exit_syscall("PAGE_IN_FILE", thread
, type
, 0, kd
[i
].arg1
, kd
[i
].arg2
, 0, FMT_PGIN
, (double)now
);
2543 else if (kd
[i
].arg4
== DBG_PAGEIND_FAULT
)
2544 exit_syscall("PAGE_IN_ANON", thread
, type
, 0, kd
[i
].arg1
, kd
[i
].arg2
, 0, FMT_PGIN
, (double)now
);
2545 else if (kd
[i
].arg4
== DBG_CACHE_HIT_FAULT
)
2546 exit_syscall("CACHE_HIT", thread
, type
, 0, kd
[i
].arg1
, kd
[i
].arg2
, 0, FMT_CACHEHIT
, (double)now
);
2548 if ((ti
= find_thread(thread
, type
))) {
2555 exit_syscall("map_fd", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, FMT_FD
, (double)now
);
2558 case BSC_mmap_extended
:
2559 case BSC_mmap_extended2
:
2560 case BSC_msync_extended
:
2561 case BSC_pread_extended
:
2562 case BSC_pwrite_extended
:
2563 extend_syscall(thread
, type
, &kd
[i
]);
2567 if ((type
& CSC_MASK
) == BSC_BASE
) {
2569 index
= BSC_INDEX(type
);
2571 if (index
>= MAX_BSD_SYSCALL
)
2574 if (bsd_syscalls
[index
].sc_name
== NULL
)
2577 if (type
== BSC_execve
)
2578 execs_in_progress
--;
2580 exit_syscall(bsd_syscalls
[index
].sc_name
, thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, kd
[i
].arg3
, kd
[i
].arg4
,
2581 bsd_syscalls
[index
].sc_format
, (double)now
);
2586 if ((type
& CLASS_MASK
) == FILEMGR_BASE
) {
2588 index
= filemgr_index(type
);
2590 if (index
>= MAX_FILEMGR
)
2593 if (filemgr_calls
[index
].fm_name
== NULL
)
2596 exit_syscall(filemgr_calls
[index
].fm_name
, thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, kd
[i
].arg3
, kd
[i
].arg4
,
2597 FMT_DEFAULT
, (double)now
);
2607 enter_syscall_now(uintptr_t thread
, int type
, kd_buf
*kd
, char *name
, double now
)
2615 kd_threadmap
*find_thread_map();
2622 if (execs_in_progress
) {
2623 if ((ti
= find_thread(thread
, BSC_execve
))) {
2625 exit_syscall("execve", thread
, BSC_execve
, 0, 0, 0, 0, FMT_DEFAULT
, (double)now
);
2626 execs_in_progress
--;
2630 if ((ti
= find_empty()) == NULL
)
2633 if ((type
& CLASS_MASK
) == FILEMGR_BASE
&&
2634 (!RAW_flag
|| (now
>= start_time
&& now
<= end_time
))) {
2636 filemgr_in_progress
++;
2640 l_usecs
= (long long)((now
- bias_now
) / divisor
);
2641 l_usecs
+= ((long long)8 * (long long)3600 * (long long)1000000);
2643 l_usecs
= (long long)(now
/ divisor
);
2644 secs
= l_usecs
/ 1000000;
2645 curr_time
= bias_secs
+ secs
;
2647 sprintf(buf
, "%-8.8s", &(ctime(&curr_time
)[11]));
2648 tsclen
= strlen(buf
);
2650 if (columns
> MAXCOLS
|| wideflag
) {
2651 usecs
= l_usecs
- (long long)((long long)secs
* 1000000);
2652 sprintf(&buf
[tsclen
], ".%03ld", (long)usecs
/ 1000);
2653 tsclen
= strlen(buf
);
2657 * Print timestamp column
2661 map
= find_thread_map(thread
);
2663 sprintf(buf
, " %-25.25s ", name
);
2664 nmclen
= strlen(buf
);
2667 sprintf(buf
, "(%d, 0x%lx, 0x%lx, 0x%lx)", (short)kd
->arg1
, kd
->arg2
, kd
->arg3
, kd
->arg4
);
2668 argsclen
= strlen(buf
);
2671 * Calculate white space out to command
2673 if (columns
> MAXCOLS
|| wideflag
) {
2674 clen
= columns
- (tsclen
+ nmclen
+ argsclen
+ 20);
2676 clen
= columns
- (tsclen
+ nmclen
+ argsclen
+ 12);
2679 printf("%s", buf
); /* print the kdargs */
2680 memset(buf
, ' ', clen
);
2684 else if ((argsclen
+ clen
) > 0) {
2686 * no room so wipe out the kdargs
2688 memset(buf
, ' ', (argsclen
+ clen
));
2689 buf
[argsclen
+ clen
] = '\0';
2692 if (columns
> MAXCOLS
|| wideflag
)
2693 printf("%-20.20s\n", map
->command
);
2695 printf("%-12.12s\n", map
->command
);
2697 printf(" %-24.24s (%5d, %#lx, 0x%lx, 0x%lx)\n", name
, (short)kd
->arg1
, kd
->arg2
, kd
->arg3
, kd
->arg4
);
2699 ti
->thread
= thread
;
2703 ti
->arg1
= kd
->arg1
;
2704 ti
->arg2
= kd
->arg2
;
2705 ti
->arg3
= kd
->arg3
;
2706 ti
->arg4
= kd
->arg4
;
2707 ti
->pathptr
= (uintptr_t *)NULL
;
2708 ti
->pathname
[0] = 0;
2713 enter_syscall(uintptr_t thread
, int type
, kd_buf
*kd
, char *name
, double now
)
2717 if (type
== MACH_pageout
|| type
== MACH_vmfault
|| type
== MSC_map_fd
|| type
== SPEC_ioctl
) {
2718 enter_syscall_now(thread
, type
, kd
, name
, now
);
2721 if ((type
& CSC_MASK
) == BSC_BASE
) {
2723 index
= BSC_INDEX(type
);
2725 if (index
>= MAX_BSD_SYSCALL
)
2728 if (type
== BSC_execve
)
2729 execs_in_progress
++;
2731 if (bsd_syscalls
[index
].sc_name
)
2732 enter_syscall_now(thread
, type
, kd
, name
, now
);
2736 if ((type
& CLASS_MASK
) == FILEMGR_BASE
) {
2738 index
= filemgr_index(type
);
2740 if (index
>= MAX_FILEMGR
)
2743 if (filemgr_calls
[index
].fm_name
)
2744 enter_syscall_now(thread
, type
, kd
, name
, now
);
2749 * Handle system call extended trace data.
2751 * Wipe out the kd args that were collected upon syscall_entry
2752 * because it is the extended info that we really want, and it
2753 * is all we really need.
2757 extend_syscall(uintptr_t thread
, int type
, kd_buf
*kd
)
2762 case BSC_mmap_extended
:
2763 if ((ti
= find_thread(thread
, BSC_mmap
)) == (struct th_info
*)0)
2765 ti
->arg8
= ti
->arg3
; /* save protection */
2766 ti
->arg1
= kd
->arg1
; /* the fd */
2767 ti
->arg3
= kd
->arg2
; /* bottom half address */
2768 ti
->arg5
= kd
->arg3
; /* bottom half size */
2770 case BSC_mmap_extended2
:
2771 if ((ti
= find_thread(thread
, BSC_mmap
)) == (struct th_info
*)0)
2773 ti
->arg2
= kd
->arg1
; /* top half address */
2774 ti
->arg4
= kd
->arg2
; /* top half size */
2775 ti
->arg6
= kd
->arg3
; /* top half file offset */
2776 ti
->arg7
= kd
->arg4
; /* bottom half file offset */
2778 case BSC_msync_extended
:
2779 if ((ti
= find_thread(thread
, BSC_msync
)) == (struct th_info
*)0) {
2780 if ((ti
= find_thread(thread
, BSC_msync_nocancel
)) == (struct th_info
*)0)
2783 ti
->arg4
= kd
->arg1
; /* top half address */
2784 ti
->arg5
= kd
->arg2
; /* top half size */
2786 case BSC_pread_extended
:
2787 if ((ti
= find_thread(thread
, BSC_pread
)) == (struct th_info
*)0) {
2788 if ((ti
= find_thread(thread
, BSC_pread_nocancel
)) == (struct th_info
*)0)
2791 ti
->arg1
= kd
->arg1
; /* the fd */
2792 ti
->arg2
= kd
->arg2
; /* nbytes */
2793 ti
->arg3
= kd
->arg3
; /* top half offset */
2794 ti
->arg4
= kd
->arg4
; /* bottom half offset */
2796 case BSC_pwrite_extended
:
2797 if ((ti
= find_thread(thread
, BSC_pwrite
)) == (struct th_info
*)0) {
2798 if ((ti
= find_thread(thread
, BSC_pwrite_nocancel
)) == (struct th_info
*)0)
2801 ti
->arg1
= kd
->arg1
; /* the fd */
2802 ti
->arg2
= kd
->arg2
; /* nbytes */
2803 ti
->arg3
= kd
->arg3
; /* top half offset */
2804 ti
->arg4
= kd
->arg4
; /* bottom half offset */
2813 exit_syscall(char *sc_name
, uintptr_t thread
, int type
, int arg1
, int arg2
, int arg3
, int arg4
,
2814 int format
, double now
)
2818 if ((ti
= find_thread(thread
, type
)) == (struct th_info
*)0)
2821 if (check_filter_mode(ti
, type
, arg1
, arg2
, sc_name
))
2822 format_print(ti
, sc_name
, thread
, type
, arg1
, arg2
, arg3
, arg4
, format
, now
, ti
->stime
, ti
->waited
, (char *)ti
->pathname
, NULL
);
2824 if ((type
& CLASS_MASK
) == FILEMGR_BASE
) {
2827 if (filemgr_in_progress
> 0)
2828 filemgr_in_progress
--;
2835 get_mode_nibble(char * buf
, int smode
, int special
, char x_on
, char x_off
)
2854 get_mode_string(int mode
, char *buf
)
2856 memset(buf
, '-', 9);
2859 get_mode_nibble(&buf
[6], mode
, (mode
& 01000), 't', 'T');
2860 get_mode_nibble(&buf
[3], (mode
>>3), (mode
& 02000), 's', 'S');
2861 get_mode_nibble(&buf
[0], (mode
>>6), (mode
& 04000), 's', 'S');
2865 int clip_64bit(char *s
, uint64_t value
)
2869 if ( (value
& 0xff00000000000000LL
) )
2870 clen
= printf("%s0x%16.16qx", s
, value
);
2871 else if ( (value
& 0x00ff000000000000LL
) )
2872 clen
= printf("%s0x%14.14qx ", s
, value
);
2873 else if ( (value
& 0x0000ff0000000000LL
) )
2874 clen
= printf("%s0x%12.12qx ", s
, value
);
2875 else if ( (value
& 0x000000ff00000000LL
) )
2876 clen
= printf("%s0x%10.10qx ", s
, value
);
2878 clen
= printf("%s0x%8.8qx ", s
, value
);
2885 format_print(struct th_info
*ti
, char *sc_name
, uintptr_t thread
, int type
, int arg1
, int arg2
, int arg3
, int arg4
,
2886 int format
, double now
, double stime
, int waited
, char *pathname
, struct diskio
*dio
)
2895 kd_threadmap
*find_thread_map();
2903 char *framework_name
;
2904 char *framework_type
;
2909 int need_msec_update
= 0;
2910 static char timestamp
[32];
2911 static int last_timestamp
= -1;
2912 static int timestamp_len
= 0;
2913 static int last_msec
= 0;
2917 l_usecs
= (long long)((now
- bias_now
) / divisor
);
2919 if ((double)l_usecs
< start_time
|| (double)l_usecs
> end_time
)
2921 l_usecs
+= ((long long)8 * (long long)3600 * (long long)1000000);
2923 l_usecs
= (long long)(now
/ divisor
);
2924 secs
= l_usecs
/ 1000000;
2925 curr_time
= bias_secs
+ secs
;
2930 command_name
= dio
->issuing_command
;
2932 if (map_is_the_same
&& thread
== last_thread
)
2935 if ((map
= find_thread_map(thread
))) {
2937 last_thread
= thread
;
2938 map_is_the_same
= 1;
2942 command_name
= map
->command
;
2944 if (last_timestamp
!= curr_time
) {
2945 timestamp_len
= sprintf(timestamp
, "%-8.8s", &(ctime(&curr_time
)[11]));
2946 last_timestamp
= curr_time
;
2947 need_msec_update
= 1;
2949 if (columns
> MAXCOLS
|| wideflag
) {
2952 tlen
= timestamp_len
;
2954 msec
= (l_usecs
- (long long)((long long)secs
* 1000000)) / 1000;
2956 if (msec
!= last_msec
|| need_msec_update
) {
2957 sprintf(×tamp
[tlen
], ".%03ld", (long)msec
);
2962 timestamp
[tlen
] = '\0';
2964 if (filemgr_in_progress
) {
2965 if (class != FILEMGR_CLASS
) {
2966 if (find_thread(thread
, -1)) {
2974 if ((class == FILEMGR_CLASS
) && (columns
> MAXCOLS
|| wideflag
))
2975 clen
= printf("%s %-20.20s", timestamp
, sc_name
);
2976 else if (in_filemgr
)
2977 clen
= printf("%s %-15.15s", timestamp
, sc_name
);
2979 clen
= printf("%s %-17.17s", timestamp
, sc_name
);
2982 framework_name
= NULL
;
2984 if (columns
> MAXCOLS
|| wideflag
) {
2986 off_t offset_reassembled
= 0LL;
2992 * pathname based system calls or
2993 * calls with no fd or pathname (i.e. sync)
2996 clen
+= printf(" [%3d] ", arg1
);
2998 clen
+= printf(" ");
3003 * fd based system call... no I/O
3006 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
3008 clen
+= printf(" F=%-3d", ti
->arg1
);
3016 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
3018 clen
+= printf(" F=%-3d F=%-3d", ti
->arg1
, arg2
);
3023 * system calls with fd's that return an I/O completion count
3026 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
3028 clen
+= printf(" F=%-3d B=0x%-6x", ti
->arg1
, arg2
);
3035 user_addr
= ((uint64_t)arg2
<< 32) | (uint32_t)arg3
;
3037 lookup_name(user_addr
, &framework_type
, &framework_name
);
3038 clen
+= clip_64bit(" A=", user_addr
);
3045 user_addr
= ((uint64_t)arg2
<< 32) | (uint32_t)arg3
;
3047 lookup_name(user_addr
, &framework_type
, &framework_name
);
3048 clen
+= clip_64bit(" A=", user_addr
);
3055 clen
+= printf(" B=0x%-8x", arg2
);
3063 clen
+= printf(" D=0x%8.8x [%3d]", dio
->blkno
, dio
->io_errno
);
3065 clen
+= printf(" D=0x%8.8x B=0x%-6x /dev/%s", dio
->blkno
, dio
->iosize
, find_disk_name(dio
->dev
));
3077 if (ti
->arg3
& MS_ASYNC
)
3078 mlen
+= sprintf(&buf
[mlen
], "MS_ASYNC | ");
3080 mlen
+= sprintf(&buf
[mlen
], "MS_SYNC | ");
3082 if (ti
->arg3
& MS_INVALIDATE
)
3083 mlen
+= sprintf(&buf
[mlen
], "MS_INVALIDATE | ");
3084 if (ti
->arg3
& MS_KILLPAGES
)
3085 mlen
+= sprintf(&buf
[mlen
], "MS_KILLPAGES | ");
3086 if (ti
->arg3
& MS_DEACTIVATE
)
3087 mlen
+= sprintf(&buf
[mlen
], "MS_DEACTIVATE | ");
3089 if (ti
->arg3
& ~(MS_ASYNC
| MS_SYNC
| MS_INVALIDATE
| MS_KILLPAGES
| MS_DEACTIVATE
))
3090 mlen
+= sprintf(&buf
[mlen
], "UNKNOWN | ");
3093 buf
[mlen
- 3] = '\0';
3096 clen
+= printf(" [%3d]", arg1
);
3098 user_addr
= (((off_t
)(unsigned int)(ti
->arg4
)) << 32) | (unsigned int)(ti
->arg1
);
3099 clen
+= clip_64bit(" A=", user_addr
);
3101 user_size
= (((off_t
)(unsigned int)(ti
->arg5
)) << 32) | (unsigned int)(ti
->arg2
);
3103 clen
+= printf(" B=0x%-16qx <%s>", user_size
, buf
);
3117 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
3119 clen
+= printf(" F=%-3d", ti
->arg1
);
3183 case F_PATHPKG_CHECK
:
3184 p
= "PATHPKG_CHECK";
3198 case F_CHECK_OPENEVT
:
3199 p
= "CHECK_OPENEVT";
3209 case F_GLOBAL_NOCACHE
:
3211 p
= "CACHING OFF (GLOBAL)";
3213 p
= "CACHING ON (GLOBAL)";
3219 clen
+= printf(" <%s>", p
);
3221 clen
+= printf(" <%s> F=%d", p
, fd
);
3223 clen
+= printf(" <CMD=%d>", ti
->arg2
);
3234 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
3236 clen
+= printf(" F=%-3d", ti
->arg1
);
3238 clen
+= printf(" <CMD=0x%x>", ti
->arg2
);
3243 case FMT_SPEC_IOCTL
:
3248 clen
+= printf(" <DKIOCSYNCHRONIZECACHE> /dev/%s", find_disk_name(arg1
));
3258 clen
+= printf(" [%3d]", arg1
);
3260 clen
+= printf(" S=%-3d", arg2
);
3267 * pread, pwrite, lseek
3269 clen
+= printf(" F=%-3d", ti
->arg1
);
3272 clen
+= printf("[%3d] ", arg1
);
3274 if (format
== FMT_PREAD
)
3275 clen
+= printf(" B=0x%-8x ", arg2
);
3277 clen
+= printf(" ");
3279 if (format
== FMT_PREAD
)
3280 offset_reassembled
= (((off_t
)(unsigned int)(ti
->arg3
)) << 32) | (unsigned int)(ti
->arg4
);
3283 offset_reassembled
= (((off_t
)(unsigned int)(arg2
)) << 32) | (unsigned int)(arg3
);
3285 offset_reassembled
= (((off_t
)(unsigned int)(arg3
)) << 32) | (unsigned int)(arg2
);
3287 clen
+= clip_64bit("O=", offset_reassembled
);
3289 if (format
== FMT_LSEEK
) {
3292 if (ti
->arg4
== SEEK_SET
)
3294 else if (ti
->arg4
== SEEK_CUR
)
3296 else if (ti
->arg4
== SEEK_END
)
3301 clen
+= printf(" <%s>", mode
);
3309 clen
+= printf(" F=%-3d ", ti
->arg1
);
3312 clen
+= printf("[%3d] ", arg1
);
3315 user_addr
= (((off_t
)(unsigned int)(ti
->arg2
)) << 32) | (unsigned int)(ti
->arg3
);
3317 clen
+= clip_64bit("A=", user_addr
);
3319 offset_reassembled
= (((off_t
)(unsigned int)(ti
->arg6
)) << 32) | (unsigned int)(ti
->arg7
);
3321 clen
+= clip_64bit("O=", offset_reassembled
);
3323 user_size
= (((off_t
)(unsigned int)(ti
->arg4
)) << 32) | (unsigned int)(ti
->arg5
);
3325 clen
+= printf("B=0x%-16qx", user_size
);
3327 clen
+= printf(" <");
3329 if (ti
->arg8
& PROT_READ
)
3330 clen
+= printf("READ");
3332 if (ti
->arg8
& PROT_WRITE
)
3333 clen
+= printf("|WRITE");
3335 if (ti
->arg8
& PROT_EXEC
)
3336 clen
+= printf("|EXEC");
3338 clen
+= printf(">");
3345 * ftruncate, truncate
3347 if (format
== FMT_FTRUNC
)
3348 clen
+= printf(" F=%-3d", ti
->arg1
);
3350 clen
+= printf(" ");
3353 clen
+= printf("[%3d]", arg1
);
3356 offset_reassembled
= (((off_t
)(unsigned int)(ti
->arg2
)) << 32) | (unsigned int)(ti
->arg3
);
3358 offset_reassembled
= (((off_t
)(unsigned int)(ti
->arg3
)) << 32) | (unsigned int)(ti
->arg2
);
3360 clen
+= clip_64bit(" O=", offset_reassembled
);
3373 if (format
== FMT_FCHFLAGS
) {
3375 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
3377 clen
+= printf(" F=%-3d", ti
->arg1
);
3380 clen
+= printf(" [%3d] ", arg1
);
3385 if (ti
->arg2
& UF_NODUMP
)
3386 mlen
+= sprintf(&buf
[mlen
], "UF_NODUMP | ");
3387 if (ti
->arg2
& UF_IMMUTABLE
)
3388 mlen
+= sprintf(&buf
[mlen
], "UF_IMMUTABLE | ");
3389 if (ti
->arg2
& UF_APPEND
)
3390 mlen
+= sprintf(&buf
[mlen
], "UF_APPEND | ");
3391 if (ti
->arg2
& UF_OPAQUE
)
3392 mlen
+= sprintf(&buf
[mlen
], "UF_OPAQUE | ");
3393 if (ti
->arg2
& SF_ARCHIVED
)
3394 mlen
+= sprintf(&buf
[mlen
], "SF_ARCHIVED | ");
3395 if (ti
->arg2
& SF_IMMUTABLE
)
3396 mlen
+= sprintf(&buf
[mlen
], "SF_IMMUTABLE | ");
3397 if (ti
->arg2
& SF_APPEND
)
3398 mlen
+= sprintf(&buf
[mlen
], "SF_APPEND | ");
3401 mlen
+= sprintf(&buf
[mlen
], "CLEAR_ALL_FLAGS | ");
3402 else if (ti
->arg2
& ~(UF_NODUMP
| UF_IMMUTABLE
| UF_APPEND
| SF_ARCHIVED
| SF_IMMUTABLE
| SF_APPEND
))
3403 mlen
+= sprintf(&buf
[mlen
], "UNKNOWN | ");
3412 memset(&buf
[mlen
], ' ', 21 - mlen
);
3415 clen
+= printf("%s", buf
);
3423 case FMT_FCHMOD_EXT
:
3428 * fchmod, fchmod_extended, chmod, chmod_extended
3432 if (format
== FMT_FCHMOD
|| format
== FMT_FCHMOD_EXT
) {
3434 clen
+= printf(" F=%-3d[%3d] ", ti
->arg1
, arg1
);
3436 clen
+= printf(" F=%-3d ", ti
->arg1
);
3439 clen
+= printf(" [%3d] ", arg1
);
3441 clen
+= printf(" ");
3443 if (format
== FMT_UMASK
)
3445 else if (format
== FMT_FCHMOD
|| format
== FMT_CHMOD
)
3450 get_mode_string(mode
, &buf
[0]);
3453 clen
+= printf("<%s> ", buf
);
3455 clen
+= printf("<%s>", buf
);
3466 memset(mode
, '_', 4);
3469 if (ti
->arg2
& R_OK
)
3471 if (ti
->arg2
& W_OK
)
3473 if (ti
->arg2
& X_OK
)
3475 if (ti
->arg2
== F_OK
)
3479 clen
+= printf(" [%3d] (%s) ", arg1
, mode
);
3481 clen
+= printf(" (%s) ", mode
);
3494 memset(mode
, '_', 6);
3497 if (ti
->arg2
& O_RDWR
) {
3500 } else if (ti
->arg2
& O_WRONLY
)
3505 if (ti
->arg2
& O_CREAT
)
3508 if (ti
->arg2
& O_APPEND
)
3511 if (ti
->arg2
& O_TRUNC
)
3514 if (ti
->arg2
& O_EXCL
)
3518 clen
+= printf(" [%3d] (%s) ", arg1
, mode
);
3520 clen
+= printf(" F=%-3d (%s) ", arg2
, mode
);
3554 domain
= "AF_IMPLINK";
3565 type
= "SOCK_STREAM";
3569 type
= "SOCK_DGRAM";
3576 case SOCK_SEQPACKET
:
3577 type
= "SOCK_SEQPACKET";
3590 clen
+= printf(" [%3d] <%s, %s, 0x%x>", arg1
, domain
, type
, ti
->arg3
);
3592 clen
+= printf(" F=%-3d <%s, %s, 0x%x>", arg2
, domain
, type
, ti
->arg3
);
3599 * aio_fsync [errno] AIOCBP OP
3603 if (ti
->arg1
== O_SYNC
|| ti
->arg1
== 0)
3606 else if (ti
->arg1
== O_DSYNC
)
3613 clen
+= printf(" [%3d] P=0x%8.8x <%s>", arg1
, ti
->arg2
, op
);
3615 clen
+= printf(" P=0x%8.8x <%s>", ti
->arg2
, op
);
3619 case FMT_AIO_RETURN
:
3621 * aio_return [errno] AIOCBP IOSIZE
3624 clen
+= printf(" [%3d] P=0x%8.8x", arg1
, ti
->arg1
);
3626 clen
+= printf(" P=0x%8.8x B=0x%-8x", ti
->arg1
, arg2
);
3629 case FMT_AIO_SUSPEND
:
3631 * aio_suspend [errno] NENTS
3634 clen
+= printf(" [%3d] N=%d", arg1
, ti
->arg2
);
3636 clen
+= printf(" N=%d", ti
->arg2
);
3639 case FMT_AIO_CANCEL
:
3641 * aio_cancel [errno] FD or AIOCBP (if non-null)
3645 clen
+= printf(" [%3d] P=0x%8.8x", arg1
, ti
->arg2
);
3647 clen
+= printf(" P=0x%8.8x", ti
->arg2
);
3650 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
3652 clen
+= printf(" F=%-3d", ti
->arg1
);
3658 * aio_error, aio_read, aio_write [errno] AIOCBP
3661 clen
+= printf(" [%3d] P=0x%8.8x", arg1
, ti
->arg1
);
3663 clen
+= printf(" P=0x%8.8x", ti
->arg1
);
3666 case FMT_LIO_LISTIO
:
3669 * lio_listio [errno] NENTS MODE
3673 if (ti
->arg1
== LIO_NOWAIT
)
3675 else if (ti
->arg1
== LIO_WAIT
)
3681 clen
+= printf(" [%3d] N=%d <%s>", arg1
, ti
->arg3
, op
);
3683 clen
+= printf(" N=%d <%s>", ti
->arg3
, op
);
3691 * Calculate space available to print pathname
3693 if (columns
> MAXCOLS
|| wideflag
)
3694 clen
= columns
- (clen
+ 14 + 20);
3696 clen
= columns
- (clen
+ 14 + 12);
3698 if (class != FILEMGR_CLASS
&& !nopadding
)
3702 len
= sprintf(&buf
[0], " %s %s ", framework_type
, framework_name
);
3703 else if (*pathname
!= '\0')
3704 len
= sprintf(&buf
[0], " %s ", pathname
);
3710 * Add null padding if column length
3711 * is wider than the pathname length.
3713 memset(&buf
[len
], ' ', clen
- len
);
3718 } else if (clen
== len
) {
3721 } else if ((clen
> 0) && (clen
< len
)) {
3723 * This prints the tail end of the pathname
3725 buf
[len
-clen
] = ' ';
3727 pathname
= &buf
[len
- clen
];
3734 * fudge some additional system call overhead
3735 * that currently isn't tracked... this also
3736 * insures that we see a minimum of 1 us for
3739 usecs
= (unsigned long)(((now
- stime
) + (divisor
-1)) / divisor
);
3740 secs
= usecs
/ 1000000;
3741 usecs
-= secs
* 1000000;
3743 if (class != FILEMGR_CLASS
&& !nopadding
)
3753 if (columns
> MAXCOLS
|| wideflag
)
3754 printf("%s%s %3ld.%06ld%s %-20.20s\n", p1
, pathname
, (unsigned long)secs
, (unsigned long)usecs
, p2
, command_name
);
3756 printf("%s%s %3ld.%06ld%s %-12.12s\n", p1
, pathname
, (unsigned long)secs
, (unsigned long)usecs
, p2
, command_name
);
3767 * This flag is turned off when calling
3768 * quit() due to a set_remove() failure.
3770 if (set_remove_flag
)
3773 fprintf(stderr
, "fs_usage: ");
3775 fprintf(stderr
, "%s", s
);
3783 struct mach_timebase_info mti
;
3785 mach_timebase_info(&mti
);
3787 divisor
= ((double)mti
.denom
/ (double)mti
.numer
) * 1000;
3791 void read_command_map()
3795 int prev_total_threads
;
3803 prev_total_threads
= total_threads
;
3807 total_threads
= bufinfo
.nkdthreads
;
3808 size
= bufinfo
.nkdthreads
* sizeof(kd_threadmap
);
3812 if ((mapptr
= (kd_threadmap
*) malloc(size
)))
3814 bzero (mapptr
, size
);
3816 /* Now read the threadmap */
3818 mib
[1] = KERN_KDEBUG
;
3819 mib
[2] = KERN_KDTHRMAP
;
3822 mib
[5] = 0; /* no flags */
3823 if (sysctl(mib
, 3, mapptr
, &size
, NULL
, 0) < 0)
3825 /* This is not fatal -- just means I cant map command strings */
3832 uint32_t count_of_names
;
3834 RAW_fd
= open(RAW_file
, O_RDONLY
);
3837 perror("Can't open RAW file");
3840 if (read(RAW_fd
, &count_of_names
, sizeof(uint32_t)) != sizeof(uint32_t)) {
3841 perror("read of RAW file failed");
3844 total_threads
= count_of_names
;
3845 size
= count_of_names
* sizeof(kd_threadmap
);
3849 if ((mapptr
= (kd_threadmap
*) malloc(size
)))
3851 bzero (mapptr
, size
);
3853 if (read(RAW_fd
, mapptr
, size
) != size
) {
3861 if (mapptr
&& (filter_mode
& (NETWORK_FILTER
| FILESYS_FILTER
)))
3865 /* We accept the fact that we lose file descriptor state if the
3867 for (i
= 0; i
< prev_total_threads
; i
++)
3869 if (fdmapptr
[i
].fd_setptr
)
3870 free (fdmapptr
[i
].fd_setptr
);
3876 size
= total_threads
* sizeof(fd_threadmap
);
3877 if ((fdmapptr
= (fd_threadmap
*) malloc(size
)))
3879 bzero (fdmapptr
, size
);
3880 /* reinitialize file descriptor state map */
3881 for (i
= 0; i
< total_threads
; i
++)
3883 fdmapptr
[i
].fd_thread
= mapptr
[i
].thread
;
3884 fdmapptr
[i
].fd_valid
= mapptr
[i
].valid
;
3885 fdmapptr
[i
].fd_setsize
= 0;
3886 fdmapptr
[i
].fd_setptr
= 0;
3891 /* Resolve any LaunchCFMApp command names */
3892 if (mapptr
&& arguments
)
3894 for (i
=0; i
< total_threads
; i
++)
3898 pid
= mapptr
[i
].valid
;
3900 if (pid
== 0 || pid
== 1)
3902 else if (!strncmp(mapptr
[i
].command
,"LaunchCFMA", 10))
3904 (void)get_real_command_name(pid
, mapptr
[i
].command
, sizeof(mapptr
[i
].command
));
3911 void create_map_entry(uintptr_t thread
, int pid
, char *command
)
3915 fd_threadmap
*fdmap
= 0;
3920 for (i
= 0, map
= 0; !map
&& i
< total_threads
; i
++)
3922 if (mapptr
[i
].thread
== thread
)
3924 map
= &mapptr
[i
]; /* Reuse this entry, the thread has been
3926 if ((filter_mode
& (NETWORK_FILTER
| FILESYS_FILTER
)) && fdmapptr
)
3928 fdmap
= &fdmapptr
[i
];
3929 if (fdmap
->fd_thread
!= thread
) /* This shouldn't happen */
3930 fdmap
= (fd_threadmap
*)0;
3935 if (!map
) /* look for invalid entries that I can reuse*/
3937 for (i
= 0, map
= 0; !map
&& i
< total_threads
; i
++)
3939 if (mapptr
[i
].valid
== 0 )
3940 map
= &mapptr
[i
]; /* Reuse this invalid entry */
3941 if ((filter_mode
& (NETWORK_FILTER
| FILESYS_FILTER
)) && fdmapptr
)
3943 fdmap
= &fdmapptr
[i
];
3951 * If reach here, then this is a new thread and
3952 * there are no invalid entries to reuse
3953 * Double the size of the thread map table.
3955 n
= total_threads
* 2;
3956 mapptr
= (kd_threadmap
*) realloc(mapptr
, n
* sizeof(kd_threadmap
));
3957 bzero(&mapptr
[total_threads
], total_threads
*sizeof(kd_threadmap
));
3958 map
= &mapptr
[total_threads
];
3960 if ((filter_mode
& (NETWORK_FILTER
| FILESYS_FILTER
)) && fdmapptr
)
3962 fdmapptr
= (fd_threadmap
*)realloc(fdmapptr
, n
* sizeof(fd_threadmap
));
3963 bzero(&fdmapptr
[total_threads
], total_threads
*sizeof(fd_threadmap
));
3964 fdmap
= &fdmapptr
[total_threads
];
3971 map
->thread
= thread
;
3973 * The trace entry that returns the command name will hold
3974 * at most, MAXCOMLEN chars, and in that case, is not
3975 * guaranteed to be null terminated.
3977 (void)strncpy (map
->command
, command
, MAXCOMLEN
);
3978 map
->command
[MAXCOMLEN
] = '\0';
3982 fdmap
->fd_valid
= 1;
3983 fdmap
->fd_thread
= thread
;
3984 if (fdmap
->fd_setptr
)
3986 free(fdmap
->fd_setptr
);
3987 fdmap
->fd_setptr
= (unsigned long *)0;
3989 fdmap
->fd_setsize
= 0;
3992 if (pid
== 0 || pid
== 1)
3994 else if (!strncmp(map
->command
, "LaunchCFMA", 10))
3995 (void)get_real_command_name(pid
, map
->command
, sizeof(map
->command
));
3999 kd_threadmap
*find_thread_map(uintptr_t thread
)
4005 return((kd_threadmap
*)0);
4007 for (i
= 0; i
< total_threads
; i
++)
4010 if (map
->valid
&& (map
->thread
== thread
))
4015 return ((kd_threadmap
*)0);
4018 fd_threadmap
*find_fd_thread_map(uintptr_t thread
)
4021 fd_threadmap
*fdmap
= 0;
4024 return((fd_threadmap
*)0);
4026 for (i
= 0; i
< total_threads
; i
++)
4028 fdmap
= &fdmapptr
[i
];
4029 if (fdmap
->fd_valid
&& (fdmap
->fd_thread
== thread
))
4034 return ((fd_threadmap
*)0);
4039 kill_thread_map(uintptr_t thread
)
4042 fd_threadmap
*fdmap
;
4044 if (thread
== last_thread
)
4045 map_is_the_same
= 0;
4047 if ((map
= find_thread_map(thread
))) {
4050 map
->command
[0] = '\0';
4053 if ((filter_mode
& (NETWORK_FILTER
| FILESYS_FILTER
)))
4055 if ((fdmap
= find_fd_thread_map(thread
)))
4057 fdmap
->fd_valid
= 0;
4058 fdmap
->fd_thread
= 0;
4059 if (fdmap
->fd_setptr
)
4061 free (fdmap
->fd_setptr
);
4062 fdmap
->fd_setptr
= (unsigned long *)0;
4064 fdmap
->fd_setsize
= 0;
4077 ret
= (int)strtol(str
, &cp
, 10);
4078 if (cp
== str
|| *cp
) {
4079 /* Assume this is a command string and find matching pids */
4083 for (i
=0; i
< kp_nentries
&& num_of_pids
< (MAX_PIDS
- 1); i
++) {
4084 if(kp_buffer
[i
].kp_proc
.p_stat
== 0)
4087 if(!strncmp(str
, kp_buffer
[i
].kp_proc
.p_comm
,
4088 sizeof(kp_buffer
[i
].kp_proc
.p_comm
) -1))
4089 pids
[num_of_pids
++] = kp_buffer
[i
].kp_proc
.p_pid
;
4093 else if (num_of_pids
< (MAX_PIDS
- 1))
4094 pids
[num_of_pids
++] = ret
;
4102 lookup_name(uint64_t user_addr
, char **type
, char **name
)
4110 if (numFrameworks
) {
4112 if ((user_addr
>= framework32
.b_address
&& user_addr
< framework32
.e_address
) ||
4113 (user_addr
>= framework64
.b_address
&& user_addr
< framework64
.e_address
)) {
4116 last
= numFrameworks
;
4118 for (i
= numFrameworks
/ 2; start
< last
; i
= start
+ ((last
- start
) / 2)) {
4119 if (user_addr
> frameworkInfo
[i
].e_address
) {
4125 if (start
< numFrameworks
&&
4126 user_addr
>= frameworkInfo
[start
].b_address
&& user_addr
< frameworkInfo
[start
].e_address
) {
4127 *type
= frameworkType
[frameworkInfo
[start
].r_type
];
4128 *name
= frameworkInfo
[start
].name
;
4136 * Comparison routines for sorting
4138 static int compareFrameworkAddress(const void *aa
, const void *bb
)
4140 LibraryInfo
*a
= (LibraryInfo
*)aa
;
4141 LibraryInfo
*b
= (LibraryInfo
*)bb
;
4143 if (a
->b_address
< b
->b_address
) return -1;
4144 if (a
->b_address
== b
->b_address
) return 0;
4149 int scanline(char *inputstring
, char **argv
, int maxtokens
)
4152 char **ap
= argv
, *p
, *val
;
4154 for (p
= inputstring
; n
< maxtokens
&& p
!= NULL
; )
4156 while ((val
= strsep(&p
, " \t")) != NULL
&& *val
== '\0');
4165 int ReadSharedCacheMap(const char *path
, LibraryRange
*lr
, char *linkedit_name
)
4167 uint64_t b_address
, e_address
;
4171 char frameworkName
[256];
4175 int linkedit_found
= 0;
4176 char *substring
, *ptr
;
4178 bzero(buf
, sizeof(buf
));
4179 bzero(tokens
, sizeof(tokens
));
4184 if ((fd
= fopen(path
, "r")) == 0)
4188 while (fgets(buf
, 1023, fd
)) {
4189 if (strncmp(buf
, "mapping", 7))
4192 buf
[strlen(buf
)-1] = 0;
4194 frameworkName
[0] = 0;
4198 * Extract lib name from path name
4200 if ((substring
= strrchr(buf
, '.')))
4203 * There is a ".": name is whatever is between the "/" around the "."
4205 while ( *substring
!= '/') { /* find "/" before "." */
4209 strncpy(frameworkName
, substring
, 256); /* copy path from "/" */
4210 frameworkName
[255] = 0;
4211 substring
= frameworkName
;
4213 while ( *substring
!= '/' && *substring
) /* find "/" after "." and stop string there */
4220 * No ".": take segment after last "/"
4228 substring
= ptr
+ 1;
4231 strncpy(frameworkName
, substring
, 256);
4232 frameworkName
[255] = 0;
4234 fnp
= (char *)malloc(strlen(frameworkName
) + 1);
4235 strcpy(fnp
, frameworkName
);
4237 while (fgets(buf
, 1023, fd
) && numFrameworks
< (MAXINDEX
- 2))
4242 buf
[strlen(buf
)-1] = 0;
4244 ntokens
= scanline(buf
, tokens
, 64);
4249 if (strncmp(tokens
[0], "__TEXT", 6) == 0)
4251 else if (strncmp(tokens
[0], "__DATA", 6) == 0)
4253 else if (strncmp(tokens
[0], "__OBJC", 6) == 0)
4255 else if (strncmp(tokens
[0], "__IMPORT", 8) == 0)
4257 else if (strncmp(tokens
[0], "__UNICODE", 9) == 0)
4259 else if (strncmp(tokens
[0], "__IMAGE", 7) == 0)
4261 else if (strncmp(tokens
[0], "__LINKEDIT", 10) == 0)
4266 if (type
== LINKEDIT_R
&& linkedit_found
)
4270 b_address
= strtoull(tokens
[1], 0, 16);
4271 e_address
= strtoull(tokens
[3], 0, 16);
4273 frameworkInfo
[numFrameworks
].b_address
= b_address
;
4274 frameworkInfo
[numFrameworks
].e_address
= e_address
;
4275 frameworkInfo
[numFrameworks
].r_type
= type
;
4277 if (type
== LINKEDIT_R
) {
4278 frameworkInfo
[numFrameworks
].name
= linkedit_name
;
4281 frameworkInfo
[numFrameworks
].name
= fnp
;
4283 printf("%s(%d): %qx-%qx\n", frameworkInfo
[numFrameworks
].name
, type
, b_address
, e_address
);
4285 if (lr
->b_address
== 0 || b_address
< lr
->b_address
)
4286 lr
->b_address
= b_address
;
4288 if (lr
->e_address
== 0 || e_address
> lr
->e_address
)
4289 lr
->e_address
= e_address
;
4293 if (type
== LINKEDIT_R
)
4296 if (fgets(buf
, 1023, fd
) == 0)
4299 buf
[strlen(buf
)-1] = 0;
4304 printf("%s range, %qx-%qx\n", path
, lr
->b_address
, lr
->e_address
);
4311 SortFrameworkAddresses()
4314 frameworkInfo
[numFrameworks
].b_address
= frameworkInfo
[numFrameworks
- 1].b_address
+ 0x800000;
4315 frameworkInfo
[numFrameworks
].e_address
= frameworkInfo
[numFrameworks
].b_address
;
4316 frameworkInfo
[numFrameworks
].name
= (char *)0;
4318 qsort(frameworkInfo
, numFrameworks
, sizeof(LibraryInfo
), compareFrameworkAddress
);
4322 struct diskio
*insert_diskio(int type
, int bp
, int dev
, int blkno
, int io_size
, uintptr_t thread
, double curtime
)
4324 register struct diskio
*dio
;
4325 register kd_threadmap
*map
;
4327 if ((dio
= free_diskios
))
4328 free_diskios
= dio
->next
;
4330 if ((dio
= (struct diskio
*)malloc(sizeof(struct diskio
))) == NULL
)
4339 dio
->iosize
= io_size
;
4340 dio
->issued_time
= curtime
;
4341 dio
->issuing_thread
= thread
;
4343 if ((map
= find_thread_map(thread
)))
4345 strncpy(dio
->issuing_command
, map
->command
, MAXCOMLEN
);
4346 dio
->issuing_command
[MAXCOMLEN
-1] = '\0';
4349 strcpy(dio
->issuing_command
, "");
4351 dio
->next
= busy_diskios
;
4353 dio
->next
->prev
= dio
;
4360 struct diskio
*complete_diskio(int bp
, int io_errno
, int resid
, uintptr_t thread
, double curtime
)
4362 register struct diskio
*dio
;
4364 for (dio
= busy_diskios
; dio
; dio
= dio
->next
) {
4365 if (dio
->bp
== bp
) {
4367 if (dio
== busy_diskios
) {
4368 if ((busy_diskios
= dio
->next
))
4369 dio
->next
->prev
= NULL
;
4372 dio
->next
->prev
= dio
->prev
;
4373 dio
->prev
->next
= dio
->next
;
4375 dio
->iosize
-= resid
;
4376 dio
->io_errno
= io_errno
;
4377 dio
->completed_time
= curtime
;
4378 dio
->completion_thread
= thread
;
4383 return ((struct diskio
*)0);
4387 void free_diskio(struct diskio
*dio
)
4389 dio
->next
= free_diskios
;
4394 void print_diskio(struct diskio
*dio
)
4398 switch (dio
->type
) {
4419 p
= " RdMeta[async]";
4422 p
= " WrMeta[async]";
4425 p
= " RdData[async]";
4428 p
= " WrData[async]";
4434 p
= " PgOut[async]";
4440 if (check_filter_mode(NULL
, dio
->type
, 0, 0, p
))
4441 format_print(NULL
, p
, dio
->issuing_thread
, dio
->type
, 0, 0, 0, 0, FMT_DISKIO
, dio
->completed_time
, dio
->issued_time
, 1, "", dio
);
4445 void cache_disk_names()
4450 struct diskrec
*dnp
;
4453 if ((dirp
= opendir("/dev")) == NULL
)
4456 while ((dir
= readdir(dirp
)) != NULL
) {
4457 char nbuf
[MAXPATHLEN
];
4459 if (dir
->d_namlen
< 5 || strncmp("disk", dir
->d_name
, 4))
4461 snprintf(nbuf
, MAXPATHLEN
, "%s/%s", "/dev", dir
->d_name
);
4463 if (stat(nbuf
, &st
) < 0)
4466 if ((dnp
= (struct diskrec
*)malloc(sizeof(struct diskrec
))) == NULL
)
4469 if ((dnp
->diskname
= (char *)malloc(dir
->d_namlen
+ 1)) == NULL
) {
4473 strncpy(dnp
->diskname
, dir
->d_name
, dir
->d_namlen
);
4474 dnp
->diskname
[dir
->d_namlen
] = 0;
4475 dnp
->dev
= st
.st_rdev
;
4477 dnp
->next
= disk_list
;
4480 (void) closedir(dirp
);
4484 void recache_disk_names()
4486 struct diskrec
*dnp
, *next_dnp
;
4488 for (dnp
= disk_list
; dnp
; dnp
= next_dnp
) {
4489 next_dnp
= dnp
->next
;
4491 free(dnp
->diskname
);
4500 char *find_disk_name(int dev
)
4502 struct diskrec
*dnp
;
4508 for (i
= 0; i
< 2; i
++) {
4509 for (dnp
= disk_list
; dnp
; dnp
= dnp
->next
) {
4510 if (dnp
->dev
== dev
)
4511 return (dnp
->diskname
);
4513 recache_disk_names();
4515 return ("NOTFOUND");
4519 fs_usage_fd_set(thread
, fd
)
4520 unsigned int thread
;
4524 fd_threadmap
*fdmap
;
4526 if(!(fdmap
= find_fd_thread_map(thread
)))
4529 /* If the map is not allocated, then now is the time */
4530 if (fdmap
->fd_setptr
== (unsigned long *)0)
4532 fdmap
->fd_setptr
= (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE
));
4533 if (fdmap
->fd_setptr
)
4535 fdmap
->fd_setsize
= FS_USAGE_FD_SETSIZE
;
4536 bzero(fdmap
->fd_setptr
,(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE
)));
4542 /* If the map is not big enough, then reallocate it */
4543 while (fdmap
->fd_setsize
<= fd
)
4545 fprintf(stderr
, "reallocating bitmap for threadid %d, fd = %d, setsize = %d\n",
4546 thread
, fd
, fdmap
->fd_setsize
);
4547 n
= fdmap
->fd_setsize
* 2;
4548 fdmap
->fd_setptr
= (unsigned long *)realloc(fdmap
->fd_setptr
, (FS_USAGE_NFDBYTES(n
)));
4549 bzero(&fdmap
->fd_setptr
[(fdmap
->fd_setsize
/FS_USAGE_NFDBITS
)], (FS_USAGE_NFDBYTES(fdmap
->fd_setsize
)));
4550 fdmap
->fd_setsize
= n
;
4554 fdmap
->fd_setptr
[fd
/FS_USAGE_NFDBITS
] |= (1 << ((fd
) % FS_USAGE_NFDBITS
));
4561 0 : File Descriptor bit is not set
4562 1 : File Descriptor bit is set
4566 fs_usage_fd_isset(thread
, fd
)
4567 unsigned int thread
;
4571 fd_threadmap
*fdmap
;
4573 if(!(fdmap
= find_fd_thread_map(thread
)))
4576 if (fdmap
->fd_setptr
== (unsigned long *)0)
4579 if (fd
< fdmap
->fd_setsize
)
4580 ret
= fdmap
->fd_setptr
[fd
/FS_USAGE_NFDBITS
] & (1 << (fd
% FS_USAGE_NFDBITS
));
4586 fs_usage_fd_clear(thread
, fd
)
4587 unsigned int thread
;
4592 if (!(map
= find_fd_thread_map(thread
)))
4595 if (map
->fd_setptr
== (unsigned long *)0)
4599 if (fd
< map
->fd_setsize
)
4600 map
->fd_setptr
[fd
/FS_USAGE_NFDBITS
] &= ~(1 << (fd
% FS_USAGE_NFDBITS
));
4607 * ret = 1 means print the entry
4608 * ret = 0 means don't print the entry
4611 check_filter_mode(struct th_info
* ti
, int type
, int error
, int retval
, char *sc_name
)
4614 int network_fd_isset
= 0;
4617 if (filter_mode
== DEFAULT_DO_NOT_FILTER
)
4620 if (sc_name
[0] == 'C' && !strcmp (sc_name
, "CACHE_HIT")) {
4621 if (filter_mode
& CACHEHIT_FILTER
)
4622 /* Do not print if cachehit filter is set */
4627 if (filter_mode
& EXEC_FILTER
)
4629 if (type
== BSC_execve
)
4634 if (filter_mode
& PATHNAME_FILTER
)
4636 if (ti
&& ti
->pathname
[0])
4638 if (type
== BSC_close
|| type
== BSC_close_nocancel
)
4643 if ( !(filter_mode
& (FILESYS_FILTER
| NETWORK_FILTER
)))
4647 if (ti
== (struct th_info
*)0)
4649 if (filter_mode
& FILESYS_FILTER
)
4658 case BSC_close_nocancel
:
4660 network_fd_isset
= fs_usage_fd_isset(ti
->thread
, fd
);
4663 fs_usage_fd_clear(ti
->thread
,fd
);
4666 if (network_fd_isset
)
4668 if (filter_mode
& NETWORK_FILTER
)
4671 else if (filter_mode
& FILESYS_FILTER
)
4676 case BSC_read_nocancel
:
4677 case BSC_write_nocancel
:
4678 /* we don't care about error in this case */
4680 network_fd_isset
= fs_usage_fd_isset(ti
->thread
, fd
);
4681 if (network_fd_isset
)
4683 if (filter_mode
& NETWORK_FILTER
)
4686 else if (filter_mode
& FILESYS_FILTER
)
4690 case BSC_accept_nocancel
:
4694 fs_usage_fd_set(ti
->thread
, fd
);
4695 if (filter_mode
& NETWORK_FILTER
)
4705 case BSC_sendto_nocancel
:
4706 case BSC_recvfrom_nocancel
:
4707 case BSC_recvmsg_nocancel
:
4708 case BSC_sendmsg_nocancel
:
4709 case BSC_connect_nocancel
:
4712 fs_usage_fd_set(ti
->thread
, fd
);
4713 if (filter_mode
& NETWORK_FILTER
)
4717 case BSC_select_nocancel
:
4718 case BSC_socketpair
:
4719 /* Cannot determine info about file descriptors */
4720 if (filter_mode
& NETWORK_FILTER
)
4725 ret
=0; /* We track these cases for fd state only */
4726 fd
= ti
->arg1
; /* oldd */
4727 network_fd_isset
= fs_usage_fd_isset(ti
->thread
, fd
);
4728 if (error
== 0 && network_fd_isset
)
4730 /* then we are duping a socket descriptor */
4731 fd
= retval
; /* the new fd */
4732 fs_usage_fd_set(ti
->thread
, fd
);
4737 if (filter_mode
& FILESYS_FILTER
)
4746 * Allocate a buffer that is large enough to hold the maximum arguments
4747 * to execve(). This is used when getting the arguments to programs
4748 * when we see LaunchCFMApps. If this fails, it is not fatal, we will
4749 * simply not resolve the command name.
4753 init_arguments_buffer()
4760 mib
[1] = KERN_ARGMAX
;
4761 size
= sizeof(argmax
);
4762 if (sysctl(mib
, 2, &argmax
, &size
, NULL
, 0) == -1)
4766 /* Hack to avoid kernel bug. */
4767 if (argmax
> 8192) {
4772 arguments
= (char *)malloc(argmax
);
4779 get_real_command_name(int pid
, char *cbuf
, int csize
)
4782 * Get command and arguments.
4786 char *command_beg
, *command
, *command_end
;
4793 bzero(arguments
, argmax
);
4798 * A sysctl() is made to find out the full path that the command
4802 mib
[1] = KERN_PROCARGS2
;
4806 if (sysctl(mib
, 3, arguments
, (size_t *)&argmax
, NULL
, 0) < 0) {
4810 /* Skip the saved exec_path. */
4811 for (cp
= arguments
; cp
< &arguments
[argmax
]; cp
++) {
4813 /* End of exec_path reached. */
4817 if (cp
== &arguments
[argmax
]) {
4821 /* Skip trailing '\0' characters. */
4822 for (; cp
< &arguments
[argmax
]; cp
++) {
4824 /* Beginning of first argument reached. */
4828 if (cp
== &arguments
[argmax
]) {
4834 * Make sure that the command is '\0'-terminated. This protects
4835 * against malicious programs; under normal operation this never
4836 * ends up being a problem..
4838 for (; cp
< &arguments
[argmax
]; cp
++) {
4840 /* End of first argument reached. */
4844 if (cp
== &arguments
[argmax
]) {
4847 command_end
= command
= cp
;
4849 /* Get the basename of command. */
4850 for (command
--; command
>= command_beg
; command
--) {
4851 if (*command
== '/') {
4857 (void) strncpy(cbuf
, (char *)command
, csize
);
4858 cbuf
[csize
-1] = '\0';