#!/usr/bin/perl -w

use strict;
use English;
use Getopt::Std;
no warnings "portable";

use vars qw($opt_v $opt_h);

my ($version) = '$Revision$ ' . "\n";
my ($usage)   = "Usage : [ -vh ] PID\n";

my ($usage_long) = "Options :\n" .
    " -v         Print version.\n" .
    "";

if (!getopts('vh')) {
    print $usage;
    exit;
}
if ($opt_v) {
    print $version;
    exit;
}
if ($opt_h) {
    print $usage_long;
    exit;
}

if ($#ARGV != 0) {
    print "Error\n";
    print $usage;
    exit 1;
}


my ($pid) = shift;
my (%maps, %nodevma);
my ($str, $a, $b, $ax, $bx, $name, $node, $inc);

open MAPS, "/proc/$pid/maps" or die "Failed to open /proc/$pid/maps\n";
foreach $str (<MAPS>) {
    ($ax, $bx, $name) = $str =~ /^([[:xdigit:]]+)\-([[:xdigit:]]+)\s+\S+\s+\S+\s+\S+\s+\S+\s*(\S*)$/;
    $a = hex $ax;
    $b = hex $bx;
    if ($name) {
	$maps{$a} = [ $b, $name ];
    }
    else {
	$maps{$a} = [ $b, "" ];
    }
}
close MAPS;

$inc = 0;
open NODEMEM, "/proc/$pid/nodemem" or die "Failed to open /proc/$pid/nodemem\n";
foreach $str (<NODEMEM>) {
    my ($vma_a);

    if (($ax, $bx, $node) = $str =~ /^([[:xdigit:]]+)\-([[:xdigit:]]+)\s+\S+\s+(\S+)$/) {
	
	$a = hex $ax;
	$b = hex $bx;

	foreach $vma_a (keys %maps) {
#	    printf "VMA a %lx a %lx VMA b %lx\n", $vma_a, $a, $maps{$vma_a}[0];
	    if (! defined $a || ! defined $maps{$vma_a}[0]) {
		print "argh \"$a\"!\n";
		exit 1;
	    }
	    if ($a >= $vma_a && $a < $maps{$vma_a}[0]) {
		$nodevma{$vma_a}{$node} += int (($b - $a) / 4096 + 1); # Fixme for pagemap
		$inc += int (($b - $a) / 4096 + 1);
#		print "VMA $vma_a is node $node\n";
		last;
	    }
	}
    }
    else {
	print "$str";
    }
}
close NODEMEM;

foreach $a (keys %nodevma) {
    $b = $maps{$a}[0];
    $name = $maps{$a}[1];
    printf "VMA %lx-%lx %s\n", $a, $b, $name;
    foreach $node (keys %{ $nodevma{$a} }) {
	if ($node eq "present") { # Yes, this is correct
	    print "\t$nodevma{$a}{$node} pages not present\n";
	}
	else {
	    print "\t$nodevma{$a}{$node} pages on node $node\n";
	}
    }
}
print "Processed $inc pages\n";
exit 0;
