]>
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
)
108 mach_error("host_statistics", kr
);
112 printf("count = %d\n", count
);
113 for (i
= 0; i
< count
; i
++) {
114 printf("%s\n",lockgroup_info
[i
].lockgroup_name
);
120 if (strcmp(argv
[1], "all") == 0) {
122 print_all_spin(lockgroup_info
);
124 print_all_mutex(lockgroup_info
);
126 print_all_rw(lockgroup_info
);
128 else if (strcmp(argv
[1], "spin") == 0) {
130 print_all_spin(lockgroup_info
);
132 else if (strcmp(argv
[1], "mutex") == 0) {
134 print_all_mutex(lockgroup_info
);
136 else if (strcmp(argv
[1], "rw") == 0) {
138 print_all_rw(lockgroup_info
);
142 for (i
= 0;i
< count
;i
++) {
143 if (strcmp(argv
[1], lockgroup_info
[i
].lockgroup_name
) == 0) {
146 print_spin(i
, lockgroup_info
);
148 print_mutex(i
, lockgroup_info
);
150 print_rw(i
, lockgroup_info
);
159 if (sscanf(argv
[2], "%d", &arg2
) != 1) {
165 prime_lockgroup_deltas();
166 if (strcmp(argv
[1], "all") == 0) {
170 get_lockgroup_deltas();
172 print_all_spin(lockgroup_deltas
);
174 print_all_mutex(lockgroup_deltas
);
176 print_all_rw(lockgroup_deltas
);
179 else if (strcmp(argv
[1], "spin") == 0) {
183 get_lockgroup_deltas();
185 print_all_spin(lockgroup_deltas
);
188 else if (strcmp(argv
[1], "mutex") == 0) {
192 get_lockgroup_deltas();
194 print_all_mutex(lockgroup_deltas
);
197 else if (strcmp(argv
[1], "rw") == 0) {
201 get_lockgroup_deltas();
203 print_all_rw(lockgroup_deltas
);
209 for (i
= 0;i
< count
;i
++) {
210 if (strcmp(argv
[1], lockgroup_info
[i
].lockgroup_name
) == 0) {
214 get_lockgroup_deltas();
216 print_spin(i
, lockgroup_deltas
);
218 print_mutex(i
, lockgroup_deltas
);
220 print_rw(i
, lockgroup_deltas
);
229 if (strcmp(argv
[3], "abs") != 0)
231 if (sscanf(argv
[2], "%d", &arg2
) != 1)
233 if (strcmp(argv
[1], "all") == 0) {
237 print_all_spin(lockgroup_info
);
239 print_all_mutex(lockgroup_info
);
241 print_all_rw(lockgroup_info
);
245 else if (strcmp(argv
[1], "spin") == 0) {
247 {print_all_spin(lockgroup_info
);
251 else if (strcmp(argv
[1], "mutex") == 0) {
254 {print_all_mutex(lockgroup_info
);
258 else if (strcmp(argv
[1], "rw") == 0) {
261 {print_all_rw(lockgroup_info
);
267 for (i
= 0;i
< count
;i
++) {
268 if (strcmp(argv
[1], lockgroup_info
[i
].lockgroup_name
) == 0) {
273 print_spin(i
, lockgroup_info
);
275 print_mutex(i
, lockgroup_info
);
277 print_rw(i
, lockgroup_info
);
297 fprintf(stderr
, "Usage: %s [all, spin, mutex, rw, <lock group name>] {<repeat interval>} {abs}\n", pgmname
);
304 printf(" Spinlock acquires misses Name\n");
308 print_spin(int requested
, lockgroup_info_t
*lockgroup
)
310 lockgroup_info_t
*curptr
= &lockgroup
[requested
];
312 if (curptr
->lock_spin_cnt
!= 0 && curptr
->lock_spin_util_cnt
!= 0) {
313 printf("%16lld ", curptr
->lock_spin_util_cnt
);
314 printf("%16lld ", curptr
->lock_spin_miss_cnt
);
315 printf("%-14s\n", curptr
->lockgroup_name
);
320 print_all_spin(lockgroup_info_t
*lockgroup
)
324 for (i
= 0;i
< count
;i
++)
325 print_spin(i
, lockgroup
);
330 print_mutex_hdr(void)
332 #if defined(__i386__) || defined(__x86_64__)
333 printf("Mutex lock attempts Misses Waits Direct Waits Name\n");
335 printf(" mutex locks misses waits name\n");
340 print_mutex(int requested
, lockgroup_info_t
*lockgroup
)
342 lockgroup_info_t
*curptr
= &lockgroup
[requested
];
344 if (curptr
->lock_mtx_cnt
!= 0 && curptr
->lock_mtx_util_cnt
!= 0) {
345 printf("%16lld ", curptr
->lock_mtx_util_cnt
);
346 #if defined(__i386__) || defined(__x86_64__)
347 printf("%10lld %10lld %10lld ", curptr
->lock_mtx_miss_cnt
, curptr
->lock_mtx_wait_cnt
, curptr
->lock_mtx_held_cnt
);
349 printf("%16lld %16lld ", curptr
->lock_mtx_miss_cnt
, curptr
->lock_mtx_wait_cnt
);
351 printf("%-14s\n", curptr
->lockgroup_name
);
356 print_all_mutex(lockgroup_info_t
*lockgroup
)
360 for (i
= 0;i
< count
;i
++)
361 print_mutex(i
, lockgroup
);
369 printf(" RW locks Misses Waits Name\n");
373 print_rw(int requested
, lockgroup_info_t
*lockgroup
)
375 lockgroup_info_t
*curptr
= &lockgroup
[requested
];
377 if (curptr
->lock_rw_cnt
!= 0 && curptr
->lock_rw_util_cnt
!= 0) {
378 printf("%16lld ", curptr
->lock_rw_util_cnt
);
379 printf("%16lld %16lld ", curptr
->lock_rw_miss_cnt
, curptr
->lock_rw_wait_cnt
);
380 printf("%-14s\n", curptr
->lockgroup_name
);
385 print_all_rw(lockgroup_info_t
*lockgroup
)
389 for (i
= 0;i
< count
;i
++)
390 print_rw(i
, lockgroup
);
396 prime_lockgroup_deltas(void)
398 lockgroup_start
= calloc(count
, sizeof(lockgroup_info_t
));
399 if (lockgroup_start
== NULL
) {
400 fprintf(stderr
, "Can't allocate memory for lockgroup info\n");
403 memcpy(lockgroup_start
, lockgroup_info
, count
* sizeof(lockgroup_info_t
));
405 lockgroup_deltas
= calloc(count
, sizeof(lockgroup_info_t
));
406 if (lockgroup_deltas
== NULL
) {
407 fprintf(stderr
, "Can't allocate memory for lockgroup info\n");
413 get_lockgroup_deltas(void)
418 kr
= host_lockgroup_info(host_control
, &lockgroup_info
, &count
);
420 if (kr
!= KERN_SUCCESS
)
422 mach_error("host_statistics", kr
);
426 memcpy(lockgroup_deltas
, lockgroup_info
, count
* sizeof(lockgroup_info_t
));
427 for (i
= 0; i
< count
; i
++) {
428 lockgroup_deltas
[i
].lock_spin_util_cnt
=
429 lockgroup_info
[i
].lock_spin_util_cnt
-
430 lockgroup_start
[i
].lock_spin_util_cnt
;
431 lockgroup_deltas
[i
].lock_spin_miss_cnt
=
432 lockgroup_info
[i
].lock_spin_miss_cnt
-
433 lockgroup_start
[i
].lock_spin_miss_cnt
;
434 lockgroup_deltas
[i
].lock_mtx_util_cnt
=
435 lockgroup_info
[i
].lock_mtx_util_cnt
-
436 lockgroup_start
[i
].lock_mtx_util_cnt
;
437 lockgroup_deltas
[i
].lock_mtx_miss_cnt
=
438 lockgroup_info
[i
].lock_mtx_miss_cnt
-
439 lockgroup_start
[i
].lock_mtx_miss_cnt
;
440 lockgroup_deltas
[i
].lock_mtx_wait_cnt
=
441 lockgroup_info
[i
].lock_mtx_wait_cnt
-
442 lockgroup_start
[i
].lock_mtx_wait_cnt
;
443 lockgroup_deltas
[i
].lock_mtx_held_cnt
=
444 lockgroup_info
[i
].lock_mtx_held_cnt
-
445 lockgroup_start
[i
].lock_mtx_held_cnt
;
446 lockgroup_deltas
[i
].lock_rw_util_cnt
=
447 lockgroup_info
[i
].lock_rw_util_cnt
-
448 lockgroup_start
[i
].lock_rw_util_cnt
;
449 lockgroup_deltas
[i
].lock_rw_miss_cnt
=
450 lockgroup_info
[i
].lock_rw_miss_cnt
-
451 lockgroup_start
[i
].lock_rw_miss_cnt
;
452 lockgroup_deltas
[i
].lock_rw_wait_cnt
=
453 lockgroup_info
[i
].lock_rw_wait_cnt
-
454 lockgroup_start
[i
].lock_rw_wait_cnt
;
456 memcpy(lockgroup_start
, lockgroup_info
, count
* sizeof(lockgroup_info_t
));