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@
27 cc -I. -DKERNEL_PRIVATE -O -o latency latency.c
30 #include <mach/mach.h>
39 #include <sys/types.h>
40 #include <sys/param.h>
45 #include <bsd/curses.h>
46 #include <sys/ioctl.h>
48 #ifndef KERNEL_PRIVATE
49 #define KERNEL_PRIVATE
50 #include <sys/kdebug.h>
53 #include <sys/kdebug.h>
54 #endif /*KERNEL_PRIVATE*/
56 #include <sys/sysctl.h>
60 #include <mach/host_info.h>
61 #include <mach/mach_error.h>
62 #include <mach/mach_types.h>
63 #include <mach/message.h>
64 #include <mach/mach_syscalls.h>
65 #include <mach/clock.h>
66 #include <mach/clock_types.h>
68 #include <libkern/OSTypes.h>
70 extern mach_port_t clock_port
;
72 #define KERN_KDPIDEX 14
75 int s_usec_10_bins
[10];
76 int s_usec_100_bins
[10];
77 int s_msec_1_bins
[10];
78 int s_msec_10_bins
[5];
81 int s_min_latency
= 0;
82 long long s_total_latency
= 0;
85 int s_exceeded_threshold
= 0;
87 int i_usec_10_bins
[10];
88 int i_usec_100_bins
[10];
89 int i_msec_1_bins
[10];
90 int i_msec_10_bins
[5];
93 int i_min_latency
= 0;
94 long long i_total_latency
= 0;
97 int i_exceeded_threshold
= 0;
106 int num_of_usecs_to_sleep
= 1000;
108 char *kernelpath
= (char *)0;
109 char *code_file
= (char *)0;
112 u_long k_sym_addr
; /* kernel symbol address from nm */
113 u_int k_sym_len
; /* length of kernel symbol string */
114 char *k_sym_name
; /* kernel symbol string from nm */
117 kern_sym_t
*kern_sym_tbl
; /* pointer to the nm table */
118 int kern_sym_count
; /* number of entries in nm table */
121 #define UNKNOWN "Can't find symbol name"
126 int trace_enabled
= 0;
128 #define SAMPLE_SIZE 300000
134 kbufinfo_t bufinfo
= {0, 0, 0};
136 FILE *log_fp
= (FILE *)0;
137 int num_of_codes
= 0;
138 int need_new_map
= 0;
139 int total_threads
= 0;
140 kd_threadmap
*mapptr
= 0;
142 #define MAX_ENTRIES 1024
146 } codes_tab
[MAX_ENTRIES
];
159 #define MAX_THREADS 512
160 struct th_info th_state
[MAX_THREADS
];
164 #define TRACE_DATA_NEWTHREAD 0x07000004
165 #define TRACE_STRING_NEWTHREAD 0x07010004
166 #define TRACE_STRING_EXEC 0x07010008
168 #define INTERRUPT 0x01050000
169 #define DECR_TRAP 0x01090000
170 #define DECR_SET 0x01090004
171 #define MACH_vmfault 0x01300000
172 #define MACH_sched 0x01400000
173 #define MACH_stkhandoff 0x01400008
174 #define VFS_LOOKUP 0x03010090
175 #define BSC_exit 0x040C0004
176 #define IES_action 0x050b0018
177 #define IES_filter 0x050b001c
178 #define TES_action 0x050c0010
179 #define CQ_action 0x050d0018
182 #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END)
183 #define DBG_FUNC_MASK 0xfffffffc
185 #define DBG_ZERO_FILL_FAULT 1
186 #define DBG_PAGEIN_FAULT 2
187 #define DBG_COW_FAULT 3
188 #define DBG_CACHE_HIT_FAULT 4
190 char *fault_name
[5] = {
198 char *pc_to_string();
199 static kern_return_t
set_time_constraint_policy(void);
200 static kern_return_t
set_standard_policy(void);
202 int decrementer_val
= 0; /* Value used to reset decrementer */
203 int set_remove_flag
= 1; /* By default, remove trace buffer */
205 /* raw read of the timebase register */
206 void clock_get_uptime( register AbsoluteTime
*result
)
212 asm volatile(" mftbu %0" : "=r" (result
->hi
));
213 asm volatile(" mftb %0" : "=r" (result
->lo
));
214 asm volatile(" mftbu %0" : "=r" (hic
));
215 } while (hic
!= result
->hi
);
224 typedef unsigned long long abstime_scalar_t
;
226 #define AbsoluteTime_to_scalar(x) \
227 (*(abstime_scalar_t *)(x))
230 #define ADD_ABSOLUTETIME(t1, t2) \
231 (AbsoluteTime_to_scalar(t1) += \
232 AbsoluteTime_to_scalar(t2))
235 #define SUB_ABSOLUTETIME(t1, t2) \
236 (AbsoluteTime_to_scalar(t1) -= \
237 AbsoluteTime_to_scalar(t2))
251 This flag is turned off when calling
252 quit() due to a set_remove() failure.
271 mib
[1] = KERN_KDEBUG
;
272 mib
[2] = KERN_KDENABLE
; /* protocol */
275 mib
[5] = 0; /* no flags */
277 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
278 quit("trace facility failure, KERN_KDENABLE\n");
282 set_numbufs(int nbufs
)
285 mib
[1] = KERN_KDEBUG
;
286 mib
[2] = KERN_KDSETBUF
;
289 mib
[5] = 0; /* no flags */
290 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
291 quit("trace facility failure, KERN_KDSETBUF\n");
294 mib
[1] = KERN_KDEBUG
;
295 mib
[2] = KERN_KDSETUP
;
298 mib
[5] = 0; /* no flags */
299 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
300 quit("trace facility failure, KERN_KDSETUP\n");
305 set_pidexclude(int pid
, int on_off
)
309 kr
.type
= KDBG_TYPENONE
;
312 needed
= sizeof(kd_regtype
);
314 mib
[1] = KERN_KDEBUG
;
315 mib
[2] = KERN_KDPIDEX
;
320 sysctl(mib
, 3, &kr
, &needed
, NULL
, 0);
329 kr
.type
= KDBG_TYPENONE
;
331 needed
= sizeof(kd_regtype
);
333 mib
[1] = KERN_KDEBUG
;
334 mib
[2] = KERN_KDSETRTCDEC
; /* protocol */
335 mib
[3] = 0; /* wildcard address family */
337 mib
[5] = 0; /* no flags */
341 if ((ret
=sysctl(mib
, 3, &kr
, &needed
, NULL
, 0)) < 0)
344 quit("trace facility failure, KERN_KDSETRTCDEC\n");
350 get_bufinfo(kbufinfo_t
*val
)
352 needed
= sizeof (*val
);
354 mib
[1] = KERN_KDEBUG
;
355 mib
[2] = KERN_KDGETBUF
;
358 mib
[5] = 0; /* no flags */
360 if (sysctl(mib
, 3, val
, &needed
, 0, 0) < 0)
361 quit("trace facility failure, KERN_KDGETBUF\n");
371 mib
[1] = KERN_KDEBUG
;
372 mib
[2] = KERN_KDREMOVE
; /* protocol */
375 mib
[5] = 0; /* no flags */
379 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
383 quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n");
385 quit("trace facility failure, KERN_KDREMOVE\n");
392 /* When we aren't logging, only collect the DECR_TRAP trace points */
394 kr
.type
= KDBG_VALCHECK
;
395 kr
.value1
= DECR_TRAP
;
399 needed
= sizeof(kd_regtype
);
401 mib
[1] = KERN_KDEBUG
;
402 mib
[2] = KERN_KDSETREG
;
405 mib
[5] = 0; /* no flags */
406 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0)
407 quit("trace facility failure, KERN_KDSETREG\n");
410 mib
[1] = KERN_KDEBUG
;
411 mib
[2] = KERN_KDSETUP
;
414 mib
[5] = 0; /* no flags */
416 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
417 quit("trace facility failure, KERN_KDSETUP\n");
424 kr
.type
= KDBG_RANGETYPE
;
427 needed
= sizeof(kd_regtype
);
429 mib
[1] = KERN_KDEBUG
;
430 mib
[2] = KERN_KDSETREG
;
433 mib
[5] = 0; /* no flags */
435 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0)
436 quit("trace facility failure, KERN_KDSETREG\n");
439 mib
[1] = KERN_KDEBUG
;
440 mib
[2] = KERN_KDSETUP
;
443 mib
[5] = 0; /* no flags */
445 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
446 quit("trace facility failure, KERN_KDSETUP\n");
457 void screen_update();
460 set_pidexclude(getpid(), 0);
461 screen_update(log_fp
);
471 set_pidexclude(getpid(), 0);
481 set_pidexclude(getpid(), 0);
490 screen_update(FILE *fp
)
497 unsigned int average_s_latency
;
498 unsigned int average_i_latency
;
501 if (fp
== (FILE *)0) {
505 fprintf(fp
,"\n\n===================================================================================================\n");
507 * Display the current time.
508 * "ctime" always returns a string that looks like this:
510 * Sun Sep 16 01:03:52 1973
511 * 012345678901234567890123
514 * We want indices 11 thru 18 (length 8).
516 elapsed_secs
= curr_time
- start_time
;
517 elapsed_hours
= elapsed_secs
/ 3600;
518 elapsed_secs
-= elapsed_hours
* 3600;
519 elapsed_mins
= elapsed_secs
/ 60;
520 elapsed_secs
-= elapsed_mins
* 60;
522 sprintf(tbuf
, "%-19.19s %2ld:%02ld:%02ld\n", &(ctime(&curr_time
)[0]),
523 elapsed_hours
, elapsed_mins
, elapsed_secs
);
525 fprintf(fp
, "%s", tbuf
);
531 sprintf(tbuf
, " SCHEDULER INTERRUPTS\n");
534 fprintf(fp
, "%s", tbuf
);
538 sprintf(tbuf
, "---------------------------------------------\n");
541 fprintf(fp
, "%s", tbuf
);
547 sprintf(tbuf
, "total_samples %10d %10d\n\n", s_total_samples
, i_total_samples
);
550 fprintf(fp
, "%s", tbuf
);
556 for (itotal
= 0, stotal
= 0, i
= 0; i
< 10; i
++) {
557 sprintf(tbuf
, "delays < %3d usecs %10d %10d\n", (i
+ 1) * 10, s_usec_10_bins
[i
], i_usec_10_bins
[i
]);
560 fprintf(fp
, "%s", tbuf
);
564 stotal
+= s_usec_10_bins
[i
];
565 itotal
+= i_usec_10_bins
[i
];
567 sprintf(tbuf
, "total < 100 usecs %10d %10d\n\n", stotal
, itotal
);
570 fprintf(fp
, "%s", tbuf
);
576 for (itotal
= 0, stotal
= 0, i
= 1; i
< 10; i
++) {
578 sprintf(tbuf
, "delays < %3d usecs %10d %10d\n", (i
+ 1) * 100, s_usec_100_bins
[i
], i_usec_100_bins
[i
]);
580 sprintf(tbuf
, "delays < 1 msec %10d %10d\n", s_usec_100_bins
[i
], i_usec_100_bins
[i
]);
583 fprintf(fp
, "%s", tbuf
);
587 stotal
+= s_usec_100_bins
[i
];
588 itotal
+= i_usec_100_bins
[i
];
590 sprintf(tbuf
, "total < 1 msec %10d %10d\n\n", stotal
, itotal
);
593 fprintf(fp
, "%s", tbuf
);
599 for (itotal
= 0, stotal
= 0, i
= 1; i
< 10; i
++) {
600 sprintf(tbuf
, "delays < %3d msecs %10d %10d\n", (i
+ 1), s_msec_1_bins
[i
], i_msec_1_bins
[i
]);
603 fprintf(fp
, "%s", tbuf
);
607 stotal
+= s_msec_1_bins
[i
];
608 itotal
+= i_msec_1_bins
[i
];
610 sprintf(tbuf
, "total < 10 msecs %10d %10d\n\n", stotal
, itotal
);
613 fprintf(fp
, "%s", tbuf
);
620 for (itotal
= 0, stotal
= 0, i
= 1; i
< 5; i
++) {
621 sprintf(tbuf
, "delays < %3d msecs %10d %10d\n", (i
+ 1)*10, s_msec_10_bins
[i
], i_msec_10_bins
[i
]);
624 fprintf(fp
, "%s", tbuf
);
628 stotal
+= s_msec_10_bins
[i
];
629 itotal
+= i_msec_10_bins
[i
];
631 sprintf(tbuf
, "total < 50 msecs %10d %10d\n\n", stotal
, itotal
);
634 fprintf(fp
, "%s", tbuf
);
638 sprintf(tbuf
, "delays > 50 msecs %10d %10d\n", s_too_slow
, i_too_slow
);
641 fprintf(fp
, "%s", tbuf
);
647 sprintf(tbuf
, "\nminimum latency(usecs) %7d %7d\n", s_min_latency
, i_min_latency
);
650 fprintf(fp
, "%s", tbuf
);
654 sprintf(tbuf
, "maximum latency(usecs) %7d %7d\n", s_max_latency
, i_max_latency
);
657 fprintf(fp
, "%s", tbuf
);
662 average_s_latency
= (unsigned int)(s_total_latency
/s_total_samples
);
664 average_s_latency
= 0;
667 average_i_latency
= (unsigned int)(i_total_latency
/i_total_samples
);
669 average_i_latency
= 0;
671 sprintf(tbuf
, "average latency(usecs) %7d %7d\n", average_s_latency
, average_i_latency
);
674 fprintf(fp
, "%s", tbuf
);
678 sprintf(tbuf
, "exceeded threshold %7d %7d\n", s_exceeded_threshold
, i_exceeded_threshold
);
681 fprintf(fp
, "%s", tbuf
);
695 fprintf(stderr
, "Usage: latency [-rt] [-c codefile] [-l logfile] [-st threshold]\n");
696 fprintf(stderr
, " [-it threshold] [-s sleep_in_usecs]\n");
697 fprintf(stderr
, " [-d decrementer_in_usecs] [-n kernel]\n\n");
699 fprintf(stderr
, " -rt Set realtime scheduling policy. Default is timeshare.\n");
700 fprintf(stderr
, " -c specify name of codes file\n");
701 fprintf(stderr
, " -l specify name of file to log trace entries to when threshold is exceeded\n");
702 fprintf(stderr
, " -st set scheduler latency threshold in microseconds... if latency exceeds this, then log trace\n");
703 fprintf(stderr
, " -it set interrupt latency threshold in microseconds... if latency exceeds this, then log trace\n");
704 fprintf(stderr
, " -s set sleep time in microseconds\n");
705 fprintf(stderr
, " -d set decrementer in microseconds.\n");
706 fprintf(stderr
, " -n specify kernel, default is /mach_kernel\n");
708 fprintf(stderr
, "\nlatency must be run as root\n\n");
719 mach_timespec_t remain
;
720 unsigned long long start
, stop
;
721 AbsoluteTime timestamp1
;
722 AbsoluteTime timestamp2
;
723 AbsoluteTime adeadline
, adelay
;
726 double nanosecs_to_sleep
;
727 int loop_cnt
, sample_sc_now
;
728 int decrementer_usec
= 0;
731 void init_code_file();
735 my_policy
= THREAD_STANDARD_POLICY
;
736 policy_name
= "TIMESHARE";
739 if (strcmp(argv
[1], "-rt") == 0) {
740 my_policy
= THREAD_TIME_CONSTRAINT_POLICY
; /* the real time band */
741 policy_name
= "REALTIME";
743 } else if (strcmp(argv
[1], "-st") == 0) {
748 s_thresh_hold
= atoi(argv
[1]);
752 } else if (strcmp(argv
[1], "-it") == 0) {
757 i_thresh_hold
= atoi(argv
[1]);
760 } else if (strcmp(argv
[1], "-c") == 0) {
768 } else if (strcmp(argv
[1], "-l") == 0) {
773 open_logfile(argv
[1]);
777 } else if (strcmp(argv
[1], "-s") == 0) {
782 num_of_usecs_to_sleep
= atoi(argv
[1]);
785 } else if (strcmp(argv
[1], "-d") == 0) {
790 decrementer_usec
= atoi(argv
[1]);
793 } else if (strcmp(argv
[1], "-n") == 0) {
798 kernelpath
= argv
[1];
808 if ( geteuid() != 0 ) {
809 printf("'latency' must be run as root...\n");
813 if (kernelpath
== (char *) 0)
814 kernelpath
= "/mach_kernel";
816 if (code_file
== (char *) 0)
817 code_file
= "/usr/share/misc/trace.codes";
821 sample_sc_now
= 25000 / num_of_usecs_to_sleep
;
824 decrementer_val
= decrementer_usec
* divisor
;
826 nanosecs_to_sleep
= (double)(num_of_usecs_to_sleep
* 1000);
827 fdelay
= nanosecs_to_sleep
* (divisor
/1000);
828 AbsoluteTime_to_scalar(&adelay
) = (abstime_scalar_t
)fdelay
;
833 When the decrementer isn't set in the options,
834 decval will be zero and this call will reset
835 the system default ...
837 set_rtcdec(decrementer_val
);
842 signal(SIGWINCH
, sigwinch
);
843 signal(SIGINT
, sigintr
);
844 signal(SIGQUIT
, sigquit
);
845 signal(SIGTERM
, sigterm
);
848 if ((my_buffer
= malloc(SAMPLE_SIZE
* sizeof(kd_buf
))) == (char *)0)
849 quit("can't allocate memory for tracing info\n");
851 set_numbufs(SAMPLE_SIZE
);
856 set_init_nologging();
857 set_pidexclude(getpid(), 1);
863 start_time
= time((long *)0);
864 refresh_time
= start_time
;
866 if (my_policy
== THREAD_TIME_CONSTRAINT_POLICY
)
868 /* the realtime band */
869 if(set_time_constraint_policy() != KERN_SUCCESS
)
870 quit("Failed to set realtime policy.\n");
874 curr_time
= time((long *)0);
876 if (curr_time
>= refresh_time
) {
877 if (my_policy
== THREAD_TIME_CONSTRAINT_POLICY
)
879 /* set standard timeshare policy during screen update */
880 if(set_standard_policy() != KERN_SUCCESS
)
881 quit("Failed to set standard policy.\n");
883 screen_update((FILE *)0);
884 if (my_policy
== THREAD_TIME_CONSTRAINT_POLICY
)
886 /* set back to realtime band */
887 if(set_time_constraint_policy() != KERN_SUCCESS
)
888 quit("Failed to set time_constraint policy.\n");
890 refresh_time
= curr_time
+ 1;
893 clock_get_uptime(×tamp1
);
894 adeadline
= timestamp1
;
895 ADD_ABSOLUTETIME(&adeadline
, &adelay
);
896 mk_wait_until(adeadline
);
897 clock_get_uptime(×tamp2
);
899 start
= (((unsigned long long)timestamp1
.hi
) << 32) |
900 (unsigned long long)((unsigned int)(timestamp1
.lo
));
902 stop
= (((unsigned long long)timestamp2
.hi
) << 32) |
903 (unsigned long long)((unsigned int)(timestamp2
.lo
));
905 elapsed_usecs
= (int)(((double)(stop
- start
)) / divisor
);
907 if ((elapsed_usecs
-= num_of_usecs_to_sleep
) <= 0)
910 if (elapsed_usecs
< 100)
911 s_usec_10_bins
[elapsed_usecs
/10]++;
912 if (elapsed_usecs
< 1000)
913 s_usec_100_bins
[elapsed_usecs
/100]++;
914 else if (elapsed_usecs
< 10000)
915 s_msec_1_bins
[elapsed_usecs
/1000]++;
916 else if (elapsed_usecs
< 50000)
917 s_msec_10_bins
[elapsed_usecs
/10000]++;
921 if (elapsed_usecs
> s_max_latency
)
922 s_max_latency
= elapsed_usecs
;
923 if (elapsed_usecs
< s_min_latency
|| s_total_samples
== 0)
924 s_min_latency
= elapsed_usecs
;
925 s_total_latency
+= elapsed_usecs
;
928 if (s_thresh_hold
&& elapsed_usecs
> s_thresh_hold
)
929 s_exceeded_threshold
++;
932 if (log_fp
&& s_thresh_hold
&& elapsed_usecs
> s_thresh_hold
)
933 sample_sc(start
, stop
);
935 if (loop_cnt
>= sample_sc_now
) {
936 sample_sc((long long)0, (long long)0);
956 unsigned int abs_to_ns_num
;
957 unsigned int abs_to_ns_denom
;
958 unsigned int proc_to_abs_num
;
959 unsigned int proc_to_abs_denom
;
961 (void)MKGetTimeBaseInfo (&delta
, &abs_to_ns_num
, &abs_to_ns_denom
,
962 &proc_to_abs_num
, &proc_to_abs_denom
);
964 divisor
= ((double)abs_to_ns_denom
/ (double)abs_to_ns_num
) * 1000;
967 /* This is the realtime band */
969 set_time_constraint_policy()
971 kern_return_t result
;
972 thread_time_constraint_policy_data_t info
;
973 mach_msg_type_number_t count
;
974 boolean_t get_default
;
977 count
= THREAD_TIME_CONSTRAINT_POLICY_COUNT
;
978 result
= thread_policy_get(mach_thread_self(), THREAD_TIME_CONSTRAINT_POLICY
,
979 (thread_policy_t
)&info
, &count
, &get_default
);
980 if (result
!= KERN_SUCCESS
)
983 result
= thread_policy_set(mach_thread_self(), THREAD_TIME_CONSTRAINT_POLICY
,
984 (thread_policy_t
)&info
, THREAD_TIME_CONSTRAINT_POLICY_COUNT
);
989 /* This is the timeshare mode */
991 set_standard_policy()
993 kern_return_t result
;
994 thread_standard_policy_data_t info
;
995 mach_msg_type_number_t count
;
996 boolean_t get_default
;
999 count
= THREAD_STANDARD_POLICY_COUNT
;
1000 result
= thread_policy_get(mach_thread_self(), THREAD_STANDARD_POLICY
,
1001 (thread_policy_t
)&info
, &count
, &get_default
);
1002 if (result
!= KERN_SUCCESS
)
1005 result
= thread_policy_set(mach_thread_self(), THREAD_STANDARD_POLICY
,
1006 (thread_policy_t
)&info
, THREAD_STANDARD_POLICY_COUNT
);
1012 void read_command_map()
1021 total_threads
= bufinfo
.nkdthreads
;
1022 size
= bufinfo
.nkdthreads
* sizeof(kd_threadmap
);
1025 if (mapptr
= (kd_threadmap
*) malloc(size
))
1026 bzero (mapptr
, size
);
1029 printf("Thread map is not initialized -- this is not fatal\n");
1034 /* Now read the threadmap */
1036 mib
[1] = KERN_KDEBUG
;
1037 mib
[2] = KERN_KDTHRMAP
;
1040 mib
[5] = 0; /* no flags */
1041 if (sysctl(mib
, 3, mapptr
, &size
, NULL
, 0) < 0)
1043 /* This is not fatal -- just means I cant map command strings */
1045 printf("Can't read the thread map -- this is not fatal\n");
1054 void create_map_entry(int thread
, char *command
)
1062 for (i
= 0, map
= 0; !map
&& i
< total_threads
; i
++)
1064 if (mapptr
[i
].thread
== thread
)
1065 map
= &mapptr
[i
]; /* Reuse this entry, the thread has been reassigned */
1068 if (!map
) /* look for invalid entries that I can reuse*/
1070 for (i
= 0, map
= 0; !map
&& i
< total_threads
; i
++)
1072 if (mapptr
[i
].valid
== 0 )
1073 map
= &mapptr
[i
]; /* Reuse this invalid entry */
1079 /* If reach here, then this is a new thread and
1080 * there are no invalid entries to reuse
1081 * Double the size of the thread map table.
1084 n
= total_threads
* 2;
1085 mapptr
= (kd_threadmap
*) realloc(mapptr
, n
* sizeof(kd_threadmap
));
1086 bzero(&mapptr
[total_threads
], total_threads
*sizeof(kd_threadmap
));
1087 map
= &mapptr
[total_threads
];
1091 fprintf(log_fp
, "MAP: increasing thread map to %d entries\n", total_threads
);
1096 fprintf(log_fp
, "MAP: adding thread %x with name %s\n", thread
, command
);
1099 map
->thread
= thread
;
1100 (void)strncpy (map
->command
, command
, sizeof(map
->command
));
1101 map
->command
[sizeof(map
->command
)-1] = '\0';
1105 kd_threadmap
*find_thread_map(int thread
)
1111 return((kd_threadmap
*)0);
1113 for (i
= 0; i
< total_threads
; i
++)
1116 if (map
->valid
&& (map
->thread
== thread
))
1121 return ((kd_threadmap
*)0);
1125 kill_thread_map(int thread
)
1129 if (map
= find_thread_map(thread
)) {
1133 fprintf(log_fp
, "MAP: deleting thread %x with name %s\n", thread
, map
->command
);
1137 map
->command
[0] = '\0';
1142 struct th_info
*find_thread(int thread
, int type1
, int type2
) {
1145 for (ti
= th_state
; ti
< &th_state
[cur_max
]; ti
++) {
1146 if (ti
->thread
== thread
) {
1149 if (type1
== ti
->type
)
1151 if (type2
== ti
->type
)
1155 return ((struct th_info
*)0);
1159 char *find_code(type
)
1163 for (i
= 0; i
< num_of_codes
; i
++) {
1164 if (codes_tab
[i
].type
== type
)
1165 return(codes_tab
[i
].name
);
1171 void sample_sc(long long start
, long long stop
)
1173 kd_buf
*kd
, *last_mach_sched
, *last_decrementer_kd
, *start_kd
, *end_of_sample
;
1174 unsigned long long now
;
1176 int first_entry
= 1;
1178 double timestamp
, last_timestamp
, delta
, start_bias
;
1179 void read_command_map();
1181 if (log_fp
&& (my_policy
== THREAD_TIME_CONSTRAINT_POLICY
))
1183 /* set standard timeshare policy when logging */
1184 if(set_standard_policy() != KERN_SUCCESS
)
1185 quit("Failed to set standard policy.\n");
1188 /* Get kernel buffer information */
1189 get_bufinfo(&bufinfo
);
1195 needed
= bufinfo
.nkdbufs
* sizeof(kd_buf
);
1197 mib
[1] = KERN_KDEBUG
;
1198 mib
[2] = KERN_KDREADTR
;
1201 mib
[5] = 0; /* no flags */
1203 if (sysctl(mib
, 3, my_buffer
, &needed
, NULL
, 0) < 0)
1204 quit("trace facility failure, KERN_KDREADTR\n");
1208 if (bufinfo
.flags
& KDBG_WRAPPED
) {
1211 for (i
= 0; i
< cur_max
; i
++) {
1212 th_state
[i
].thread
= 0;
1213 th_state
[i
].type
= -1;
1214 th_state
[i
].vfslookup
= 0;
1215 th_state
[i
].pathname
[0] = 0;
1226 latency
= (double)(stop
- start
) / divisor
;
1227 latency
-= (double)num_of_usecs_to_sleep
;
1229 fprintf(log_fp
, "\n\n%-19.19s scheduling latency = %.1fus num_of_traces = %d <<<<<<< trace buffer wrapped >>>>>>>\n\n",
1230 &(ctime(&curr_time
)[0]), latency
, count
);
1233 end_of_sample
= &((kd_buf
*)my_buffer
)[count
];
1234 last_decrementer_kd
= (kd_buf
*)my_buffer
;
1235 last_mach_sched
= (kd_buf
*)0;
1237 for (kd
= (kd_buf
*)my_buffer
; kd
< end_of_sample
; kd
++) {
1238 int debugid
, thread
, cpunum
;
1239 int type
, clen
, mode
;
1245 char sched_info
[64];
1247 kd_threadmap
*find_thread_map();
1248 double handle_decrementer();
1249 kd_buf
*log_decrementer();
1250 int check_for_thread_update();
1251 void enter_syscall();
1252 void exit_syscall();
1255 thread
= kd
->arg5
& KDBG_THREAD_MASK
;
1256 cpunum
= (kd
->arg5
& KDBG_CPU_MASK
) ? 1: 0;
1257 debugid
= kd
->debugid
;
1258 type
= kd
->debugid
& DBG_FUNC_MASK
;
1260 if (check_for_thread_update(thread
, type
, kd
))
1263 if (type
== DECR_TRAP
)
1264 i_latency
= handle_decrementer(kd
);
1266 now
= (((unsigned long long)kd
->timestamp
.tv_sec
) << 32) |
1267 (unsigned long long)((unsigned int)(kd
->timestamp
.tv_nsec
));
1269 timestamp
= ((double)now
) / divisor
;
1271 if (now
< start
|| now
> stop
) {
1272 if (debugid
& DBG_FUNC_START
)
1273 enter_syscall(log_fp
, kd
, thread
, type
, command
, timestamp
, delta
, start_bias
, 0);
1274 else if (debugid
& DBG_FUNC_END
)
1275 exit_syscall(log_fp
, kd
, thread
, type
, command
, timestamp
, delta
, start_bias
, 0);
1276 else if (type
== DECR_TRAP
) {
1277 if (log_fp
&& i_thresh_hold
&& (int)i_latency
> i_thresh_hold
) {
1278 start_kd
= last_decrementer_kd
;
1279 kd
= log_decrementer(start_kd
, kd
, end_of_sample
, i_latency
);
1281 if (kd
>= end_of_sample
)
1284 last_decrementer_kd
= kd
;
1293 latency
= (double)(stop
- start
) / divisor
;
1294 latency
-= (double)num_of_usecs_to_sleep
;
1297 sprintf(buf2
, "default");
1299 sprintf(buf2
, "%d", my_pri
);
1300 sprintf(buf1
, "%-19.19s scheduling latency = %.1fus sleep_request = %dus policy = %s priority = %s",
1301 &(ctime(&curr_time
)[0]), latency
, num_of_usecs_to_sleep
, policy_name
, buf2
);
1302 clen
= strlen(buf1
);
1303 memset(buf2
, '-', clen
);
1307 fprintf(log_fp
, "\n\n%s\n", buf2
);
1308 fprintf(log_fp
, "%s\n\n", buf1
);
1309 fprintf(log_fp
, "RelTime(Us) Delta debugid arg1 arg2 arg3 arg4 thread cpu command\n\n");
1311 start_bias
= ((double)start
) / divisor
;
1312 last_timestamp
= timestamp
;
1315 delta
= timestamp
- last_timestamp
;
1317 if (map
= find_thread_map(thread
))
1318 strcpy(command
, map
->command
);
1326 fprintf(log_fp
, "%9.1f %8.1f\t\tCQ_action @ %-59.59s %-8x %d %s\n",
1327 timestamp
- start_bias
, delta
, pc_to_string(kd
->arg1
, 59, 1) , thread
, cpunum
, command
);
1329 last_timestamp
= timestamp
;
1334 fprintf(log_fp
, "%9.1f %8.1f\t\tTES_action @ %-58.58s %-8x %d %s\n",
1335 timestamp
- start_bias
, delta
, pc_to_string(kd
->arg1
, 58, 1) , thread
, cpunum
, command
);
1338 last_timestamp
= timestamp
;
1343 fprintf(log_fp
, "%9.1f %8.1f\t\tIES_action @ %-58.58s %-8x %d %s\n",
1344 timestamp
- start_bias
, delta
, pc_to_string(kd
->arg1
, 58, 1) , thread
, cpunum
, command
);
1347 last_timestamp
= timestamp
;
1352 fprintf(log_fp
, "%9.1f %8.1f\t\tIES_filter @ %-58.58s %-8x %d %s\n",
1353 timestamp
- start_bias
, delta
, pc_to_string(kd
->arg1
, 58, 1) , thread
, cpunum
, command
);
1356 last_timestamp
= timestamp
;
1360 last_decrementer_kd
= kd
;
1362 if (i_thresh_hold
&& (int)i_latency
> i_thresh_hold
)
1369 if (ti
= find_thread((kd
->arg5
& KDBG_THREAD_MASK
), 0, 0)) {
1370 if (ti
->type
== -1 && strcmp(command
, "kernel_task"))
1375 fprintf(log_fp
, "%9.1f %8.1f[%.1f]%s\tDECR_TRAP @ %-59.59s %-8x %d %s\n",
1376 timestamp
- start_bias
, delta
, i_latency
, p
, pc_to_string(kd
->arg2
, 59, mode
) , thread
, cpunum
, command
);
1379 last_timestamp
= timestamp
;
1384 fprintf(log_fp
, "%9.1f %8.1f[%.1f] \t%-28.28s %-8x %d %s\n",
1385 timestamp
- start_bias
, delta
, (double)kd
->arg1
/divisor
, "DECR_SET", thread
, cpunum
, command
);
1388 last_timestamp
= timestamp
;
1392 case MACH_stkhandoff
:
1393 last_mach_sched
= kd
;
1395 if (map
= find_thread_map(kd
->arg2
))
1396 strcpy(command1
, map
->command
);
1398 sprintf(command1
, "%-8x", kd
->arg2
);
1400 if (ti
= find_thread(kd
->arg2
, 0, 0)) {
1401 if (ti
->type
== -1 && strcmp(command1
, "kernel_task"))
1407 memset(sched_info
, ' ', sizeof(sched_info
));
1409 sprintf(sched_info
, "%14.14s", command
);
1410 clen
= strlen(sched_info
);
1411 sched_info
[clen
] = ' ';
1413 sprintf(&sched_info
[14], " @ pri %3d --> %14.14s", kd
->arg3
, command1
);
1414 clen
= strlen(sched_info
);
1415 sched_info
[clen
] = ' ';
1417 sprintf(&sched_info
[45], " @ pri %3d%s", kd
->arg4
, p
);
1420 fprintf(log_fp
, "%9.1f %8.1f\t\t%-10.10s %s %-8x %d\n",
1421 timestamp
- start_bias
, delta
, "MACH_SCHED", sched_info
, thread
, cpunum
);
1424 last_timestamp
= timestamp
;
1428 if ((ti
= find_thread(thread
, 0, 0)) == (struct th_info
*)0) {
1429 if (cur_max
>= MAX_THREADS
)
1431 ti
= &th_state
[cur_max
++];
1433 ti
->thread
= thread
;
1436 ti
->child_thread
= 0;
1438 if (ti
->vfslookup
== 0) {
1440 ti
->arg1
= kd
->arg1
;
1441 memset(&ti
->pathname
[0], 0, 32);
1442 sargptr
= (long *)&ti
->pathname
[0];
1444 *sargptr
++ = kd
->arg2
;
1445 *sargptr
++ = kd
->arg3
;
1446 *sargptr
++ = kd
->arg4
;
1448 } else if (ti
->vfslookup
== 1) {
1451 sargptr
= (long *)&ti
->pathname
[12];
1452 *sargptr
++ = kd
->arg1
;
1453 *sargptr
++ = kd
->arg2
;
1454 *sargptr
++ = kd
->arg3
;
1455 *sargptr
++ = kd
->arg4
;
1458 fprintf(log_fp
, "%9.1f %8.1f\t\t%-28.28s %-28s %-8x %-8x %d %s\n",
1459 timestamp
- start_bias
, delta
, "VFS_LOOKUP",
1460 ti
->pathname
, ti
->arg1
, thread
, cpunum
, command
);
1463 last_timestamp
= timestamp
;
1467 if (debugid
& DBG_FUNC_START
)
1468 enter_syscall(log_fp
, kd
, thread
, type
, command
, timestamp
, delta
, start_bias
, 1);
1469 else if (debugid
& DBG_FUNC_END
)
1470 exit_syscall(log_fp
, kd
, thread
, type
, command
, timestamp
, delta
, start_bias
, 1);
1472 print_entry(log_fp
, kd
, thread
, type
, command
, timestamp
, delta
, start_bias
);
1474 last_timestamp
= timestamp
;
1478 if (last_mach_sched
&& log_fp
)
1479 fprintf(log_fp
, "\nblocked by %s @ priority %d\n", command
, last_mach_sched
->arg3
);
1481 if (first_entry
== 0 && log_fp
)
1482 fprintf(log_fp
, "\n start = %qd stop = %qd count = %d now = %qd\n", start
, stop
, count
, now
);
1487 if (log_fp
&& (my_policy
== THREAD_TIME_CONSTRAINT_POLICY
))
1489 /* set back to realtime band */
1490 if(set_time_constraint_policy() != KERN_SUCCESS
)
1491 quit("Failed to set time_constraint policy.\n");
1496 enter_syscall(FILE *fp
, kd_buf
*kd
, int thread
, int type
, char *command
, double timestamp
, double delta
, double bias
, int print_info
)
1503 cpunum
= (kd
->arg5
& KDBG_CPU_MASK
) ? 1: 0;
1505 if (print_info
&& fp
) {
1506 if (p
= find_code(type
)) {
1507 if (type
== INTERRUPT
) {
1510 if (ti
= find_thread((kd
->arg5
& KDBG_THREAD_MASK
), 0, 0)) {
1511 if (ti
->type
== -1 && strcmp(command
, "kernel_task"))
1515 fprintf(fp
, "%9.1f %8.1f\t\tINTERRUPT @ %-59.59s %-8x %d %s\n",
1516 timestamp
- bias
, delta
, pc_to_string(kd
->arg2
, 59, mode
), thread
, cpunum
, command
);
1517 } else if (type
== MACH_vmfault
) {
1518 fprintf(fp
, "%9.1f %8.1f\t\t%-28.28s %-8x %d %s\n",
1519 timestamp
- bias
, delta
, p
, thread
, cpunum
, command
);
1521 fprintf(fp
, "%9.1f %8.1f\t\t%-28.28s %-8x %-8x %-8x %-8x %-8x %d %s\n",
1522 timestamp
- bias
, delta
, p
, kd
->arg1
, kd
->arg2
, kd
->arg3
, kd
->arg4
,
1523 thread
, cpunum
, command
);
1526 fprintf(fp
, "%9.1f %8.1f\t\t%-8x %-8x %-8x %-8x %-8x %-8x %d %s\n",
1527 timestamp
- bias
, delta
, type
, kd
->arg1
, kd
->arg2
, kd
->arg3
, kd
->arg4
,
1528 thread
, cpunum
, command
);
1531 if ((ti
= find_thread(thread
, -1, type
)) == (struct th_info
*)0) {
1532 if (cur_max
>= MAX_THREADS
) {
1533 static int do_this_once
= 1;
1536 for (i
= 0; i
< cur_max
; i
++) {
1539 fprintf(fp
, "thread = %x, type = %x\n",
1540 th_state
[i
].thread
, th_state
[i
].type
);
1547 ti
= &th_state
[cur_max
++];
1549 ti
->thread
= thread
;
1550 ti
->child_thread
= 0;
1552 if (type
!= BSC_exit
)
1556 ti
->stime
= timestamp
;
1559 if (print_info
&& fp
)
1560 fprintf(fp
, "cur_max = %d, ti = %x, type = %x, thread = %x\n", cur_max
, ti
, ti
->type
, ti
->thread
);
1566 exit_syscall(FILE *fp
, kd_buf
*kd
, int thread
, int type
, char *command
, double timestamp
, double delta
, double bias
, int print_info
)
1572 cpunum
= (kd
->arg5
& KDBG_CPU_MASK
) ? 1: 0;
1573 ti
= find_thread(thread
, type
, type
);
1575 if (print_info
&& fp
)
1576 fprintf(fp
, "cur_max = %d, ti = %x, type = %x, thread = %x\n", cur_max
, ti
, type
, thread
);
1578 if (print_info
&& fp
) {
1580 fprintf(fp
, "%9.1f %8.1f(%.1f) \t", timestamp
- bias
, delta
, timestamp
- ti
->stime
);
1582 fprintf(fp
, "%9.1f %8.1f() \t", timestamp
- bias
, delta
);
1584 if (p
= find_code(type
)) {
1585 if (type
== INTERRUPT
) {
1586 fprintf(fp
, "INTERRUPT %-8x %d %s\n", thread
, cpunum
, command
);
1587 } else if (type
== MACH_vmfault
&& kd
->arg2
<= DBG_CACHE_HIT_FAULT
) {
1588 fprintf(fp
, "%-28.28s %-8.8s %-8x %-8x %d %s\n",
1589 p
, fault_name
[kd
->arg2
], kd
->arg1
,
1590 thread
, cpunum
, command
);
1592 fprintf(fp
, "%-28.28s %-8x %-8x %-8x %d %s\n",
1593 p
, kd
->arg1
, kd
->arg2
,
1594 thread
, cpunum
, command
);
1597 fprintf(fp
, "%-8x %-8x %-8x %-8x %d %s\n",
1598 type
, kd
->arg1
, kd
->arg2
,
1599 thread
, cpunum
, command
);
1602 if (ti
== (struct th_info
*)0) {
1603 if ((ti
= find_thread(thread
, -1, -1)) == (struct th_info
*)0) {
1604 if (cur_max
>= MAX_THREADS
)
1606 ti
= &th_state
[cur_max
++];
1608 ti
->thread
= thread
;
1609 ti
->child_thread
= 0;
1617 print_entry(FILE *fp
, kd_buf
*kd
, int thread
, int type
, char *command
, double timestamp
, double delta
, double bias
)
1625 cpunum
= (kd
->arg5
& KDBG_CPU_MASK
) ? 1: 0;
1628 fprintf(fp
, "cur_max = %d, type = %x, thread = %x, cpunum = %d\n", cur_max
, type
, thread
, cpunum
);
1630 if (p
= find_code(type
)) {
1631 fprintf(fp
, "%9.1f %8.1f\t\t%-28.28s %-8x %-8x %-8x %-8x %-8x %d %s\n",
1632 timestamp
- bias
, delta
, p
, kd
->arg1
, kd
->arg2
, kd
->arg3
, kd
->arg4
,
1633 thread
, cpunum
, command
);
1635 fprintf(fp
, "%9.1f %8.1f\t\t%-8x %-8x %-8x %-8x %-8x %-8x %d %s\n",
1636 timestamp
- bias
, delta
, type
, kd
->arg1
, kd
->arg2
, kd
->arg3
, kd
->arg4
,
1637 thread
, cpunum
, command
);
1642 check_for_thread_update(int thread
, int type
, kd_buf
*kd
)
1645 void create_map_entry();
1649 case TRACE_DATA_NEWTHREAD
:
1650 if ((ti
= find_thread(thread
, 0, 0)) == (struct th_info
*)0) {
1651 if (cur_max
>= MAX_THREADS
)
1653 ti
= &th_state
[cur_max
++];
1655 ti
->thread
= thread
;
1659 ti
->child_thread
= kd
->arg1
;
1662 case TRACE_STRING_NEWTHREAD
:
1663 if ((ti
= find_thread(thread
, 0, 0)) == (struct th_info
*)0)
1665 if (ti
->child_thread
== 0)
1667 create_map_entry(ti
->child_thread
, (char *)&kd
->arg1
);
1669 ti
->child_thread
= 0;
1672 case TRACE_STRING_EXEC
:
1673 create_map_entry(thread
, (char *)&kd
->arg1
);
1681 kd_buf
*log_decrementer(kd_buf
*kd_beg
, kd_buf
*kd_end
, kd_buf
*end_of_sample
, double i_latency
)
1683 kd_buf
*kd
, *kd_start
, *kd_stop
;
1684 double timestamp
, last_timestamp
, delta
, start_bias
;
1686 int debugid
, type
, clen
;
1687 unsigned long long now
;
1693 char sched_info
[64];
1697 kd_threadmap
*find_thread_map();
1699 sprintf(buf1
, "%-19.19s interrupt latency = %.1fus", &(ctime(&curr_time
)[0]), i_latency
);
1700 clen
= strlen(buf1
);
1701 memset(buf2
, '-', clen
);
1703 fprintf(log_fp
, "\n\n%s\n", buf2
);
1704 fprintf(log_fp
, "%s\n\n", buf1
);
1706 fprintf(log_fp
, "RelTime(Us) Delta debugid arg1 arg2 arg3 arg4 thread cpu command\n\n");
1708 thread
= kd_beg
->arg5
& KDBG_THREAD_MASK
;
1710 for (kd_start
= kd_beg
- 1; (kd_start
>= (kd_buf
*)my_buffer
) && (kd_start
->arg5
& KDBG_THREAD_MASK
) == thread
; kd_start
--) {
1711 if ((kd_start
->debugid
& DBG_FUNC_MASK
) == DECR_TRAP
)
1714 if (kd_start
< (kd_buf
*)my_buffer
)
1715 kd_start
= (kd_buf
*)my_buffer
;
1717 for (kd_stop
= kd_end
+ 1; kd_stop
< end_of_sample
&& (kd_start
->arg5
& KDBG_THREAD_MASK
) == thread
; kd_stop
++) {
1718 if ((kd_stop
->debugid
& DBG_FUNC_MASK
) == DECR_TRAP
)
1721 if (kd_stop
>= end_of_sample
)
1722 kd_stop
= end_of_sample
- 1;
1724 now
= (((unsigned long long)kd_start
->timestamp
.tv_sec
) << 32) |
1725 (unsigned long long)((unsigned int)(kd_start
->timestamp
.tv_nsec
));
1726 timestamp
= ((double)now
) / divisor
;
1728 for (kd
= kd_start
; kd
<= kd_stop
; kd
++) {
1729 type
= kd
->debugid
& DBG_FUNC_MASK
;
1731 if (ti
= find_thread((kd
->arg5
& KDBG_THREAD_MASK
), type
, type
)) {
1732 if (ti
->stime
>= timestamp
)
1736 for (kd
= kd_start
; kd
<= kd_stop
; kd
++) {
1739 thread
= kd
->arg5
& KDBG_THREAD_MASK
;
1740 cpunum
= (kd
->arg5
& KDBG_CPU_MASK
) ? 1: 0;
1741 debugid
= kd
->debugid
;
1742 type
= kd
->debugid
& DBG_FUNC_MASK
;
1744 now
= (((unsigned long long)kd
->timestamp
.tv_sec
) << 32) |
1745 (unsigned long long)((unsigned int)(kd
->timestamp
.tv_nsec
));
1747 timestamp
= ((double)now
) / divisor
;
1749 if (kd
== kd_start
) {
1750 start_bias
= timestamp
;
1751 last_timestamp
= timestamp
;
1753 delta
= timestamp
- last_timestamp
;
1755 if (map
= find_thread_map(thread
))
1756 strcpy(command
, map
->command
);
1764 fprintf(log_fp
, "%9.1f %8.1f\t\tCQ_action @ %-59.59s %-8x %d %s\n",
1765 timestamp
- start_bias
, delta
, pc_to_string(kd
->arg1
, 59, 1) , thread
, cpunum
, command
);
1767 last_timestamp
= timestamp
;
1771 if ((int)(kd
->arg1
) >= 0)
1774 i_latency
= (((double)(-1 - kd
->arg1
)) / divisor
);
1776 if (i_thresh_hold
&& (int)i_latency
> i_thresh_hold
)
1783 if (ti
= find_thread((kd
->arg5
& KDBG_THREAD_MASK
), 0, 0)) {
1784 if (ti
->type
== -1 && strcmp(command
, "kernel_task"))
1787 fprintf(log_fp
, "%9.1f %8.1f[%.1f]%s\tDECR_TRAP @ %-59.59s %-8x %d %s\n",
1788 timestamp
- start_bias
, delta
, i_latency
, p
, pc_to_string(kd
->arg2
, 59, mode
) , thread
, cpunum
, command
);
1790 last_timestamp
= timestamp
;
1794 fprintf(log_fp
, "%9.1f %8.1f[%.1f] \t%-28.28s %-8x %d %s\n",
1795 timestamp
- start_bias
, delta
, (double)kd
->arg1
/divisor
,
1796 "DECR_SET", thread
, cpunum
, command
);
1798 last_timestamp
= timestamp
;
1802 case MACH_stkhandoff
:
1803 if (map
= find_thread_map(kd
->arg2
))
1804 strcpy(command1
, map
->command
);
1806 sprintf(command1
, "%-8x", kd
->arg2
);
1808 if (ti
= find_thread(kd
->arg2
, 0, 0)) {
1809 if (ti
->type
== -1 && strcmp(command1
, "kernel_task"))
1815 memset(sched_info
, ' ', sizeof(sched_info
));
1817 sprintf(sched_info
, "%14.14s", command
);
1818 clen
= strlen(sched_info
);
1819 sched_info
[clen
] = ' ';
1821 sprintf(&sched_info
[14], " @ pri %3d --> %14.14s", kd
->arg3
, command1
);
1822 clen
= strlen(sched_info
);
1823 sched_info
[clen
] = ' ';
1825 sprintf(&sched_info
[45], " @ pri %3d%s", kd
->arg4
, p
);
1827 fprintf(log_fp
, "%9.1f %8.1f\t\t%-10.10s %s %-8x %d\n",
1828 timestamp
- start_bias
, delta
, "MACH_SCHED", sched_info
, thread
, cpunum
);
1830 last_timestamp
= timestamp
;
1834 if ((ti
= find_thread(thread
, 0, 0)) == (struct th_info
*)0) {
1835 if (cur_max
>= MAX_THREADS
)
1837 ti
= &th_state
[cur_max
++];
1839 ti
->thread
= thread
;
1842 ti
->child_thread
= 0;
1844 if (ti
->vfslookup
== 0) {
1846 ti
->arg1
= kd
->arg1
;
1847 memset(&ti
->pathname
[0], 0, 32);
1848 sargptr
= (long *)&ti
->pathname
[0];
1850 *sargptr
++ = kd
->arg2
;
1851 *sargptr
++ = kd
->arg3
;
1852 *sargptr
++ = kd
->arg4
;
1854 } else if (ti
->vfslookup
== 1) {
1857 sargptr
= (long *)&ti
->pathname
[12];
1858 *sargptr
++ = kd
->arg1
;
1859 *sargptr
++ = kd
->arg2
;
1860 *sargptr
++ = kd
->arg3
;
1861 *sargptr
++ = kd
->arg4
;
1863 fprintf(log_fp
, "%9.1f %8.1f\t\t%-28.28s %-28s %-8x %-8x %d %s\n",
1864 timestamp
- start_bias
, delta
, "VFS_LOOKUP",
1865 ti
->pathname
, ti
->arg1
, thread
, cpunum
, command
);
1867 last_timestamp
= timestamp
;
1871 if (debugid
& DBG_FUNC_START
)
1872 enter_syscall(log_fp
, kd
, thread
, type
, command
, timestamp
, delta
, start_bias
, 1);
1873 else if (debugid
& DBG_FUNC_END
)
1874 exit_syscall(log_fp
, kd
, thread
, type
, command
, timestamp
, delta
, start_bias
, 1);
1876 print_entry(log_fp
, kd
, thread
, type
, command
, timestamp
, delta
, start_bias
);
1878 last_timestamp
= timestamp
;
1886 double handle_decrementer(kd_buf
*kd
)
1891 if ((int)(kd
->arg1
) >= 0)
1894 latency
= (((double)(-1 - kd
->arg1
)) / divisor
);
1895 elapsed_usecs
= (int)latency
;
1897 if (elapsed_usecs
< 100)
1898 i_usec_10_bins
[elapsed_usecs
/10]++;
1899 if (elapsed_usecs
< 1000)
1900 i_usec_100_bins
[elapsed_usecs
/100]++;
1901 else if (elapsed_usecs
< 10000)
1902 i_msec_1_bins
[elapsed_usecs
/1000]++;
1903 else if (elapsed_usecs
< 50000)
1904 i_msec_10_bins
[elapsed_usecs
/10000]++;
1908 if (i_thresh_hold
&& elapsed_usecs
> i_thresh_hold
)
1909 i_exceeded_threshold
++;
1910 if (elapsed_usecs
> i_max_latency
)
1911 i_max_latency
= elapsed_usecs
;
1912 if (elapsed_usecs
< i_min_latency
|| i_total_samples
== 0)
1913 i_min_latency
= elapsed_usecs
;
1914 i_total_latency
+= elapsed_usecs
;
1921 void init_code_file()
1924 int i
, n
, cnt
, code
;
1927 if ((fp
= fopen(code_file
, "r")) == (FILE *)0) {
1929 fprintf(log_fp
, "open of %s failed\n", code_file
);
1932 n
= fscanf(fp
, "%d\n", &cnt
);
1936 fprintf(log_fp
, "bad format found in %s\n", code_file
);
1939 for (i
= 0; i
< MAX_ENTRIES
; i
++) {
1940 n
= fscanf(fp
, "%x%s\n", &code
, name
);
1945 strncpy(codes_tab
[i
].name
, name
, 32);
1946 codes_tab
[i
].type
= code
;
1958 FILE *fp
= (FILE *)0;
1959 char tmp_nm_file
[128];
1963 bzero(tmp_nm_file
, 128);
1964 bzero(tmpstr
, 1024);
1966 /* Build the temporary nm file path */
1967 sprintf(tmp_nm_file
, "/tmp/knm.out.%d", getpid());
1969 /* Build the nm command and create a tmp file with the output*/
1970 sprintf (tmpstr
, "/usr/bin/nm -f -n -s __TEXT __text %s > %s",
1971 kernelpath
, tmp_nm_file
);
1974 /* Parse the output from the nm command */
1975 if ((fp
=fopen(tmp_nm_file
, "r")) == (FILE *)0)
1977 /* Hmmm, let's not treat this as fatal */
1978 fprintf(stderr
, "Failed to open nm symbol file [%s]\n", tmp_nm_file
);
1982 /* Count the number of symbols in the nm symbol table */
1984 while ( (inchr
= getc(fp
)) != -1)
1992 /* Malloc the space for symbol table */
1993 if (kern_sym_count
> 0)
1995 kern_sym_tbl
= (kern_sym_t
*)malloc(kern_sym_count
* sizeof (kern_sym_t
));
1998 /* Hmmm, lets not treat this as fatal */
1999 fprintf(stderr
, "Can't allocate memory for kernel symbol table\n");
2002 bzero(kern_sym_tbl
, (kern_sym_count
* sizeof(kern_sym_t
)));
2006 /* Hmmm, lets not treat this as fatal */
2007 fprintf(stderr
, "No kernel symbol table \n");
2010 for (i
=0; i
<kern_sym_count
; i
++)
2012 bzero(tmpstr
, 1024);
2013 if (fscanf(fp
, "%x %c %s", &kern_sym_tbl
[i
].k_sym_addr
, &inchr
, tmpstr
) != 3)
2017 len
= strlen(tmpstr
);
2018 kern_sym_tbl
[i
].k_sym_name
= malloc(len
+ 1);
2020 if (kern_sym_tbl
[i
].k_sym_name
== (char *)0)
2022 fprintf(stderr
, "Can't allocate memory for symbol name [%s]\n", tmpstr
);
2023 kern_sym_tbl
[i
].k_sym_name
= (char *)0;
2027 strcpy(kern_sym_tbl
[i
].k_sym_name
, tmpstr
);
2029 kern_sym_tbl
[i
].k_sym_len
= len
;
2033 if (i
!= kern_sym_count
)
2035 /* Hmmm, didn't build up entire table from nm */
2036 /* scrap the entire thing */
2038 free (kern_sym_tbl
);
2039 kern_sym_tbl
= (kern_sym_t
*)0;
2045 /* Remove the temporary nm file */
2046 unlink(tmp_nm_file
);
2049 /* Dump the kernel symbol table */
2050 for (i
=0; i
< kern_sym_count
; i
++)
2052 if (kern_sym_tbl
[i
].k_sym_name
)
2053 printf ("[%d] 0x%x %s\n", i
,
2054 kern_sym_tbl
[i
].k_sym_addr
, kern_sym_tbl
[i
].k_sym_name
);
2056 printf ("[%d] 0x%x %s\n", i
,
2057 kern_sym_tbl
[i
].k_sym_addr
, "No symbol name");
2063 pc_to_string(unsigned int pc
, int max_len
, int mode
)
2068 int binary_search();
2072 sprintf(pcstring
, "0x%-8x [usermode addr]", pc
);
2077 ret
= binary_search(kern_sym_tbl
, 0, kern_sym_count
-1, pc
);
2081 sprintf(pcstring
, "0x%x", pc
);
2084 else if (kern_sym_tbl
[ret
].k_sym_name
== (char *)0)
2086 sprintf(pcstring
, "0x%x", pc
);
2091 if ((len
= kern_sym_tbl
[ret
].k_sym_len
) > (max_len
- 8))
2094 memcpy(pcstring
, kern_sym_tbl
[ret
].k_sym_name
, len
);
2095 sprintf(&pcstring
[len
], "+0x%-5x", pc
- kern_sym_tbl
[ret
].k_sym_addr
);
2102 /* Return -1 if not found, else return index */
2103 int binary_search(list
, low
, high
, addr
)
2110 mid
= (low
+ high
) / 2;
2113 return (-1); /* failed */
2114 else if (low
+ 1 == high
)
2116 if (list
[low
].k_sym_addr
<= addr
&&
2117 addr
< list
[high
].k_sym_addr
)
2119 /* We have a range match */
2122 else if (list
[high
].k_sym_addr
<= addr
)
2127 return(-1); /* Failed */
2129 else if (addr
< list
[mid
].k_sym_addr
)
2131 return(binary_search (list
, low
, mid
, addr
));
2135 return(binary_search (list
, mid
, high
, addr
));
2140 open_logfile(char *path
)
2142 log_fp
= fopen(path
, "a");
2146 /* failed to open path */
2147 fprintf(stderr
, "latency: failed to open logfile [%s]\n", path
);