Ulrich Drepper | 5 Aug 21:02
Picon
Favicon

Closing the list

I'll have this list closed now.  There is no need for this separate list
anymore.  Bug reports and RFEs go into the bugzilla at
sources.redhat.com, thread discussions to comp.programming.threads.

-- 
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖

--

-- 
Phil-list mailing list
Phil-list <at> redhat.com
https://www.redhat.com/mailman/listinfo/phil-list

C Jaiprakash, Noida | 23 Jun 10:18

RE: Porting NPTL

Hi,
  I gathered that following are the requirements for NPTL support for a new target.

1.       Linux Kernel 2.6 (or previous version if backported)
2.       NPTL ported to the particular target.
3.       glibc 2.3.2 configured with TLS support 
4.       gcc 3.4, with TLS support for the target.
5.       binutils support for TLS

Am i missing anything else? 

CJ

-----Original Message-----
From: phil-list-bounces <at> redhat.com [mailto:phil-list-bounces <at> redhat.com]On Behalf Of C
Jaiprakash, Noida
Sent: Thursday, June 10, 2004 9:27 PM
To: phil-list <at> redhat.com
Subject: Porting NPTL

Hi, 
  I want to start porint NPTL to a new architecture. Though I have just started looking into the code but I would
appreciate if anyone can tell me from where should I start. Please add me in CC since I am not yet member of
this list. I will subscribe for it.
C Jaiprakash 

--

-- 
Phil-list mailing list
Phil-list <at> redhat.com
https://www.redhat.com/mailman/listinfo/phil-list
(Continue reading)

Trevor Lobban | 18 Jun 16:58

LinuxThreads & NPTL compatibility

Hi,
    I've been searching for confirmation that LinuxThreads and NPTL are binary compatible for 'well written' applications (i.e sensible use of getpid and don't use any NPTL only features [process-shared etc.])
 
Can I build a thareded application on SLES 8 and expect it work on Red Hat AS 3 (or even AS 4)? The reason I ask is I notice the size of the pthread_cond_t has changed between SLES 8 and Red Hat AS 3 albeit the size increase appears all padding.
 
If the size is a problem, can I simply ensure that the memory I declare for my condition variables on SLES 8 has sufficient padding for the extra 36 bytes required by Red hat AS 3?
 
Any help is much appreciated.
 
Thanks,
 
Trevor
 
 
C Jaiprakash, Noida | 10 Jun 17:56

Porting NPTL

Hi,
  I want to start porint NPTL to a new architecture. Though I have just started looking into the code but I would appreciate if anyone can tell me from where should I start. Please add me in CC since I am not yet member of this list. I will subscribe for it.

C Jaiprakash

Sebastien DECUGIS | 27 May 16:23
Picon

Erroneous behavior

Hi,

I've run into an issue with pthread_cond_timedwait() and
clock_settime().

The basics of my attached test is:

clock_gettime() -> time in ts
create a thread
[thread] pthread_cond_timedwait() with timeout = ts + 20sec
[main]clock_settime() with new ts > timeout

In this situation, the POSIX IEEE 1003.1 (2004) standard states that the
behavior of the thread should be as if the time had runned out (please
refer to the clock_settime() reference, §4). But when I run my test with
a fresh nptl (cvs from monday), I have to wait for the timeout as if the
clock had not been changed. Please note that even if I signal the
condition, I get the ETIMEDOUT error code return (which is normal).

I think this is due to the absolute timeout parameter being tranformed
into a relative timeout in the pthread_cond_timedwait routine. Is this
operation unavoidable?

Maybe a workaround would be to wake every threads waiting (in
pthread_cond_timedwait) on a given clock when this clock is set forward.
At worst, it results in a legal spurious wakeup, if the time out is not
expired. Please let me know if this is a kernel issue?

Thank you,
Sebastien.

--

-- 
Sébastien DECUGIS
Bull S.A.
NPTL Tests & Trace project
http://nptl.bullopensource.org/phpBB/
Attachment (test.tar.gz): application/x-compressed-tar, 9 KiB
Jakub Jelinek | 20 May 11:20
Picon
Favicon

[PATCH] tst-cond16 fix - NPTL part

Hi!

This is the NPTL part of the tst-cond16 fix.

2004-05-20  Jakub Jelinek  <jakub <at> redhat.com>

	* Makefile (tests): Add tst-cond16.
	* sysdeps/unix/sysv/linux/lowlevelcond.sym (cond_futex): Add.
	* pthread_cond_init.c (__pthread_cond_init): Clear __data.__futex.
	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t):
	Add __data.__futex field, reshuffle __data.__clock.
	* sysdeps/unix/sysv/linux/i386/pthread_cond_signal.S
	(__pthread_cond_signal): Increment __futex at the same time as
	__wakeup_seq or __total_seq.  Pass address of __futex instead of
	address of low 32-bits of __wakeup_seq to futex syscall.
	* sysdeps/unix/sysv/linux/i386/pthread_cond_wait.S
	(__pthread_cond_wait): Likewise.  Pass __futex value from before
	releasing internal lock to FUTEX_WAIT.
	* sysdeps/unix/sysv/linux/i386/pthread_cond_timedwait.S
	(__pthread_cond_timedwait): Likewise.
	* sysdeps/unix/sysv/linux/i386/pthread_cond_broadcast.S
	(FUTEX_CMP_REQUEUE): Define.
	(__pthread_cond_broadcast): Set __futex to 2 * __total_seq.
	Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE.
	Pass __futex value from before the unlock and __futex address instead
	of address of low 32-bits of __wakeup_seq to futex syscall.
	Fallback to FUTEX_WAKE all on any errors.
	* sysdeps/unix/sysv/linux/alpha/lowlevellock.h (FUTEX_CMP_REQUEUE):
	Define.
	(lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE
	internally.  Return non-zero if error, zero if success.
	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t):
	Add __data.__futex field, reshuffle __data.__clock.
	* sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_CMP_REQUEUE):
	Define.
	(lll_futex_requeue): Add val argument, return 1 unconditionally
	for the time being.
	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t):
	Add __data.__futex field, reshuffle __data.__clock.
	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (FUTEX_CMP_REQUEUE):
	Define.
	(lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE
	internally.  Return non-zero if error, zero if success.
	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
	(pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock.
	* sysdeps/unix/sysv/linux/sparc/lowlevellock.h (FUTEX_CMP_REQUEUE):
	Define.
	(lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE
	internally.  Return non-zero if error, zero if success.
	* sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h (pthread_cond_t):
	Add __data.__futex field, reshuffle __data.__clock.
	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h (FUTEX_CMP_REQUEUE):
	Define.
	(lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE
	internally.  Return non-zero if error, zero if success.
	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h (pthread_cond_t):
	Add __data.__futex field, reshuffle __data.__clock.
	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h (pthread_cond_t):
	Add __data.__futex field, reshuffle __data.__clock.
	* sysdeps/pthread/pthread_cond_signal.c (__pthread_cond_signal):
	Increment __futex at the same time as __wakeup_seq or __total_seq.
	Pass address of __futex instead of address of low 32-bits of
	__wakeup_seq to futex syscall.
	* sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Likewise.
	Pass __futex value from before releasing internal lock
	to FUTEX_WAIT.
	* sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait):
	Likewise.  Avoid unnecessary shadowing of variables.
	* sysdeps/pthread/pthread_cond_broadcast.c (__pthread_cond_broadcast):
	Set __futex to 2 * __total_seq.  Pass __futex value from before the
	unlock and __futex address instead of address of low 32-bits of
	__wakeup_seq to futex_requeue macro, adjust for new return value
	meaning.
	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
	(__pthread_cond_signal): Increment __futex at the same time as
	__wakeup_seq or __total_seq.  Pass address of __futex instead of
	address of low 32-bits of __wakeup_seq to futex syscall.
	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
	(__pthread_cond_wait): Likewise.  Pass __futex value from before
	releasing internal lock to FUTEX_WAIT.
	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
	(__pthread_cond_timedwait): Likewise.
	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
	(FUTEX_CMP_REQUEUE): Define.
	(__pthread_cond_broadcast): Set __futex to 2 * __total_seq.
	Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE.
	Pass __futex value from before the unlock and __futex address instead
	of address of low 32-bits of __wakeup_seq to futex syscall.
	Fallback to FUTEX_WAKE all on any errors.

--- libc/nptl/Makefile	2004-05-19 22:58:46.405674919 +0200
+++ libc/nptl/Makefile	2004-05-18 14:43:22.000000000 +0200
@@ -194,7 +194,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
 	tst-spin1 tst-spin2 tst-spin3 \
 	tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
 	tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
-	tst-cond14 tst-cond15 tst-cond17 tst-cond18 \
+	tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 \
 	tst-rwlock1 tst-rwlock2 tst-rwlock3 tst-rwlock4 tst-rwlock5 \
 	tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 tst-rwlock10 \
 	tst-rwlock11 tst-rwlock12 tst-rwlock13 \
--- libc/nptl/pthread_cond_init.c	2004-05-19 22:58:46.405674919 +0200
+++ libc/nptl/pthread_cond_init.c	2004-05-18 14:43:22.000000000 +0200
@@ -31,6 +31,7 @@ __pthread_cond_init (cond, cond_attr)
   struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr;

   cond->__data.__lock = LLL_MUTEX_LOCK_INITIALIZER;
+  cond->__data.__futex = 0;
   cond->__data.__clock = (icond_attr == NULL
 			  ? CLOCK_REALTIME : (icond_attr->value & 0xfe) >> 1);
   cond->__data.__total_seq = 0;
--- libc/nptl/sysdeps/pthread/pthread_cond_broadcast.c	2004-05-19 22:58:46.532652163 +0200
+++ libc/nptl/sysdeps/pthread/pthread_cond_broadcast.c	2004-05-18 14:56:08.000000000 +0200
@@ -41,31 +41,25 @@ __pthread_cond_broadcast (cond)
       /* Yes.  Mark them all as woken.  */
       cond->__data.__wakeup_seq = cond->__data.__total_seq;
       cond->__data.__woken_seq = cond->__data.__total_seq;
+      cond->__data.__futex = (unsigned int) cond->__data.__total_seq * 2;
+      int futex_val = cond->__data.__futex;
       /* Signal that a broadcast happened.  */
       ++cond->__data.__broadcast_seq;

       /* We are done.  */
       lll_mutex_unlock (cond->__data.__lock);

-      /* The futex syscall operates on a 32-bit word.  That is fine,
-	 we just use the low 32 bits of the sequence counter.  */
-#if BYTE_ORDER == LITTLE_ENDIAN
-      int *futex = ((int *) (&cond->__data.__wakeup_seq));
-#elif BYTE_ORDER == BIG_ENDIAN
-      int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1;
-#else
-# error "No valid byte order"
-#endif
-
       /* Do not use requeue for pshared condvars.  */
       if (cond->__data.__mutex == (void *) ~0l)
 	goto wake_all;

       /* Wake everybody.  */
       pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
-      if (__builtin_expect (lll_futex_requeue (futex, 1, INT_MAX,
-					       &mut->__data.__lock) == -EINVAL,
-			    0))
+      /* lll_futex_requeue returns 0 for success and non-zero
+	 for errors.  */
+      if (__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1,
+					       INT_MAX, &mut->__data.__lock,
+					       futex_val), 0))
 	{
 	  /* The requeue functionality is not available.  */
 	wake_all:
--- libc/nptl/sysdeps/pthread/pthread_cond_signal.c	2003-09-22 07:44:27.000000000 +0200
+++ libc/nptl/sysdeps/pthread/pthread_cond_signal.c	2004-05-18 14:58:04.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Martin Schwidefsky <schwidefsky <at> de.ibm.com>, 2003.

@@ -40,19 +40,10 @@ __pthread_cond_signal (cond)
     {
       /* Yes.  Mark one of them as woken.  */
       ++cond->__data.__wakeup_seq;
-
-      /* The futex syscall operates on a 32-bit word.  That is fine,
-	 we just use the low 32 bits of the sequence counter.  */
-#if BYTE_ORDER == LITTLE_ENDIAN
-      int *futex = ((int *) (&cond->__data.__wakeup_seq));
-#elif BYTE_ORDER == BIG_ENDIAN
-      int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1;
-#else
-# error "No valid byte order"
-#endif
+      ++cond->__data.__futex;

       /* Wake one.  */
-      lll_futex_wake (futex, 1);
+      lll_futex_wake (&cond->__data.__futex, 1);
     }

   /* We are done.  */
--- libc/nptl/sysdeps/pthread/pthread_cond_timedwait.c	2004-05-19 22:58:46.533651984 +0200
+++ libc/nptl/sysdeps/pthread/pthread_cond_timedwait.c	2004-05-18 15:05:55.000000000 +0200
@@ -66,6 +66,7 @@ __pthread_cond_timedwait (cond, mutex, a

   /* We have one new user of the condvar.  */
   ++cond->__data.__total_seq;
+  ++cond->__data.__futex;

   /* Remember the mutex we are using here.  If there is already a
      different address store this is a bad user bug.  Do not store
@@ -89,27 +90,17 @@ __pthread_cond_timedwait (cond, mutex, a
   /* Remember the broadcast counter.  */
   cbuffer.bc_seq = cond->__data.__broadcast_seq;

-  /* The futex syscall operates on a 32-bit word.  That is fine, we
-     just use the low 32 bits of the sequence counter.  */
-#if BYTE_ORDER == LITTLE_ENDIAN
-  int *futex = ((int *) (&cond->__data.__wakeup_seq));
-#elif BYTE_ORDER == BIG_ENDIAN
-  int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1;
-#else
-# error "No valid byte order"
-#endif
-
   while (1)
     {
       struct timespec rt;
       {
 #ifdef __NR_clock_gettime
 	INTERNAL_SYSCALL_DECL (err);
-	int val;
-	val = INTERNAL_SYSCALL (clock_gettime, err, 2,
+	int ret;
+	ret = INTERNAL_SYSCALL (clock_gettime, err, 2,
 				cond->__data.__clock, &rt);
 # ifndef __ASSUME_POSIX_TIMERS
-	if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (val, err), 0))
+	if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (ret, err), 0))
 	  {
 	    struct timeval tv;
 	    (void) gettimeofday (&tv, NULL);
@@ -149,15 +140,17 @@ __pthread_cond_timedwait (cond, mutex, a
 	  goto timeout;
 	}

+      unsigned int futex_val = cond->__data.__futex;
+
       /* Prepare to wait.  Release the condvar futex.  */
       lll_mutex_unlock (cond->__data.__lock);

       /* Enable asynchronous cancellation.  Required by the standard.  */
       cbuffer.oldtype = __pthread_enable_asynccancel ();

-      /* Wait until woken by signal or broadcast.  Note that we
-	 truncate the 'val' value to 32 bits.  */
-      err = lll_futex_timed_wait (futex, (unsigned int) val, &rt);
+      /* Wait until woken by signal or broadcast.  */
+      err = lll_futex_timed_wait (&cond->__data.__futex,
+				  futex_val, &rt);

       /* Disable asynchronous cancellation.  */
       __pthread_disable_asynccancel (cbuffer.oldtype);
--- libc/nptl/sysdeps/pthread/pthread_cond_wait.c	2004-05-19 22:58:46.552648579 +0200
+++ libc/nptl/sysdeps/pthread/pthread_cond_wait.c	2004-05-18 15:10:07.000000000 +0200
@@ -52,20 +52,14 @@ __condvar_cleanup (void *arg)
 	 appropriately.  */
       ++cbuffer->cond->__data.__wakeup_seq;
       ++cbuffer->cond->__data.__woken_seq;
+      ++cbuffer->cond->__data.__futex;
     }

   /* We are done.  */
   lll_mutex_unlock (cbuffer->cond->__data.__lock);

   /* Wake everybody to make sure no condvar signal gets lost.  */
-#if BYTE_ORDER == LITTLE_ENDIAN
-  int *futex = ((int *) (&cbuffer->cond->__data.__wakeup_seq));
-#elif BYTE_ORDER == BIG_ENDIAN
-  int *futex = ((int *) (&cbuffer->cond->__data.__wakeup_seq)) + 1;
-#else
-# error "No valid byte order"
-#endif
-  lll_futex_wake (futex, INT_MAX);
+  lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX);

   /* Get the mutex before returning unless asynchronous cancellation
      is in effect.  */
@@ -95,6 +89,7 @@ __pthread_cond_wait (cond, mutex)

   /* We have one new user of the condvar.  */
   ++cond->__data.__total_seq;
+  ++cond->__data.__futex;

   /* Remember the mutex we are using here.  If there is already a
      different address store this is a bad user bug.  Do not store
@@ -118,27 +113,18 @@ __pthread_cond_wait (cond, mutex)
   /* Remember the broadcast counter.  */
   cbuffer.bc_seq = cond->__data.__broadcast_seq;

-  /* The futex syscall operates on a 32-bit word.  That is fine, we
-     just use the low 32 bits of the sequence counter.  */
-#if BYTE_ORDER == LITTLE_ENDIAN
-  int *futex = ((int *) (&cond->__data.__wakeup_seq));
-#elif BYTE_ORDER == BIG_ENDIAN
-  int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1;
-#else
-# error "No valid byte order"
-#endif
-
   do
     {
+      unsigned int futex_val = cond->__data.__futex;
+
       /* Prepare to wait.  Release the condvar futex.  */
       lll_mutex_unlock (cond->__data.__lock);

       /* Enable asynchronous cancellation.  Required by the standard.  */
       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);
+      /* Wait until woken by signal or broadcast.  */
+      lll_futex_wait (&cond->__data.__futex, futex_val);

       /* Disable asynchronous cancellation.  */
       __pthread_disable_asynccancel (cbuffer.oldtype);
--- libc/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h	2004-05-19
22:58:46.609638366 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h	2004-05-18
14:44:38.000000000 +0200
@@ -76,11 +76,12 @@ typedef union
   struct
   {
     int __lock;
-    int __clock;
+    unsigned int __futex;
     unsigned long long int __total_seq;
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    int __clock;
     unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
--- libc/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h	2004-03-24 12:16:58.000000000 +0100
+++ libc/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h	2004-05-18 15:13:18.000000000 +0200
@@ -30,6 +30,7 @@
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
+#define FUTEX_CMP_REQUEUE	4

 /* Initializer for compatibility lock.	*/
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
@@ -61,14 +62,15 @@
     INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret;		      \
   })

-#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex) \
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \
   ({									      \
     INTERNAL_SYSCALL_DECL (__err);					      \
     long int __ret;							      \
-    __ret = INTERNAL_SYSCALL (futex, __err, 5,				      \
-			      (futexp), FUTEX_REQUEUE, (nr_wake), (nr_move),  \
-			      (mutex));					      \
-    INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret;		      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6,				      \
+			      (futexp), FUTEX_CMP_REQUEUE, (nr_wake),	      \
+			      (nr_move), (mutex), (val));		      \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \
   })

 
--- libc/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h	2004-05-19 22:58:46.610638187 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h	2004-05-18 14:43:22.000000000 +0200
@@ -76,11 +76,12 @@ typedef union
   struct
   {
     int __lock;
-    int __clock;
+    unsigned int __futex;
     unsigned long long int __total_seq;
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    int __clock;
     unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S	2004-05-19
22:58:46.611638008 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S	2004-05-18
14:43:22.000000000 +0200
@@ -32,6 +32,7 @@
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
+#define FUTEX_CMP_REQUEUE	4

 #define EINVAL			22

@@ -47,8 +48,9 @@ __pthread_cond_broadcast:
 	pushl	%ebx
 	pushl	%esi
 	pushl	%edi
+	pushl	%ebp

-	movl	16(%esp), %ebx
+	movl	20(%esp), %ebx

 	/* Get internal lock.  */
 	movl	$1, %edx
@@ -61,29 +63,31 @@ __pthread_cond_broadcast:
 #endif
 	jnz	1f

-2:	addl	$wakeup_seq, %ebx
-	movl	total_seq+4-wakeup_seq(%ebx), %eax
-	movl	total_seq-wakeup_seq(%ebx), %ecx
-	cmpl	4(%ebx), %eax
+2:	addl	$cond_futex, %ebx
+	movl	total_seq+4-cond_futex(%ebx), %eax
+	movl	total_seq-cond_futex(%ebx), %ebp
+	cmpl	wakeup_seq+4-cond_futex(%ebx), %eax
 	ja	3f
 	jb	4f
-	cmpl	(%ebx), %ecx
+	cmpl	wakeup_seq-cond_futex(%ebx), %ebp
 	jna	4f

 	/* Cause all currently waiting threads to recognize they are
 	   woken up.  */
-3:	movl	%ecx, (%ebx)
-	movl	%eax, 4(%ebx)
-	movl	%ecx, woken_seq-wakeup_seq(%ebx)
-	movl	%eax, woken_seq-wakeup_seq+4(%ebx)
-	addl	$1, broadcast_seq-wakeup_seq(%ebx)
+3:	movl	%ebp, wakeup_seq-cond_futex(%ebx)
+	movl	%eax, wakeup_seq-cond_futex+4(%ebx)
+	movl	%ebp, woken_seq-cond_futex(%ebx)
+	movl	%eax, woken_seq-cond_futex+4(%ebx)
+	addl	%ebp, %ebp
+	addl	$1, broadcast_seq-cond_futex(%ebx)
+	movl	%ebp, (%ebx)

 	/* Get the address of the mutex used.  */
-	movl	dep_mutex-wakeup_seq(%ebx), %edi
+	movl	dep_mutex-cond_futex(%ebx), %edi

 	/* Unlock.  */
 	LOCK
-	subl	$1, cond_lock-wakeup_seq(%ebx)
+	subl	$1, cond_lock-cond_futex(%ebx)
 	jne	7f

 	/* Don't use requeue for pshared condvars.  */
@@ -91,7 +95,7 @@ __pthread_cond_broadcast:
 	je	9f

 	/* Wake up all threads.  */
-	movl	$FUTEX_REQUEUE, %ecx
+	movl	$FUTEX_CMP_REQUEUE, %ecx
 	movl	$SYS_futex, %eax
 	movl	$0x7fffffff, %esi
 	movl	$1, %edx
@@ -99,14 +103,18 @@ __pthread_cond_broadcast:
 # if MUTEX_FUTEX != 0
 	addl	$MUTEX_FUTEX, %edi
 # endif
-	ENTER_KERNEL
-
-#ifndef __ASSUME_FUTEX_REQUEUE
-	cmpl	$-EINVAL, %eax
-	je	9f
-#endif
+/* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter.
+	ENTER_KERNEL  */
+	int	$0x80
+
+	/* For any kind of error, which mainly is EAGAIN, we try again
+	   with WAKE.  The general test also covers running on old
+	   kernels.  */
+	cmpl	$0xfffff001, %eax
+	jae	9f

 10:	xorl	%eax, %eax
+	popl	%ebp
 	popl	%edi
 	popl	%esi
 	popl	%ebx
@@ -115,10 +123,11 @@ __pthread_cond_broadcast:
 	.align	16
 	/* Unlock.  */
 4:	LOCK
-	subl	$1, cond_lock-wakeup_seq(%ebx)
+	subl	$1, cond_lock-cond_futex(%ebx)
 	jne	5f

 6:	xorl	%eax, %eax
+	popl	%ebp
 	popl	%edi
 	popl	%esi
 	popl	%ebx
@@ -135,12 +144,12 @@ __pthread_cond_broadcast:
 	jmp	2b

 	/* Unlock in loop requires waekup.  */
-5:	leal	cond_lock-wakeup_seq(%ebx), %eax
+5:	leal	cond_lock-cond_futex(%ebx), %eax
 	call	__lll_mutex_unlock_wake
 	jmp	6b

 	/* Unlock in loop requires waekup.  */
-7:	leal	cond_lock-wakeup_seq(%ebx), %eax
+7:	leal	cond_lock-cond_futex(%ebx), %eax
 	call	__lll_mutex_unlock_wake
 	jmp	8b

--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S	2004-02-19
17:50:40.000000000 +0100
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S	2004-05-18
14:43:22.000000000 +0200
@@ -60,22 +60,23 @@ __pthread_cond_signal:
 #endif
 	jnz	1f

-2:	leal	wakeup_seq(%edi), %ebx
+2:	leal	cond_futex(%edi), %ebx
 	movl	total_seq+4(%edi), %eax
 	movl	total_seq(%edi), %ecx
-	cmpl	4(%ebx), %eax
+	cmpl	wakeup_seq+4(%edi), %eax
 #if cond_lock != 0
 	/* Must use leal to preserve the flags.  */
 	leal	cond_lock(%edi), %edi
 #endif
 	ja	3f
 	jb	4f
-	cmpl	(%ebx), %ecx
+	cmpl	wakeup_seq-cond_futex(%ebx), %ecx
 	jbe	4f

 	/* Bump the wakeup number.  */
-3:	addl	$1, (%ebx)
-	adcl	$0, 4(%ebx)
+3:	addl	$1, wakeup_seq-cond_futex(%ebx)
+	adcl	$0, wakeup_seq-cond_futex+4(%ebx)
+	addl	$1, (%ebx)

 	/* Wake up one thread.  */
 	movl	$FUTEX_WAKE, %ecx
--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S	2004-05-19
22:58:46.612637829 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S	2004-05-18
14:43:22.000000000 +0200
@@ -82,6 +82,7 @@ __pthread_cond_timedwait:

 	addl	$1, total_seq(%ebx)
 	adcl	$0, total_seq+4(%ebx)
+	addl	$1, cond_futex(%ebx)

 #define FRAME_SIZE 24
 	subl	$FRAME_SIZE, %esp
@@ -148,6 +149,8 @@ __pthread_cond_timedwait:
 21:	movl	%ecx, 4(%esp)
 	movl	%edx, 8(%esp)

+	movl	cond_futex(%ebx), %edi
+
 	/* Unlock.  */
 	LOCK
 #if cond_lock == 0
@@ -164,12 +167,12 @@ __pthread_cond_timedwait:
 	leal	4(%esp), %esi
 	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */
 	movl	%edi, %edx
-	addl	$wakeup_seq, %ebx
-.Ladd_wakeup:
+	addl	$cond_futex, %ebx
+.Ladd_cond_futex:
 	movl	$SYS_futex, %eax
 	ENTER_KERNEL
-	subl	$wakeup_seq, %ebx
-.Lsub_wakeup:
+	subl	$cond_futex, %ebx
+.Lsub_cond_futex:
 	movl	%eax, %esi

 	movl	(%esp), %eax
@@ -212,6 +215,7 @@ __pthread_cond_timedwait:

 	addl	$1, wakeup_seq(%ebx)
 	adcl	$0, wakeup_seq+4(%ebx)
+	addl	$1, cond_futex(%ebx)
 	movl	$ETIMEDOUT, %esi
 	jmp	14f

@@ -359,7 +363,7 @@ __condvar_tw_cleanup3:
 	.size	__condvar_tw_cleanup3, .-__condvar_tw_cleanup3
 	.type	__condvar_tw_cleanup2, @function
 __condvar_tw_cleanup2:
-	subl	$wakeup_seq, %ebx
+	subl	$cond_futex, %ebx
 	.size	__condvar_tw_cleanup2, .-__condvar_tw_cleanup2
 	.type	__condvar_tw_cleanup, @function
 __condvar_tw_cleanup:
@@ -390,6 +394,8 @@ __condvar_tw_cleanup:
 	addl	$1, wakeup_seq(%ebx)
 	adcl	$0, wakeup_seq+4(%ebx)

+	addl	$1, cond_futex(%ebx)
+
 	addl	$1, woken_seq(%ebx)
 	adcl	$0, woken_seq+4(%ebx)

@@ -409,7 +415,7 @@ __condvar_tw_cleanup:
 	call	__lll_mutex_unlock_wake

 	/* Wake up all waiters to make sure no signal gets lost.  */
-2:	addl	$wakeup_seq, %ebx
+2:	addl	$cond_futex, %ebx
 	movl	$FUTEX_WAKE, %ecx
 	movl	$SYS_futex, %eax
 	movl	$0x7fffffff, %edx
@@ -435,7 +441,7 @@ __condvar_tw_cleanup:
 	.uleb128 .Lcstend-.Lcstbegin
 .Lcstbegin:
 	.long	.LcleanupSTART-.LSTARTCODE
-	.long	.Ladd_wakeup-.LcleanupSTART
+	.long	.Ladd_cond_futex-.LcleanupSTART
 	.long	__condvar_tw_cleanup-.LSTARTCODE
 	.uleb128  0
 	.long	.LebxmovedUR-.LSTARTCODE
@@ -443,15 +449,15 @@ __condvar_tw_cleanup:
 	.long	__condvar_tw_cleanup3-.LSTARTCODE
 	.uleb128  0
 	.long	.LebxmovedUR-.LSTARTCODE
-	.long	.Ladd_wakeup-.LebxmovedUR
+	.long	.Ladd_cond_futex-.LebxmovedUR
 	.long	__condvar_tw_cleanup-.LSTARTCODE
 	.uleb128  0
-	.long	.Ladd_wakeup-.LSTARTCODE
-	.long	.Lsub_wakeup-.Ladd_wakeup
+	.long	.Ladd_cond_futex-.LSTARTCODE
+	.long	.Lsub_cond_futex-.Ladd_cond_futex
 	.long	__condvar_tw_cleanup2-.LSTARTCODE
 	.uleb128  0
-	.long	.Lsub_wakeup-.LSTARTCODE
-	.long	.LcleanupEND-.Lsub_wakeup
+	.long	.Lsub_cond_futex-.LSTARTCODE
+	.long	.LcleanupEND-.Lsub_cond_futex
 	.long	__condvar_tw_cleanup-.LSTARTCODE
 	.uleb128  0
 	.long	.LcallUR-.LSTARTCODE
--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S	2004-05-19
22:58:46.613637649 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S	2004-05-18
14:43:22.000000000 +0200
@@ -79,6 +79,7 @@ __pthread_cond_wait:

 	addl	$1, total_seq(%ebx)
 	adcl	$0, total_seq+4(%ebx)
+	addl	$1, cond_futex(%ebx)

 #define FRAME_SIZE 16
 	subl	$FRAME_SIZE, %esp
@@ -92,8 +93,10 @@ __pthread_cond_wait:
 	movl	%edx, 8(%esp)
 	movl	%eax, 12(%esp)

+8:	movl	cond_futex(%ebx), %edi
+
 	/* Unlock.  */
-8:	LOCK
+	LOCK
 #if cond_lock == 0
 	subl	$1, (%ebx)
 #else
@@ -107,12 +110,12 @@ __pthread_cond_wait:

 	movl	%esi, %ecx	/* movl $FUTEX_WAIT, %ecx */
 	movl	%edi, %edx
-	addl	$wakeup_seq, %ebx
-.Ladd_wakeup:
+	addl	$cond_futex, %ebx
+.Ladd_cond_futex:
 	movl	$SYS_futex, %eax
 	ENTER_KERNEL
-	subl	$wakeup_seq, %ebx
-.Lsub_wakeup:
+	subl	$cond_futex, %ebx
+.Lsub_cond_futex:

 	movl	(%esp), %eax
 	call	__pthread_disable_asynccancel
@@ -246,7 +249,7 @@ versioned_symbol (libpthread, __pthread_
 
 	.type	__condvar_w_cleanup2, @function
 __condvar_w_cleanup2:
-	subl	$wakeup_seq, %ebx
+	subl	$cond_futex, %ebx
 	.size	__condvar_w_cleanup2, .-__condvar_w_cleanup2
 .LSbl4:
 	.type	__condvar_w_cleanup, @function
@@ -278,6 +281,8 @@ __condvar_w_cleanup:
 	addl	$1, wakeup_seq(%ebx)
 	adcl	$0, wakeup_seq+4(%ebx)

+	addl	$1, cond_futex(%ebx)
+
 	addl	$1, woken_seq(%ebx)
 	adcl	$0, woken_seq+4(%ebx)

@@ -297,7 +302,7 @@ __condvar_w_cleanup:
 	call	__lll_mutex_unlock_wake

 	/* Wake up all waiters to make sure no signal gets lost.  */
-2:	addl	$wakeup_seq, %ebx
+2:	addl	$cond_futex, %ebx
 	movl	$FUTEX_WAKE, %ecx
 	movl	$SYS_futex, %eax
 	movl	$0x7fffffff, %edx
@@ -323,15 +328,15 @@ __condvar_w_cleanup:
 	.uleb128 .Lcstend-.Lcstbegin
 .Lcstbegin:
 	.long	.LcleanupSTART-.LSTARTCODE
-	.long	.Ladd_wakeup-.LcleanupSTART
+	.long	.Ladd_cond_futex-.LcleanupSTART
 	.long	__condvar_w_cleanup-.LSTARTCODE
 	.uleb128  0
-	.long	.Ladd_wakeup-.LSTARTCODE
-	.long	.Lsub_wakeup-.Ladd_wakeup
+	.long	.Ladd_cond_futex-.LSTARTCODE
+	.long	.Lsub_cond_futex-.Ladd_cond_futex
 	.long	__condvar_w_cleanup2-.LSTARTCODE
 	.uleb128  0
-	.long	.Lsub_wakeup-.LSTARTCODE
-	.long	.LcleanupEND-.Lsub_wakeup
+	.long	.Lsub_cond_futex-.LSTARTCODE
+	.long	.LcleanupEND-.Lsub_cond_futex
 	.long	__condvar_w_cleanup-.LSTARTCODE
 	.uleb128  0
 	.long	.LcallUR-.LSTARTCODE
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h	2004-05-19 22:58:46.614637470 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h	2004-05-18 14:46:13.000000000 +0200
@@ -76,11 +76,12 @@ typedef union
   struct
   {
     int __lock;
-    int __clock;
+    unsigned int __futex;
     unsigned long long int __total_seq;
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    int __clock;
     unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h	2004-03-24 12:16:59.000000000 +0100
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h	2004-05-18 15:27:23.000000000 +0200
@@ -30,6 +30,7 @@
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
+#define FUTEX_CMP_REQUEUE	4

 /* Delay in spinlock loop.  */
 #define BUSY_WAIT_NOP          asm ("hint @pause")
@@ -52,11 +53,13 @@
    _r10 == -1 ? -_retval : _retval;					\
 })

-#define lll_futex_requeue(ftx, nr_wake, nr_move, mutex)			     \
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_requeue(ftx, nr_wake, nr_move, mutex, val)		     \
 ({									     \
-   DO_INLINE_SYSCALL(futex, 5, (long) (ftx), FUTEX_REQUEUE, (int) (nr_wake), \
-		     (int) (nr_move), (long) (mutex));			     \
-   _r10 == -1 ? -_retval : _retval;					     \
+   DO_INLINE_SYSCALL(futex, 6, (long) (ftx), FUTEX_CMP_REQUEUE,		     \
+		     (int) (nr_wake), (int) (nr_move), (long) (mutex),	     \
+		     (int) val);					     \
+   _r10 == -1;								     \
 })

 
--- libc/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym	2004-05-19 22:58:46.588642129 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym	2004-05-18 14:43:22.000000000 +0200
@@ -4,6 +4,7 @@
 --

 cond_lock	offsetof (pthread_cond_t, __data.__lock)
+cond_futex	offsetof (pthread_cond_t, __data.__futex)
 cond_clock	offsetof (pthread_cond_t, __data.__clock)
 total_seq	offsetof (pthread_cond_t, __data.__total_seq)
 wakeup_seq	offsetof (pthread_cond_t, __data.__wakeup_seq)
--- libc/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h	2004-05-19
22:58:46.623635858 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h	2004-05-18
14:45:21.000000000 +0200
@@ -96,11 +96,12 @@ typedef union
   struct
   {
     int __lock;
-    int __clock;
+    unsigned int __futex;
     unsigned long long int __total_seq;
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    int __clock;
     unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
--- libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h	2004-04-13 10:42:53.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h	2004-05-18 15:19:01.000000000 +0200
@@ -30,6 +30,7 @@
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
+#define FUTEX_CMP_REQUEUE	4

 /* Initializer for compatibility lock.	*/
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
@@ -64,15 +65,16 @@
     INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret;		      \
   })

-#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex) \
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \
   ({									      \
     INTERNAL_SYSCALL_DECL (__err);					      \
     long int __ret;							      \
 									      \
-    __ret = INTERNAL_SYSCALL (futex, __err, 5,				      \
-			      (futexp), FUTEX_REQUEUE, (nr_wake), (nr_move),  \
-			      (mutex));					      \
-    INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret;		      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6,				      \
+			      (futexp), FUTEX_CMP_REQUEUE, (nr_wake),	      \
+			      (nr_move), (mutex), (val));		      \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \
   })

 #ifdef UP
--- libc/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h	2004-05-19 22:58:46.628634962 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h	2004-05-18 14:44:56.000000000 +0200
@@ -95,11 +95,12 @@ typedef union
   struct
   {
     int __lock;
-    int __clock;
+    unsigned int __futex;
     unsigned long long int __total_seq;
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    int __clock;
     unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
--- libc/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h	2004-03-24 12:17:00.000000000 +0100
+++ libc/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h	2004-05-18 15:16:44.000000000 +0200
@@ -29,6 +29,7 @@
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
+#define FUTEX_CMP_REQUEUE	4

 /* Initializer for compatibility lock.	*/
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
@@ -82,22 +83,29 @@
   })

 
-#define lll_futex_requeue(futex, nr_wake, nr_move, mutex) \
+/* Returns non-zero if error happened, zero if success.  */
+#if 0
+/* FIXME: s390 only supports up to 5 argument syscalls.  Once FUTEX_CMP_REQUEUE
+   kernel interface for s390 is finalized, adjust this.  */
+#define lll_futex_requeue(futex, nr_wake, nr_move, mutex, val) \
   ({									      \
-     register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \
-     register unsigned long int __r3 asm ("3") = FUTEX_REQUEUE;		      \
-     register unsigned long int __r4 asm ("4") = (long int) (nr_wake);	      \
-     register unsigned long int __r5 asm ("5") = (long int) (nr_move);	      \
-     register unsigned long int __r6 asm ("6") = (unsigned long int) (mutex); \
-     register unsigned long __result asm ("2");				      \
+    register unsigned long int __r2 asm ("2") = (unsigned long int) (futex);  \
+    register unsigned long int __r3 asm ("3") = FUTEX_CMP_REQUEUE;	      \
+    register unsigned long int __r4 asm ("4") = (long int) (nr_wake);	      \
+    register unsigned long int __r5 asm ("5") = (long int) (nr_move);	      \
+    register unsigned long int __r6 asm ("6") = (unsigned long int) (mutex);  \
+    register unsigned long __result asm ("2");				      \
 									      \
     __asm __volatile ("svc %b1"						      \
 		      : "=d" (__result)					      \
 		      : "i" (SYS_futex), "0" (__r2), "d" (__r3),	      \
 			"d" (__r4), "d" (__r5), "d" (__r6)		      \
 		      : "cc", "memory" );				      \
-    __result;								      \
+    __result > -4096UL;							      \
   })
+#else
+#define lll_futex_requeue(futex, nr_wake, nr_move, mutex, val) 1
+#endif

 
 #define lll_compare_and_swap(futex, oldval, newval, operation) \
--- libc/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h	2004-05-19
22:58:46.637633349 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h	2004-05-18
14:45:41.000000000 +0200
@@ -96,11 +96,12 @@ typedef union
   struct
   {
     int __lock;
-    int __clock;
+    unsigned int __futex;
     unsigned long long int __total_seq;
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    int __clock;
     unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
--- libc/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h	2004-03-24 12:17:00.000000000 +0100
+++ libc/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h	2004-05-18 15:21:43.000000000 +0200
@@ -29,6 +29,7 @@
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
+#define FUTEX_CMP_REQUEUE	4

 /* Initializer for compatibility lock.	*/
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
@@ -63,15 +64,16 @@
     __ret;								      \
   })

-#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex) \
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \
   ({									      \
     INTERNAL_SYSCALL_DECL (__err);					      \
     long int __ret;							      \
 									      \
-    __ret = INTERNAL_SYSCALL (futex, __err, 5,				      \
-			      (futexp), FUTEX_REQUEUE, (nr_wake), (nr_move),  \
-			      (mutex));					      \
-    __ret;								      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6,				      \
+			      (futexp), FUTEX_CMP_REQUEUE, (nr_wake),	      \
+			      (nr_move), (mutex), (val));		      \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \
   })

 #ifdef __sparc32_atomic_do_lock
--- libc/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h	2004-05-19
22:58:46.739615073 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h	2004-05-18
14:46:25.000000000 +0200
@@ -76,11 +76,12 @@ typedef union
   struct
   {
     int __lock;
-    int __clock;
+    unsigned int __futex;
     unsigned long long int __total_seq;
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    int __clock;
     unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
--- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S	2004-05-19
22:58:46.651630841 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S	2004-05-18
17:35:15.000000000 +0200
@@ -32,6 +32,7 @@
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
+#define FUTEX_CMP_REQUEUE	4

 #define EINVAL			22

@@ -55,39 +56,42 @@ __pthread_cond_broadcast:
 #endif
 	jnz	1f

-2:	addq	$wakeup_seq, %rdi
-	movq	total_seq-wakeup_seq(%rdi), %rcx
-	cmpq	(%rdi), %rcx
+2:	addq	$cond_futex, %rdi
+	movq	total_seq-cond_futex(%rdi), %r9
+	cmpq	wakeup_seq-cond_futex(%rdi), %r9
 	jna	4f

 	/* Cause all currently waiting threads to recognize they are
 	   woken up.  */
-	movq	%rcx, (%rdi)
-	movq	%rcx, woken_seq-wakeup_seq(%rdi)
-	incl	broadcast_seq-wakeup_seq(%rdi)
+	movq	%r9, wakeup_seq-cond_futex(%rdi)
+	movq	%r9, woken_seq-cond_futex(%rdi)
+	addq	%r9, %r9
+	movl	%r9d, (%rdi)
+	incl	broadcast_seq-cond_futex(%rdi)

 	/* Get the address of the mutex used.  */
-	movq	dep_mutex-wakeup_seq(%rdi), %r8
+	movq	dep_mutex-cond_futex(%rdi), %r8

 	/* Unlock.  */
 	LOCK
-	decl	cond_lock-wakeup_seq(%rdi)
+	decl	cond_lock-cond_futex(%rdi)
 	jne	7f

 8:	cmpq	$-1, %r8
 	je	9f

 	/* Wake up all threads.  */
-	movq	$FUTEX_REQUEUE, %rsi
+	movq	$FUTEX_CMP_REQUEUE, %rsi
 	movq	$SYS_futex, %rax
 	movl	$1, %edx
 	movq	$0x7fffffff, %r10
 	syscall

-#ifndef __ASSUME_FUTEX_REQUEUE
-	cmpq	$-EINVAL, %rax
-	je	9f
-#endif
+	/* For any kind of error, which mainly is EAGAIN, we try again
+	   with WAKE.  The general test also covers running on old
+	   kernels.  */
+	cmpq	$-4095, %rax
+	jae	9f

 10:	xorl	%eax, %eax
 	retq
@@ -95,7 +99,7 @@ __pthread_cond_broadcast:
 	.align	16
 	/* Unlock.  */
 4:	LOCK
-	decl	cond_lock-wakeup_seq(%rdi)
+	decl	cond_lock-cond_futex(%rdi)
 	jne	5f

 6:	xorl	%eax, %eax
@@ -113,14 +117,14 @@ __pthread_cond_broadcast:
 	jmp	2b

 	/* Unlock in loop requires wakeup.  */
-5:	addq	$cond_lock-wakeup_seq, %rdi
+5:	addq	$cond_lock-cond_futex, %rdi
 	callq	__lll_mutex_unlock_wake
 	jmp	6b

 	/* Unlock in loop requires wakeup.  */
-7:	addq	$cond_lock-wakeup_seq, %rdi
+7:	addq	$cond_lock-cond_futex, %rdi
 	callq	__lll_mutex_unlock_wake
-	subq	$cond_lock-wakeup_seq, %rdi
+	subq	$cond_lock-cond_futex, %rdi
 	jmp	8b

 9:	/* The futex requeue functionality is not available.  */
--- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S	2003-09-22
06:40:38.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S	2004-05-18
16:26:43.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper <at> redhat.com>, 2002.

@@ -56,13 +56,14 @@ __pthread_cond_signal:
 #endif
 	jnz	1f

-2:	addq	$wakeup_seq, %rdi
+2:	addq	$cond_futex, %rdi
 	movq	total_seq(%r8), %rcx
-	cmpq	(%rdi), %rcx
+	cmpq	wakeup_seq(%r8), %rcx
 	jbe	4f

 	/* Bump the wakeup number.  */
-	addq	$1, (%rdi)
+	addq	$1, wakeup_seq(%r8)
+	addl	$1, (%rdi)

 	/* Wake up one thread.  */
 	movq	$FUTEX_WAKE, %rsi
@@ -95,11 +96,7 @@ __pthread_cond_signal:

 	/* Unlock in loop requires wakeup.  */
 5:
-#if cond_lock != 0
-	addq	$cond_lock-wakeup_seq, %rdi
-#else
 	movq	%r8, %rdi
-#endif
 	callq	__lll_mutex_unlock_wake
 	jmp	6b
 	.size	__pthread_cond_signal, .-__pthread_cond_signal
--- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S	2004-05-19
22:58:46.652630661 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S	2004-05-18
16:18:52.000000000 +0200
@@ -105,6 +105,7 @@ __pthread_cond_timedwait:

 	movq	8(%rsp), %rdi
 	incq	total_seq(%rdi)
+	incl	cond_futex(%rdi)

 	/* Install cancellation handler.  */
 #ifdef PIC
@@ -118,9 +119,9 @@ __pthread_cond_timedwait:

 	/* Get and store current wakeup_seq value.  */
 	movq	8(%rsp), %rdi
-	movq	wakeup_seq(%rdi), %r12
+	movq	wakeup_seq(%rdi), %r9
 	movl	broadcast_seq(%rdi), %edx
-	movq	%r12, 40(%rsp)
+	movq	%r9, 40(%rsp)
 	movl	%edx, 4(%rsp)

 	/* Get the current time.  */
@@ -172,6 +173,8 @@ __pthread_cond_timedwait:
 21:	movq	%rcx, 24(%rsp)
 	movq	%rdx, 32(%rsp)

+	movl	cond_futex(%rdi), %r12d
+
 	/* Unlock.  */
 	LOCK
 #if cond_lock == 0
@@ -187,7 +190,7 @@ __pthread_cond_timedwait:
 	leaq	24(%rsp), %r10
 	xorq	%rsi, %rsi	/* movq $FUTEX_WAIT, %rsi */
 	movq	%r12, %rdx
-	addq	$wakeup_seq-cond_lock, %rdi
+	addq	$cond_futex, %rdi
 	movq	$SYS_futex, %rax
 	syscall
 	movq	%rax, %r14
@@ -211,21 +214,22 @@ __pthread_cond_timedwait:

 	movq	woken_seq(%rdi), %rax

-	movq	wakeup_seq(%rdi), %r12
+	movq	wakeup_seq(%rdi), %r9

 	cmpl	4(%rsp), %edx
 	jne	23f

-	cmpq	40(%rsp), %r12
+	cmpq	40(%rsp), %r9
 	jbe	15f

-	cmpq	%rax, %r12
+	cmpq	%rax, %r9
 	ja	9f

 15:	cmpq	$-ETIMEDOUT, %r14
 	jne	8b

 13:	incq	wakeup_seq(%rdi)
+	incl	cond_futex(%rdi)
 	movq	$ETIMEDOUT, %r14
 	jmp	14f

--- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S	2004-05-19
22:58:46.739615073 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S	2004-05-18
17:47:31.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper <at> redhat.com>, 2002.

@@ -69,6 +69,8 @@ __condvar_cleanup:

 	incq	woken_seq(%rdi)

+	incl	cond_futex(%rdi)
+
 3:	LOCK
 #if cond_lock == 0
 	decl	(%rdi)
@@ -82,7 +84,7 @@ __condvar_cleanup:
 	callq	__lll_mutex_unlock_wake

 	/* Wake up all waiters to make sure no signal gets lost.  */
-2:	addq	$wakeup_seq, %rdi
+2:	addq	$cond_futex, %rdi
 	movq	$FUTEX_WAKE, %rsi
 	movl	$0x7fffffff, %edx
 	movq	$SYS_futex, %rax
@@ -154,6 +156,7 @@ __pthread_cond_wait:

 	movq	8(%rsp), %rdi
 	incq	total_seq(%rdi)
+	incl	cond_futex(%rdi)

 	/* Install cancellation handler.  */
 #ifdef PIC
@@ -167,13 +170,14 @@ __pthread_cond_wait:

 	/* Get and store current wakeup_seq value.  */
 	movq	8(%rsp), %rdi
-	movq	wakeup_seq(%rdi), %r12
+	movq	wakeup_seq(%rdi), %r9
 	movl	broadcast_seq(%rdi), %edx
-	movq	%r12, 24(%rsp)
+	movq	%r9, 24(%rsp)
 	movl	%edx, 4(%rsp)

 	/* Unlock.  */
-8:	LOCK
+8:	movl	cond_futex(%rdi), %r12d
+	LOCK
 #if cond_lock == 0
 	decl	(%rdi)
 #else
@@ -187,7 +191,7 @@ __pthread_cond_wait:
 	movq	8(%rsp), %rdi
 	xorq	%r10, %r10
 	movq	%r12, %rdx
-	addq	$wakeup_seq-cond_lock, %rdi
+	addq	$cond_futex-cond_lock, %rdi
 	movq	$SYS_futex, %rax
 	movq	%r10, %rsi	/* movq $FUTEX_WAIT, %rsi */
 	syscall
@@ -211,15 +215,15 @@ __pthread_cond_wait:

 	movq	woken_seq(%rdi), %rax

-	movq	wakeup_seq(%rdi), %r12
+	movq	wakeup_seq(%rdi), %r9

 	cmpl	4(%rsp), %edx
 	jne	16f

-	cmpq	24(%rsp), %r12
+	cmpq	24(%rsp), %r9
 	jbe	8b

-	cmpq	%rax, %r12
+	cmpq	%rax, %r9
 	jna	8b

 	incq	woken_seq(%rdi)
@@ -359,8 +363,8 @@ versioned_symbol (libpthread, __pthread_
 	.byte	0x40+.Lsubq-.Lpush_r12		# DW_CFA_advance_loc+N
 	.byte	14				# DW_CFA_def_cfa_offset
 	.uleb128 16+FRAME_SIZE
-	.byte	2				# DW_CFA_advance_loc1
-	.byte	.Laddq-.Lsubq
+	.byte	3				# DW_CFA_advance_loc2
+	.2byte	.Laddq-.Lsubq
 	.byte	14				# DW_CFA_def_cfa_offset
 	.uleb128 16
 	.byte	0x40+.Lpop_r12-.Laddq		# DW_CFA_advance_loc+N

	Jakub

Jakub Jelinek | 20 May 11:01
Picon
Favicon

[PATCH] tst-cond16 fix - kernel part

Hi!

This is the kernel part of tst-cond16 fix.

--- linux-2.6.5/include/linux/futex.h.jj	2004-04-04 05:37:36.000000000 +0200
+++ linux-2.6.5/include/linux/futex.h	2004-05-05 09:57:09.200306101 +0200
@@ -8,9 +8,10 @@
 #define FUTEX_WAKE (1)
 #define FUTEX_FD (2)
 #define FUTEX_REQUEUE (3)
-
+#define FUTEX_CMP_REQUEUE (4)

 long do_futex(unsigned long uaddr, int op, int val,
-		unsigned long timeout, unsigned long uaddr2, int val2);
+		unsigned long timeout, unsigned long uaddr2, int val2,
+		int val3);

 #endif
--- linux-2.6.5/kernel/futex.c.jj	2004-04-04 05:36:52.000000000 +0200
+++ linux-2.6.5/kernel/futex.c	2004-05-05 12:23:33.481048623 +0200
@@ -96,6 +96,7 @@ struct futex_q {
  */
 struct futex_hash_bucket {
        spinlock_t              lock;
+       unsigned int	    nqueued;
        struct list_head       chain;
 };

@@ -318,13 +319,14 @@ out:
  * physical page.
  */
 static int futex_requeue(unsigned long uaddr1, unsigned long uaddr2,
-				int nr_wake, int nr_requeue)
+			 int nr_wake, int nr_requeue, int *valp)
 {
 	union futex_key key1, key2;
 	struct futex_hash_bucket *bh1, *bh2;
 	struct list_head *head1;
 	struct futex_q *this, *next;
 	int ret, drop_count = 0;
+	unsigned int nqueued;

 	down_read(&current->mm->mmap_sem);

@@ -338,12 +340,33 @@ static int futex_requeue(unsigned long u
 	bh1 = hash_futex(&key1);
 	bh2 = hash_futex(&key2);

+	nqueued = bh1->nqueued;
+	if (likely (valp != NULL)) {
+		int curval;
+
+		smp_mb ();
+
+		if (get_user(curval, (int *)uaddr1) != 0) {
+			ret = -EFAULT;
+			goto out;
+		}
+		if (curval != *valp) {
+			ret = -EAGAIN;
+			goto out;
+		}
+	}
+
 	if (bh1 < bh2)
 		spin_lock(&bh1->lock);
 	spin_lock(&bh2->lock);
 	if (bh1 > bh2)
 		spin_lock(&bh1->lock);

+	if (unlikely (nqueued != bh1->nqueued && valp != NULL)) {
+		ret = -EAGAIN;
+		goto out_unlock;
+	}
+
 	head1 = &bh1->chain;
 	list_for_each_entry_safe(this, next, head1, list) {
 		if (!match_futex (&this->key, &key1))
@@ -365,6 +388,7 @@ static int futex_requeue(unsigned long u
 		}
 	}

+out_unlock:
 	spin_unlock(&bh1->lock);
 	if (bh1 != bh2)
 		spin_unlock(&bh2->lock);
@@ -398,6 +422,7 @@ static void queue_me(struct futex_q *q, 
 	q->lock_ptr = &bh->lock;

 	spin_lock(&bh->lock);
+	bh->nqueued++;
 	list_add_tail(&q->list, &bh->chain);
 	spin_unlock(&bh->lock);
 }
@@ -625,7 +650,7 @@ out:
 }

 long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout,
-		unsigned long uaddr2, int val2)
+		unsigned long uaddr2, int val2, int val3)
 {
 	int ret;

@@ -641,7 +666,10 @@ long do_futex(unsigned long uaddr, int o
 		ret = futex_fd(uaddr, val);
 		break;
 	case FUTEX_REQUEUE:
-		ret = futex_requeue(uaddr, uaddr2, val, val2);
+		ret = futex_requeue(uaddr, uaddr2, val, val2, NULL);
+		break;
+	case FUTEX_CMP_REQUEUE:
+		ret = futex_requeue(uaddr, uaddr2, val, val2, &val3);
 		break;
 	default:
 		ret = -ENOSYS;
@@ -651,7 +679,8 @@ long do_futex(unsigned long uaddr, int o

 
 asmlinkage long sys_futex(u32 __user *uaddr, int op, int val,
-			  struct timespec __user *utime, u32 __user *uaddr2)
+			  struct timespec __user *utime, u32 __user *uaddr2,
+			  int val3)
 {
 	struct timespec t;
 	unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
@@ -665,11 +694,11 @@ asmlinkage long sys_futex(u32 __user *ua
 	/*
 	 * requeue parameter in 'utime' if op == FUTEX_REQUEUE.
 	 */
-	if (op == FUTEX_REQUEUE)
+	if (op >= FUTEX_REQUEUE)
 		val2 = (int) (long) utime;

 	return do_futex((unsigned long)uaddr, op, val, timeout,
-			(unsigned long)uaddr2, val2);
+			(unsigned long)uaddr2, val2, val3);
 }

 static struct super_block *
--- linux-2.6.5/kernel/compat.c.jj	2004-04-04 05:37:07.000000000 +0200
+++ linux-2.6.5/kernel/compat.c	2004-05-05 09:56:36.761119626 +0200
@@ -208,7 +208,7 @@ asmlinkage long compat_sys_sigprocmask(i

 #ifdef CONFIG_FUTEX
 asmlinkage long compat_sys_futex(u32 *uaddr, int op, int val,
-		struct compat_timespec *utime, u32 *uaddr2)
+		struct compat_timespec *utime, u32 *uaddr2, int val3)
 {
 	struct timespec t;
 	unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
@@ -219,11 +219,11 @@ asmlinkage long compat_sys_futex(u32 *ua
 			return -EFAULT;
 		timeout = timespec_to_jiffies(&t) + 1;
 	}
-	if (op == FUTEX_REQUEUE)
+	if (op >= FUTEX_REQUEUE)
 		val2 = (int) (long) utime;

 	return do_futex((unsigned long)uaddr, op, val, timeout,
-			(unsigned long)uaddr2, val2);
+			(unsigned long)uaddr2, val2, val3);
 }
 #endif

	Jakub

Jakub Jelinek | 20 May 10:58
Picon
Favicon

tst-cond16 hang analysis

Hi!

This is posted mainly for archival purposes.
It describes what happens with NPTL CVS as of 2004-05-19 (i.e. after
broadcast_seq has been added; the analysis would be slightly different
before broadcast_seq has been introduced, but the hang has been there
as well (simply remove the b column, ", bc_seq = N" assignments,
++broadcast_seq line and bc_seq == broadcast_seq comparison).

thr1	thr2	thr3
pthread_mutex_lock (&m);
pthread_cond_wait (&c, &m);
	pthread_mutex_lock (&m);
	pthread_mutex_unlock (&m);
	pthread_cond_broadcast (&c);
		pthread_mutex_lock (&m);
		pthread_cond_wait (&c);
	pthread_mutex_lock &m);
	pthread_cond_wait (&c, &m);
[ hang ]
# Normally following would happen afterwards:
pthread_mutex_unlock (&m);
pthread_mutex_lock (&m);
pthread_mutex_unlock (&m);
pthread_cond_broadcast (&c);
and the waiters would be awaken.

Detailed:
taob	thread	action
0000	1	locks m
0000	1	enters cond_wait
0000	1	locks c->__data.__lock
0000	1	unlocks m
1000	1	++total_seq, thr1's seq = 0, bc_seq = 0
1000	1	unlocks c->__data.__lock
1000	2	locks m
1000	2	unlocks m
1000	2	enters cond_broadcast
1000	2	locks c->__data.__lock
1110	2	wakeup_seq = woken_seq = total_seq
1111	2	++broadcast_seq
1111	2	unlocks c->__data.__lock
1111	3	locks m
1111	3	enters cond_wait
1111	3	locks c->__data.__lock
1111	3	unlocks m
2111	3	++total_seq, thr3's seq = 1, bc_seq = 1
2111	3	unlocks c->__data.__lock
2111	3	futex_wait (&wakeup_seq)
2111	1	futex_wait (&wakeup_seq)
2111	2	futex_requeue
[ thr3 awaken, thr1 requeued to mutex ]
2111	3	locks c->__data.__lock
2111	3	bc_seq (1) == broadcast_seq, no early exit
2111	3	val = 1; val == seq (1), val (1) == woken_seq (1), therefore loop
2111	3	unlocks c->__data.__lock
2111	3	futex_wait (&wakeup_seq)
2111	2	locks m
[ note, m->__data.__lock went from 0 to 1 ]
2111	2	enters cond_wait
2111	2	locks c->__data.__lock
2111	2	unlocks m
[ note, m->__data.__lock went from 1 to 0, so thr1 has not been awaken ]
3111	2	++total_seq, thr1's seq = 1, bc_seq = 1
3111	2	unlocks c->__data.__lock
3111	1	futex_wait (&wakeup_seq)
[ hang ]

Legend:
taob	total_seq/wakeup_seq/woken_seq/broadcast_seq

	Jakub

Jakub Jelinek | 20 May 10:53
Picon
Favicon

tst-cond18 hang analysis

Hi!

This is posted mainly for archival purposes.
It documents a nptl/tst-cond18.c hang with NPTL CVS as of 2004-05-16.

This ought to be fixed in current CVS (after the 2004-05-18 CVS
commits to nptl/) by introducing broadcast_seq.

thr1    thr2    thr3    thr4    thr5    thr6
pthread_mutex_lock (&m);
pthread_cond_wait (&c, &m);
        pthread_mutex_lock (&m);
        pthread_cond_wait (&c, &m);
                pthread_mutex_lock (&m);
                        pthread_mutex_lock (&m);
                                pthread_mutex_lock (&m);
                                        pthread_mutex_lock (&m);
                pthread_cond_broadcast (&c);
                pthread_mutex_unlock (&m);
                        pthread_cond_wait (&c, &m);
                                pthread_cond_wait (&c, &m);
                                        pthread_cond_signal (&c);
                                        pthread_mutex_unlock (&m);
                pthread_mutex_lock (&m);
                                        pthread_mutex_lock (&m);
[hang]

Detailed:
tao	thread	action
000	1	locks m
000	1	enters cond_wait
000	1	locks c->__data.__lock
000	1	unlocks m
100	1	++total_seq, thr1's seq = 0
100	1	unlocks c->__data.__lock
100	1	futex_wait (&wakeup_seq)
100	2	locks m
100	2	enters cond_wait
100	2	locks c->__data.__lock
100	2	unlocks m
200	2	++total_seq, thr2's seq = 0
200	2	unlocks c->__data.__lock
200	2	futex_wait (&wakeup_seq)
200	3	locks m
200	4	attempts to lock m
200	4	futex_wait (&m->__data.__lock)
200	5	attempts to lock m
200	5	futex_wait (&m->__data.__lock)
200	6	attempts to lock m
200	6	futex_wait (&m->__data.__lock)
200	3	enters cond_broadcast
200	3	locks c->__data.__lock
220	3	wakeup_seq = total_seq
220	3	unlocks c->__data.__lock
220	3	futex_requeue (&wakeup_seq)
[ thr1 awaken, thr2 requeued to mutex ]
220	3	leaves cond_broadcast
220	1	locks c->__data.__lock
220	1	val = 2; val != seq (0) && val != woken_seq (0), no looping
221	1	++woken_seq
221	1	unlocks c->__data.__lock
221	1	attempts to lock m
221	1	futex_wait (&m->__data.__lock)
221	3	unlocks m
221	3	futex_wake (&m->__data.__lock)
[ thr4 awaken ]
221	4	enters cond_wait
221	4	locks c->__data.__lock
221	4	unlocks m
221	4	futex_wake (&m->__data.__lock)
[ thr5 awaken ]
321	4	++total_seq, thr4's seq = 2
321	4	unlocks c->__data.__lock
321	5	enters cond_wait
321	5	locks c->__data.__lock
321	5	unlocks m
321	5	futex_wake (&m->__data.__lock)
[ thr6 awaken ]
421	5	++total_seq, thr5's seq = 2
421	5	unlocks c->__data.__lock
421	6	enters cond_broadcast
421	6	locks c->__data.__lock
431	6	++wakeup_seq
431	6	futex_wake (&wakeup_seq)
[ nobody awaken ]
431	6	unlocks c->__data.__lock
431	4	futex_wait (&wakeup_seq), returns -EWOULDBLOCK immediately
431	4	locks c->__data.__lock
431	4	val = 3; val != seq (2) && val != woken_seq (1), no looping
432	4	++woken_seq
432	4	unlocks c->__data.__lock
432	4	attempts to lock m
432	4	futex_wait (&m->__data.__lock)
432	5	futex_wait (&wakeup_seq), returns -EWOULDBLOCK immediately
432	4	locks c->__data.__lock
432	4	val = 3; val != seq (2) && val != woken_seq (2), no looping
433	4	++woken_seq
433	4	unlocks c->__data.__lock
433	4	attempts to lock m
433	4	futex_wait (&m->__data.__lock)
433	6	unlocks m
433	6	futex_wake (&m->__data.__lock)
[ thr2 awaken ]
433	2	locks c->__data.__lock
433	2	val = 3; val != seq (0), but val == woken_seq (3), therefore loop
433	2	unlocks c->__data.__lock
433	2	futex_wait (&wakeup_seq)
433	3	attempts to lock m
433	3	futex_wait (&m->__data.__lock)
433	6	attempts to lock m
433	6	futex_wait (&m->__data.__lock)
[ hang ]
# thr{1,3,4,5,6} waiting on m->__data.__lock, thr2 waiting on wakeup_seq

Legend:
tao     - total_seq/wakeup_seq/woken_seq

	Jakub

Dinakar Guniguntala | 18 May 09:10
Picon

pthread_cond_broadcast and FUTEX_REQUEUE


Ulrich,

I noticed that pthread_cond_broadcast still uses the FUTEX_REQUEUE
functionality in the latest CVS sources whereas this has been
removed in RHEL 3.0 update 2. Since there seems to be a testcase
that demonstrates this problem,
(http://bugme.osdl.org/show_bug.cgi?id=2364)
I was wondering if the fix will get into CVS as well.

I had also previously noted that another fix for this problem would be to
continue to use FUTEX_REQUEUE without releasing the internal
condvar lock to prevent corruption of the counters.

What are your thoughts on this

Regards,

Dinakar

Ali Ijaz Sheikh | 17 May 21:11

Debugging and NPTL


Hi,

I have recently started seeing some problems with debugging of multithreaded
applications with NPTL on 2.6 series kernels.  It seems that GDB is no longer
being informed of the events occurring in the child threads because
create_thread (nptl/sysdeps/pthread/create_thread.c) routine does not pass the
CLONE_PTRACE flag to the clone system call.  For example, if the child thread
gets a SEGV, the whole thread group is terminated without GDB ever being told.

When creating a thread in a thread group that is being ptraced, shouldn't the
child thread be created with a CLONE_PTRACE?  It this a nptl bug?  Or is this
GDB's fault?

A simple program that creates a thread and does raise(SIGSEGV) in the child
thread can be used to reproduce this problem.  Try running that in gdb.

-Ali
ali <at> binish.com

--

-- 
Phil-list mailing list
Phil-list <at> redhat.com
https://www.redhat.com/mailman/listinfo/phil-list


Gmane