1#!/usr/bin/perl -Tw 2#- 3# Copyright (c) 2002 Dag-Erling Coïdan 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