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