From 7ce5c1640cbeb86d2094d992f30438ddda40ac14 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Mon, 3 Mar 2003 21:11:12 +0000 Subject: Update. 2003-03-03 Martin Schwidefsky * 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. --- nptl/ChangeLog | 22 ++++++++++++ nptl/atomic.h | 2 +- nptl/sysdeps/pthread/pthread_cond_timedwait.c | 23 +++++++++--- nptl/sysdeps/pthread/pthread_cond_wait.c | 42 +++++++++++++++++----- nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c | 8 +++-- .../unix/sysv/linux/s390/libc-lowlevellock.c | 25 +++++++++++-- nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.c | 2 -- nptl/sysdeps/unix/sysv/linux/s390/sem_post.c | 2 +- 8 files changed, 103 insertions(+), 23 deletions(-) (limited to 'nptl') diff --git a/nptl/ChangeLog b/nptl/ChangeLog index d6ca84806c..740d6ff1f8 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,25 @@ +2003-03-03 Martin Schwidefsky + + * 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. + 2003-03-03 Roland McGrath * forward.c: Fix typo in __pthread_attr_init_2_0 compat_symbol decl. diff --git a/nptl/atomic.h b/nptl/atomic.h index 4279235a71..813fb80a03 100644 --- a/nptl/atomic.h +++ b/nptl/atomic.h @@ -60,7 +60,7 @@ while (atomic_compare_and_exchange_acq (__memp, __oldval + __value, \ __oldval)); \ \ - __oldval; }) + __oldval + __value; }) #endif 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 +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; diff --git a/nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c index 40b5c3e441..7035479c1a 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c +++ b/nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c @@ -17,5 +17,26 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -/* No difference to lowlevellock.c */ -#include "lowlevellock.c" +#include +#include +#include +#include + + +void +___lll_lock (futex, newval) + int *futex; + int newval; +{ + do + { + int oldval; + + lll_futex_wait (futex, newval); + lll_compare_and_swap (futex, oldval, newval, "lr %2,%1; ahi %2,-1"); + } + while (newval != 0); + + *futex = -1; +} +hidden_proto (___lll_lock) diff --git a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.c index bc501c7ee4..f98e163ae1 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.c +++ b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.c @@ -42,7 +42,6 @@ ___lll_lock (futex, newval) hidden_proto (___lll_lock) -/* XXX Should not be in libc.so */ int lll_unlock_wake_cb (futex) int *futex; @@ -58,7 +57,6 @@ lll_unlock_wake_cb (futex) hidden_proto (lll_unlock_wake_cb) -/* XXX Should not be in libc.so */ int ___lll_timedwait_tid (ptid, abstime) int *ptid; diff --git a/nptl/sysdeps/unix/sysv/linux/s390/sem_post.c b/nptl/sysdeps/unix/sysv/linux/s390/sem_post.c index df64c03ba6..b573532a32 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/sem_post.c +++ b/nptl/sysdeps/unix/sysv/linux/s390/sem_post.c @@ -34,7 +34,7 @@ __new_sem_post (sem_t *sem) lll_compare_and_swap ((int *) sem, oldval, newval, "lr %2,%1; ahi %2,1"); err = lll_futex_wake(((int *) sem), newval); - if (err != 0) + if (err < 0) { __set_errno(-err); return -1; -- cgit v1.2.3