Change 16210 by sky@sky-lab on 2002/04/27 12:56:44
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.
Affected files ...
.... //depot/perl/MANIFEST#863 edit
.... //depot/perl/ext/threads/shared/shared.xs#24 edit
.... //depot/perl/ext/threads/shared/t/cond.t#1 add
.... //depot/perl/ext/threads/shared/t/queue.t#2 edit
Differences ...
==== //depot/perl/MANIFEST#863 (text) ====
Index: perl/MANIFEST
--- perl/MANIFEST.~1~ Sat Apr 27 07:00:05 2002
+++ perl/MANIFEST Sat Apr 27 07:00:05 2002
@@ -662,6 +662,7 @@
ext/threads/shared/t/0nothread.t Tests for basic shared array functionality.
ext/threads/shared/t/av_refs.t Tests for arrays containing references
ext/threads/shared/t/av_simple.t Tests for basic shared array functionality.
+ext/threads/shared/t/cond.t Test condition variables
ext/threads/shared/t/hv_refs.t Test shared hashes containing references
ext/threads/shared/t/hv_simple.t Tests for basic shared hash functionality.
ext/threads/shared/t/no_share.t Tests for disabled share on variables.
==== //depot/perl/ext/threads/shared/shared.xs#24 (text) ====
Index: perl/ext/threads/shared/shared.xs
--- perl/ext/threads/shared/shared.xs.~1~ Sat Apr 27 07:00:05 2002
+++ perl/ext/threads/shared/shared.xs Sat Apr 27 07:00:05 2002
@@ -982,7 +982,14 @@
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);
==== //depot/perl/ext/threads/shared/t/queue.t#2 (text) ====
Index: perl/ext/threads/shared/t/queue.t
--- perl/ext/threads/shared/t/queue.t.~1~ Sat Apr 27 07:00:05 2002
+++ perl/ext/threads/shared/t/queue.t Sat Apr 27 07:00:05 2002
@@ -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 @@
$q = new threads::shared::queue;
+print "1..26\n";
+
sub reader {
my $tid = threads->self->tid;
my $i = 0;
@@ -23,8 +25,9 @@
$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 @@
}
}
-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 @@
$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";
==== //depot/perl/ext/threads/shared/t/cond.t#1 (text) ====
Index: perl/ext/threads/shared/t/cond.t
--- perl/ext/threads/shared/t/cond.t.~1~ Sat Apr 27 07:00:05 2002
+++ perl/ext/threads/shared/t/cond.t Sat Apr 27 07:00:05 2002
@@ -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();
+
End of Patch.