+
+sub read_log {
+ my ($nth) = @_;
+
+ open (LOG, "<", $checkbochs_log) or die "$checkbochs_log: open: $!\n";
+ my ($min_loc, $max_loc);
+ my ($count) = 0;
+ my ($bts) = '';
+ my ($last_bts) = '';
+ while (<LOG>) {
+ if (my ($loc) = /^Warning on location (.*):$/) {
+ $bts = '';
+ while (<LOG>) {
+ last if /^$/;
+ $bts .= $_;
+ }
+ if ($bts ne $last_bts || hex ($loc) != hex ($min_loc) + 1) {
+ last if defined ($nth) && $nth == $count;
+ $min_loc = $max_loc = $loc;
+ $last_bts = $bts;
+ $count++;
+ } else {
+ $max_loc = $loc;
+ }
+ }
+ }
+ close LOG;
+
+ return ($last_bts, $min_loc, $max_loc) if defined ($nth) && $nth == $count;
+ return ($count);
+}
+
+sub intersect {
+ my ($set1, $set2) = @_;
+ my (%set);
+ $set{$_}++ foreach @$set1;
+ $set{$_}++ foreach @$set2;
+ my (@out);
+ $set{$_} == 2 && push (@out, $_) foreach keys %set;
+ return sort {$a <=> $b} @out;
+}
+
+sub print_lockset {
+ my ($name, $empty, @locks) = @_;
+ print "$name:";
+ if (@locks) {
+ my ($if) = 0;
+ my ($lock_pfx) = 0;
+ foreach my $lock (@locks) {
+ if ($lock == 0xffff0001) {
+ $if = 1;
+ } elsif ($lock == 0xffff0002) {
+ $lock_pfx = 1;
+ } else {
+ printf " %x", $lock;
+ }
+ }
+ print " (interrupts disabled)" if $if;
+ print " (LOCK prefix)" if $lock_pfx;
+ print ".\n";
+ } else {
+ print " $empty.\n";
+ }
+}