summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorArtur Bergman <sky@nanisky.com>2002-04-27 12:56:44 +0000
committerArtur Bergman <sky@nanisky.com>2002-04-27 12:56:44 +0000
commit89661126d223f04756e59db5fd133f962b0514c6 (patch)
treeb80407d6a0691b87f5b9bce6355f5fbf5894a8f9 /ext
parent39f33d92fc728b977d8cfe3563fd57f4046e5401 (diff)
downloadperl-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.xs7
-rw-r--r--ext/threads/shared/t/cond.t40
-rw-r--r--ext/threads/shared/t/queue.t26
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";