#!/usr/bin/perl use strict; use threads; use threads::shared; $|=1; my $mutex :shared; my @i=(); while( my $x = ) { chomp( $x ); push( @i, $x ); } my $inos=scalar(@i); my $p0=init( 0 ); my $p1=init( 1 ); $p0->{outq}=\@{$p1->{inq}}; $p1->{outq}=\@{$p0->{inq}}; share( $p0->{is_blocked} ); share( $p1->{is_blocked} ); $p0->{other_blocked}=\$p1->{is_blocked}; $p1->{other_blocked}=\$p0->{is_blocked}; share( @{$p0->{inq}} ); share( @{$p1->{inq}} ); share( $p1->{sendct} ); my $t0=threads->create( 'run', $p0 ); my $t1=threads->create( 'run', $p1 ); $t0->join(); $t1->join(); while( scalar( threads->list() ) > 1 ) { sleep( 1 ); } print "p1 sent $p1->{sendct} values\n"; exit; sub init { my ( $p ) = @_; my %p=(); $p{p}=$p; $p{pc}=0; $p{reg}=(); $p{reg}{p}=$p; $p{sendct}=0; $p{run}=1; $p{inq}=(); $p{is_blocked}=0; return( \%p ); } sub run { my ( $comp ) = @_; while( $comp->{run} == 1 ) { go( $comp ); } } sub go { my ( $comp ) = @_; if( $comp->{run} != 1 ) { return; } my $pc=$comp->{pc}; if( $i[$pc] =~ /^snd (-?\d+)$/ ) { my $f=$1; #print "SND: $comp->{p} $comp->{sendct}\n"; { #print "SND: $comp->{p} awaiting\n"; lock( $mutex ); #print "SND: $comp->{p} obtained\n"; push( @{$comp->{outq}}, $f ); ${$comp->{other_blocked}}=0; $comp->{sendct}++; } $comp->{pc}++; } elsif( $i[$pc] =~ /^snd ([a-z]+)$/ ) { my $r=$1; #print "SND: $comp->{p} $comp->{sendct}\n"; { #print "SND: $comp->{p} awaiting\n"; lock( $mutex ); #print "SND: $comp->{p} obtained\n"; push( @{$comp->{outq}}, $comp->{reg}{$r} ); ${$comp->{other_blocked}}=0; $comp->{sendct}++; } $comp->{pc}++; } elsif( $i[$pc] =~ /^rcv ([a-z]+)$/ ) { my $r=$1; { #print "RCV: $comp->{p} awaiting\n"; lock( $mutex ); #print "RCV: $comp->{p} obtained $comp->{is_blocked} ${$comp->{other_blocked}}\n"; if( scalar( @{$comp->{inq}} ) == 0 ) { #print "RCV: $comp->{p} nothing on queue\n"; $comp->{is_blocked}=1; if( ${$comp->{other_blocked}} ) { print "DEADLOCK! $comp->{p}\n"; threads->exit(); } sleep(0.001); return; } #print "RCV: $comp->{p} ".scalar( @{$comp->{inq}} )." on queue\n"; $comp->{reg}{$r}=shift( @{$comp->{inq}} ); } $comp->{pc}++; } elsif( $i[$pc] =~ /^set ([a-z]+) (-?\d+)$/ ) { my $r=$1; my $n=$2; $comp->{reg}{$r}=$n; $comp->{pc}++; } elsif( $i[$pc] =~ /^set ([a-z]+) ([a-z]+)$/ ) { my $r1=$1; my $r2=$2; $comp->{reg}{$r1}=$comp->{reg}{$r2}; $comp->{pc}++; } elsif( $i[$pc] =~ /^add ([a-z]+) (-?\d+)$/ ) { my $r=$1; my $n=$2; $comp->{reg}{$r}+=$n; $comp->{pc}++; } elsif( $i[$pc] =~ /^add ([a-z]+) ([a-z]+)$/ ) { my $r1=$1; my $r2=$2; $comp->{reg}{$r1}+=$comp->{reg}{$r2}; $comp->{pc}++; } elsif( $i[$pc] =~ /^mul ([a-z]+) (-?\d+)$/ ) { my $r=$1; my $n=$2; $comp->{reg}{$r}*=$n; $comp->{pc}++; } elsif( $i[$pc] =~ /^mul ([a-z]+) ([a-z]+)$/ ) { my $r1=$1; my $r2=$2; $comp->{reg}{$r1}*=$comp->{reg}{$r2}; $comp->{pc}++; } elsif( $i[$pc] =~ /^mod ([a-z]+) (-?\d+)$/ ) { my $r=$1; my $n=$2; $comp->{reg}{$r}%=$n; $comp->{pc}++; } elsif( $i[$pc] =~ /^mod ([a-z]+) ([a-z]+)$/ ) { my $r1=$1; my $r2=$2; $comp->{reg}{$r1}%=$comp->{reg}{$r2}; $comp->{pc}++; } elsif( $i[$pc] =~ /^jgz (-?\d+) (-?\d+)$/ ) { my $rn=$1; my $n=$2; if( $rn > 0 ) { $comp->{pc}+=$n; } else { $comp->{pc}++; } } elsif( $i[$pc] =~ /^jgz ([a-z]+) (-?\d+)$/ ) { my $r=$1; my $n=$2; if( int($comp->{reg}{$r}) > 0 ) { $comp->{pc}+=$n; } else { $comp->{pc}++; } } elsif( $i[$pc] =~ /^jgz ([a-z]+) ([a-z]+)$/ ) { my $r1=$1; my $r2=$2; if( int($comp->{reg}{$r1}) > 0 ) { $comp->{pc}+=$comp->{reg}{$r2}; } else { $comp->{pc}++; } } else { print "UNHANDLED: [$i[$pc]]\n"; exit; } if( $pc < 0 || $pc >= $inos ) { $comp->{run}=0; } }