]>
git.saurik.com Git - apple/xnu.git/blob - tools/lockstat/lockstat.c
8 #include <mach/error.h>
9 #include <mach/mach_error.h>
10 #include <mach/mig_errors.h>
11 #include <mach/machine.h>
12 #include <mach/processor_info.h>
17 #include <mach/mach.h>
18 #include <mach/host_info.h>
23 * Utility to display kernel lock contention statistics.
25 * lockstat [all, spin, mutex, rw, <lock group name>] {<repeat interval>} {abs}
27 * Argument 1 specifies the type of lock to display contention statistics
28 * for; alternatively, a lock group (a logically grouped set of locks,
29 * which can encompass multiple types of locks) can be specified by name.
30 * When argument 1 is "all", statistics are displayed for all lock groups
31 * which have statistics enabled.
32 * Lock types include mutexes, reader-writer locks and spin locks.
33 * Note that support for gathering contention statistics may not be present
34 * for all types of locks on all platforms.
36 * Argument 2 specifies a periodic interval. The program will display an
37 * updated list of statistics every <repeat interval> seconds. This
38 * argument is optional. The updates display the deltas from the previous
39 * set of statistics, unless "abs" is specified as argument 3.
41 * Argument 3, if "abs", causes the periodically refreshed lock statistics
42 * to be displayed as absolute values rather than deltas from the previous
45 * Types of statistics:
46 * Acquisitions: These can include both normal acquisitions, as well
47 * as acquisition attempts. These are listed in the first column.
48 * Examples include calls to lck_mtx_lock and lck_mtx_try_lock
49 * Misses: Incremented if a lock acquisition attempt failed, due to
51 * Waits (Meaningful only for lock types that can block): Incremented
52 * if a lock acquisition attempt proceeded to block.
54 * Direct Waits (currently implemented only on i386/x86_64): For adaptive
55 * locks, such as mutexes, incremented if the owner of the mutex
56 * wasn't active on another processor at the time of the lock
57 * attempt. This indicates that no adaptive spin occurred.
62 * 2005: Bernard Semeria
65 * Display i386 specific stats, fix incremental display, add
66 * explanatory block comment.
69 void print_spin_hdr(void);
70 void print_spin(int requested
, lockgroup_info_t
*lockgroup
);
71 void print_all_spin(lockgroup_info_t
*lockgroup
);
72 void print_mutex_hdr(void);
73 void print_mutex(int requested
, lockgroup_info_t
*lockgroup
);
74 void print_all_mutex(lockgroup_info_t
*lockgroup
);
75 void print_rw_hdr(void);
76 void print_rw(int requested
, lockgroup_info_t
*lockgroup
);
77 void print_all_rw(lockgroup_info_t
*lockgroup
);
78 void prime_lockgroup_deltas(void);
79 void get_lockgroup_deltas(void);
82 mach_port_t host_control
;
84 lockgroup_info_t
*lockgroup_info
, *lockgroup_start
, *lockgroup_deltas
;
87 unsigned int gDebug
= 1;
90 main(int argc
, char **argv
)
100 gDebug
= (NULL
!= strstr(argv
[0], "debug"));
102 host_control
= mach_host_self();
104 kr
= host_lockgroup_info(host_control
, &lockgroup_info
, &count
);
106 if (kr
!= KERN_SUCCESS
) {
107 mach_error("host_statistics", kr
);
111 printf("count = %d\n", count
);
112 for (i
= 0; i
< count
; i
++) {
113 printf("%s\n", lockgroup_info
[i
].lockgroup_name
);
119 if (strcmp(argv
[1], "all") == 0) {
121 print_all_spin(lockgroup_info
);
123 print_all_mutex(lockgroup_info
);
125 print_all_rw(lockgroup_info
);
126 } else if (strcmp(argv
[1], "spin") == 0) {
128 print_all_spin(lockgroup_info
);
129 } else if (strcmp(argv
[1], "mutex") == 0) {
131 print_all_mutex(lockgroup_info
);
132 } else if (strcmp(argv
[1], "rw") == 0) {
134 print_all_rw(lockgroup_info
);
137 for (i
= 0; i
< count
; i
++) {
138 if (strcmp(argv
[1], lockgroup_info
[i
].lockgroup_name
) == 0) {
141 print_spin(i
, lockgroup_info
);
143 print_mutex(i
, lockgroup_info
);
145 print_rw(i
, lockgroup_info
);
155 if (sscanf(argv
[2], "%d", &arg2
) != 1) {
161 prime_lockgroup_deltas();
162 if (strcmp(argv
[1], "all") == 0) {
165 get_lockgroup_deltas();
167 print_all_spin(lockgroup_deltas
);
169 print_all_mutex(lockgroup_deltas
);
171 print_all_rw(lockgroup_deltas
);
173 } else if (strcmp(argv
[1], "spin") == 0) {
176 get_lockgroup_deltas();
178 print_all_spin(lockgroup_deltas
);
180 } else if (strcmp(argv
[1], "mutex") == 0) {
183 get_lockgroup_deltas();
185 print_all_mutex(lockgroup_deltas
);
187 } else if (strcmp(argv
[1], "rw") == 0) {
190 get_lockgroup_deltas();
192 print_all_rw(lockgroup_deltas
);
196 for (i
= 0; i
< count
; i
++) {
197 if (strcmp(argv
[1], lockgroup_info
[i
].lockgroup_name
) == 0) {
201 get_lockgroup_deltas();
203 print_spin(i
, lockgroup_deltas
);
205 print_mutex(i
, lockgroup_deltas
);
207 print_rw(i
, lockgroup_deltas
);
217 if (strcmp(argv
[3], "abs") != 0) {
220 if (sscanf(argv
[2], "%d", &arg2
) != 1) {
223 if (strcmp(argv
[1], "all") == 0) {
226 print_all_spin(lockgroup_info
);
228 print_all_mutex(lockgroup_info
);
230 print_all_rw(lockgroup_info
);
233 } else if (strcmp(argv
[1], "spin") == 0) {
235 print_all_spin(lockgroup_info
);
238 } else if (strcmp(argv
[1], "mutex") == 0) {
241 print_all_mutex(lockgroup_info
);
244 } else if (strcmp(argv
[1], "rw") == 0) {
247 print_all_rw(lockgroup_info
);
252 for (i
= 0; i
< count
; i
++) {
253 if (strcmp(argv
[1], lockgroup_info
[i
].lockgroup_name
) == 0) {
257 print_spin(i
, lockgroup_info
);
259 print_mutex(i
, lockgroup_info
);
261 print_rw(i
, lockgroup_info
);
282 fprintf(stderr
, "Usage: %s [all, spin, mutex, rw, <lock group name>] {<repeat interval>} {abs}\n", pgmname
);
289 printf(" Spinlock acquires misses Name\n");
293 print_spin(int requested
, lockgroup_info_t
*lockgroup
)
295 lockgroup_info_t
*curptr
= &lockgroup
[requested
];
297 if (curptr
->lock_spin_cnt
!= 0 && curptr
->lock_spin_util_cnt
!= 0) {
298 printf("%16lld ", curptr
->lock_spin_util_cnt
);
299 printf("%16lld ", curptr
->lock_spin_miss_cnt
);
300 printf("%-14s\n", curptr
->lockgroup_name
);
305 print_all_spin(lockgroup_info_t
*lockgroup
)
309 for (i
= 0; i
< count
; i
++) {
310 print_spin(i
, lockgroup
);
316 print_mutex_hdr(void)
318 #if defined(__i386__) || defined(__x86_64__)
319 printf("Mutex lock attempts Misses Waits Direct Waits Name\n");
321 printf(" mutex locks misses waits name\n");
326 print_mutex(int requested
, lockgroup_info_t
*lockgroup
)
328 lockgroup_info_t
*curptr
= &lockgroup
[requested
];
330 if (curptr
->lock_mtx_cnt
!= 0 && curptr
->lock_mtx_util_cnt
!= 0) {
331 printf("%16lld ", curptr
->lock_mtx_util_cnt
);
332 #if defined(__i386__) || defined(__x86_64__)
333 printf("%10lld %10lld %10lld ", curptr
->lock_mtx_miss_cnt
, curptr
->lock_mtx_wait_cnt
, curptr
->lock_mtx_held_cnt
);
335 printf("%16lld %16lld ", curptr
->lock_mtx_miss_cnt
, curptr
->lock_mtx_wait_cnt
);
337 printf("%-14s\n", curptr
->lockgroup_name
);
342 print_all_mutex(lockgroup_info_t
*lockgroup
)
346 for (i
= 0; i
< count
; i
++) {
347 print_mutex(i
, lockgroup
);
355 printf(" RW locks Misses Waits Name\n");
359 print_rw(int requested
, lockgroup_info_t
*lockgroup
)
361 lockgroup_info_t
*curptr
= &lockgroup
[requested
];
363 if (curptr
->lock_rw_cnt
!= 0 && curptr
->lock_rw_util_cnt
!= 0) {
364 printf("%16lld ", curptr
->lock_rw_util_cnt
);
365 printf("%16lld %16lld ", curptr
->lock_rw_miss_cnt
, curptr
->lock_rw_wait_cnt
);
366 printf("%-14s\n", curptr
->lockgroup_name
);
371 print_all_rw(lockgroup_info_t
*lockgroup
)
375 for (i
= 0; i
< count
; i
++) {
376 print_rw(i
, lockgroup
);
382 prime_lockgroup_deltas(void)
384 lockgroup_start
= calloc(count
, sizeof(lockgroup_info_t
));
385 if (lockgroup_start
== NULL
) {
386 fprintf(stderr
, "Can't allocate memory for lockgroup info\n");
389 memcpy(lockgroup_start
, lockgroup_info
, count
* sizeof(lockgroup_info_t
));
391 lockgroup_deltas
= calloc(count
, sizeof(lockgroup_info_t
));
392 if (lockgroup_deltas
== NULL
) {
393 fprintf(stderr
, "Can't allocate memory for lockgroup info\n");
399 get_lockgroup_deltas(void)
404 kr
= host_lockgroup_info(host_control
, &lockgroup_info
, &count
);
406 if (kr
!= KERN_SUCCESS
) {
407 mach_error("host_statistics", kr
);
411 memcpy(lockgroup_deltas
, lockgroup_info
, count
* sizeof(lockgroup_info_t
));
412 for (i
= 0; i
< count
; i
++) {
413 lockgroup_deltas
[i
].lock_spin_util_cnt
=
414 lockgroup_info
[i
].lock_spin_util_cnt
-
415 lockgroup_start
[i
].lock_spin_util_cnt
;
416 lockgroup_deltas
[i
].lock_spin_miss_cnt
=
417 lockgroup_info
[i
].lock_spin_miss_cnt
-
418 lockgroup_start
[i
].lock_spin_miss_cnt
;
419 lockgroup_deltas
[i
].lock_mtx_util_cnt
=
420 lockgroup_info
[i
].lock_mtx_util_cnt
-
421 lockgroup_start
[i
].lock_mtx_util_cnt
;
422 lockgroup_deltas
[i
].lock_mtx_miss_cnt
=
423 lockgroup_info
[i
].lock_mtx_miss_cnt
-
424 lockgroup_start
[i
].lock_mtx_miss_cnt
;
425 lockgroup_deltas
[i
].lock_mtx_wait_cnt
=
426 lockgroup_info
[i
].lock_mtx_wait_cnt
-
427 lockgroup_start
[i
].lock_mtx_wait_cnt
;
428 lockgroup_deltas
[i
].lock_mtx_held_cnt
=
429 lockgroup_info
[i
].lock_mtx_held_cnt
-
430 lockgroup_start
[i
].lock_mtx_held_cnt
;
431 lockgroup_deltas
[i
].lock_rw_util_cnt
=
432 lockgroup_info
[i
].lock_rw_util_cnt
-
433 lockgroup_start
[i
].lock_rw_util_cnt
;
434 lockgroup_deltas
[i
].lock_rw_miss_cnt
=
435 lockgroup_info
[i
].lock_rw_miss_cnt
-
436 lockgroup_start
[i
].lock_rw_miss_cnt
;
437 lockgroup_deltas
[i
].lock_rw_wait_cnt
=
438 lockgroup_info
[i
].lock_rw_wait_cnt
-
439 lockgroup_start
[i
].lock_rw_wait_cnt
;
441 memcpy(lockgroup_start
, lockgroup_info
, count
* sizeof(lockgroup_info_t
));