|
|
- #!/usr/bin/perl
- #!/usr/local/bin/perl
- use Getopt::Std;
-
- #######################################################################
- # checktrace - trace file consistency checker and balancer.
- #
- # Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved.
- # May not be used, modified, or copied without permission.
- #
- # This script reads a Malloc Lab trace file, checks it for consistency,
- # and outputs a balanced version by appending any necessary free requests.
- #
- #######################################################################
-
- $| = 1; # autoflush output on every print statement
-
- #
- # void usage(void) - print help message and terminate
- #
- sub usage
- {
- printf STDERR "$_[0]\n";
- printf STDERR "Usage: $0 [-hs]\n";
- printf STDERR "Options:\n";
- printf STDERR " -h Print this message\n";
- printf STDERR " -s Emit only a brief summary\n";
- die "\n" ;
- }
-
- ##############
- # Main routine
- ##############
-
- #
- # Parse and check the command line arguments
- #
- getopts('hs');
- if ($opt_h) {
- usage("");
- }
- $summary = $opt_s;
-
- #
- # HASH keeps a running tally of outstanding alloc/realloc
- # requests. When a free request is encountered, the corresponding
- # hash entry is deleted. When we are finished reading the trace,
- # what is left are the unmatched alloc/realloc requests.
- #
- %HASH = ();
-
- # Read the trace header values
- $heap_size = <STDIN>;
- chomp($heap_size);
-
- $num_blocks = <STDIN>;
- chomp($num_blocks);
-
- $old_num_ops = <STDIN>;
- chomp($old_num_ops);
-
- $weight = <STDIN>;
- chomp($weight);
-
- #
- # Find any allocate requests that don't have a matching free requests
- #
- $linenum = 4;
- $requestnum = 0;
- while ($line = <STDIN>) {
- chomp($line);
- $linenum++;
-
- ($cmd, $id, $size) = split(" ", $line);
-
- # ignore blank lines
- if (!$cmd) {
- next;
- }
-
- # save the line for output later
- $lines[$requestnum++] = $line;
-
- #ignore realloc requests, as long as they are preceeded by an alloc request
- if ($cmd eq "r") {
- if (!$HASH{$id}) {
- die "$0: ERROR[$linenum]: realloc without previous alloc\n";
- }
- next;
- }
-
- if ($cmd eq "a" and $HASH{$id} eq "a") {
- die "$0: ERROR[$linenum]: allocate with no intervening free.\n";
- }
-
- if ($cmd eq "a" and $HASH{$id} eq "f") {
- die "$0: ERROR[$linenum]: reused ID $id.\n";
- }
-
- if ($cmd eq "f" and !exists($HASH{$id})) {
- die "$0: ERROR[$linenum]: freeing unallocated block.\n";
- next;
- }
-
- if ($cmd eq "f" and !$HASH{$id} eq "f") {
- die "$0: ERROR[$linenum]: freeing already freed block.\n";
- next;
- }
-
- if ($cmd eq "f") {
- delete $HASH{$id};
- }
- else {
- $HASH{$id} = $cmd;
- }
- }
-
- #
- # If called with -s argument , print a brief balance summary and exit
- #
- if ($summary) {
- if (!%HASH) {
- print "Balanced trace.\n";
- }
- else {
- print "Unbalanced tree.\n";
- }
- exit;
- }
-
- #
- # Output a balanced version of the trace
- #
- $new_ops = keys %HASH;
- $new_num_ops = $old_num_ops + $new_ops;
-
- print "$heap_size\n";
- print "$num_blocks\n";
- print "$new_num_ops\n";
- print "$weight\n";
-
- # print the old requests
- foreach $item (@lines) {
- print "$item\n";
- }
-
- # print a set of free requests that will balance the trace
- foreach $key (sort keys %HASH) {
- if ($HASH{$key} ne "a" and $HASH{$key} ne "r") {
- die "$0: ERROR: Invalid free request in residue.\n";
- }
- print "f $key\n";
- }
-
- exit;
|