Correct threads_mutex locking in main thread destruction.
Malcolm Beattie [Thu, 16 Oct 1997 16:26:53 +0000 (16:26 +0000)]
Add per-interp thrsv to hold SV struct thread for main thread.
Move Thread.xs MUTEX_DESTROY from end of threadstart to remove_thread.
Add Thread/list.t test of Thread->list method.
Let Thread::Semaphore methods up and down take an extra argument.

p4raw-id: //depot/perlext/Thread@140

Thread.xs
Thread/Semaphore.pm
list.t [new file with mode: 0644]

index a5382d9..3dc2516 100644 (file)
--- a/Thread.xs
+++ b/Thread.xs
@@ -15,6 +15,7 @@ Thread t;
     DEBUG_L(WITH_THR(PerlIO_printf(PerlIO_stderr(),
                                   "%p: remove_thread %p\n", thr, t)));
     MUTEX_LOCK(&threads_mutex);
+    MUTEX_DESTROY(&t->mutex);
     nthreads--;
     t->prev->next = t->next;
     t->next->prev = t->prev;
@@ -181,7 +182,6 @@ void *arg;
        croak("panic: illegal state %u at end of threadstart", ThrSTATE(thr));
        /* NOTREACHED */
     }
-    MUTEX_DESTROY(&thr->mutex);
     return (void *) returnav;  /* Available for anyone to join with us */
                                /* unless we are detached in which case */
                                /* noone will see the value anyway. */
@@ -474,7 +474,6 @@ list(class)
        do {
            n = nthreads;
            MUTEX_UNLOCK(&threads_mutex);
-           DEBUG_L(PerlIO_printf(PerlIO_stderr(), "list: n = %d\n", n));
            if (AvFILL(av) < n - 1) {
                int i = AvFILL(av);
                for (i = AvFILL(av); i < n - 1; i++) {
@@ -498,14 +497,13 @@ list(class)
        t = thr;
        svp = AvARRAY(av);
        do {
-           SV *sv = SvRV(*svp++);
-           DEBUG_L(PerlIO_printf(PerlIO_stderr(),
-                                 "list: filling in thread %p\n", t));
+           SV *sv = (SV*)SvRV(*svp);
            sv_setiv(sv, t->tid);
            SvMAGIC(sv)->mg_obj = SvREFCNT_inc(t->Toursv);
            SvMAGIC(sv)->mg_flags |= MGf_REFCOUNTED;
            SvMAGIC(sv)->mg_private = Thread_MAGIC_SIGNATURE;
            t = t->next;
+           svp++;
        } while (t != thr);
        /*  */
        MUTEX_UNLOCK(&threads_mutex);
index d34d6bd..9e5852f 100644 (file)
@@ -10,14 +10,16 @@ sub new {
 sub down {
     use attrs qw(locked method);
     my $s = shift;
-    cond_wait $s until $$s > 0;
-    $$s--;
+    my $inc = @_ ? shift : 1;
+    cond_wait $s until $$s >= $inc;
+    $$s -= $inc;
 }
 
 sub up {
     use attrs qw(locked method);
     my $s = shift;
-    $$s++ > 0 and cond_broadcast $s;
+    my $inc = @_ ? shift : 1;
+    ($$s += $inc) > 0 and cond_broadcast $s;
 }
 
 1;
diff --git a/list.t b/list.t
new file mode 100644 (file)
index 0000000..f13f4b2
--- /dev/null
+++ b/list.t
@@ -0,0 +1,30 @@
+use Thread qw(async);
+use Thread::Semaphore;
+
+my $sem = Thread::Semaphore->new(0);
+
+$nthreads = 4;
+
+for (my $i = 0; $i < $nthreads; $i++) {
+    async {
+       my $tid = Thread->self->tid;
+       print "thread $tid started...\n";
+       $sem->down;
+       print "thread $tid finishing\n";
+    };
+}
+
+print "main: started $nthreads threads\n";
+sleep 2;
+
+my @list = Thread->list;
+printf "main: Thread->list returned %d threads\n", scalar(@list);
+
+foreach my $t (@list) {
+    print "inspecting thread $t...\n";
+    print "...deref is $$t\n";
+    print "...flags = ", $t->flags, "\n";
+    print "...tid = ", $t->tid, "\n";
+}
+print "main thread telling workers to finish off...\n";
+$sem->up($nthreads);