about summary refs log tree commit diff
path: root/nptl
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
parent625f22fc7f8e0d61e3e6cff2c65468b91dbad426 (diff)
downloadglibc-7ce5c1640cbeb86d2094d992f30438ddda40ac14.tar.gz
glibc-7ce5c1640cbeb86d2094d992f30438ddda40ac14.tar.xz
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')
-rw-r--r--nptl/ChangeLog22
-rw-r--r--nptl/atomic.h2
-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
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c25
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.c2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/sem_post.c2
8 files changed, 103 insertions, 23 deletions
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  <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.
+
 2003-03-03  Roland McGrath  <roland@redhat.com>
 
 	* 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 <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;
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 <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <sys/time.h>
+
+
+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;