about summary refs log tree commit diff
path: root/nptl/sysdeps
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-05-18 20:18:14 +0000
committerUlrich Drepper <drepper@redhat.com>2004-05-18 20:18:14 +0000
commit893a351195a2997133892ffac80573a9984ba4cf (patch)
treead1b9f1a9e7d55b25353c57f9fbd5f76c4804054 /nptl/sysdeps
parentd40eb37aad4145ae4d047b6d7f633f740bf3a610 (diff)
downloadglibc-893a351195a2997133892ffac80573a9984ba4cf.tar.gz
glibc-893a351195a2997133892ffac80573a9984ba4cf.tar.xz
glibc-893a351195a2997133892ffac80573a9984ba4cf.zip
[BZ #163]
Update.
2004-05-18  Petter Reinholdtsen  <pere@hungry.com>

	* locales/sl_SI [LC_TIME]: Correct d_fmt date format from
	'22.06.2003' to '22. 06. 2003'.  Change requested from Aleks
	Reinhardt, and approved by the locale author Borka
	Jerman-Blazic. [BZ #163]
Diffstat (limited to 'nptl/sysdeps')
-rw-r--r--nptl/sysdeps/pthread/pthread_cond_broadcast.c5
-rw-r--r--nptl/sysdeps/pthread/pthread_cond_timedwait.c15
-rw-r--r--nptl/sysdeps/pthread/pthread_cond_wait.c19
-rw-r--r--nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S5
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S31
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S21
-rw-r--r--nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S8
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S35
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S33
17 files changed, 138 insertions, 42 deletions
diff --git a/nptl/sysdeps/pthread/pthread_cond_broadcast.c b/nptl/sysdeps/pthread/pthread_cond_broadcast.c
index 44c3fe6d5f..a42c579658 100644
--- a/nptl/sysdeps/pthread/pthread_cond_broadcast.c
+++ b/nptl/sysdeps/pthread/pthread_cond_broadcast.c
@@ -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@de.ibm.com>, 2003.
 
@@ -40,6 +40,9 @@ __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;
+      /* Signal that a broadcast happened.  */
+      ++cond->__data.__broadcast_seq;
 
       /* We are done.  */
       lll_mutex_unlock (cond->__data.__lock);
diff --git a/nptl/sysdeps/pthread/pthread_cond_timedwait.c b/nptl/sysdeps/pthread/pthread_cond_timedwait.c
index a03f51e0f0..96b1029cf5 100644
--- a/nptl/sysdeps/pthread/pthread_cond_timedwait.c
+++ b/nptl/sysdeps/pthread/pthread_cond_timedwait.c
@@ -36,6 +36,7 @@ struct _condvar_cleanup_buffer
   int oldtype;
   pthread_cond_t *cond;
   pthread_mutex_t *mutex;
+  unsigned int bc_seq;
 };
 
 int
@@ -85,6 +86,8 @@ __pthread_cond_timedwait (cond, mutex, abstime)
   unsigned long long int val;
   unsigned long long int seq;
   val = seq = cond->__data.__wakeup_seq;
+  /* 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.  */
@@ -139,7 +142,12 @@ __pthread_cond_timedwait (cond, mutex, abstime)
 	}
       /* Did we already time out?  */
       if (__builtin_expect (rt.tv_sec < 0, 0))
-	goto timeout;
+	{
+	  if (cbuffer.bc_seq != cond->__data.__broadcast_seq)
+	    goto bc_out;
+
+	  goto timeout;
+	}
 
       /* Prepare to wait.  Release the condvar futex.  */
       lll_mutex_unlock (cond->__data.__lock);
@@ -157,6 +165,10 @@ __pthread_cond_timedwait (cond, mutex, abstime)
       /* We are going to look at shared data again, so get the lock.  */
       lll_mutex_lock(cond->__data.__lock);
 
+      /* If a broadcast happened, we are done.  */
+      if (cbuffer.bc_seq != cond->__data.__broadcast_seq)
+	goto bc_out;
+
       /* Check whether we are eligible for wakeup.  */
       val = cond->__data.__wakeup_seq;
       if (val != seq && cond->__data.__woken_seq != val)
@@ -178,6 +190,7 @@ __pthread_cond_timedwait (cond, mutex, abstime)
   /* Another thread woken up.  */
   ++cond->__data.__woken_seq;
 
+ bc_out:
   /* We are done with the condvar.  */
   lll_mutex_unlock (cond->__data.__lock);
 
diff --git a/nptl/sysdeps/pthread/pthread_cond_wait.c b/nptl/sysdeps/pthread/pthread_cond_wait.c
index 01415bf051..a05060a107 100644
--- a/nptl/sysdeps/pthread/pthread_cond_wait.c
+++ b/nptl/sysdeps/pthread/pthread_cond_wait.c
@@ -32,6 +32,7 @@ struct _condvar_cleanup_buffer
   int oldtype;
   pthread_cond_t *cond;
   pthread_mutex_t *mutex;
+  unsigned int bc_seq;
 };
 
 
@@ -45,10 +46,13 @@ __condvar_cleanup (void *arg)
   /* We are going to modify shared data.  */
   lll_mutex_lock (cbuffer->cond->__data.__lock);
 
-  /* This thread is not waiting anymore.  Adjust the sequence counters
-     appropriately.  */
-  ++cbuffer->cond->__data.__wakeup_seq;
-  ++cbuffer->cond->__data.__woken_seq;
+  if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq)
+    {
+      /* This thread is not waiting anymore.  Adjust the sequence counters
+	 appropriately.  */
+      ++cbuffer->cond->__data.__wakeup_seq;
+      ++cbuffer->cond->__data.__woken_seq;
+    }
 
   /* We are done.  */
   lll_mutex_unlock (cbuffer->cond->__data.__lock);
@@ -111,6 +115,8 @@ __pthread_cond_wait (cond, mutex)
   unsigned long long int val;
   unsigned long long int seq;
   val = seq = cond->__data.__wakeup_seq;
+  /* 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.  */
@@ -137,6 +143,10 @@ __pthread_cond_wait (cond, mutex)
       /* Disable asynchronous cancellation.  */
       __pthread_disable_asynccancel (cbuffer.oldtype);
 
+      /* If a broadcast happened, we are done.  */
+      if (cbuffer.bc_seq != cond->__data.__broadcast_seq)
+	goto bc_out;
+
       /* We are going to look at shared data again, so get the lock.  */
       lll_mutex_lock (cond->__data.__lock);
 
@@ -148,6 +158,7 @@ __pthread_cond_wait (cond, mutex)
   /* Another thread woken up.  */
   ++cond->__data.__woken_seq;
 
+ bc_out:
   /* We are done with the condvar.  */
   lll_mutex_unlock (cond->__data.__lock);
 
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
index 0fed5cc918..1bb2968120 100644
--- a/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
@@ -81,6 +81,7 @@ typedef union
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   long long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
index f998138d7e..9da84c66d6 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
@@ -81,6 +81,7 @@ typedef union
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   long long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S
index 8d09e22afd..456f3dbfb1 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S
@@ -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@redhat.com>, 2002.
 
@@ -74,6 +74,9 @@ __pthread_cond_broadcast:
 	   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)
 
 	/* Get the address of the mutex used.  */
 	movl	dep_mutex-wakeup_seq(%ebx), %edi
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
index acc5a6a5f6..c0fd1a99a8 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
@@ -83,15 +83,17 @@ __pthread_cond_timedwait:
 	addl	$1, total_seq(%ebx)
 	adcl	$0, total_seq+4(%ebx)
 
-#define FRAME_SIZE 20
+#define FRAME_SIZE 24
 	subl	$FRAME_SIZE, %esp
 .Lsubl:
 
 	/* Get and store current wakeup_seq value.  */
 	movl	wakeup_seq(%ebx), %edi
 	movl	wakeup_seq+4(%ebx), %edx
+	movl	broadcast_seq(%ebx), %eax
 	movl	%edi, 12(%esp)
 	movl	%edx, 16(%esp)
+	movl	%eax, 20(%esp)
 
 	/* Get the current time.  */
 8:	movl	%ebx, %edx
@@ -139,7 +141,8 @@ __pthread_cond_timedwait:
 	addl	$1000000000, %edx
 	subl	$1, %ecx
 12:	testl	%ecx, %ecx
-	js	13f
+	movl	$-ETIMEDOUT, %esi
+	js	6f
 
 	/* Store relative timeout.  */
 21:	movl	%ecx, 4(%esp)
@@ -184,7 +187,11 @@ __pthread_cond_timedwait:
 #endif
 	jnz	5f
 
-6:	movl	woken_seq(%ebx), %eax
+6:	movl	broadcast_seq(%ebx), %eax
+	cmpl	20(%esp), %eax
+	jne	23f
+
+	movl	woken_seq(%ebx), %eax
 	movl	woken_seq+4(%ebx), %ecx
 
 	movl	wakeup_seq(%ebx), %edi
@@ -203,16 +210,19 @@ __pthread_cond_timedwait:
 15:	cmpl	$-ETIMEDOUT, %esi
 	jne	8b
 
-13:	addl	$1, wakeup_seq(%ebx)
+	addl	$1, wakeup_seq(%ebx)
 	adcl	$0, wakeup_seq+4(%ebx)
 	movl	$ETIMEDOUT, %esi
 	jmp	14f
 
+23:	xorl	%esi, %esi
+	jmp	24f
+
 9:	xorl	%esi, %esi
 14:	addl	$1, woken_seq(%ebx)
 	adcl	$0, woken_seq+4(%ebx)
 
-	LOCK
+24:	LOCK
 #if cond_lock == 0
 	subl	$1, (%ebx)
 #else
@@ -332,7 +342,8 @@ __pthread_cond_timedwait:
 	addl	$1000000000, %edx
 	subl	$1, %ecx
 20:	testl	%ecx, %ecx
-	js	13b
+	movl	$-ETIMEDOUT, %esi
+	js	6b
 	jmp	21b
 #endif
 	.size	__pthread_cond_timedwait, .-__pthread_cond_timedwait
@@ -372,13 +383,17 @@ __condvar_tw_cleanup:
 #endif
 	call	__lll_mutex_lock_wait
 
-1:	addl	$1, wakeup_seq(%ebx)
+1:	movl	broadcast_seq(%ebx), %eax
+	cmpl	12(%esp), %eax
+	jne	3f
+
+	addl	$1, wakeup_seq(%ebx)
 	adcl	$0, wakeup_seq+4(%ebx)
 
 	addl	$1, woken_seq(%ebx)
 	adcl	$0, woken_seq+4(%ebx)
 
-	LOCK
+3:	LOCK
 #if cond_lock == 0
 	subl	$1, (%ebx)
 #else
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
index 08a0588910..74e3172ab0 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
@@ -80,15 +80,17 @@ __pthread_cond_wait:
 	addl	$1, total_seq(%ebx)
 	adcl	$0, total_seq+4(%ebx)
 
-#define FRAME_SIZE 12
+#define FRAME_SIZE 16
 	subl	$FRAME_SIZE, %esp
 .Lsubl:
 
 	/* Get and store current wakeup_seq value.  */
 	movl	wakeup_seq(%ebx), %edi
 	movl	wakeup_seq+4(%ebx), %edx
+	movl	broadcast_seq(%ebx), %eax
 	movl	%edi, 4(%esp)
 	movl	%edx, 8(%esp)
+	movl	%eax, 12(%esp)
 
 	/* Unlock.  */
 8:	LOCK
@@ -127,7 +129,11 @@ __pthread_cond_wait:
 #endif
 	jnz	5f
 
-6:	movl	woken_seq(%ebx), %eax
+6:	movl	broadcast_seq(%ebx), %eax
+	cmpl	12(%esp), %eax
+	jne	16f
+
+	movl	woken_seq(%ebx), %eax
 	movl	woken_seq+4(%ebx), %ecx
 
 	movl	wakeup_seq(%ebx), %edi
@@ -146,7 +152,8 @@ __pthread_cond_wait:
 9:	addl	$1, woken_seq(%ebx)
 	adcl	$0, woken_seq+4(%ebx)
 
-	LOCK
+	/* Unlock */
+16:	LOCK
 #if cond_lock == 0
 	subl	$1, (%ebx)
 #else
@@ -264,13 +271,17 @@ __condvar_w_cleanup:
 #endif
 	call	__lll_mutex_lock_wait
 
-1:	addl	$1, wakeup_seq(%ebx)
+1:	movl	broadcast_seq(%ebx), %eax
+	cmpl	12(%esp), %eax
+	jne	3f
+
+	addl	$1, wakeup_seq(%ebx)
 	adcl	$0, wakeup_seq+4(%ebx)
 
 	addl	$1, woken_seq(%ebx)
 	adcl	$0, woken_seq+4(%ebx)
 
-	LOCK
+3:	LOCK
 #if cond_lock == 0
 	subl	$1, (%ebx)
 #else
diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h
index e4c15d1e20..bdf3ee741b 100644
--- a/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h
@@ -81,6 +81,7 @@ typedef union
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym b/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym
index 1463e0810e..d0559da86f 100644
--- a/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym
+++ b/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym
@@ -9,3 +9,4 @@ total_seq	offsetof (pthread_cond_t, __data.__total_seq)
 wakeup_seq	offsetof (pthread_cond_t, __data.__wakeup_seq)
 woken_seq	offsetof (pthread_cond_t, __data.__woken_seq)
 dep_mutex	offsetof (pthread_cond_t, __data.__mutex)
+broadcast_seq	offsetof (pthread_cond_t, __data.__broadcast_seq)
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
index d6d94cda24..794d888a13 100644
--- a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
@@ -101,6 +101,7 @@ typedef union
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   long long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h
index e2606aff8e..02b061b05c 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h
@@ -100,6 +100,7 @@ typedef union
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   long long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h
index d123fd059f..b0c1372bba 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h
@@ -101,6 +101,7 @@ typedef union
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   long long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
index 1b4820eb0c..e29c77529e 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
@@ -81,6 +81,7 @@ typedef union
     unsigned long long int __wakeup_seq;
     unsigned long long int __woken_seq;
     void *__mutex;
+    unsigned int __broadcast_seq;
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
index 8e26681b3b..6d29d761fa 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
@@ -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@redhat.com>, 2002.
 
@@ -63,6 +63,8 @@ __pthread_cond_broadcast:
 	/* 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)
 
 	/* Get the address of the mutex used.  */
 	movq	dep_mutex-wakeup_seq(%rdi), %r8
@@ -110,12 +112,12 @@ __pthread_cond_broadcast:
 #endif
 	jmp	2b
 
-	/* Unlock in loop requires waekup.  */
+	/* Unlock in loop requires wakeup.  */
 5:	addq	$cond_lock-wakeup_seq, %rdi
 	callq	__lll_mutex_unlock_wake
 	jmp	6b
 
-	/* Unlock in loop requires waekup.  */
+	/* Unlock in loop requires wakeup.  */
 7:	addq	$cond_lock-wakeup_seq, %rdi
 	callq	__lll_mutex_unlock_wake
 	subq	$cond_lock-wakeup_seq, %rdi
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
index f6b6ab246c..80cbf7e430 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
@@ -51,7 +51,8 @@ __pthread_cond_timedwait:
 .Lpush_r13:
 	pushq	%r14
 .Lpush_r14:
-	subq	$80, %rsp
+#define FRAME_SIZE 80
+	subq	$FRAME_SIZE, %rsp
 .Lsubq:
 	/* Stack frame:
 
@@ -67,6 +68,8 @@ __pthread_cond_timedwait:
 	            +--------------------------+
 	   rsp +  8 | condvar pointer          |
 	            +--------------------------+
+	   rsp +  4 | old broadcast_seq value  |
+	            +--------------------------+
 	   rsp +  0 | old cancellation mode    |
 	            +--------------------------+
 	*/
@@ -116,7 +119,9 @@ __pthread_cond_timedwait:
 	/* Get and store current wakeup_seq value.  */
 	movq	8(%rsp), %rdi
 	movq	wakeup_seq(%rdi), %r12
+	movl	broadcast_seq(%rdi), %edx
 	movq	%r12, 40(%rsp)
+	movl	%edx, 4(%rsp)
 
 	/* Get the current time.  */
 8:
@@ -160,7 +165,8 @@ __pthread_cond_timedwait:
 	decq	%rcx
 12:	testq	%rcx, %rcx
 	movq	8(%rsp), %rdi
-	js	13f
+	movq	$-ETIMEDOUT, %r14
+	js	6f
 
 	/* Store relative timeout.  */
 21:	movq	%rcx, 24(%rsp)
@@ -201,10 +207,15 @@ __pthread_cond_timedwait:
 #endif
 	jne	5f
 
-6:	movq	woken_seq(%rdi), %rax
+6:	movl	broadcast_seq(%rdi), %edx
+
+	movq	woken_seq(%rdi), %rax
 
 	movq	wakeup_seq(%rdi), %r12
 
+	cmpl	4(%rsp), %edx
+	jne	23f
+
 	cmpq	40(%rsp), %r12
 	jbe	15f
 
@@ -218,10 +229,13 @@ __pthread_cond_timedwait:
 	movq	$ETIMEDOUT, %r14
 	jmp	14f
 
+23:	xorq	%r14, %r14
+	jmp	24f
+
 9:	xorq	%r14, %r14
 14:	incq	woken_seq(%rdi)
 
-	LOCK
+24:	LOCK
 #if cond_lock == 0
 	decl	(%rdi)
 #else
@@ -239,7 +253,7 @@ __pthread_cond_timedwait:
 	testq	%rax, %rax
 	cmoveq	%r14, %rax
 
-18:	addq	$80, %rsp
+18:	addq	$FRAME_SIZE, %rsp
 .Laddq:
 	popq	%r14
 .Lpop_r14:
@@ -259,7 +273,7 @@ __pthread_cond_timedwait:
 	callq	__lll_mutex_lock_wait
 	jmp	2b
 
-	/* Unlock in loop requires waekup.  */
+	/* Unlock in loop requires wakeup.  */
 3:
 #if cond_lock != 0
 	addq	$cond_lock, %rdi
@@ -278,7 +292,7 @@ __pthread_cond_timedwait:
 #endif
 	jmp	6b
 
-	/* Unlock after loop requires waekup.  */
+	/* Unlock after loop requires wakeup.  */
 10:
 #if cond_lock != 0
 	addq	$cond_lock, %rdi
@@ -325,7 +339,8 @@ __pthread_cond_timedwait:
 	decq	%rcx
 20:	testq	%rcx, %rcx
 	movq	8(%rsp), %rdi
-	js	13b
+	movq	$-ETIMEDOUT, %r14
+	js	6b
 	jmp	21b
 #endif
 .LENDCODE:
@@ -394,7 +409,7 @@ versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
 	.uleb128 4
 	.byte	0x40+.Lsubq-.Lpush_r14		# DW_CFA_advance_loc+N
 	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 112
+	.uleb128 32+FRAME_SIZE
 	.byte	3				# DW_CFA_advance_loc2
 	.2byte	.Laddq-.Lsubq
 	.byte	14				# DW_CFA_def_cfa_offset
@@ -413,7 +428,7 @@ versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
 	.byte	0xcc				# DW_CFA_restore %r12
 	.byte	0x40+.LSbl1-.Lpop_r12		# DW_CFA_advance_loc+N
 	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 112
+	.uleb128 32+FRAME_SIZE
 	.byte	0x8c				# DW_CFA_offset %r12
 	.uleb128 2
 	.byte	0x8d				# DW_CFA_offset %r13
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
index e572874d7a..065eb11813 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
@@ -61,11 +61,15 @@ __condvar_cleanup:
 	subq	$cond_lock, %rdi
 #endif
 
-1:	incq	wakeup_seq(%rdi)
+1:	movl	broadcast_seq(%rdi), %edx
+	cmpl	4(%r8), %edx
+	jne	3f
+
+	incq	wakeup_seq(%rdi)
 
 	incq	woken_seq(%rdi)
 
-	LOCK
+3:	LOCK
 #if cond_lock == 0
 	decl	(%rdi)
 #else
@@ -99,20 +103,23 @@ __pthread_cond_wait:
 .LSTARTCODE:
 	pushq	%r12
 .Lpush_r12:
-	subq	$64, %rsp
+#define FRAME_SIZE 64
+	subq	$FRAME_SIZE, %rsp
 .Lsubq:
 	/* Stack frame:
 
 	   rsp + 64
 	            +--------------------------+
 	   rsp + 32 | cleanup buffer           |
-	            +--------------------------+
+		    +--------------------------+
 	   rsp + 24 | old wake_seq value       |
 	            +--------------------------+
 	   rsp + 16 | mutex pointer            |
 	            +--------------------------+
 	   rsp +  8 | condvar pointer          |
 	            +--------------------------+
+	   rsp +  4 | old broadcast_seq value  |
+	            +--------------------------+
 	   rsp +  0 | old cancellation mode    |
 	            +--------------------------+
 	*/
@@ -161,7 +168,9 @@ __pthread_cond_wait:
 	/* Get and store current wakeup_seq value.  */
 	movq	8(%rsp), %rdi
 	movq	wakeup_seq(%rdi), %r12
+	movl	broadcast_seq(%rdi), %edx
 	movq	%r12, 24(%rsp)
+	movl	%edx, 4(%rsp)
 
 	/* Unlock.  */
 8:	LOCK
@@ -198,10 +207,15 @@ __pthread_cond_wait:
 #endif
 	jnz	5f
 
-6:	movq	woken_seq(%rdi), %rax
+6:	movl	broadcast_seq(%rdi), %edx
+
+	movq	woken_seq(%rdi), %rax
 
 	movq	wakeup_seq(%rdi), %r12
 
+	cmpl	4(%rsp), %edx
+	jne	16f
+
 	cmpq	24(%rsp), %r12
 	jbe	8b
 
@@ -210,7 +224,8 @@ __pthread_cond_wait:
 
 	incq	woken_seq(%rdi)
 
-	LOCK
+	/* Unlock */
+16:	LOCK
 #if cond_lock == 0
 	decl	(%rdi)
 #else
@@ -224,7 +239,7 @@ __pthread_cond_wait:
 
 	movq	16(%rsp), %rdi
 	callq	__pthread_mutex_cond_lock
-14:	addq	$64, %rsp
+14:	addq	$FRAME_SIZE, %rsp
 .Laddq:
 
 	popq	%r12
@@ -242,7 +257,7 @@ __pthread_cond_wait:
 	callq	__lll_mutex_lock_wait
 	jmp	2b
 
-	/* Unlock in loop requires waekup.  */
+	/* Unlock in loop requires wakeup.  */
 3:
 #if cond_lock != 0
 	addq	$cond_lock, %rdi
@@ -343,7 +358,7 @@ versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
 	.uleb128 2
 	.byte	0x40+.Lsubq-.Lpush_r12		# DW_CFA_advance_loc+N
 	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 80
+	.uleb128 16+FRAME_SIZE
 	.byte	2				# DW_CFA_advance_loc1
 	.byte	.Laddq-.Lsubq
 	.byte	14				# DW_CFA_def_cfa_offset