Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/nathanw_sa]: src/lib/libpthread Analagous to the fixes in pthread_cond.c...



details:   https://anonhg.NetBSD.org/src/rev/7773cb614259
branches:  nathanw_sa
changeset: 506590:7773cb614259
user:      nathanw <nathanw%NetBSD.org@localhost>
date:      Wed Dec 18 22:56:12 2002 +0000

description:
Analagous to the fixes in pthread_cond.c, ensure that only one of an
alarm callback or an unlock can remove a thread from a timed lock
sleep and schedule it.

Don't call pthread__alarm_fired() until after pthread__alarm_del().

diffstat:

 lib/libpthread/pthread_rwlock.c |  55 ++++++++++++++++++++--------------------
 1 files changed, 28 insertions(+), 27 deletions(-)

diffs (130 lines):

diff -r e727a249c43f -r 7773cb614259 lib/libpthread/pthread_rwlock.c
--- a/lib/libpthread/pthread_rwlock.c   Wed Dec 18 22:53:14 2002 +0000
+++ b/lib/libpthread/pthread_rwlock.c   Wed Dec 18 22:56:12 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pthread_rwlock.c,v 1.1.2.1 2002/10/28 00:06:09 nathanw Exp $ */
+/*     $NetBSD: pthread_rwlock.c,v 1.1.2.2 2002/12/18 22:56:12 nathanw Exp $ */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -238,7 +238,7 @@
        pthread_t self;
        struct pthread_rwlock__waitarg wait;
        struct pt_alarm_t alarm;
-       int retval, armed;
+       int retval;
 #ifdef ERRORCHECK
        if ((rwlock == NULL) || (rwlock->ptr_magic != _PT_RWLOCK_MAGIC))
                return EINVAL;
@@ -257,17 +257,14 @@
         * writers; i.e. prefer writers to readers. This strategy is dictated
         * by SUSv3.
         */
-       retval = armed = 0;
+       retval = 0;
        while ((retval == 0) && ((rwlock->ptr_writer != NULL) ||
            (!PTQ_EMPTY(&rwlock->ptr_wblocked)))) {
-               if (!armed) {
-                       armed = 1;
-                       wait.ptw_thread = self;
-                       wait.ptw_rwlock = rwlock;
-                       wait.ptw_queue = &rwlock->ptr_rblocked;
-                       pthread__alarm_add(self, &alarm, abs_timeout,
-                           pthread_rwlock__callback, &wait);
-               }
+               wait.ptw_thread = self;
+               wait.ptw_rwlock = rwlock;
+               wait.ptw_queue = &rwlock->ptr_rblocked;
+               pthread__alarm_add(self, &alarm, abs_timeout,
+                   pthread_rwlock__callback, &wait);
                PTQ_INSERT_TAIL(&rwlock->ptr_rblocked, self, pt_sleep);
                /* Locking a rwlock is not a cancellation point; don't check */
                pthread_spinlock(self, &self->pt_statelock);
@@ -278,6 +275,7 @@
                pthread_spinunlock(self, &self->pt_statelock);
                pthread__block(self, &rwlock->ptr_interlock);
                /* interlock is not held when we return */
+               pthread__alarm_del(self, &alarm);
                if (pthread__alarm_fired(&alarm))
                        retval = ETIMEDOUT;
                pthread_spinlock(self, &rwlock->ptr_interlock);
@@ -286,8 +284,6 @@
        if (retval == 0)
                rwlock->ptr_nreaders++;
        pthread_spinunlock(self, &rwlock->ptr_interlock);
-       if (armed)
-               pthread__alarm_del(self, &alarm);
 
        return retval;
 }
@@ -299,7 +295,7 @@
 {
        struct pthread_rwlock__waitarg wait;
        struct pt_alarm_t alarm;
-       int retval, armed;
+       int retval;
        pthread_t self;
 #ifdef ERRORCHECK
        if ((rwlock == NULL) || (rwlock->ptr_magic != _PT_RWLOCK_MAGIC))
@@ -312,17 +308,14 @@
         * Prefer writers to readers here; permit writers even if there are
         * waiting readers.
         */
-       retval = armed = 0;
+       retval = 0;
        while (retval == 0 &&
            ((rwlock->ptr_nreaders > 0) || (rwlock->ptr_writer != NULL))) {
-               if (armed == 0) {
-                       armed = 1;
-                       wait.ptw_thread = self;
-                       wait.ptw_rwlock = rwlock;
-                       wait.ptw_queue = &rwlock->ptr_wblocked;
-                       pthread__alarm_add(self, &alarm, abs_timeout,
-                           pthread_rwlock__callback, &wait);
-               }
+               wait.ptw_thread = self;
+               wait.ptw_rwlock = rwlock;
+               wait.ptw_queue = &rwlock->ptr_wblocked;
+               pthread__alarm_add(self, &alarm, abs_timeout,
+                   pthread_rwlock__callback, &wait);
                PTQ_INSERT_TAIL(&rwlock->ptr_wblocked, self, pt_sleep);
                /* Locking a rwlock is not a cancellation point; don't check */
                pthread_spinlock(self, &self->pt_statelock);
@@ -333,6 +326,7 @@
                pthread_spinunlock(self, &self->pt_statelock);
                pthread__block(self, &rwlock->ptr_interlock);
                /* interlock is not held when we return */
+               pthread__alarm_del(self, &alarm);
                if (pthread__alarm_fired(&alarm))
                        retval = ETIMEDOUT;
                pthread_spinlock(self, &rwlock->ptr_interlock);
@@ -341,8 +335,6 @@
        if (retval == 0)
                rwlock->ptr_writer = self;
        pthread_spinunlock(self, &rwlock->ptr_interlock);
-       if (armed)
-               pthread__alarm_del(self, &alarm);
 
        return 0;
 }
@@ -358,9 +350,18 @@
        self = pthread__self();
 
        pthread_spinlock(self, &a->ptw_rwlock->ptr_interlock);
-       PTQ_REMOVE(a->ptw_queue, a->ptw_thread, pt_sleep);
+       /*
+        * Don't dequeue and schedule the thread if it's already been
+        * queued up by a signal or broadcast (but hasn't yet run as far
+        * as pthread__alarm_del(), or we wouldn't be here, and hence can't
+        * have become blocked on some *other* queue).
+        */
+       if (a->ptw_thread->pt_state == PT_STATE_BLOCKED_QUEUE) {
+               PTQ_REMOVE(a->ptw_queue, a->ptw_thread, pt_sleep);
+               pthread__sched(self, a->ptw_thread);
+       }
        pthread_spinunlock(self, &a->ptw_rwlock->ptr_interlock);
-       pthread__sched(self, a->ptw_thread);
+
 }
 
 



Home | Main Index | Thread Index | Old Index