197303Sdes#!/usr/bin/perl -Tw 297303Sdes#- 3228953Suqs# Copyright (c) 2002 Dag-Erling Co��dan Sm��rgrav 497303Sdes# All rights reserved. 597303Sdes# 697303Sdes# Redistribution and use in source and binary forms, with or without 797303Sdes# modification, are permitted provided that the following conditions 897303Sdes# are met: 997303Sdes# 1. Redistributions of source code must retain the above copyright 1097303Sdes# notice, this list of conditions and the following disclaimer 1197303Sdes# in this position and unchanged. 1297303Sdes# 2. Redistributions in binary form must reproduce the above copyright 1397303Sdes# notice, this list of conditions and the following disclaimer in the 1497303Sdes# documentation and/or other materials provided with the distribution. 1597303Sdes# 3. The name of the author may not be used to endorse or promote products 1697303Sdes# derived from this software without specific prior written permission. 1797303Sdes# 1897303Sdes# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1997303Sdes# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2097303Sdes# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2197303Sdes# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2297303Sdes# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2397303Sdes# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2497303Sdes# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2597303Sdes# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2697303Sdes# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2797303Sdes# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2897303Sdes# 2997303Sdes# $FreeBSD$ 3097303Sdes# 3197303Sdes 3297303Sdesuse strict; 3397303Sdesuse Getopt::Std; 3497303Sdes 3597303Sdessub usage() { 3697303Sdes 3797303Sdes print(STDERR "usage: mtxstat [-gr] [-a|c|m|t] [-l limit]\n"); 3897303Sdes exit(1); 3997303Sdes} 4097303Sdes 4197303SdesMAIN:{ 4297303Sdes my %opts; # Command-line options 4397303Sdes my $key; # Sort key 4497303Sdes my $limit; # Output limit 4597303Sdes local *PIPE; # Pipe 4697303Sdes my $header; # Header line 4797303Sdes my @names; # Field names 4897303Sdes my %data; # Mutex data 4997303Sdes my @list; # List of entries 5097303Sdes 5197303Sdes getopts("acgl:mrt", \%opts) 5297303Sdes or usage(); 5397303Sdes if ($opts{'a'}) { 5497303Sdes usage() 5597303Sdes if ($opts{'c'} || $opts{'m'} || $opts{'t'}); 56120245Ssam $key = 'avg'; 5797303Sdes } elsif ($opts{'c'}) { 5897303Sdes usage() 5997303Sdes if ($opts{'m'} || $opts{'t'}); 6097303Sdes $key = 'count'; 6197303Sdes } elsif ($opts{'m'}) { 6297303Sdes usage() 6397303Sdes if ($opts{'t'}); 6497303Sdes $key = 'max'; 6597303Sdes } elsif ($opts{'t'}) { 6697303Sdes $key = 'total'; 6797303Sdes } 6897303Sdes if ($opts{'l'}) { 6997303Sdes if ($opts{'l'} !~ m/^\d+$/) { 7097303Sdes usage(); 7197303Sdes } 7297303Sdes $limit = $opts{'l'}; 7397303Sdes } 7497303Sdes $ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin'; 7597303Sdes open(PIPE, "sysctl -n debug.mutex.prof.stats|") 7697303Sdes or die("open(): $!\n"); 7797303Sdes $header = <PIPE>; 7897303Sdes chomp($header); 7997303Sdes @names = split(' ', $header); 8097303Sdes if (defined($key) && !grep(/^$key$/, @names)) { 8197303Sdes die("can't find sort key '$key' in header\n"); 8297303Sdes } 8397303Sdes while (<PIPE>) { 8497303Sdes chomp(); 8597303Sdes my @fields = split(' ', $_, @names); 8697303Sdes next unless @fields; 8797303Sdes my %entry; 8897303Sdes foreach (@names) { 8997303Sdes $entry{$_} = ($_ eq 'name') ? shift(@fields) : 0.0 + shift(@fields); 9097303Sdes } 9197303Sdes if ($opts{'g'}) { 9297303Sdes $entry{'name'} =~ s/^(\S+)\s+\((.*)\)$/$2/; 9397303Sdes } 9497303Sdes my $name = $entry{'name'}; 9597303Sdes if ($data{$name}) { 9697303Sdes if ($entry{'max'} > $data{$name}->{'max'}) { 9797303Sdes $data{$name}->{'max'} = $entry{'max'}; 9897303Sdes } 9997303Sdes $data{$name}->{'total'} += $entry{'total'}; 10097303Sdes $data{$name}->{'count'} += $entry{'count'}; 101120245Ssam $data{$name}->{'avg'} = 10297303Sdes $data{$name}->{'total'} / $data{$name}->{'count'}; 10397303Sdes } else { 10497303Sdes $data{$name} = \%entry; 10597303Sdes } 10697303Sdes } 10797303Sdes if (defined($key)) { 10897303Sdes @list = sort({ $data{$a}->{$key} <=> $data{$b}->{$key} } 10997303Sdes sort(keys(%data))); 11097303Sdes } else { 11197303Sdes @list = sort(keys(%data)); 11297303Sdes } 11397303Sdes if ($opts{'r'}) { 11497303Sdes @list = reverse(@list); 11597303Sdes } 11697303Sdes print("$header\n"); 11797303Sdes if ($limit) { 11897303Sdes while (@list > $limit) { 11997303Sdes pop(@list); 12097303Sdes } 12197303Sdes } 12297303Sdes foreach (@list) { 123120245Ssam printf("%6.0f %12.0f %11.0f %5.0f %-40.40s\n", 12497303Sdes $data{$_}->{'max'}, 12597303Sdes $data{$_}->{'total'}, 12697303Sdes $data{$_}->{'count'}, 127120245Ssam $data{$_}->{'avg'}, 12897303Sdes $data{$_}->{'name'}); 12997303Sdes } 13097303Sdes} 131