#!/usr/bin/perl -w
# interrupts_counter.pl /proc/interrupts_start /proc/interrupts_end
use strict;

if ($#ARGV != 1) {
    print "Usage: interrupts_counter.pl /proc/interrupts_start /proc/interrupts_end\n";
    exit;
}

foreach (@ARGV) {
    die ("File $_ is not readable!\n") unless ( -r $_) ;
} 

my %irqs;
my %last;
my $cpus;
my %irq_type;
my %irq_device;
my @list_of_keys;

my $file_count=0;
while (<>) {

    chomp;
    if ( $. == 1 ) {
	# Count CPUs
	$cpus = () = $_ =~ /CPU/g;
    }

    if (/^\s*(\S+):\s*(\d+\s+.*$)/) {
	my $irq = $1;
	my @fields = split ' ', $2;
	next unless ($#fields >= $cpus + 1 );
	push(@list_of_keys, $irq) unless ($file_count==0); 
	for (my $cpu = 0; $cpu < $cpus; $cpu++) {
	    my $value = shift @fields;
	    #print $value," ";
	    if ( $value =~ /\d+/) {
		$irqs{$irq}[$cpu] = $value;
	    } else {
		warn "Problem when parsing $ARGV, line $_\n";
		warn "CPU$cpu is $value\n";
		$irqs{$irq}[$cpu] = 0;
	    }
	}
	#print "\n";
	my $desc = join ' ', @fields;
	$desc =~ /(\S+)\s+(.*)$/;
	$irq_type{$irq} = $1;
	$irq_device{$irq} = $2;
    }
} continue {
    if ( eof ) { # Not eof()!
	close ARGV;
	if ( $file_count == 0 ) {
	    %last = %irqs;
	    %irqs = ();
	}
        $file_count++;	
    }
}

# Output header
printf("%28s%" . ($cpus + 1) * 8 . "s", "", "IRQs\n");
printf('%20s (%3s)  ', "Device", "IRQ");
foreach (my $cpu = 0; $cpu < $cpus; $cpu++) {
    printf('%7s ', 'CPU' . $cpu);
}
printf("%7s\n", "TOTAL");
#foreach my $irq (keys %irqs) {
foreach my $irq (@list_of_keys) {
    printf('%20s (%3s): ', substr($irq_device{$irq}, 0, 20), $irq);
    my $total = 0;
    for (my $cpu = 0; $cpu < $cpus; $cpu ++) {
	$total += $irqs{$irq}[$cpu] - $last{$irq}[$cpu];
    }
    for (my $cpu = 0; $cpu < $cpus; $cpu ++) {
	if ( $total == 0 ) {
	    printf("%6.2f%% ",0);
	} else {
	    printf("%6.2f%% ", ($irqs{$irq}[$cpu] - $last{$irq}[$cpu])*100.0/$total);
	}
    }
    printf("%8s\n", $total);
}

