1#!/usr/bin/perl -Tw
2#-
3# Copyright (c) 2002 Dag-Erling Sm��rgrav
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer
11#    in this position and unchanged.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15# 3. The name of the author may not be used to endorse or promote products
16#    derived from this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28#
29#
30
31use strict;
32use Getopt::Std;
33
34sub usage() {
35
36    print(STDERR "usage: mtxstat [-gr] [-a|c|m|t] [-l limit]\n");
37    exit(1);
38}
39
40MAIN:{
41    my %opts;			# Command-line options
42    my $key;			# Sort key
43    my $limit;			# Output limit
44    local *PIPE;		# Pipe
45    my $header;			# Header line
46    my @names;			# Field names
47    my %data;			# Mutex data
48    my @list;			# List of entries
49
50    getopts("acgl:mrt", \%opts)
51	or usage();
52    if ($opts{'a'}) {
53	usage()
54	    if ($opts{'c'} || $opts{'m'} || $opts{'t'});
55	$key = 'avg';
56    } elsif ($opts{'c'}) {
57	usage()
58	    if ($opts{'m'} || $opts{'t'});
59	$key = 'count';
60    } elsif ($opts{'m'}) {
61	usage()
62	    if ($opts{'t'});
63	$key = 'max';
64    } elsif ($opts{'t'}) {
65	$key = 'total';
66    }
67    if ($opts{'l'}) {
68	if ($opts{'l'} !~ m/^\d+$/) {
69	    usage();
70	}
71	$limit = $opts{'l'};
72    }
73    $ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin';
74    open(PIPE, "sysctl -n debug.mutex.prof.stats|")
75	or die("open(): $!\n");
76    $header = <PIPE>;
77    chomp($header);
78    @names = split(' ', $header);
79    if (defined($key) && !grep(/^$key$/, @names)) {
80	die("can't find sort key '$key' in header\n");
81    }
82    while (<PIPE>) {
83	chomp();
84	my @fields = split(' ', $_, @names);
85	next unless @fields;
86	my %entry;
87	foreach (@names) {
88	    $entry{$_} = ($_ eq 'name') ? shift(@fields) : 0.0 + shift(@fields);
89	}
90	if ($opts{'g'}) {
91	    $entry{'name'} =~ s/^(\S+)\s+\((.*)\)$/$2/;
92	}
93	my $name = $entry{'name'};
94	if ($data{$name}) {
95	    if ($entry{'max'} > $data{$name}->{'max'}) {
96		$data{$name}->{'max'} = $entry{'max'};
97	    }
98	    $data{$name}->{'total'} += $entry{'total'};
99	    $data{$name}->{'count'} += $entry{'count'};
100	    $data{$name}->{'avg'} =
101		$data{$name}->{'total'} / $data{$name}->{'count'};
102	} else {
103	    $data{$name} = \%entry;
104	}
105    }
106    if (defined($key)) {
107	@list = sort({ $data{$a}->{$key} <=> $data{$b}->{$key} }
108		     sort(keys(%data)));
109    } else {
110	@list = sort(keys(%data));
111    }
112    if ($opts{'r'}) {
113	@list = reverse(@list);
114    }
115    print("$header\n");
116    if ($limit) {
117	while (@list > $limit) {
118	    pop(@list);
119	}
120    }
121    foreach (@list) {
122	printf("%6.0f %12.0f %11.0f %5.0f %-40.40s\n",
123	       $data{$_}->{'max'},
124	       $data{$_}->{'total'},
125	       $data{$_}->{'count'},
126	       $data{$_}->{'avg'},
127	       $data{$_}->{'name'});
128    }
129}
130