diff options
author | Artur Bergman <sky@nanisky.com> | 2002-04-27 12:56:44 +0000 |
---|---|---|
committer | Artur Bergman <sky@nanisky.com> | 2002-04-27 12:56:44 +0000 |
commit | 89661126d223f04756e59db5fd133f962b0514c6 (patch) | |
tree | b80407d6a0691b87f5b9bce6355f5fbf5894a8f9 /ext | |
parent | 39f33d92fc728b977d8cfe3563fd57f4046e5401 (diff) | |
download | perl-89661126d223f04756e59db5fd133f962b0514c6.tar.gz |
Fixed race condtions and deadlocks in interaction with
cond_wait/cond_signal and lock.
Now we wait for a lock to gie up if we return from COND_WAIT
and we are still locked. We also notifiers potential
lockers that it is free for locking when we go into COND_WAIT.
p4raw-id: //depot/perl@16210
Diffstat (limited to 'ext')
-rw-r--r-- | ext/threads/shared/shared.xs | 7 | ||||
-rw-r--r-- | ext/threads/shared/t/cond.t | 40 | ||||
-rw-r--r-- | ext/threads/shared/t/queue.t | 26 |
3 files changed, 61 insertions, 12 deletions
diff --git a/ext/threads/shared/shared.xs b/ext/threads/shared/shared.xs index 3d339e49f6..344221324f 100644 --- a/ext/threads/shared/shared.xs +++ b/ext/threads/shared/shared.xs @@ -982,7 +982,14 @@ cond_wait_enabled(SV *ref) shared->lock.owner = NULL; locks = shared->lock.locks; shared->lock.locks = 0; + + /* since we are releasing the lock here we need to tell other + people that is ok to go ahead and use it */ + COND_SIGNAL(&shared->lock.cond); COND_WAIT(&shared->user_cond, &shared->lock.mutex); + while(shared->lock.owner != NULL) { + COND_WAIT(&shared->lock.cond,&shared->lock.mutex); + } shared->lock.owner = aTHX; shared->lock.locks = locks; MUTEX_UNLOCK(&shared->lock.mutex); diff --git a/ext/threads/shared/t/cond.t b/ext/threads/shared/t/cond.t new file mode 100644 index 0000000000..c143c02395 --- /dev/null +++ b/ext/threads/shared/t/cond.t @@ -0,0 +1,40 @@ +BEGIN { + chdir 't' if -d 't'; + push @INC ,'../lib'; + require Config; import Config; + unless ($Config{'useithreads'}) { + print "1..0 # Skip: no threads\n"; + exit 0; + } +} +print "1..5\n"; +use strict; + + +use threads; + +use threads::shared; + +my $lock : shared; + +sub foo { + lock($lock); + print "ok 1\n"; + sleep 2; + print "ok 2\n"; + cond_wait($lock); + print "ok 5\n"; +} + +sub bar { + lock($lock); + print "ok 3\n"; + cond_signal($lock); + print "ok 4\n"; +} + +my $tr = threads->create(\&foo); +my $tr2 = threads->create(\&bar); +$tr->join(); +$tr2->join(); + diff --git a/ext/threads/shared/t/queue.t b/ext/threads/shared/t/queue.t index 1b255b7e42..cf28eb4a90 100644 --- a/ext/threads/shared/t/queue.t +++ b/ext/threads/shared/t/queue.t @@ -1,13 +1,13 @@ BEGIN { -# chdir 't' if -d 't'; -# push @INC ,'../lib'; -# require Config; import Config; -# unless ($Config{'useithreads'}) { + chdir 't' if -d 't'; + push @INC ,'../lib'; + require Config; import Config; + unless ($Config{'useithreads'}) { print "1..0 # Skip: might still hang\n"; exit 0; -# } + } } @@ -16,6 +16,8 @@ use threads::queue; $q = new threads::shared::queue; +print "1..26\n"; + sub reader { my $tid = threads->self->tid; my $i = 0; @@ -23,8 +25,9 @@ sub reader { $i++; # print "reader (tid $tid): waiting for element $i...\n"; my $el = $q->dequeue; + print "ok\n"; # print "reader (tid $tid): dequeued element $i: value $el\n"; - select(undef, undef, undef, rand(2)); + select(undef, undef, undef, rand(1)); if ($el == -1) { # end marker # print "reader (tid $tid) returning\n"; @@ -33,16 +36,16 @@ sub reader { } } -my $nthreads = 1; +my $nthreads = 5; my @threads; for (my $i = 0; $i < $nthreads; $i++) { push @threads, threads->new(\&reader, $i); } -for (my $i = 1; $i <= 10; $i++) { +for (my $i = 1; $i <= 20; $i++) { my $el = int(rand(100)); - select(undef, undef, undef, rand(2)); + select(undef, undef, undef, rand(1)); # print "writer: enqueuing value $el\n"; $q->enqueue($el); } @@ -50,10 +53,9 @@ for (my $i = 1; $i <= 10; $i++) { $q->enqueue((-1) x $nthreads); # one end marker for each thread for(@threads) { - print "waiting for join\n"; +# print "waiting for join\n"; $_->join(); - } - +print "ok\n"; |