#!/usr/bin/perl use warnings; use strict; use IPC::SysV qw(IPC_CREAT ftok SEM_UNDO); use IPC::Semaphore; my $semtok = ftok($0,1); my $shmtok = ftok($0,2); my $sem = IPC::Semaphore->new($semtok, 1, 0700 | IPC_CREAT) or die "Couldn't create semaphore: $!\n"; my $shmid = shmget($shmtok,4,0700 | IPC_CREAT) or die "Couldn't create shm: $!\n"; if ($ENV{RESET}) { $sem->setval(0,0); my $buf = pack("L",0); shmwrite($shmid, $buf, 0, 4) or die "shmwrite failed: $!\n"; if (!$ARGV[0]) { exit(0); } } foreach my $i(1..$ARGV[0]||100) { my $r = add(1); if ($ENV{VERBOSE}) { print $r,"\n"; } } sub add { my($add) = @_; # Lock: wait for 0, then semaphore up $sem->op(0, 0, 0, 0, 1, 0) or die "semaphore lock failed: $!\n"; # Read counter my $buf; shmread($shmid, $buf, 0, 4) or die "shmread failed: $!\n"; my $val = unpack("L",$buf); # Increment $val += $add; # Write it back $buf = pack("L",$val); shmwrite($shmid, $buf, 0, 4) or die "shmwrite failed: $!\n"; # Now unlock; semaphore down $sem->op(0, -1, 0) or die "semaphore unlock failed: $!\n"; return $val; }