aboutsummaryrefslogtreecommitdiff
path: root/nptl/sysdeps/pthread
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-03-03 21:11:12 +0000
committerUlrich Drepper <drepper@redhat.com>2003-03-03 21:11:12 +0000
commit7ce5c1640cbeb86d2094d992f30438ddda40ac14 (patch)
tree63f44821134b350f7eef50c06f75b4a4caf5b71b /nptl/sysdeps/pthread
parent625f22fc7f8e0d61e3e6cff2c65468b91dbad426 (diff)
downloadglibc-7ce5c1640cbeb86d2094d992f30438ddda40ac14.tar
glibc-7ce5c1640cbeb86d2094d992f30438ddda40ac14.tar.gz
glibc-7ce5c1640cbeb86d2094d992f30438ddda40ac14.tar.bz2
glibc-7ce5c1640cbeb86d2094d992f30438ddda40ac14.zip
Update.
2003-03-03 Martin Schwidefsky <schwidefsky@de.ibm.com> * atomic.h (atomic_exchange_and_add): Return newval, not oldval. * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): Fix handling of cancellation and failing pthread_mutex_unlock call. * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Likewise. (__pthread_cond_wait): Likewise. * sysdeps/pthread/pthread_rwlock_timedrdlock.c (pthread_rwlock_timedrdlock): Fix clobber of result variable by lll_futex_timed_wait call. * sysdeps/pthread/pthread_rwlock_timedwrlock.c (pthread_rwlock_timedwrlock): Likewise. * sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c (___lll_lock): Don't define lll_unlock_wake_cb and ___lll_timedwait_tid in libc.so. * sysdeps/unix/sysv/linux/s390/lowlevellock.c: Remove XXX comments. * sysdeps/unix/sysv/linux/s390/sem_post.c (__new_sem_post): Fix check of lll_futex_wake return value.
Diffstat (limited to 'nptl/sysdeps/pthread')
-rw-r--r--nptl/sysdeps/pthread/pthread_cond_timedwait.c23
-rw-r--r--nptl/sysdeps/pthread/pthread_cond_wait.c42
-rw-r--r--nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c8
3 files changed, 56 insertions, 17 deletions
diff --git a/nptl/sysdeps/pthread/pthread_cond_timedwait.c b/nptl/sysdeps/pthread/pthread_cond_timedwait.c
index 797d244cf7..3b29cb4ea6 100644
--- a/nptl/sysdeps/pthread/pthread_cond_timedwait.c
+++ b/nptl/sysdeps/pthread/pthread_cond_timedwait.c
@@ -31,6 +31,12 @@
extern void __condvar_cleanup (void *arg)
__attribute__ ((visibility ("hidden")));
+struct _condvar_cleanup_buffer
+{
+ int oldtype;
+ pthread_cond_t *cond;
+ pthread_mutex_t *mutex;
+};
int
__pthread_cond_timedwait (cond, mutex, abstime)
@@ -39,6 +45,7 @@ __pthread_cond_timedwait (cond, mutex, abstime)
const struct timespec *abstime;
{
struct _pthread_cleanup_buffer buffer;
+ struct _condvar_cleanup_buffer cbuffer;
int result = 0;
/* Catch invalid parameters. */
@@ -54,9 +61,13 @@ __pthread_cond_timedwait (cond, mutex, abstime)
/* We have one new user of the condvar. */
++cond->__data.__total_seq;
+ /* Prepare structure passed to cancellation handler. */
+ cbuffer.cond = cond;
+ cbuffer.mutex = mutex;
+
/* Before we block we enable cancellation. Therefore we have to
install a cancellation handler. */
- __pthread_cleanup_push (&buffer, __condvar_cleanup, cond);
+ __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer);
/* The current values of the wakeup counter. The "woken" counter
must exceed this value. */
@@ -76,6 +87,8 @@ __pthread_cond_timedwait (cond, mutex, abstime)
while (1)
{
+ int err;
+
/* Get the current time. So far we support only one clock. */
struct timeval tv;
(void) gettimeofday (&tv, NULL);
@@ -104,14 +117,14 @@ __pthread_cond_timedwait (cond, mutex, abstime)
lll_mutex_unlock (cond->__data.__lock);
/* Enable asynchronous cancellation. Required by the standard. */
- int oldtype = __pthread_enable_asynccancel ();
+ cbuffer.oldtype = __pthread_enable_asynccancel ();
/* Wait until woken by signal or broadcast. Note that we
truncate the 'val' value to 32 bits. */
- result = lll_futex_timed_wait (futex, (unsigned int) val, &rt);
+ err = lll_futex_timed_wait (futex, (unsigned int) val, &rt);
/* Disable asynchronous cancellation. */
- __pthread_disable_asynccancel (oldtype);
+ __pthread_disable_asynccancel (cbuffer.oldtype);
/* We are going to look at shared data again, so get the lock. */
lll_mutex_lock(cond->__data.__lock);
@@ -123,7 +136,7 @@ __pthread_cond_timedwait (cond, mutex, abstime)
break;
/* Not woken yet. Maybe the time expired? */
- if (result == -ETIMEDOUT)
+ if (err == -ETIMEDOUT)
{
/* Yep. Adjust the counters. */
++cond->__data.__wakeup_seq;
diff --git a/nptl/sysdeps/pthread/pthread_cond_wait.c b/nptl/sysdeps/pthread/pthread_cond_wait.c
index d0b63bd8df..d96444f49b 100644
--- a/nptl/sysdeps/pthread/pthread_cond_wait.c
+++ b/nptl/sysdeps/pthread/pthread_cond_wait.c
@@ -27,22 +27,35 @@
#include <shlib-compat.h>
+struct _condvar_cleanup_buffer
+{
+ int oldtype;
+ pthread_cond_t *cond;
+ pthread_mutex_t *mutex;
+};
+
void
__attribute__ ((visibility ("hidden")))
__condvar_cleanup (void *arg)
{
- pthread_cond_t *cond = (pthread_cond_t *) arg;
+ struct _condvar_cleanup_buffer *cbuffer =
+ (struct _condvar_cleanup_buffer *) arg;
/* We are going to modify shared data. */
- lll_mutex_lock (cond->__data.__lock);
+ lll_mutex_lock (cbuffer->cond->__data.__lock);
/* This thread is not waiting anymore. Adjust the sequence counters
appropriately. */
- ++cond->__data.__wakeup_seq;
- ++cond->__data.__woken_seq;
+ ++cbuffer->cond->__data.__wakeup_seq;
+ ++cbuffer->cond->__data.__woken_seq;
/* We are done. */
- lll_mutex_unlock (cond->__data.__lock);
+ lll_mutex_unlock (cbuffer->cond->__data.__lock);
+
+ /* Get the mutex before returning unless asynchronous cancellation
+ is in effect. */
+ if (!(cbuffer->oldtype & CANCELTYPE_BITMASK))
+ __pthread_mutex_lock_internal (cbuffer->mutex);
}
@@ -52,19 +65,30 @@ __pthread_cond_wait (cond, mutex)
pthread_mutex_t *mutex;
{
struct _pthread_cleanup_buffer buffer;
+ struct _condvar_cleanup_buffer cbuffer;
+ int err;
/* Make sure we are along. */
lll_mutex_lock (cond->__data.__lock);
/* Now we can release the mutex. */
- __pthread_mutex_unlock_internal (mutex);
+ err = __pthread_mutex_unlock_internal (mutex);
+ if (err)
+ {
+ lll_mutex_unlock (cond->__data.__lock);
+ return err;
+ }
/* We have one new user of the condvar. */
++cond->__data.__total_seq;
+ /* Prepare structure passed to cancellation handler. */
+ cbuffer.cond = cond;
+ cbuffer.mutex = mutex;
+
/* Before we block we enable cancellation. Therefore we have to
install a cancellation handler. */
- __pthread_cleanup_push (&buffer, __condvar_cleanup, cond);
+ __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer);
/* The current values of the wakeup counter. The "woken" counter
must exceed this value. */
@@ -88,14 +112,14 @@ __pthread_cond_wait (cond, mutex)
lll_mutex_unlock (cond->__data.__lock);
/* Enable asynchronous cancellation. Required by the standard. */
- int oldtype = __pthread_enable_asynccancel ();
+ cbuffer.oldtype = __pthread_enable_asynccancel ();
/* Wait until woken by signal or broadcast. Note that we
truncate the 'val' value to 32 bits. */
lll_futex_wait (futex, (unsigned int) val);
/* Disable asynchronous cancellation. */
- __pthread_disable_asynccancel (oldtype);
+ __pthread_disable_asynccancel (cbuffer.oldtype);
/* We are going to look at shared data again, so get the lock. */
lll_mutex_lock(cond->__data.__lock);
diff --git a/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c b/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
index fb6382544e..9c1815570f 100644
--- a/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
+++ b/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
@@ -37,6 +37,8 @@ pthread_rwlock_timedrdlock (rwlock, abstime)
while (1)
{
+ int err;
+
/* Get the rwlock if there is no writer... */
if (rwlock->__data.__writer == 0
/* ...and if either no writer is waiting or we prefer readers. */
@@ -111,14 +113,14 @@ pthread_rwlock_timedrdlock (rwlock, abstime)
lll_mutex_unlock (rwlock->__data.__lock);
/* Wait for the writer to finish. */
- result = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup,
- waitval, &rt);
+ err = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup,
+ waitval, &rt);
/* Get the lock. */
lll_mutex_lock (rwlock->__data.__lock);
/* Did the futex call time out? */
- if (result == -ETIMEDOUT)
+ if (err == -ETIMEDOUT)
{
/* Yep, report it. */
result = ETIMEDOUT;