diff mbox

New condvar implementation that provides stronger ordering guarantees.

Message ID 1465937639.31784.7.camel@localhost.localdomain
State New
Headers show

Commit Message

Torvald Riegel June 14, 2016, 8:53 p.m. UTC
I've now tested this patch successfully using our existing tests on ppc,
ppc64, ppc64le, s390x, and aarch64.  I couldn't test on s390 due to
https://www.sourceware.org/ml/libc-alpha/2016-06/msg00545.html.

The attached patch is a minor revision that just fixes some formatting
and adds an include (revealing by testing on s390x).

I think this patch is ready for wider testing, for example in Rawhide or
perhaps even by committing it on trunk.
Some more testing of the overflow case in the atomic monotonic 64b
counters we use on archs that just have 32b atomic ops (see
pthread_cond_common.c) would be good; I plan to do this later, as it
requires creating new tests and doesn't affect the core condvar
algorithm really.

I'd still appreciate further reviews, even if this is just about whether
the algorithm is accessible enough and the comments do a good-enough job
of explaining it.

Thoughts?

On Thu, 2016-05-26 at 15:21 +0200, Torvald Riegel wrote:
> This replaces the current condvar with a new algorithm that's different
> that the one I proposed last year.  I wasn't able to fix the
> futex-spurious-wake-up-related issue in last year's algorithm without
> the risk of decreasing performance significantly.
> 
> I would appreciate testing on weak memory model architectures such as
> ARM and POWER.  I have tested on x86 and x86_64.
> I would of course also appreciate more sets of eyes on the algorithm.
> I'm not aware of any issues, but reviews never hurt; even if you just
> would like to see more detailed comments, please let me know. 
> 
> Once we have that, testing in Rawhide should be the next step.  We still
> have a month until the feature freeze deadline, so I'd like to get this
> done this cycle if possible.
> 
> pre-v9 sparc and hppa are currently broken by this patch.
> For sparc, I'd like to get feedback by sparc maintainers regarding how
> they would like to deal with the lack of proper atomics support in
> pre-v9 sparc; it's a recurring theme, so maybe we should tackle that in
> a more foundational way than just creating custom pre-v9 sparc for all
> synchronization algorithms.
> Regarding hppa, I might leave it to the hppa maintainer to use the new
> condvar (it has to support old LinuxThreads initializers).  Or I'll do
> it later if he tells me I should do it myself ;)
> 
> This patch doesn't do anything in terms of support for PI and real time.
> I believe we'd need a significantly adapted implementation (and perhaps
> algorithm) to support it; for example, we're short on space in
> pthread_cond_t, so even sticking in a PI mutex as replacement for the
> currently used condvar-internal lock would require jumping through
> hoops.
> 
> 
> 2016-05-26  Torvald Riegel  <triegel@redhat.com>
> 
> 	[BZ #13165]
> 	* nptl/pthread_cond_broadcast.c (__pthread_cond_broadcast): Rewrite to
> 	use new algorithm.
> 	* nptl/pthread_cond_destroy.c (__pthread_cond_destroy): Likewise.
> 	* nptl/pthread_cond_init.c (__pthread_cond_init): Likewise.
> 	* nptl/pthread_cond_signal.c (__pthread_cond_signal): Likewise.
> 	* nptl/pthread_cond_wait.c (__pthread_cond_wait): Likewise.
> 	(__pthread_cond_timedwait): Move here from pthread_cond_timedwait.c.
> 	(__condvar_confirm_wakeup, __condvar_cancel_waiting,
> 	__condvar_cleanup_waiting, __condvar_dec_grefs,
> 	__pthread_cond_wait_common): New.
> 	(__condvar_cleanup): Remove.
> 	* npt/pthread_condattr_getclock.c (pthread_condattr_getclock): Adapt.
> 	* npt/pthread_condattr_setclock.c (pthread_condattr_setclock):
> 	Likewise.
> 	* npt/pthread_condattr_getpshared.c (pthread_condattr_getpshared):
> 	Likewise.
> 	* npt/pthread_condattr_init.c (pthread_condattr_init): Likewise.
> 	* nptl/tst-cond1.c: Add comment.
> 	* nptl/tst-cond20.c (do_test): Adapt.
> 	* nptl/tst-cond22.c (do_test): Likewise.
> 	* sysdeps/aarch64/nptl/bits/pthreadtypes.h (pthread_cond_t): Adapt
> 	structure.
> 	* sysdeps/arm/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
> 	* sysdeps/ia64/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
> 	* sysdeps/m68k/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
> 	* sysdeps/microblaze/nptl/bits/pthreadtypes.h (pthread_cond_t):
> 	Likewise.
> 	* sysdeps/mips/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
> 	* sysdeps/nios2/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
> 	* sysdeps/s390/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
> 	* sysdeps/sh/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
> 	* sysdeps/tile/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
> 	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h (pthread_cond_t):
> 	Likewise.
> 	* sysdeps/x86/bits/pthreadtypes.h (pthread_cond_t): Likewise.
> 	* sysdeps/nptl/internaltypes.h (COND_NWAITERS_SHIFT): Remove.
> 	(COND_CLOCK_BITS): Adapt.
> 	* sysdeps/nptl/pthread.h (PTHREAD_COND_INITIALIZER): Adapt.
> 	* sysdeps/unix/sysv/linux/hppa/internaltypes.h (cond_compat_clear,
> 	cond_compat_check_and_clear): Adapt.
> 	* sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c: Remove file ...
> 	* sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c
> 	(__pthread_cond_timedwait): ... and move here.
> 	* nptl/DESIGN-condvar.txt: Remove file.
> 	* nptl/lowlevelcond.sym: Likewise.
> 	* nptl/pthread_cond_timedwait.c: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise.

Comments

Carlos O'Donell Dec. 30, 2016, 7:17 p.m. UTC | #1
Torvald,

At a high level this patch looks good to me and should go in right
away along with your changes to pretty-printers. They are fully ready
for glibc 2.25.

I apologize for the delayed review.

Thank you very much for tackling what is our largest algorithm rewrite
for NPTL. I appreciate that each of these rewrites is rooted in solving
a real problem with the existing algorithm. The results of the decision
in the Austin Group bug 609 make it clear that glibc needs to fix up the
implementation to meet the stronger ordering guarantees. I will note that
Austin Group bug 609 is not fixed yet, but the consensus is there that the
stronger ordering guarantee is required.

Given that this is a conformance fix with POSIX I am OK with the fact that
we are not adding a microbenchmark to cover the changes. In the future when
we consider any optimizations like requeue, we will need to add a performance
test. I agree at the high level that to make things faster we should just be
looking at making the mutex faster with various optimizations.

From an operational hours and testing perspective we have been running with
the new condition variables in Fedora Rawhide since October 2016 without
any problems. By the time we release in February that will have been roughly
4 months of testing in an active distribution doing continuous builds and
test cycles of various project regression test suites. The last time there
were algorithmic defects they were quickly caught by either Perl, Ruby, or
Python test suites.

I have no opinion on how we might adapt the implementation to PI. I'd like to
tackle one problem at a time, right now, moving this forward to the point where
we are following POSIX with regards to exactly which waiters can consume a
the signal/broadcast is progress.

~~~

(1) Architecture.

The design of this new algorithm with G1/G2 distinctions layers nicely into
the POSIX requirements. Perhaps the most complex sequence to review is actually
the quiescing code to make sure the state transition from G2->G1 is correct.
I don't see any way to simplify this given the various states of waiters, and
signalers that are using the two groups.

(2) Design.

I am impressed overall by the usage of futex-internal.h to make the entire code
more readable and easier to undertand. It has been a forward step to use futex-internal.h
in all of these places along with the atomic.h C11-like atomics which we know
make the code more readable.

The placement of key functions in the common code certainly makes it easier to
just have that file open when reviewing key aspects of the algorithm or how the
functions operate at an implementation level.

(3) Implementation.

The implmentation looks very good to me, the core common code and the cleanup
are all great. The only things I don't like about the code, but which do not
block commit, are the magic numbers in the shift and mask operations that deal
with the low and high bits that have special meanings. I had to keep a list of
variables and bit meanings on a sheet of paper beside me during review to make
sure I remembered "Oh yes, __wrefs, bits 2-0 mean this...". Overall the cleanups
far outweight the singular uses of these special bits. The original code was also
full of such special bit add and mask operations. Over time I'd like to see these
become cleaned up a bit.

On 06/14/2016 04:53 PM, Torvald Riegel wrote:
> I've now tested this patch successfully using our existing tests on ppc,
> ppc64, ppc64le, s390x, and aarch64.  I couldn't test on s390 due to
> https://www.sourceware.org/ml/libc-alpha/2016-06/msg00545.html.
> 
> The attached patch is a minor revision that just fixes some formatting
> and adds an include (revealing by testing on s390x).
> 
> I think this patch is ready for wider testing, for example in Rawhide or
> perhaps even by committing it on trunk.
> Some more testing of the overflow case in the atomic monotonic 64b
> counters we use on archs that just have 32b atomic ops (see
> pthread_cond_common.c) would be good; I plan to do this later, as it
> requires creating new tests and doesn't affect the core condvar
> algorithm really.
> 
> I'd still appreciate further reviews, even if this is just about whether
> the algorithm is accessible enough and the comments do a good-enough job
> of explaining it.
> 
> Thoughts?
> 
> On Thu, 2016-05-26 at 15:21 +0200, Torvald Riegel wrote:
>> This replaces the current condvar with a new algorithm that's different
>> that the one I proposed last year.  I wasn't able to fix the
>> futex-spurious-wake-up-related issue in last year's algorithm without
>> the risk of decreasing performance significantly.
>>
>> I would appreciate testing on weak memory model architectures such as
>> ARM and POWER.  I have tested on x86 and x86_64.
>> I would of course also appreciate more sets of eyes on the algorithm.
>> I'm not aware of any issues, but reviews never hurt; even if you just
>> would like to see more detailed comments, please let me know. 
>>
>> Once we have that, testing in Rawhide should be the next step.  We still
>> have a month until the feature freeze deadline, so I'd like to get this
>> done this cycle if possible.
>>
>> pre-v9 sparc and hppa are currently broken by this patch.
>> For sparc, I'd like to get feedback by sparc maintainers regarding how
>> they would like to deal with the lack of proper atomics support in
>> pre-v9 sparc; it's a recurring theme, so maybe we should tackle that in
>> a more foundational way than just creating custom pre-v9 sparc for all
>> synchronization algorithms.
>> Regarding hppa, I might leave it to the hppa maintainer to use the new
>> condvar (it has to support old LinuxThreads initializers).  Or I'll do
>> it later if he tells me I should do it myself ;)

I have just received new hardware for my hppa box and will be doing the
testing and changes required during the January freeze portion, considering
it a bug-fix that hppa doesn't work.

Thank you for this help.

>> This patch doesn't do anything in terms of support for PI and real time.
>> I believe we'd need a significantly adapted implementation (and perhaps
>> algorithm) to support it; for example, we're short on space in
>> pthread_cond_t, so even sticking in a PI mutex as replacement for the
>> currently used condvar-internal lock would require jumping through
>> hoops.

As I mentioned above, I have no good solution for PI support and I don't
think we can tackle it all in one go. This new implementation is forward
progress for now, and if I had to choose between PI vs. Robust, I'd choose
Robust for now. The PI support is definitely a corner case that is much
more niche than recovering a condvar mutex, and we have lost of Robust
bugs to fix (and now patches to review, thanks to you).

>>
>> 2016-05-26  Torvald Riegel  <triegel@redhat.com>
>>
>> 	[BZ #13165]
>> 	* nptl/pthread_cond_broadcast.c (__pthread_cond_broadcast): Rewrite to
>> 	use new algorithm.
>> 	* nptl/pthread_cond_destroy.c (__pthread_cond_destroy): Likewise.
>> 	* nptl/pthread_cond_init.c (__pthread_cond_init): Likewise.
>> 	* nptl/pthread_cond_signal.c (__pthread_cond_signal): Likewise.
>> 	* nptl/pthread_cond_wait.c (__pthread_cond_wait): Likewise.
>> 	(__pthread_cond_timedwait): Move here from pthread_cond_timedwait.c.
>> 	(__condvar_confirm_wakeup, __condvar_cancel_waiting,
>> 	__condvar_cleanup_waiting, __condvar_dec_grefs,
>> 	__pthread_cond_wait_common): New.
>> 	(__condvar_cleanup): Remove.
>> 	* npt/pthread_condattr_getclock.c (pthread_condattr_getclock): Adapt.
>> 	* npt/pthread_condattr_setclock.c (pthread_condattr_setclock):
>> 	Likewise.
>> 	* npt/pthread_condattr_getpshared.c (pthread_condattr_getpshared):
>> 	Likewise.
>> 	* npt/pthread_condattr_init.c (pthread_condattr_init): Likewise.
>> 	* nptl/tst-cond1.c: Add comment.
>> 	* nptl/tst-cond20.c (do_test): Adapt.
>> 	* nptl/tst-cond22.c (do_test): Likewise.
>> 	* sysdeps/aarch64/nptl/bits/pthreadtypes.h (pthread_cond_t): Adapt
>> 	structure.
>> 	* sysdeps/arm/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>> 	* sysdeps/ia64/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>> 	* sysdeps/m68k/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>> 	* sysdeps/microblaze/nptl/bits/pthreadtypes.h (pthread_cond_t):
>> 	Likewise.
>> 	* sysdeps/mips/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>> 	* sysdeps/nios2/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>> 	* sysdeps/s390/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>> 	* sysdeps/sh/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>> 	* sysdeps/tile/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>> 	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t):
>> 	Likewise.
>> 	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h (pthread_cond_t):
>> 	Likewise.
>> 	* sysdeps/x86/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>> 	* sysdeps/nptl/internaltypes.h (COND_NWAITERS_SHIFT): Remove.
>> 	(COND_CLOCK_BITS): Adapt.
>> 	* sysdeps/nptl/pthread.h (PTHREAD_COND_INITIALIZER): Adapt.
>> 	* sysdeps/unix/sysv/linux/hppa/internaltypes.h (cond_compat_clear,
>> 	cond_compat_check_and_clear): Adapt.
>> 	* sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c: Remove file ...
>> 	* sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c
>> 	(__pthread_cond_timedwait): ... and move here.
>> 	* nptl/DESIGN-condvar.txt: Remove file.
>> 	* nptl/lowlevelcond.sym: Likewise.
>> 	* nptl/pthread_cond_timedwait.c: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise.
>> 	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise.
> 
> 
> condvar.patch
> 
> 
> commit 1846a30fb9728dbc22730e56a9eaa3a996a4ef08
> Author: Torvald Riegel <triegel@redhat.com>
> Date:   Wed May 25 23:43:36 2016 +0200
> 
>     New condvar implementation that provides stronger ordering guarantees.
>     
>     This is a new implementation for condition variables, required
>     after http://austingroupbugs.net/view.php?id=609 to fix bug 13165.  In
>     essence, we need to be stricter in which waiters a signal or broadcast
>     is required to wake up; this couldn't be solved using the old algorithm.
>     ISO C++ made a similar clarification, so this also fixes a bug in
>     current libstdc++, for example.
>     
>     We can't use the old algorithm anymore because futexes do not guarantee
>     to wake in FIFO order.  Thus, when we wake, we can't simply let any
>     waiter grab a signal, but we need to ensure that one of the waiters
>     happening before the signal is woken up.  This is something the previous
>     algorithm violated (see bug 13165).
>     
>     There's another issue specific to condvars: ABA issues on the underlying
>     futexes.  Unlike mutexes that have just three states, or semaphores that
>     have no tokens or a limited number of them, the state of a condvar is
>     the *order* of the waiters.  A waiter on a semaphore can grab a token
>     whenever one is available; a condvar waiter must only consume a signal
>     if it is eligible to do so as determined by the relative order of the
>     waiter and the signal.
>     Therefore, this new algorithm maintains two groups of waiters: Those
>     eligible to consume signals (G1), and those that have to wait until
>     previous waiters have consumed signals (G2).  Once G1 is empty, G2
>     becomes the new G1.  64b counters are used to avoid ABA issues.
>     
>     This condvar doesn't yet use a requeue optimization (ie, on a broadcast,
>     waking just one thread and requeueing all others on the futex of the
>     mutex supplied by the program).  I don't think doing the requeue is
>     necessarily the right approach (but I haven't done real measurements
>     yet):
>     * If a program expects to wake many threads at the same time and make
>     that scalable, a condvar isn't great anyway because of how it requires
>     waiters to operate mutually exclusive (due to the mutex usage).  Thus, a
>     thundering herd problem is a scalability problem with or without the
>     optimization.  Using something like a semaphore might be more
>     appropriate in such a case.
>     * The scalability problem is actually at the mutex side; the condvar
>     could help (and it tries to with the requeue optimization), but it
>     should be the mutex who decides how that is done, and whether it is done
>     at all.
>     * Forcing all but one waiter into the kernel-side wait queue of the
>     mutex prevents/avoids the use of lock elision on the mutex.  Thus, it
>     prevents the only cure against the underlying scalability problem
>     inherent to condvars.
>     * If condvars use short critical sections (ie, hold the mutex just to
>     check a binary flag or such), which they should do ideally, then forcing
>     all those waiter to proceed serially with kernel-based hand-off (ie,
>     futex ops in the mutex' contended state, via the futex wait queues) will
>     be less efficient than just letting a scalable mutex implementation take
>     care of it.  Our current mutex impl doesn't employ spinning at all, but
>     if critical sections are short, spinning can be much better.
>     * Doing the requeue stuff requires all waiters to always drive the mutex
>     into the contended state.  This leads to each waiter having to call
>     futex_wake after lock release, even if this wouldn't be necessary.
>     
>     	[BZ #13165]
>     	* nptl/pthread_cond_broadcast.c (__pthread_cond_broadcast): Rewrite to
>     	use new algorithm.
>     	* nptl/pthread_cond_destroy.c (__pthread_cond_destroy): Likewise.
>     	* nptl/pthread_cond_init.c (__pthread_cond_init): Likewise.
>     	* nptl/pthread_cond_signal.c (__pthread_cond_signal): Likewise.
>     	* nptl/pthread_cond_wait.c (__pthread_cond_wait): Likewise.
>     	(__pthread_cond_timedwait): Move here from pthread_cond_timedwait.c.
>     	(__condvar_confirm_wakeup, __condvar_cancel_waiting,
>     	__condvar_cleanup_waiting, __condvar_dec_grefs,
>     	__pthread_cond_wait_common): New.
>     	(__condvar_cleanup): Remove.
>     	* npt/pthread_condattr_getclock.c (pthread_condattr_getclock): Adapt.
>     	* npt/pthread_condattr_setclock.c (pthread_condattr_setclock):
>     	Likewise.
>     	* npt/pthread_condattr_getpshared.c (pthread_condattr_getpshared):
>     	Likewise.
>     	* npt/pthread_condattr_init.c (pthread_condattr_init): Likewise.
>     	* nptl/tst-cond1.c: Add comment.
>     	* nptl/tst-cond20.c (do_test): Adapt.
>     	* nptl/tst-cond22.c (do_test): Likewise.
>     	* sysdeps/aarch64/nptl/bits/pthreadtypes.h (pthread_cond_t): Adapt
>     	structure.
>     	* sysdeps/arm/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>     	* sysdeps/ia64/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>     	* sysdeps/m68k/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>     	* sysdeps/microblaze/nptl/bits/pthreadtypes.h (pthread_cond_t):
>     	Likewise.
>     	* sysdeps/mips/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>     	* sysdeps/nios2/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>     	* sysdeps/s390/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>     	* sysdeps/sh/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>     	* sysdeps/tile/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>     	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t):
>     	Likewise.
>     	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h (pthread_cond_t):
>     	Likewise.
>     	* sysdeps/x86/bits/pthreadtypes.h (pthread_cond_t): Likewise.
>     	* sysdeps/nptl/internaltypes.h (COND_NWAITERS_SHIFT): Remove.
>     	(COND_CLOCK_BITS): Adapt.
>     	* sysdeps/nptl/pthread.h (PTHREAD_COND_INITIALIZER): Adapt.
>     	* sysdeps/unix/sysv/linux/hppa/internaltypes.h (cond_compat_clear,
>     	cond_compat_check_and_clear): Adapt.
>     	* sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c: Remove file ...
>     	* sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c
>     	(__pthread_cond_timedwait): ... and move here.
>     	* nptl/DESIGN-condvar.txt: Remove file.
>     	* nptl/lowlevelcond.sym: Likewise.
>     	* nptl/pthread_cond_timedwait.c: Likewise.
>     	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise.
>     	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise.
>     	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise.
>     	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise.
>     	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S: Likewise.
>     	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S: Likewise.
>     	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S: Likewise.
>     	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S: Likewise.
>     	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S: Likewise.
>     	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S: Likewise.
>     	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S: Likewise.
>     	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S: Likewise.
>     	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise.
>     	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise.
>     	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise.
>     	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise.
> 
> diff --git a/nptl/DESIGN-condvar.txt b/nptl/DESIGN-condvar.txt
> deleted file mode 100644
> index 4845251..0000000
> --- a/nptl/DESIGN-condvar.txt
> +++ /dev/null

OK. Deleted old design document.

> diff --git a/nptl/Makefile b/nptl/Makefile
> index e0bc1b7..cbd7f4b 100644
> --- a/nptl/Makefile
> +++ b/nptl/Makefile
> @@ -71,7 +71,7 @@ libpthread-routines = nptl-init vars events version pt-interp \
>  		      pthread_rwlockattr_getkind_np \
>  		      pthread_rwlockattr_setkind_np \
>  		      pthread_cond_init pthread_cond_destroy \
> -		      pthread_cond_wait pthread_cond_timedwait \
> +		      pthread_cond_wait \

OK. Merged implementations into one file. This makes the static linking
case pull in both implementations, but who cares really, we already have
other issues with static linking libpthread. I mention it here just to
point out that we thought about the issue and have chosen to ignore it.

>  		      pthread_cond_signal pthread_cond_broadcast \
>  		      old_pthread_cond_init old_pthread_cond_destroy \
>  		      old_pthread_cond_wait old_pthread_cond_timedwait \
> @@ -181,7 +181,6 @@ CFLAGS-pthread_timedjoin.c = -fexceptions -fasynchronous-unwind-tables
>  CFLAGS-pthread_once.c = $(uses-callbacks) -fexceptions \
>  			-fasynchronous-unwind-tables
>  CFLAGS-pthread_cond_wait.c = -fexceptions -fasynchronous-unwind-tables
> -CFLAGS-pthread_cond_timedwait.c = -fexceptions -fasynchronous-unwind-tables

OK. Removed file.

>  CFLAGS-sem_wait.c = -fexceptions -fasynchronous-unwind-tables
>  CFLAGS-sem_timedwait.c = -fexceptions -fasynchronous-unwind-tables
>  
> @@ -302,8 +301,7 @@ test-xfail-tst-once5 = yes
>  # Files which must not be linked with libpthread.
>  tests-nolibpthread = tst-unload
>  
> -gen-as-const-headers = pthread-errnos.sym \
> -		       lowlevelcond.sym lowlevelrwlock.sym \
> +gen-as-const-headers = pthread-errnos.sym lowlevelrwlock.sym \

OK. Removed sym file since assembly implementations are now gone.

>  		       unwindbuf.sym \
>  		       lowlevelrobustlock.sym pthread-pi-defines.sym
>  
> diff --git a/nptl/lowlevelcond.sym b/nptl/lowlevelcond.sym
> deleted file mode 100644
> index 18e1ada..0000000
> --- a/nptl/lowlevelcond.sym
> +++ /dev/null
> @@ -1,16 +0,0 @@

OK. Sym file removed because asm impls are removed.

> diff --git a/nptl/pthread_cond_broadcast.c b/nptl/pthread_cond_broadcast.c
> index 552fd42..87c0755 100644
> --- a/nptl/pthread_cond_broadcast.c
> +++ b/nptl/pthread_cond_broadcast.c
> @@ -19,72 +19,71 @@
>  #include <endian.h>
>  #include <errno.h>
>  #include <sysdep.h>
> -#include <lowlevellock.h>
> +#include <futex-internal.h>

OK. Switch to futex internal API with proper error checking.

>  #include <pthread.h>
>  #include <pthreadP.h>
>  #include <stap-probe.h>
> +#include <atomic.h>

OK. Use C11-like atomics.

>  
>  #include <shlib-compat.h>
> -#include <kernel-features.h>
>  
> +#include "pthread_cond_common.c"

OK. Include common code.

> +
> +/* We do the following steps from __pthread_cond_signal in one critical
> +   section: (1) signal all waiters in G1, (2) close G1 so that it can become
> +   the new G2 and make G2 the new G1, and (3) signal all waiters in the new
> +   G1.  We don't need to do all these steps if there are no waiters in G1
> +   and/or G2.  See __pthread_cond_signal for further details.  */
>  int
>  __pthread_cond_broadcast (pthread_cond_t *cond)
>  {
>    LIBC_PROBE (cond_broadcast, 1, cond);
>  
> -  int pshared = (cond->__data.__mutex == (void *) ~0l)
> -		? LLL_SHARED : LLL_PRIVATE;
> -  /* Make sure we are alone.  */
> -  lll_lock (cond->__data.__lock, pshared);
> +  unsigned int wrefs = atomic_load_relaxed (&cond->__data.__wrefs);
> +  if (wrefs >> 3 == 0)

OK.

[Optional] Don't use magic constant 3. Use a define with a comment that explains
           what the low 3-bits are for.

> +    return 0;
> +  int private = __condvar_get_private (wrefs);
> +
> +  __condvar_acquire_lock (cond, private);
>  
> -  /* Are there any waiters to be woken?  */
> -  if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
> +  unsigned long long int wseq = __condvar_load_wseq_relaxed (cond);
> +  unsigned int g2 = wseq & 1;
> +  unsigned int g1 = g2 ^ 1;
> +  wseq >>= 1;
> +  bool do_futex_wake = false;
> +
> +  /* Step (1): signal all waiters remaining in G1.  */
> +  if (cond->__data.__g_size[g1] != 0)
>      {
> -      /* 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_unlock (cond->__data.__lock, pshared);
> -
> -      /* Wake everybody.  */
> -      pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
> -
> -      /* Do not use requeue for pshared condvars.  */
> -      if (mut == (void *) ~0l
> -	  || PTHREAD_MUTEX_PSHARED (mut) & PTHREAD_MUTEX_PSHARED_BIT)
> -	goto wake_all;
> -
> -#if (defined lll_futex_cmp_requeue_pi \
> -     && defined __ASSUME_REQUEUE_PI)
> -      if (USE_REQUEUE_PI (mut))
> -	{
> -	  if (lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, INT_MAX,
> -					&mut->__data.__lock, futex_val,
> -					LLL_PRIVATE) == 0)
> -	    return 0;
> -	}
> -      else
> -#endif
> -	/* 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, LLL_PRIVATE), 0))
> -	  return 0;
> -
> -wake_all:
> -      lll_futex_wake (&cond->__data.__futex, INT_MAX, pshared);
> -      return 0;
> +      /* Add as many signals as the remaining size of the group.  */
> +      atomic_fetch_add_relaxed (cond->__data.__g_signals + g1,
> +				cond->__data.__g_size[g1] << 1);
> +      cond->__data.__g_size[g1] = 0;
> +
> +      /* We need to wake G1 waiters before we quiesce G1 below.  */
> +      /* TODO Only set it if there are indeed futex waiters.  We could
> +	 also try to move this out of the critical section in cases when
> +	 G2 is empty (and we don't need to quiesce).  */
> +      futex_wake (cond->__data.__g_signals + g1, INT_MAX, private);
>      }
>  
> -  /* We are done.  */
> -  lll_unlock (cond->__data.__lock, pshared);
> +  /* G1 is complete.  Step (2) is next unless there are no waiters in G2, in
> +     which case we can stop.  */
> +  if (__condvar_quiesce_and_switch_g1 (cond, wseq, &g1, private))
> +    {
> +      /* Step (3): Send signals to all waiters in the old G2 / new G1.  */
> +      atomic_fetch_add_relaxed (cond->__data.__g_signals + g1,
> +				cond->__data.__g_size[g1] << 1);
> +      cond->__data.__g_size[g1] = 0;
> +      /* TODO Only set it if there are indeed futex waiters.  */
> +      do_futex_wake = true;
> +    }
> +
> +  __condvar_release_lock (cond, private);
> +
> +  if (do_futex_wake)
> +    futex_wake (cond->__data.__g_signals + g1, INT_MAX, private);
>  
>    return 0;
>  }
> diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c
> new file mode 100644
> index 0000000..b374396
> --- /dev/null
> +++ b/nptl/pthread_cond_common.c
> @@ -0,0 +1,466 @@
> +/* pthread_cond_common -- shared code for condition variable.
> +   Copyright (C) 2016 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <atomic.h>
> +#include <stdint.h>
> +#include <pthread.h>
> +#include <libc-internal.h>
> +
> +/* We need 3 least-significant bits on __wrefs for something else.  */
> +#define __PTHREAD_COND_MAX_GROUP_SIZE ((unsigned) 1 << 29)
> +
> +#if __HAVE_64B_ATOMICS == 1
> +

OK. These operations are all simpler to implement with 64-bit atomic.
The assumption here is that we won't overflow and that ABA on a 64-bit
counter is not going to happen.

> +static uint64_t __attribute__ ((unused))
> +__condvar_load_wseq_relaxed (pthread_cond_t *cond)
> +{
> +  return atomic_load_relaxed (&cond->__data.__wseq);
> +}
> +
> +static uint64_t __attribute__ ((unused))
> +__condvar_fetch_add_wseq_acquire (pthread_cond_t *cond, unsigned int val)
> +{
> +  return atomic_fetch_add_acquire (&cond->__data.__wseq, val);
> +}
> +
> +static uint64_t __attribute__ ((unused))
> +__condvar_fetch_xor_wseq_release (pthread_cond_t *cond, unsigned int val)
> +{
> +  return atomic_fetch_xor_release (&cond->__data.__wseq, val);
> +}
> +
> +static uint64_t __attribute__ ((unused))
> +__condvar_load_g1_start_relaxed (pthread_cond_t *cond)
> +{
> +  return atomic_load_relaxed (&cond->__data.__g1_start);
> +}
> +
> +static void __attribute__ ((unused))
> +__condvar_add_g1_start_relaxed (pthread_cond_t *cond, unsigned int val)
> +{
> +  atomic_store_relaxed (&cond->__data.__g1_start,
> +      atomic_load_relaxed (&cond->__data.__g1_start) + val);
> +}
> +
> +#else
> +
> +/* We use two 64b counters: __wseq and __g1_start.  They are monotonically
> +   increasing and single-writer-multiple-readers counters, so we can implement
> +   load, fetch-and-add, and fetch-and-xor operations even when we just have
> +   32b atomics.  Values we add or xor are less than or equal to 1<<31 (*),
> +   so we only have to make overflow-and-addition atomic wrt. to concurrent
> +   load operations and xor operations.  To do that, we split each counter into
> +   two 32b values of which we reserve the MSB of each to represent an
> +   overflow from the lower-order half to the higher-order half.
> +
> +   In the common case, the state is (higher-order / lower-order half, and . is
> +   basically concatenation of the bits):
> +   0.h     / 0.l  = h.l
> +
> +   When we add a value of x that overflows (i.e., 0.l + x == 1.L), we run the
> +   following steps S1-S4 (the values these represent are on the right-hand
> +   side):
> +   S1:  0.h     / 1.L == (h+1).L
> +   S2:  1.(h+1) / 1.L == (h+1).L
> +   S3:  1.(h+1) / 0.L == (h+1).L
> +   S4:  0.(h+1) / 0.L == (h+1).L
> +   If the LSB of the higher-order half is set, readers will ignore the
> +   overflow bit in the lower-order half.
> +
> +   To get an atomic snapshot in load operations, we exploit that the
> +   higher-order half is monotonically increasing; if we load a value V from
> +   it, then read the lower-order half, and then read the higher-order half
> +   again and see the same value V, we know that both halves have existed in
> +   the sequence of values the full counter had.  This is similar to the
> +   validated reads in the time-based STMs in GCC's libitm (e.g.,
> +   method_ml_wt).
> +
> +   The xor operation needs to be an atomic read-modify-write.  The write
> +   itself is not an issue as it affects just the lower-order half but not bits
> +   used in the add operation.  To make the full fetch-and-xor atomic, we
> +   exploit that concurrently, the value can increase by at most 1<<31 (*): The
> +   xor operation is only called while having acquired the lock, so not more
> +   than __PTHREAD_COND_MAX_GROUP_SIZE waiters can enter concurrently and thus
> +   increment __wseq.  Therefore, if the xor operation observes a value of
> +   __wseq, then the value it applies the modification to later on can be
> +   derived (see below).
> +
> +   One benefit of this scheme is that this makes load operations
> +   obstruction-free because unlike if we would just lock the counter, readers
> +   can almost always interpret a snapshot of each halves.  Readers can be
> +   forced to read a new snapshot when the read is concurrent with an overflow.
> +   However, overflows will happen infrequently, so load operations are
> +   practically lock-free.
> +
> +   (*) The highest value we add is __PTHREAD_COND_MAX_GROUP_SIZE << 2 to
> +   __g1_start (the two extra bits are for the lock in the two LSBs of
> +   __g1_start).  */

OK. This is a practical obstruction-free algorithm method to use two consistency
markers (the MSB bits) to ensure that you see a consistent value.

> +
> +typedef struct
> +{
> +  unsigned int low;
> +  unsigned int high;
> +} _condvar_lohi;
> +
> +static uint64_t
> +__condvar_fetch_add_64_relaxed (_condvar_lohi *lh, unsigned int op)
> +{
> +  /* S1. Note that this is an atomic read-modify-write so it extends the
> +     release sequence of release MO store at S3.  */
> +  unsigned int l = atomic_fetch_add_relaxed (&lh->low, op);
> +  unsigned int h = atomic_load_relaxed (&lh->high);
> +  uint64_t result = ((uint64_t) h << 31) | l;

OK. The extension of the release MO store is clearly documented in the
comments of __condvar_load_64_relaxed so that makes perfect sense.

> +  l += op;
> +  if ((l >> 31) > 0)
> +    {
> +      /* Overflow.  Need to increment higher-order half.  Note that all
> +	 add operations are ordered in happens-before.  */
> +      h++;
> +      /* S2. Release MO to synchronize with the loads of the higher-order half
> +	 in the load operation.  See __condvar_load_64_relaxed.  */
> +      atomic_store_release (&lh->high, h | ((unsigned int) 1 << 31));
> +      l ^= (unsigned int) 1 << 31;
> +      /* S3.  See __condvar_load_64_relaxed.  */
> +      atomic_store_release (&lh->low, l);
> +      /* S4.  Likewise.  */
> +      atomic_store_release (&lh->high, h);
> +    }
> +  return result;
> +}
> +
> +static uint64_t
> +__condvar_load_64_relaxed (_condvar_lohi *lh)
> +{
> +  unsigned int h, l, h2;
> +  do
> +    {
> +      /* This load and the second one below to the same location read from the
> +	 stores in the overflow handling of the add operation or the
> +	 initializing stores (which is a simple special case because
> +	 initialization always completely happens before further use).
> +	 Because no two stores to the higher-order half write the same value,
> +	 the loop ensures that if we continue to use the snapshot, this load
> +	 and the second one read from the same store operation.  All candidate
> +	 store operations have release MO.
> +	 If we read from S2 in the first load, then we will see the value of
> +	 S1 on the next load (because we synchronize with S2), or a value
> +	 later in modification order.  We correctly ignore the lower-half's
> +	 overflow bit in this case.  If we read from S4, then we will see the
> +	 value of S3 in the next load (or a later value), which does not have
> +	 the overflow bit set anymore.
> +	  */
> +      h = atomic_load_acquire (&lh->high);

OK. Excellent comments.

> +      /* This will read from the release sequence of S3 (i.e, either the S3
> +	 store or the read-modify-writes at S1 following S3 in modification
> +	 order).  Thus, the read synchronizes with S3, and the following load
> +	 of the higher-order half will read from the matching S2 (or a later
> +	 value).
> +	 Thus, if we read a lower-half value here that already overflowed and
> +	 belongs to an increased higher-order half value, we will see the
> +	 latter and h and h2 will not be equal.  */
> +      l = atomic_load_acquire (&lh->low);
> +      /* See above.  */
> +      h2 = atomic_load_relaxed (&lh->high);
> +    }
> +  while (h != h2);

OK. Again, great comments.

> +  if (((l >> 31) > 0) && ((h >> 31) > 0))
> +    l ^= (unsigned int) 1 << 31;
> +  return ((uint64_t) (h & ~((unsigned int) 1 << 31)) << 31) + l;

OK. Assembly of the final value looks good, with a total of 62 usable bits,
which is more than enough for the task at hand.

> +}
> +
> +static uint64_t __attribute__ ((unused))
> +__condvar_load_wseq_relaxed (pthread_cond_t *cond)
> +{
> +  return __condvar_load_64_relaxed ((_condvar_lohi *) &cond->__data.__wseq32);
> +}
> +
> +static uint64_t __attribute__ ((unused))
> +__condvar_fetch_add_wseq_acquire (pthread_cond_t *cond, unsigned int val)
> +{
> +  uint64_t r = __condvar_fetch_add_64_relaxed
> +      ((_condvar_lohi *) &cond->__data.__wseq32, val);
> +  atomic_thread_fence_acquire ();
> +  return r;
> +}
> +
> +static uint64_t __attribute__ ((unused))
> +__condvar_fetch_xor_wseq_release (pthread_cond_t *cond, unsigned int val)
> +{
> +  _condvar_lohi *lh = (_condvar_lohi *) &cond->__data.__wseq32;
> +  /* First, get the current value.  See __condvar_load_64_relaxed.  */
> +  unsigned int h, l, h2;
> +  do
> +    {
> +      h = atomic_load_acquire (&lh->high);
> +      l = atomic_load_acquire (&lh->low);
> +      h2 = atomic_load_relaxed (&lh->high);
> +    }
> +  while (h != h2);

OK. Consistency marker check sequence.

> +  if (((l >> 31) > 0) && ((h >> 31) == 0))
> +    h++;

OK. Count the overflow.

> +  h &= ~((unsigned int) 1 << 31);
> +  l &= ~((unsigned int) 1 << 31);
> +
> +  /* Now modify.  Due to the coherence rules, the prior load will read a value
> +     earlier in modification order than the following fetch-xor.
> +     This uses release MO to make the full operation have release semantics
> +     (all other operations access the lower-order half).  */
> +  unsigned int l2 = atomic_fetch_xor_release (&lh->low, val)
> +      & ~((unsigned int) 1 << 31);
> +  if (l2 < l)
> +    /* The lower-order half overflowed in the meantime.  This happened exactly
> +       once due to the limit on concurrent waiters (see above).  */
> +    h++;

OK.

> +  return ((uint64_t) h << 31) + l2;

OK.

> +}
> +
> +static uint64_t __attribute__ ((unused))
> +__condvar_load_g1_start_relaxed (pthread_cond_t *cond)
> +{
> +  return __condvar_load_64_relaxed
> +      ((_condvar_lohi *) &cond->__data.__g1_start32);
> +}
> +
> +static void __attribute__ ((unused))
> +__condvar_add_g1_start_relaxed (pthread_cond_t *cond, unsigned int val)
> +{
> +  ignore_value (__condvar_fetch_add_64_relaxed
> +      ((_condvar_lohi *) &cond->__data.__g1_start32, val));
> +}
> +
> +#endif  /* !__HAVE_64B_ATOMICS  */
> +
> +
> +/* The lock that signalers use.  See pthread_cond_wait_common for uses.
> +   The lock is our normal three-state lock: not acquired (0) / acquired (1) /
> +   acquired-with-futex_wake-request (2).  However, we need to preserve the
> +   other bits in the unsigned int used for the lock, and therefore it is a
> +   little more complex.  */

OK. Similar to the robust futex case were we must preserve the rest of the bits also.

> +static void __attribute__ ((unused))
> +__condvar_acquire_lock (pthread_cond_t *cond, int private)
> +{
> +  unsigned int s = atomic_load_relaxed (&cond->__data.__g1_orig_size);
> +  while ((s & 3) == 0)
> +    {
> +      if (atomic_compare_exchange_weak_acquire (&cond->__data.__g1_orig_size,
> +	  &s, s | 1))
> +	return;
> +      /* TODO Spinning and back-off.  */
> +    }
> +  /* We can't change from not acquired to acquired, so try to change to
> +     acquired-with-futex-wake-request and do a futex wait if we cannot change
> +     from not acquired.  */
> +  while (1)
> +    {
> +      while ((s & 3) != 2)
> +	{
> +	  if (atomic_compare_exchange_weak_acquire
> +	      (&cond->__data.__g1_orig_size, &s, (s & ~(unsigned int) 3) | 2))
> +	    {
> +	      if ((s & 3) == 0)
> +		return;
> +	      break;
> +	    }
> +	  /* TODO Back off.  */
> +	}
> +      futex_wait_simple (&cond->__data.__g1_orig_size,
> +	  (s & ~(unsigned int) 3) | 2, private);
> +      /* Reload so we see a recent value.  */
> +      s = atomic_load_relaxed (&cond->__data.__g1_orig_size);
> +    }
> +}

OK.

> +
> +/* See __condvar_acquire_lock.  */
> +static void __attribute__ ((unused))
> +__condvar_release_lock (pthread_cond_t *cond, int private)
> +{
> +  if ((atomic_fetch_and_release (&cond->__data.__g1_orig_size,
> +				 ~(unsigned int) 3) & 3)
> +      == 2)
> +    futex_wake (&cond->__data.__g1_orig_size, 1, private);
> +}
> +

OK.

> +/* Only use this when having acquired the lock.  */
> +static unsigned int __attribute__ ((unused))
> +__condvar_get_orig_size (pthread_cond_t *cond)
> +{
> +  return atomic_load_relaxed (&cond->__data.__g1_orig_size) >> 2;
> +}
> +
> +/* Only use this when having acquired the lock.  */
> +static void __attribute__ ((unused))
> +__condvar_set_orig_size (pthread_cond_t *cond, unsigned int size)
> +{
> +  /* We have acquired the lock, but might get one concurrent update due to a
> +     lock state change from acquired to acquired-with-futex_wake-request.
> +     The store with relaxed MO is fine because there will be no further
> +     changes to the lock bits nor the size, and we will subsequently release
> +     the lock with release MO.  */
> +  unsigned int s;
> +  s = (atomic_load_relaxed (&cond->__data.__g1_orig_size) & 3)
> +      | (size << 2);
> +  if ((atomic_exchange_relaxed (&cond->__data.__g1_orig_size, s) & 3)
> +      != (s & 3))
> +    atomic_store_relaxed (&cond->__data.__g1_orig_size, (size << 2) | 2);
> +}

OK.

> +
> +/* Returns FUTEX_SHARED or FUTEX_PRIVATE based on the provided __wrefs
> +   value.  */
> +static int __attribute__ ((unused))
> +__condvar_get_private (int flags)
> +{
> +  if ((flags & __PTHREAD_COND_SHARED_MASK) == 0)
> +    return FUTEX_PRIVATE;
> +  else
> +    return FUTEX_SHARED;
> +}
> +

OK.

> +/* This closes G1 (whose index is in G1INDEX), waits for all futex waiters to
> +   leave G1, converts G1 into a fresh G2, and then switches group roles so that
> +   the former G2 becomes the new G1 ending at the current __wseq value when we
> +   eventually make the switch (WSEQ is just an observation of __wseq by the
> +   signaler).
> +   If G2 is empty, it will not switch groups because then it would create an
> +   empty G1 which would require switching groups again on the next signal.
> +   Returns false iff groups were not switched because G2 was empty.  */

OK.

> +static bool __attribute__ ((unused))
> +__condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
> +    unsigned int *g1index, int private)
> +{
> +  const unsigned int maxspin = 0;
> +  unsigned int g1 = *g1index;
> +
> +  /* If there is no waiter in G2, we don't do anything.  The expression may
> +     look odd but remember that __g_size might hold a negative value, so
> +     putting the expression this way avoids relying on implementation-defined
> +     behavior.
> +     Note that this works correctly for a zero-initialized condvar too.  */
> +  unsigned int old_orig_size = __condvar_get_orig_size (cond);
> +  uint64_t old_g1_start = __condvar_load_g1_start_relaxed (cond) >> 1;
> +  if (((unsigned) (wseq - old_g1_start - old_orig_size)
> +	  + cond->__data.__g_size[g1 ^ 1]) == 0)
> +	return false;

OK.

> +
> +  /* Now try to close and quiesce G1.  We have to consider the following kinds
> +     of waiters:
> +     * Waiters from less recent groups than G1 are not affected because
> +       nothing will change for them apart from __g1_start getting larger.
> +     * New waiters arriving concurrently with the group switching will all go
> +       into G2 until we atomically make the switch.  Waiters existing in G2
> +       are not affected.
> +     * Waiters in G1 will be closed out immediately by setting a flag in
> +       __g_signals, which will prevent waiters from blocking using a futex on
> +       __g_signals and also notifies them that the group is closed.  As a
> +       result, they will eventually remove their group reference, allowing us
> +       to close switch group roles.  */

OK.

> +
> +  /* First, set the closed flag on __g_signals.  This tells waiters that are
> +     about to wait that they shouldn't do that anymore.  This basically
> +     serves as an advance notificaton of the upcoming change to __g1_start;
> +     waiters interpret it as if __g1_start was larger than their waiter
> +     sequence position.  This allows us to change __g1_start after waiting
> +     for all existing waiters with group references to leave, which in turn
> +     makes recovery after stealing a signal simpler because it then can be
> +     skipped if __g1_start indicates that the group is closed (otherwise,
> +     we would have to recover always because waiters don't know how big their
> +     groups are).  Relaxed MO is fine.  */
> +  atomic_fetch_or_relaxed (cond->__data.__g_signals + g1, 1);
> +
> +  /* Wait until there are no group references anymore.  The fetch-or operation
> +     injects us into the modification order of __g_refs; release MO ensures
> +     that waiters incrementing __g_refs after our fetch-or see the previous
> +     changes to __g_signals and to __g1_start that had to happen before we can
> +     switch this G1 and alias with an older group (we have two groups, so
> +     aliasing requires switching group roles twice).  Note that nobody else
> +     can have set the wake-request flag, so we do not have to act upon it.
> +
> +     Also note that it is harmless if older waiters or waiters from this G1
> +     get a group reference after we have quiesced the group because it will
> +     remain closed for them either because of the closed flag in __g_signals
> +     or the later update to __g1_start.  New waiters will never arrive here
> +     but instead continue to go into the still current G2.  */
> +  unsigned r = atomic_fetch_or_release (cond->__data.__g_refs + g1, 0);
> +  while ((r >> 1) > 0)
> +    {
> +      for (unsigned int spin = maxspin; ((r >> 1) > 0) && (spin > 0); spin--)
> +	{
> +	  /* TODO Back off.  */
> +	  r = atomic_load_relaxed (cond->__data.__g_refs + g1);
> +	}
> +      if ((r >> 1) > 0)
> +	{
> +	  /* There is still a waiter after spinning.  Set the wake-request
> +	     flag and block.  Relaxed MO is fine because this is just about
> +	     this futex word.  */
> +	  r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1);
> +
> +	  if ((r >> 1) > 0)
> +	    futex_wait_simple (cond->__data.__g_refs + g1, r, private);
> +	  /* Reload here so we eventually see the most recent value even if we
> +	     do not spin.   */
> +	  r = atomic_load_relaxed (cond->__data.__g_refs + g1);
> +	}
> +    }
> +  /* Acquire MO so that we synchronize with the release operation that waiters
> +     use to decrement __g_refs and thus happen after the waiters we waited
> +     for.  */
> +  atomic_thread_fence_acquire ();
> +
> +  /* Update __g1_start, which finishes closing this group.  The value we add
> +     will never be negative because old_orig_size can only be zero when we
> +     switch groups the first time after a condvar was initialized, in which
> +     case G1 will be at index 1 and we will add a value of 1.  See above for
> +     why this takes place after waiting for quiescence of the group.
> +     Relaxed MO is fine because the change comes with no additional
> +     constraints that others would have to observe.  */
> +  __condvar_add_g1_start_relaxed (cond,
> +      (old_orig_size << 1) + (g1 == 1 ? 1 : - 1));

OK.

> +
> +  /* Now reopen the group, thus enabling waiters to again block using the
> +     futex controlled by __g_signals.  Release MO so that observers that see
> +     no signals (and thus can block) also see the write __g1_start and thus
> +     that this is now a new group (see __pthread_cond_wait_common for the
> +     matching acquire MO loads).  */
> +  atomic_store_release (cond->__data.__g_signals + g1, 0);

OK.

> +
> +  /* At this point, the old G1 is now a valid new G2 (but not in use yet).
> +     No old waiter can neither grab a signal nor acquire a reference without
> +     noticing that __g1_start is larger.
> +     We can now publish the group switch by flipping the G2 index in __wseq.
> +     Release MO so that this synchronizes with the acquire MO operation
> +     waiters use to obtain a position in the waiter sequence.  */
> +  wseq = __condvar_fetch_xor_wseq_release (cond, 1) >> 1;
> +  g1 ^= 1;
> +  *g1index ^= 1;

OK.

> +
> +  /* These values are just observed by signalers, and thus protected by the
> +     lock.  */
> +  unsigned int orig_size = wseq - (old_g1_start + old_orig_size);
> +  __condvar_set_orig_size (cond, orig_size);
> +  /* Use and addition to not loose track of cancellations in what was
> +     previously G2.  */
> +  cond->__data.__g_size[g1] += orig_size;

OK.

> +
> +  /* The new G1's size may be zero because of cancellations during its time
> +     as G2.  If this happens, there are no waiters that have to receive a
> +     signal, so we do not need to add any and return false.  */
> +  if (cond->__data.__g_size[g1] == 0)
> +    return false;
> +
> +  return true;
> +}
> diff --git a/nptl/pthread_cond_destroy.c b/nptl/pthread_cond_destroy.c
> index 1acd804..5845c6a 100644
> --- a/nptl/pthread_cond_destroy.c
> +++ b/nptl/pthread_cond_destroy.c
> @@ -20,66 +20,42 @@
>  #include <shlib-compat.h>
>  #include "pthreadP.h"
>  #include <stap-probe.h>
> -
> -
> +#include <atomic.h>
> +#include <futex-internal.h>
> +
> +#include "pthread_cond_common.c"
> +
> +/* See __pthread_cond_wait for a high-level description of the algorithm.
> +
> +   A correct program must make sure that no waiters are blocked on the condvar
> +   when it is destroyed, and that there are no concurrent signals or
> +   broadcasts.  To wake waiters reliably, the program must signal or
> +   broadcast while holding the mutex or after having held the mutex.  It must
> +   also ensure that no signal or broadcast are still pending to unblock
> +   waiters; IOW, because waiters can wake up spuriously, the program must
> +   effectively ensure that destruction happens after the execution of those
> +   signal or broadcast calls.
> +   Thus, we can assume that all waiters that are still accessing the condvar
> +   have been woken.  We wait until they have confirmed to have woken up by
> +   decrementing __wrefs.  */

OK. I like the the design and it simply meets the POSIX requirements.

>  int
>  __pthread_cond_destroy (pthread_cond_t *cond)
>  {
> -  int pshared = (cond->__data.__mutex == (void *) ~0l)
> -		? LLL_SHARED : LLL_PRIVATE;
> -
>    LIBC_PROBE (cond_destroy, 1, cond);
>  
> -  /* Make sure we are alone.  */
> -  lll_lock (cond->__data.__lock, pshared);
> -
> -  if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
> -    {
> -      /* If there are still some waiters which have not been
> -	 woken up, this is an application bug.  */
> -      lll_unlock (cond->__data.__lock, pshared);
> -      return EBUSY;
> -    }
> -
> -  /* Tell pthread_cond_*wait that this condvar is being destroyed.  */
> -  cond->__data.__total_seq = -1ULL;
> -
> -  /* If there are waiters which have been already signalled or
> -     broadcasted, but still are using the pthread_cond_t structure,
> -     pthread_cond_destroy needs to wait for them.  */
> -  unsigned int nwaiters = cond->__data.__nwaiters;
> -
> -  if (nwaiters >= (1 << COND_NWAITERS_SHIFT))
> +  /* Set the wake request flag.  We could also spin, but destruction that is
> +     concurrent with still-active waiters is probably neither common nor
> +     performance critical.  Acquire MO to synchronize with waiters confirming
> +     that they finished.  */
> +  unsigned int wrefs = atomic_fetch_or_acquire (&cond->__data.__wrefs, 4);
> +  int private = __condvar_get_private (wrefs);
> +  while (wrefs >> 3 != 0)

OK.

>      {
> -      /* Wake everybody on the associated mutex in case there are
> -	 threads that have been requeued to it.
> -	 Without this, pthread_cond_destroy could block potentially
> -	 for a long time or forever, as it would depend on other
> -	 thread's using the mutex.
> -	 When all threads waiting on the mutex are woken up, pthread_cond_wait
> -	 only waits for threads to acquire and release the internal
> -	 condvar lock.  */
> -      if (cond->__data.__mutex != NULL
> -	  && cond->__data.__mutex != (void *) ~0l)
> -	{
> -	  pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
> -	  lll_futex_wake (&mut->__data.__lock, INT_MAX,
> -			  PTHREAD_MUTEX_PSHARED (mut));
> -	}
> -
> -      do
> -	{
> -	  lll_unlock (cond->__data.__lock, pshared);
> -
> -	  lll_futex_wait (&cond->__data.__nwaiters, nwaiters, pshared);
> -
> -	  lll_lock (cond->__data.__lock, pshared);
> -
> -	  nwaiters = cond->__data.__nwaiters;
> -	}
> -      while (nwaiters >= (1 << COND_NWAITERS_SHIFT));
> +      futex_wait_simple (&cond->__data.__wrefs, wrefs, private);
> +      /* See above.  */
> +      wrefs = atomic_load_acquire (&cond->__data.__wrefs);
>      }
> -
> +  /* The memory the condvar occupies can now be reused.  */
>    return 0;
>  }
>  versioned_symbol (libpthread, __pthread_cond_destroy,
> diff --git a/nptl/pthread_cond_init.c b/nptl/pthread_cond_init.c
> index 9023370..cdd9b7d 100644
> --- a/nptl/pthread_cond_init.c
> +++ b/nptl/pthread_cond_init.c
> @@ -19,25 +19,25 @@
>  #include <shlib-compat.h>
>  #include "pthreadP.h"
>  #include <stap-probe.h>
> +#include <string.h>
>  
>  
> +/* See __pthread_cond_wait for details.  */
>  int
>  __pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
>  {
>    struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr;
>  
> -  cond->__data.__lock = LLL_LOCK_INITIALIZER;
> -  cond->__data.__futex = 0;
> -  cond->__data.__nwaiters = (icond_attr != NULL
> -			     ? ((icond_attr->value >> 1)
> -				& ((1 << COND_NWAITERS_SHIFT) - 1))
> -			     : CLOCK_REALTIME);
> -  cond->__data.__total_seq = 0;
> -  cond->__data.__wakeup_seq = 0;
> -  cond->__data.__woken_seq = 0;
> -  cond->__data.__mutex = (icond_attr == NULL || (icond_attr->value & 1) == 0
> -			  ? NULL : (void *) ~0l);
> -  cond->__data.__broadcast_seq = 0;
> +  memset (cond, 0, sizeof (pthread_cond_t));

OK.

> +  /* Iff not equal to ~0l, this is a PTHREAD_PROCESS_PRIVATE condvar.  */
> +  if (icond_attr != NULL && (icond_attr->value & 1) != 0)
> +    cond->__data.__wrefs |= __PTHREAD_COND_SHARED_MASK;
> +  int clockid = (icond_attr != NULL
> +		 ? ((icond_attr->value >> 1) & ((1 << COND_CLOCK_BITS) - 1))
> +		 : CLOCK_REALTIME);
> +  /* If 0, CLOCK_REALTIME is used; CLOCK_MONOTONIC otherwise.  */
> +  if (clockid != CLOCK_REALTIME)
> +    cond->__data.__wrefs |= __PTHREAD_COND_CLOCK_MONOTONIC_MASK;

OK.

>  
>    LIBC_PROBE (cond_init, 2, cond, cond_attr);
>  
> diff --git a/nptl/pthread_cond_signal.c b/nptl/pthread_cond_signal.c
> index b3a6d3d..a95d569 100644
> --- a/nptl/pthread_cond_signal.c
> +++ b/nptl/pthread_cond_signal.c
> @@ -19,62 +19,79 @@
>  #include <endian.h>
>  #include <errno.h>
>  #include <sysdep.h>
> -#include <lowlevellock.h>
> +#include <futex-internal.h>
>  #include <pthread.h>
>  #include <pthreadP.h>
> +#include <atomic.h>
> +#include <stdint.h>
>  
>  #include <shlib-compat.h>
> -#include <kernel-features.h>
>  #include <stap-probe.h>
>  
> +#include "pthread_cond_common.c"
>  
> +/* See __pthread_cond_wait for a high-level description of the algorithm.  */
>  int
>  __pthread_cond_signal (pthread_cond_t *cond)
>  {
> -  int pshared = (cond->__data.__mutex == (void *) ~0l)
> -		? LLL_SHARED : LLL_PRIVATE;
> -
>    LIBC_PROBE (cond_signal, 1, cond);
>  
> -  /* Make sure we are alone.  */
> -  lll_lock (cond->__data.__lock, pshared);
> -
> -  /* Are there any waiters to be woken?  */
> -  if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
> +  /* First check whether there are waiters.  Relaxed MO is fine for that for
> +     the same reasons that relaxed MO is fine when observing __wseq (see
> +     below).  */
> +  unsigned int wrefs = atomic_load_relaxed (&cond->__data.__wrefs);
> +  if (wrefs >> 3 == 0)
> +    return 0;
> +  int private = __condvar_get_private (wrefs);
> +
> +  __condvar_acquire_lock (cond, private);
> +
> +  /* Load the waiter sequence number, which represents our relative ordering
> +     to any waiters.  Relaxed MO is sufficient for that because:
> +     1) We can pick any position that is allowed by external happens-before
> +        constraints.  In particular, if another __pthread_cond_wait call
> +        happened before us, this waiter must be eligible for being woken by
> +        us.  The only way do establish such a happens-before is by signaling
> +        while having acquired the mutex associated with the condvar and
> +        ensuring that the signal's critical section happens after the waiter.
> +        Thus, the mutex ensures that we see that waiter's __wseq increase.
> +     2) Once we pick a position, we do not need to communicate this to the
> +        program via a happens-before that we set up: First, any wake-up could
> +        be a spurious wake-up, so the program must not interpret a wake-up as
> +        an indication that the waiter happened before a particular signal;
> +        second, a program cannot detect whether a waiter has not yet been
> +        woken (i.e., it cannot distinguish between a non-woken waiter and one
> +        that has been woken but hasn't resumed execution yet), and thus it
> +        cannot try to deduce that a signal happened before a particular
> +        waiter.  */
> +  unsigned long long int wseq = __condvar_load_wseq_relaxed (cond);
> +  unsigned int g1 = (wseq & 1) ^ 1;
> +  wseq >>= 1;
> +  bool do_futex_wake = false;
> +
> +  /* If G1 is still receiving signals, we put the signal there.  If not, we
> +     check if G2 has waiters, and if so, quiesce and switch G1 to the former
> +     G2; if this results in a new G1 with waiters (G2 might have cancellations
> +     already, see __condvar_quiesce_and_switch_g1), we put the signal in the
> +     new G1.  */
> +  if ((cond->__data.__g_size[g1] != 0)
> +      || __condvar_quiesce_and_switch_g1 (cond, wseq, &g1, private))
>      {
> -      /* Yes.  Mark one of them as woken.  */
> -      ++cond->__data.__wakeup_seq;
> -      ++cond->__data.__futex;
> -
> -#if (defined lll_futex_cmp_requeue_pi \
> -     && defined __ASSUME_REQUEUE_PI)
> -      pthread_mutex_t *mut = cond->__data.__mutex;
> -
> -      if (USE_REQUEUE_PI (mut)
> -	/* This can only really fail with a ENOSYS, since nobody can modify
> -	   futex while we have the cond_lock.  */
> -	  && lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, 0,
> -				       &mut->__data.__lock,
> -				       cond->__data.__futex, pshared) == 0)
> -	{
> -	  lll_unlock (cond->__data.__lock, pshared);
> -	  return 0;
> -	}
> -      else
> -#endif
> -	/* Wake one.  */
> -	if (! __builtin_expect (lll_futex_wake_unlock (&cond->__data.__futex,
> -						       1, 1,
> -						       &cond->__data.__lock,
> -						       pshared), 0))
> -	  return 0;
> -
> -      /* Fallback if neither of them work.  */
> -      lll_futex_wake (&cond->__data.__futex, 1, pshared);
> +      /* Add a signal.  Relaxed MO is fine because signaling does not need to
> +	 establish a happens-before relation (see above).  We do not mask the
> +	 release-MO store when initializing a group in
> +	 __condvar_quiesce_and_switch_g1 because we use an atomic
> +	 read-modify-write and thus extend that store's release sequence.  */
> +      atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, 2);
> +      cond->__data.__g_size[g1]--;
> +      /* TODO Only set it if there are indeed futex waiters.  */
> +      do_futex_wake = true;

OK.

>      }
>  
> -  /* We are done.  */
> -  lll_unlock (cond->__data.__lock, pshared);
> +  __condvar_release_lock (cond, private);
> +
> +  if (do_futex_wake)
> +    futex_wake (cond->__data.__g_signals + g1, 1, private);
>  
>    return 0;
>  }
> diff --git a/nptl/pthread_cond_timedwait.c b/nptl/pthread_cond_timedwait.c
> deleted file mode 100644
> index 711a51d..0000000
> --- a/nptl/pthread_cond_timedwait.c
> +++ /dev/null
> @@ -1,268 +0,0 @@

OK. Merged into the pthread_cond_wait.c file.

> diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
> index 3f62acc..984f01f 100644
> --- a/nptl/pthread_cond_wait.c
> +++ b/nptl/pthread_cond_wait.c
> @@ -19,219 +19,653 @@
>  #include <endian.h>
>  #include <errno.h>
>  #include <sysdep.h>
> -#include <lowlevellock.h>
> +#include <futex-internal.h>
>  #include <pthread.h>
>  #include <pthreadP.h>
> -#include <kernel-features.h>
> +#include <sys/time.h>
> +#include <atomic.h>
> +#include <stdint.h>
> +#include <stdbool.h>
>  
>  #include <shlib-compat.h>
>  #include <stap-probe.h>
> +#include <time.h>
> +
> +#include "pthread_cond_common.c"
> +
>  
>  struct _condvar_cleanup_buffer
>  {
> -  int oldtype;
> +  uint64_t wseq;

OK.

>    pthread_cond_t *cond;
>    pthread_mutex_t *mutex;
> -  unsigned int bc_seq;
> +  int private;

OK.

>  };

OK. We can change this internal cleanup buffer as much as we want
since it's private and not part of the ABI.

>  
>  
> -void
> -__attribute__ ((visibility ("hidden")))
> -__condvar_cleanup (void *arg)
> +/* Decrease the waiter reference count.  */
> +static void
> +__condvar_confirm_wakeup (pthread_cond_t *cond, int private)
>  {
> -  struct _condvar_cleanup_buffer *cbuffer =
> -    (struct _condvar_cleanup_buffer *) arg;
> -  unsigned int destroying;
> -  int pshared = (cbuffer->cond->__data.__mutex == (void *) ~0l)
> -		? LLL_SHARED : LLL_PRIVATE;
> +  /* If destruction is pending (i.e., the wake-request flag is nonzero) and we
> +     are the last waiter (prior value of __wrefs was 1 << 3), then wake any
> +     threads waiting in pthread_cond_destroy.  Release MO to synchronize with
> +     these threads.  Don't bother clearing the wake-up request flag.  */
> +  if ((atomic_fetch_add_release (&cond->__data.__wrefs, -8) >> 2) == 3)
> +    futex_wake (&cond->__data.__wrefs, INT_MAX, private);
> +}

OK.

> +
>  
> -  /* We are going to modify shared data.  */
> -  lll_lock (cbuffer->cond->__data.__lock, pshared);
> +/* Cancel waiting after having registered as a waiter previously.  SEQ is our
> +   position and G is our group index.
> +   The goal of cancellation is to make our group smaller if that is still
> +   possible.  If we are in a closed group, this is not possible anymore; in
> +   this case, we need to send a replacement signal for the one we effectively
> +   consumed because the signal should have gotten consumed by another waiter
> +   instead; we must not both cancel waiting and consume a signal.
> +
> +   Must not be called while still holding a reference on the group.
> +
> +   Returns true iff we consumed a signal.
> +
> +   On some kind of timeouts, we may be able to pretend that a signal we
> +   effectively consumed happened before the timeout (i.e., similarly to first
> +   spinning on signals before actually checking whether the timeout has
> +   passed already).  Doing this would allow us to skip sending a replacement
> +   signal, but this case might happen rarely because the end of the timeout
> +   must race with someone else sending a signal.  Therefore, we don't bother
> +   trying to optimize this.  */

OK. Good comment.

> +static void
> +__condvar_cancel_waiting (pthread_cond_t *cond, uint64_t seq, unsigned int g,
> +			  int private)
> +{
> +  bool consumed_signal = false;
>  
> -  if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq)
> +  /* No deadlock with group switching is possible here because we have do
> +     not hold a reference on the group.  */
> +  __condvar_acquire_lock (cond, private);

OK.

> +
> +  uint64_t g1_start = __condvar_load_g1_start_relaxed (cond) >> 1;
> +  if (g1_start > seq)
> +    {
> +      /* Our group is closed, so someone provided enough signals for it.
> +	 Thus, we effectively consumed a signal.  */
> +      consumed_signal = true;

OK.

> +    }
> +  else
>      {
> -      /* This thread is not waiting anymore.  Adjust the sequence counters
> -	 appropriately.  We do not increment WAKEUP_SEQ if this would
> -	 bump it over the value of TOTAL_SEQ.  This can happen if a thread
> -	 was woken and then canceled.  */
> -      if (cbuffer->cond->__data.__wakeup_seq
> -	  < cbuffer->cond->__data.__total_seq)
> +      if (g1_start + __condvar_get_orig_size (cond) <= seq)
> +	{
> +	  /* We are in the current G2 and thus cannot have consumed a signal.
> +	     Reduce its effective size or handle overflow.  Remember that in
> +	     G2, unsigned int size is zero or a negative value.  */
> +	  if (cond->__data.__g_size[g] + __PTHREAD_COND_MAX_GROUP_SIZE > 0)
> +	    {
> +	      cond->__data.__g_size[g]--;
> +	    }
> +	  else
> +	    {
> +	      /* Cancellations would overflow the maximum group size.  Just
> +		 wake up everyone spuriously to create a clean state.  This
> +		 also means we do not consume a signal someone else sent.  */
> +	      __condvar_release_lock (cond, private);
> +	      __pthread_cond_broadcast (cond);
> +	      return;

OK. I guess the idea is that maybe someone will be able to make progress and
reduce the number of waiters, otherwise we're going to be in a similar situation
pretty soon. So performance degrades at the limit of the implementation, which
is fine.

> +	    }
> +	}
> +      else
>  	{
> -	  ++cbuffer->cond->__data.__wakeup_seq;
> -	  ++cbuffer->cond->__data.__futex;
> +	  /* We are in current G1.  If the group's size is zero, someone put
> +	     a signal in the group that nobody else but us can consume.  */
> +	  if (cond->__data.__g_size[g] == 0)
> +	    consumed_signal = true;
> +	  else
> +	    {
> +	      /* Otherwise, we decrease the size of the group.  This is
> +		 equivalent to atomically putting in a signal just for us and
> +		 consuming it right away.  We do not consume a signal sent
> +		 by someone else.  We also cannot have consumed a futex
> +		 wake-up because if we were cancelled or timed out in a futex
> +		 call, the futex will wake another waiter.  */
> +	      cond->__data.__g_size[g]--;
> +	    }
>  	}
> -      ++cbuffer->cond->__data.__woken_seq;
>      }
>  
> -  cbuffer->cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT;
> +  __condvar_release_lock (cond, private);
>  

OK.

> -  /* If pthread_cond_destroy was called on this variable already,
> -     notify the pthread_cond_destroy caller all waiters have left
> -     and it can be successfully destroyed.  */
> -  destroying = 0;
> -  if (cbuffer->cond->__data.__total_seq == -1ULL
> -      && cbuffer->cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT))
> +  if (consumed_signal)
>      {
> -      lll_futex_wake (&cbuffer->cond->__data.__nwaiters, 1, pshared);
> -      destroying = 1;
> +      /* We effectively consumed a signal even though we didn't want to.
> +	 Therefore, we need to send a replacement signal.
> +	 If we would want to optimize this, we could do what
> +	 pthread_cond_signal does right in the critical section above.  */
> +      __pthread_cond_signal (cond);

OK.

>      }
> +}
>  
> -  /* We are done.  */
> -  lll_unlock (cbuffer->cond->__data.__lock, pshared);
> -
> -  /* Wake everybody to make sure no condvar signal gets lost.  */
> -  if (! destroying)
> -    lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX, pshared);
> -
> -  /* Get the mutex before returning unless asynchronous cancellation
> -     is in effect.  We don't try to get the mutex if we already own it.  */
> -  if (!(USE_REQUEUE_PI (cbuffer->mutex))
> -      || ((cbuffer->mutex->__data.__lock & FUTEX_TID_MASK)
> -	  != THREAD_GETMEM (THREAD_SELF, tid)))
> -  {
> -    __pthread_mutex_cond_lock (cbuffer->mutex);
> -  }
> -  else
> -    __pthread_mutex_cond_lock_adjust (cbuffer->mutex);
> +/* Wake up any signalers that might be waiting.  */
> +static void
> +__condvar_dec_grefs (pthread_cond_t *cond, unsigned int g, int private)
> +{
> +  /* Release MO to synchronize-with the acquire load in
> +     __condvar_quiesce_and_switch_g1.  */
> +  if (atomic_fetch_add_release (cond->__data.__g_refs + g, -2) == 3)
> +    {
> +      /* Clear the wake-up request flag before waking up.  We do not need more
> +	 than relaxed MO and it doesn't matter if we apply this for an aliased
> +	 group because we wake all futex waiters right after clearing the
> +	 flag.  */
> +      atomic_fetch_and_relaxed (cond->__data.__g_refs + g, ~(unsigned int) 1);
> +      futex_wake (cond->__data.__g_refs + g, INT_MAX, private);
> +    }
>  }

OK.

>  
> +/* Clean-up for cancellation of waiters waiting for normal signals.  We cancel
> +   our registration as a waiter, confirm we have woken up, and re-acquire the
> +   mutex.  */
> +static void
> +__condvar_cleanup_waiting (void *arg)
> +{
> +  struct _condvar_cleanup_buffer *cbuffer =
> +    (struct _condvar_cleanup_buffer *) arg;
> +  pthread_cond_t *cond = cbuffer->cond;
> +  unsigned g = cbuffer->wseq & 1;
>  
> -int
> -__pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
> +  __condvar_dec_grefs (cond, g, cbuffer->private);
> +
> +  __condvar_cancel_waiting (cond, cbuffer->wseq >> 1, g, cbuffer->private);
> +  /* FIXME With the current cancellation implementation, it is possible that
> +     a thread is cancelled after it has returned from a syscall.  This could
> +     result in a cancelled waiter consuming a futex wake-up that is then
> +     causing another waiter in the same group to not wake up.  To work around
> +     this issue until we have fixed cancellation, just add a futex wake-up
> +     conservatively.  */
> +  futex_wake (cond->__data.__g_signals + g, 1, cbuffer->private);

OK. Agreed.

> +
> +  __condvar_confirm_wakeup (cond, cbuffer->private);
> +
> +  /* XXX If locking the mutex fails, should we just stop execution?  This
> +     might be better than silently ignoring the error.  */

OK. This is worse than the case of the internal unlock failing, since there
one assumes the process eventually deadlocks. Here I think we have no choice
but to abort. However, for now it is fine that we do nothing. Please file
a bug about this if you haven't already to fix this up later. I think it is
exceedinly rare that the lock would fail to be acquired, but maybe, if we were
very close to the machine memory limit and kernel futex queue setup failed.

> +  __pthread_mutex_cond_lock (cbuffer->mutex);
> +}
> +
> +/* This condvar implementation guarantees that all calls to signal and
> +   broadcast and all of the three virtually atomic parts of each call to wait
> +   (i.e., (1) releasing the mutex and blocking, (2) unblocking, and (3) re-
> +   acquiring the mutex) happen in some total order that is consistent with the
> +   happens-before relations in the calling program.  However, this order does
> +   not necessarily result in additional happens-before relations being
> +   established (which aligns well with spurious wake-ups being allowed).
> +

OK.

> +   All waiters acquire a certain position in a 64b waiter sequence (__wseq).
> +   This sequence determines which waiters are allowed to consume signals.
> +   A broadcast is equal to sending as many signals as are unblocked waiters.
> +   When a signal arrives, it samples the current value of __wseq with a
> +   relaxed-MO load (i.e., the position the next waiter would get).  (This is
> +   sufficient because it is consistent with happens-before; the caller can
> +   enforce stronger ordering constraints by calling signal while holding the
> +   mutex.)  Only waiters with a position less than the __wseq value observed
> +   by the signal are eligible to consume this signal.
> +

OK.

> +   This would be straight-forward to implement if waiters would just spin but
> +   we need to let them block using futexes.  Futexes give no guarantee of
> +   waking in FIFO order, so we cannot reliably wake eligible waiters if we
> +   just use a single futex.  Also, futex words are 32b in size, but we need
> +   to distinguish more than 1<<32 states because we need to represent the
> +   order of wake-up (and thus which waiters are eligible to consume signals);
> +   blocking in a futex is not atomic with a waiter determining its position in
> +   the waiter sequence, so we need the futex word to reliably notify waiters
> +   that they should not attempt to block anymore because they have been
> +   already signaled in the meantime.  While an ABA issue on a 32b value will
> +   be rare, ignoring it when we are aware of it is not the right thing to do
> +   either.
> +

OK.

> +   Therefore, we use a 64b counter to represent the waiter sequence (on
> +   architectures which only support 32b atomics, we use a few bits less).
> +   To deal with the blocking using futexes, we maintain two groups of waiters:
> +   * Group G1 consists of waiters that are all eligible to consume signals;
> +     incoming signals will always signal waiters in this group until all
> +     waiters in G1 have been signaled.
> +   * Group G2 consists of waiters that arrive when a G1 is present and still
> +     contains waiters that have not been signaled.  When all waiters in G1
> +     are signaled and a new signal arrives, the new signal will convert G2
> +     into the new G1 and create a new G2 for future waiters.
> +

OK. Conceptually it's nice and easy to think of G1/G2, and I admire the simplicity
of a closed G1 while signaling is happening, and an open G2 (though I had slight
trepidation that size == 0 for G2 since it's unbounded and growing but it's a
reasonable design tradeoff).

> +   We cannot allocate new memory because of process-shared condvars, so we
> +   have just two slots of groups that change their role between G1 and G2.
> +   Each has a separate futex word, a number of signals available for
> +   consumption, a size (number of waiters in the group that have not been
> +   signaled), and a reference count.
> +

OK. You _could_ allocate memory for non-process-shared though if it gave you some
kind of performance win, but yes, you effectively need two algorithms then one
for process shared and another for non-process-shared. All things to consider later
(like if we really want to support 32-bit/64-bit shared mutexes/condvars like we
might have to for nscd shared maps).

> +   The group reference count is used to maintain the number of waiters that
> +   are using the group's futex.  Before a group can change its role, the
> +   reference count must show that no waiters are using the futex anymore; this
> +   prevents ABA issues on the futex word.
> +

OK.

> +   To represent which intervals in the waiter sequence the groups cover (and
> +   thus also which group slot contains G1 or G2), we use a 64b counter to
> +   designate the start position of G1 (inclusive), and a single bit in the
> +   waiter sequence counter to represent which group slot currently contains
> +   G2.  This allows us to switch group roles atomically wrt. waiters obtaining
> +   a position in the waiter sequence.  The G1 start position allows waiters to
> +   figure out whether they are in a group that has already been completely
> +   signaled (i.e., if the current G1 starts at a later position that the
> +   waiter's position).  Waiters cannot determine whether they are currently
> +   in G2 or G1 -- but they do not have too because all they are interested in
> +   is whether there are available signals, and they always start in G2 (whose
> +   group slot they know because of the bit in the waiter sequence.  Signalers
> +   will simply fill the right group until it is completely signaled and can
> +   be closed (they do not switch group roles until they really have to to
> +   decrease the likelihood of having to wait for waiters still holding a
> +   reference on the now-closed G1).

OK. Again, I like the design, and the comments are great.

> +
> +   Signalers maintain the initial size of G1 to be able to determine where
> +   G2 starts (G2 is always open-ended until it becomes G1).  They track the
> +   remaining size of a group; when waiters cancel waiting (due to PThreads
> +   cancellation or timeouts), they will decrease this remaining size as well.
> +

OK.

> +   To implement condvar destruction requirements (i.e., that
> +   pthread_cond_destroy can be called as soon as all waiters have been
> +   signaled), waiters increment a reference count before starting to wait and
> +   decrement it after they stopped waiting but right before they acquire the
> +   mutex associated with the condvar.

OK.

> +
> +   pthread_cond_t thus consists of the following (bits that are used for
> +   flags and are not part of the primary value of each field but necessary
> +   to make some things atomic or because there was no space for them
> +   elsewhere in the data structure):

OK.

> +
> +   __wseq: Waiter sequence counter
> +     * LSB is index of current G2.
> +     * Waiters fetch-add while having acquire the mutex associated with the
> +       condvar.  Signalers load it and fetch-xor it concurrently.

OK.

> +   __g1_start: Starting position of G1 (inclusive)
> +     * LSB is index of current G2.
> +     * Modified by signalers while having acquired the condvar-internal lock
> +       and observed concurrently by waiters.

OK.

> +   __g1_orig_size: Initial size of G1
> +     * The two least-significant bits represent the condvar-internal lock.
> +     * Only accessed while having acquired the condvar-internal lock.

OK.

> +   __wrefs: Waiter reference counter.
> +     * Bit 2 is true if waiters should run futex_wake when they remove the
> +       last reference.  pthread_cond_destroy uses this as futex word.
> +     * Bit 1 is the clock ID (0 == CLOCK_REALTIME, 1 == CLOCK_MONOTONIC).
> +     * Bit 0 is true iff this is a process-shared condvar.
> +     * Simple reference count used by both waiters and pthread_cond_destroy.

OK.

> +   For each of the two groups, we have:
> +   __g_refs: Futex waiter reference count.
> +     * LSB is true if waiters should run futex_wake when they remove the
> +       last reference.
> +     * Reference count used by waiters concurrently with signalers that have
> +       acquired the condvar-internal lock.

OK.

> +   __g_signals: The number of signals that can still be consumed.
> +     * Used as a futex word by waiters.  Used concurrently by waiters and
> +       signalers.
> +     * LSB is true iff this group has been completely signaled (i.e., it is
> +       closed).

OK.

> +   __g_size: Waiters remaining in this group (i.e., which have not been
> +     signaled yet.
> +     * Accessed by signalers and waiters that cancel waiting (both do so only
> +       when having acquired the condvar-internal lock.
> +     * The size of G2 is always zero because it cannot be determined until
> +       the group becomes G1.
> +     * Although this is of unsigned type, we rely on using unsigned overflow
> +       rules to make this hold effectively negative values too (in
> +       particular, when waiters in G2 cancel waiting).

OK.

> +
> +   A PTHREAD_COND_INITIALIZER condvar has all fields set to zero, which yields
> +   a condvar that has G2 starting at position 0 and a G1 that is closed.

OK. This is critically important that the static initializers continue working.

> +
> +   Because waiters do not claim ownership of a group right when obtaining a
> +   position in __wseq but only reference count the group when using futexes
> +   to block, it can happen that a group gets closed before a waiter can
> +   increment the reference count.  Therefore, waiters have to check whether
> +   their group is already closed using __g1_start.  They also have to perform
> +   this check when spinning when trying to grab a signal from __g_signals.
> +   Note that for these checks, using relaxed MO to load __g1_start is
> +   sufficient because if a waiter can see a sufficiently large value, it could
> +   have also consume a signal in the waiters group.
> +
> +   Waiters try to grab a signal from __g_signals without holding a reference
> +   count, which can lead to stealing a signal from a more recent group after
> +   their own group was already closed.  They cannot always detect whether they
> +   in fact did because they do not know when they stole, but they can
> +   conservatively add a signal back to the group they stole from; if they
> +   did so unnecessarily, all that happens is a spurious wake-up.  To make this
> +   even less likely, __g1_start contains the index of the current g2 too,
> +   which allows waiters to check if there aliasing on the group slots; if
> +   there wasn't, they didn't steal from the current G1, which means that the
> +   G1 they stole from must have been already closed and they do not need to
> +   fix anything.

OK. I reviewed the spurious wake-up case here in the related code and it looks
good to me.

> +
> +   It is essential that the last field in pthread_cond_t is __g_signals[1]:
> +   The previous condvar used a pointer-sized field in pthread_cond_t, so a
> +   PTHREAD_COND_INITIALIZER from that condvar implementation might only
> +   initialize 4 bytes to zero instead of the 8 bytes we need (i.e., 44 bytes
> +   in total instead of the 48 we need).  __g_signals[1] is not accessed before
> +   the first group switch (G2 starts at index 0), which will set its value to
> +   zero after a harmless fetch-or whose return value is ignored.  This
> +   effectively completes initialization.

OK. Ugh, I wish the initializer had just used the char[] to initialize all the
fields to zero, since that would make it trivially correct.

> +
> +
> +   Limitations:
> +   * This condvar isn't designed to allow for more than
> +     __PTHREAD_COND_MAX_GROUP_SIZE * (1 << 31) calls to __pthread_cond_wait.

OK.

> +   * More than __PTHREAD_COND_MAX_GROUP_SIZE concurrent waiters are not
> +     supported.

OK. While "not designed" is true, it probably will work, just not very optimally
since we detect waiter overflow and spuriously wake everyone because we can't
track their state correctly?

> +   * Beyond what is allowed as errors by POSIX or documented, we can also
> +     return the following errors:
> +     * EPERM if MUTEX is a recursive mutex and the caller doesn't own it.
> +     * EOWNERDEAD or ENOTRECOVERABLE when using robust mutexes.  Unlike
> +       for other errors, this can happen when we re-acquire the mutex; this
> +       isn't allowed by POSIX (which requires all errors to virtually happen
> +       before we release the mutex or change the condvar state), but there's
> +       nothing we can do really.
> +     * When using PTHREAD_MUTEX_PP_* mutexes, we can also return all errors
> +       returned by __pthread_tpp_change_priority.  We will already have
> +       released the mutex in such cases, so the caller cannot expect to own
> +       MUTEX.

OK.

> +
> +   Other notes:
> +   * Instead of the normal mutex unlock / lock functions, we use
> +     __pthread_mutex_unlock_usercnt(m, 0) / __pthread_mutex_cond_lock(m)
> +     because those will not change the mutex-internal users count, so that it
> +     can be detected when a condvar is still associated with a particular
> +     mutex because there is a waiter blocked on this condvar using this mutex.

OK. Good point.

> +*/
> +static __always_inline int
> +__pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
> +    const struct timespec *abstime)
>  {
> -  struct _pthread_cleanup_buffer buffer;
> -  struct _condvar_cleanup_buffer cbuffer;
> +  const int maxspin = 0;
>    int err;
> -  int pshared = (cond->__data.__mutex == (void *) ~0l)
> -		? LLL_SHARED : LLL_PRIVATE;
> -
> -#if (defined lll_futex_wait_requeue_pi \
> -     && defined __ASSUME_REQUEUE_PI)
> -  int pi_flag = 0;
> -#endif
> +  int result = 0;
>  
>    LIBC_PROBE (cond_wait, 2, cond, mutex);
>  
> -  /* Make sure we are alone.  */
> -  lll_lock (cond->__data.__lock, pshared);
> -
> -  /* Now we can release the mutex.  */
> +  /* Acquire a position (SEQ) in the waiter sequence (WSEQ).  We use an
> +     atomic operation because signals and broadcasts may update the group
> +     switch without acquiring the mutex.  We do not need release MO here
> +     because we do not need to establish any happens-before relation with
> +     signalers (see __pthread_cond_signal); modification order alone
> +     establishes a total order of waiters/signals.  We do need acquire MO
> +     to synchronize with group reinitialization in
> +     __condvar_quiesce_and_switch_g1.  */
> +  uint64_t wseq = __condvar_fetch_add_wseq_acquire (cond, 2);

OK. Add 2 because we want to leave LSB alone since it indicates G1/G2 position.

> +  /* Find our group's index.  We always go into what was G2 when we acquired
> +     our position.  */
> +  unsigned int g = wseq & 1;
> +  uint64_t seq = wseq >> 1;
> +
> +  /* Increase the waiter reference count.  Relaxed MO is sufficient because
> +     we only need to synchronize when decrementing the reference count.  */
> +  unsigned int flags = atomic_fetch_add_relaxed (&cond->__data.__wrefs, 8);

OK. Increment by 8 because bits 2-0 are reserved (futex wake, clock id, pshared).

> +  int private = __condvar_get_private (flags);
> +
> +  /* Now that we are registered as a waiter, we can release the mutex.
> +     Waiting on the condvar must be atomic with releasing the mutex, so if
> +     the mutex is used to establish a happens-before relation with any
> +     signaler, the waiter must be visible to the latter; thus, we release the
> +     mutex after registering as waiter.
> +     If releasing the mutex fails, we just cancel our registration as a
> +     waiter and confirm that we have woken up.  */
>    err = __pthread_mutex_unlock_usercnt (mutex, 0);
> -  if (__glibc_unlikely (err))
> +  if (__glibc_unlikely (err != 0))
>      {
> -      lll_unlock (cond->__data.__lock, pshared);
> +      __condvar_cancel_waiting (cond, seq, g, private);
> +      __condvar_confirm_wakeup (cond, private);

OK.

>        return err;
>      }
>  
> -  /* We have one new user of the condvar.  */
> -  ++cond->__data.__total_seq;
> -  ++cond->__data.__futex;
> -  cond->__data.__nwaiters += 1 << COND_NWAITERS_SHIFT;
> -
> -  /* Remember the mutex we are using here.  If there is already a
> -     different address store this is a bad user bug.  Do not store
> -     anything for pshared condvars.  */
> -  if (cond->__data.__mutex != (void *) ~0l)
> -    cond->__data.__mutex = mutex;
> -
> -  /* 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, &cbuffer);
> -
> -  /* The current values of the wakeup counter.  The "woken" counter
> -     must exceed this value.  */
> -  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;
> +  /* Now wait until a signal is available in our group or it is closed.
> +     Acquire MO so that if we observe a value of zero written after group
> +     switching in __condvar_quiesce_and_switch_g1, we synchronize with that
> +     store and will see the prior update of __g1_start done while switching
> +     groups too.  */
> +  unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
>  

OK.

>    do
>      {
> -      unsigned int futex_val = cond->__data.__futex;
> -      /* Prepare to wait.  Release the condvar futex.  */
> -      lll_unlock (cond->__data.__lock, pshared);
> -
> -      /* Enable asynchronous cancellation.  Required by the standard.  */
> -      cbuffer.oldtype = __pthread_enable_asynccancel ();
> -
> -#if (defined lll_futex_wait_requeue_pi \
> -     && defined __ASSUME_REQUEUE_PI)
> -      /* If pi_flag remained 1 then it means that we had the lock and the mutex
> -	 but a spurious waker raced ahead of us.  Give back the mutex before
> -	 going into wait again.  */
> -      if (pi_flag)
> +      while (1)
>  	{
> -	  __pthread_mutex_cond_lock_adjust (mutex);
> -	  __pthread_mutex_unlock_usercnt (mutex, 0);
> +	  /* Spin-wait first.
> +	     Note that spinning first without checking whether a timeout
> +	     passed might lead to what looks like a spurious wake-up even
> +	     though we should return ETIMEDOUT (e.g., if the caller provides
> +	     an absolute timeout that is clearly in the past).  However,
> +	     (1) spurious wake-ups are allowed, (2) it seems unlikely that a
> +	     user will (ab)use pthread_cond_wait as a check for whether a
> +	     point in time is in the past, and (3) spinning first without
> +	     having to compare against the current time seems to be the right
> +	     choice from a performance perspective for most use cases.  */

OK. I can agree with (1), (2), and (3).

> +	  unsigned int spin = maxspin;
> +	  while (signals == 0 && spin > 0)
> +	    {
> +	      /* Check that we are not spinning on a group that's already
> +		 closed.  */
> +	      if (seq < (__condvar_load_g1_start_relaxed (cond) >> 1))
> +		goto done;
> +
> +	      /* TODO Back off.  */
> +
> +	      /* Reload signals.  See above for MO.  */
> +	      signals = atomic_load_acquire (cond->__data.__g_signals + g);
> +	      spin--;
> +	    }
> +
> +	  /* If our group will be closed as indicated by the flag on signals,
> +	     don't bother grabbing a signal.  */
> +	  if (signals & 1)
> +	    goto done;

OK.

> +
> +	  /* If there is an available signal, don't block.  */
> +	  if (signals != 0)
> +	    break;

OK.

> +
> +	  /* No signals available after spinning, so prepare to block.
> +	     We first acquire a group reference and use acquire MO for that so
> +	     that we synchronize with the dummy read-modify-write in
> +	     __condvar_quiesce_and_switch_g1 if we read from that.  In turn,
> +	     in this case this will make us see the closed flag on __g_signals
> +	     that designates a concurrent attempt to reuse the group's slot.
> +	     We use acquire MO for the __g_signals check to make the
> +	     __g1_start check work (see spinning above).
> +	     Note that the group reference acquisition will not mask the
> +	     release MO when decrementing the reference count because we use
> +	     an atomic read-modify-write operation and thus extend the release
> +	     sequence.  */
> +	  atomic_fetch_add_acquire (cond->__data.__g_refs + g, 2);
> +	  if (((atomic_load_acquire (cond->__data.__g_signals + g) & 1) != 0)
> +	      || (seq < (__condvar_load_g1_start_relaxed (cond) >> 1)))
> +	    {
> +	      /* Our group is closed.  Wake up any signalers that might be
> +		 waiting.  */
> +	      __condvar_dec_grefs (cond, g, private);
> +	      goto done;
> +	    }

OK. This is complex and a lot to digest, but I see no simpler way to split up
these conditionals.

> +
> +	  // Now block.
> +	  struct _pthread_cleanup_buffer buffer;
> +	  struct _condvar_cleanup_buffer cbuffer;
> +	  cbuffer.wseq = wseq;
> +	  cbuffer.cond = cond;
> +	  cbuffer.mutex = mutex;
> +	  cbuffer.private = private;
> +	  __pthread_cleanup_push (&buffer, __condvar_cleanup_waiting, &cbuffer);
> +
> +	  if (abstime == NULL)
> +	    {
> +	      /* Block without a timeout.  */
> +	      err = futex_wait_cancelable (
> +		  cond->__data.__g_signals + g, 0, private);
> +	    }
> +	  else
> +	    {
> +	      /* Block, but with a timeout.
> +		 Work around the fact that the kernel rejects negative timeout
> +		 values despite them being valid.  */
> +	      if (__glibc_unlikely (abstime->tv_sec < 0))
> +	        err = ETIMEDOUT;
> +
> +	      else if ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0)
> +		{
> +		  /* CLOCK_MONOTONIC is requested.  */
> +		  struct timespec rt;
> +		  if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
> +		    __libc_fatal ("clock_gettime does not support "
> +				  "CLOCK_MONOTONIC");
> +		  /* Convert the absolute timeout value to a relative
> +		     timeout.  */
> +		  rt.tv_sec = abstime->tv_sec - rt.tv_sec;
> +		  rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec;
> +		  if (rt.tv_nsec < 0)
> +		    {
> +		      rt.tv_nsec += 1000000000;
> +		      --rt.tv_sec;
> +		    }
> +		  /* Did we already time out?  */
> +		  if (__glibc_unlikely (rt.tv_sec < 0))
> +		    err = ETIMEDOUT;
> +		  else
> +		    err = futex_reltimed_wait_cancelable
> +			(cond->__data.__g_signals + g, 0, &rt, private);
> +		}
> +	      else
> +		{
> +		  /* Use CLOCK_REALTIME.  */
> +		  err = futex_abstimed_wait_cancelable
> +		      (cond->__data.__g_signals + g, 0, abstime, private);
> +		}
> +	    }
> +
> +	  __pthread_cleanup_pop (&buffer, 0);
> +

OK.

> +	  if (__glibc_unlikely (err == ETIMEDOUT))
> +	    {
> +	      __condvar_dec_grefs (cond, g, private);
> +	      /* If we timed out, we effectively cancel waiting.  Note that
> +		 we have decremented __g_refs before cancellation, so that a
> +		 deadlock between waiting for quiescence of our group in
> +		 __condvar_quiesce_and_switch_g1 and us trying to acquire
> +		 the lock during cancellation is not possible.  */
> +	      __condvar_cancel_waiting (cond, seq, g, private);

OK.

> +	      result = ETIMEDOUT;
> +	      goto done;
> +	    }
> +	  else
> +	    __condvar_dec_grefs (cond, g, private);
> +
> +	  /* Reload signals.  See above for MO.  */
> +	  signals = atomic_load_acquire (cond->__data.__g_signals + g);
>  	}
> -      pi_flag = USE_REQUEUE_PI (mutex);
>  
> -      if (pi_flag)
> +    }
> +  /* Try to grab a signal.  Use acquire MO so that we see an up-to-date value
> +     of __g1_start below (see spinning above for a similar case).  In
> +     particular, if we steal from a more recent group, we will also see a
> +     more recent __g1_start below.  */

OK.

> +  while (!atomic_compare_exchange_weak_acquire (cond->__data.__g_signals + g,
> +						&signals, signals - 2));
> +
> +  /* We consumed a signal but we could have consumed from a more recent group
> +     that aliased with ours due to being in the same group slot.  If this
> +     might be the case our group must be closed as visible through
> +     __g1_start.  */
> +  uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
> +  if (seq < (g1_start >> 1))
> +    {
> +      /* We potentially stole a signal from a more recent group but we do not
> +	 know which group we really consumed from.
> +	 We do not care about groups older than current G1 because they are
> +	 closed; we could have stolen from these, but then we just add a
> +	 spurious wake-up for the current groups.
> +	 We will never steal a signal from current G2 that was really intended
> +	 for G2 because G2 never receives signals (until it becomes G1).  We
> +	 could have stolen a signal from G2 that was conservatively added by a
> +	 previous waiter that also thought it stole a signal -- but given that
> +	 that signal was added unnecessarily, it's not a problem if we steal
> +	 it.
> +	 Thus, the remaining case is that we could have stolen from the current
> +	 G1, where "current" means the __g1_start value we observed.  However,
> +	 if the current G1 does not have the same slot index as we do, we did
> +	 not steal from it and do not need to undo that.  This is the reason
> +	 for putting a bit with G2's index into__g1_start as well.  */

OK.

> +      if (((g1_start & 1) ^ 1) == g)
>  	{
> -	  err = lll_futex_wait_requeue_pi (&cond->__data.__futex,
> -					   futex_val, &mutex->__data.__lock,
> -					   pshared);
> -
> -	  pi_flag = (err == 0);
> +	  /* We have to conservatively undo our potential mistake of stealing
> +	     a signal.  We can stop trying to do that when the current G1
> +	     changes because other spinning waiters will notice this too and
> +	     __condvar_quiesce_and_switch_g1 has checked that there are no
> +	     futex waiters anymore before switching G1.
> +	     Relaxed MO is fine for the __g1_start load because we need to
> +	     merely be able to observe this fact and not have to observe
> +	     something else as well.
> +	     ??? Would it help to spin for a little while to see whether the
> +	     current G1 gets closed?  This might be worthwhile if the group is
> +	     small or close to being closed.  */
> +	  unsigned int s = atomic_load_relaxed (cond->__data.__g_signals + g);
> +	  while (__condvar_load_g1_start_relaxed (cond) == g1_start)
> +	    {
> +	      /* Try to add a signal.  We don't need to acquire the lock
> +		 because at worst we can cause a spurious wake-up.  If the
> +		 group is in the process of being closed (LSB is true), this
> +		 has an effect similar to us adding a signal.  */
> +	      if (((s & 1) != 0)
> +		  || atomic_compare_exchange_weak_relaxed
> +		       (cond->__data.__g_signals + g, &s, s + 2))
> +		{
> +		  /* If we added a signal, we also need to add a wake-up on
> +		     the futex.  We also need to do that if we skipped adding
> +		     a signal because the group is being closed because
> +		     while __condvar_quiesce_and_switch_g1 could have closed
> +		     the group, it might stil be waiting for futex waiters to
> +		     leave (and one of those waiters might be the one we stole
> +		     the signal from, which cause it to block using the
> +		     futex).  */
> +		  futex_wake (cond->__data.__g_signals + g, 1, private);

OK.

> +		  break;
> +		}
> +	      /* TODO Back off.  */
> +	    }
>  	}
> -      else
> -#endif
> -	  /* Wait until woken by signal or broadcast.  */
> -	lll_futex_wait (&cond->__data.__futex, futex_val, pshared);
> -
> -      /* Disable asynchronous cancellation.  */
> -      __pthread_disable_asynccancel (cbuffer.oldtype);
> -
> -      /* We are going to look at shared data again, so get the lock.  */
> -      lll_lock (cond->__data.__lock, pshared);
> -
> -      /* 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;
>      }
> -  while (val == seq || cond->__data.__woken_seq == val);
>  
> -  /* Another thread woken up.  */
> -  ++cond->__data.__woken_seq;
> + done:
>  
> - bc_out:
> +  /* Confirm that we have been woken.  We do that before acquiring the mutex
> +     to allow for execution of pthread_cond_destroy while having acquired the
> +     mutex.  */
> +  __condvar_confirm_wakeup (cond, private);

OK.

>  
> -  cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT;
> -
> -  /* If pthread_cond_destroy was called on this varaible already,
> -     notify the pthread_cond_destroy caller all waiters have left
> -     and it can be successfully destroyed.  */
> -  if (cond->__data.__total_seq == -1ULL
> -      && cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT))
> -    lll_futex_wake (&cond->__data.__nwaiters, 1, pshared);
> +  /* Woken up; now re-acquire the mutex.  If this doesn't fail, return RESULT,
> +     which is set to ETIMEDOUT if a timeout occured, or zero otherwise.  */
> +  err = __pthread_mutex_cond_lock (mutex);
> +  /* XXX Abort on errors that are disallowed by POSIX?  */

Yes, but we can do that in another pass. I already asked you at the other point
to file a bug upstream to track this potential for defects in failed
lock acquires.

> +  return (err != 0) ? err : result;

OK.

> +}
>  
> -  /* We are done with the condvar.  */
> -  lll_unlock (cond->__data.__lock, pshared);
>  
> -  /* The cancellation handling is back to normal, remove the handler.  */
> -  __pthread_cleanup_pop (&buffer, 0);
> +/* See __pthread_cond_wait_common.  */
> +int
> +__pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
> +{
> +  return __pthread_cond_wait_common (cond, mutex, NULL);
> +}
>  
> -  /* Get the mutex before returning.  Not needed for PI.  */
> -#if (defined lll_futex_wait_requeue_pi \
> -     && defined __ASSUME_REQUEUE_PI)
> -  if (pi_flag)
> -    {
> -      __pthread_mutex_cond_lock_adjust (mutex);
> -      return 0;
> -    }
> -  else
> -#endif
> -    return __pthread_mutex_cond_lock (mutex);
> +/* See __pthread_cond_wait_common.  */
> +int
> +__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
> +    const struct timespec *abstime)
> +{
> +  /* Check parameter validity.  This should also tell the compiler that
> +     it can assume that abstime is not NULL.  */
> +  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
> +    return EINVAL;
> +  return __pthread_cond_wait_common (cond, mutex, abstime);
>  }
>  
>  versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
>  		  GLIBC_2_3_2);
> +versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
> +		  GLIBC_2_3_2);

OK.

> diff --git a/nptl/pthread_condattr_getclock.c b/nptl/pthread_condattr_getclock.c
> index d156302..cecb4aa 100644
> --- a/nptl/pthread_condattr_getclock.c
> +++ b/nptl/pthread_condattr_getclock.c
> @@ -23,6 +23,6 @@ int
>  pthread_condattr_getclock (const pthread_condattr_t *attr, clockid_t *clock_id)
>  {
>    *clock_id = (((((const struct pthread_condattr *) attr)->value) >> 1)
> -	       & ((1 << COND_NWAITERS_SHIFT) - 1));
> +	       & ((1 << COND_CLOCK_BITS) - 1));

OK.

>    return 0;
>  }
> diff --git a/nptl/pthread_condattr_getpshared.c b/nptl/pthread_condattr_getpshared.c
> index 5a10f3e..8147966 100644
> --- a/nptl/pthread_condattr_getpshared.c
> +++ b/nptl/pthread_condattr_getpshared.c
> @@ -22,7 +22,8 @@
>  int
>  pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
>  {
> -  *pshared = ((const struct pthread_condattr *) attr)->value & 1;
> +  *pshared = (((const struct pthread_condattr *) attr)->value & 1
> +	      ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE);

OK. Like the use of the constants :-)

>  
>    return 0;
>  }
> diff --git a/nptl/pthread_condattr_init.c b/nptl/pthread_condattr_init.c
> index 0ce42e5..6e5168d 100644
> --- a/nptl/pthread_condattr_init.c
> +++ b/nptl/pthread_condattr_init.c
> @@ -23,7 +23,9 @@
>  int
>  __pthread_condattr_init (pthread_condattr_t *attr)
>  {
> -  memset (attr, '\0', sizeof (*attr));
> +  struct pthread_condattr *iattr = (struct pthread_condattr *) attr;
> +  /* Default is not pshared and CLOCK_REALTIME.  */
> +  iattr-> value = CLOCK_REALTIME << 1;

OK.

>  
>    return 0;
>  }
> diff --git a/nptl/pthread_condattr_setclock.c b/nptl/pthread_condattr_setclock.c
> index 25e2a17..3cfad84 100644
> --- a/nptl/pthread_condattr_setclock.c
> +++ b/nptl/pthread_condattr_setclock.c
> @@ -18,7 +18,7 @@
>  
>  #include <assert.h>
>  #include <errno.h>
> -#include <stdbool.h>
> +#include <futex-internal.h>
>  #include <time.h>
>  #include <sysdep.h>
>  #include "pthreadP.h"
> @@ -33,12 +33,17 @@ pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock_id)
>         in the pthread_cond_t structure needs to be adjusted.  */
>      return EINVAL;
>  
> +  /* If we do not support waiting using CLOCK_MONOTONIC, return an error.  */
> +  if (clock_id == CLOCK_MONOTONIC
> +      && !futex_supports_exact_relative_timeouts())
> +    return ENOTSUP;

OK.

> +
>    /* Make sure the value fits in the bits we reserved.  */
> -  assert (clock_id < (1 << COND_NWAITERS_SHIFT));
> +  assert (clock_id < (1 << COND_CLOCK_BITS));

OK.

>  
>    int *valuep = &((struct pthread_condattr *) attr)->value;
>  
> -  *valuep = ((*valuep & ~(((1 << COND_NWAITERS_SHIFT) - 1) << 1))
> +  *valuep = ((*valuep & ~(((1 << COND_CLOCK_BITS) - 1) << 1))
>  	     | (clock_id << 1));

OK. Hideously sloppy way to do 1-bit for the clock and 1-bit for pshared, but
it's fine here. Clear via mask and then OR would have been nicer to read and
understand.

>  
>    return 0;
> diff --git a/nptl/tst-cond1.c b/nptl/tst-cond1.c
> index 75ab9c8..509bbd0 100644
> --- a/nptl/tst-cond1.c
> +++ b/nptl/tst-cond1.c
> @@ -73,6 +73,9 @@ do_test (void)
>  
>    puts ("parent: wait for condition");
>  
> +  /* This test will fail on spurious wake-ups, which are allowed; however,
> +     the current implementation shouldn't produce spurious wake-ups in the
> +     scenario we are testing here.  */

OK. Right, spurious wakeups are not going to happen in this case of
a single wait and a single signal. This test is pretty simple.

>    err = pthread_cond_wait (&cond, &mut);
>    if (err != 0)
>      error (EXIT_FAILURE, err, "parent: cannot wait fir signal");
> diff --git a/nptl/tst-cond20.c b/nptl/tst-cond20.c
> index 918c4ad..665a66a 100644
> --- a/nptl/tst-cond20.c
> +++ b/nptl/tst-cond20.c
> @@ -96,7 +96,10 @@ do_test (void)
>  
>    for (i = 0; i < ROUNDS; ++i)
>      {
> -      pthread_cond_wait (&cond2, &mut);
> +      /* Make sure we discard spurious wake-ups.  */
> +      do
> +	pthread_cond_wait (&cond2, &mut);
> +      while (count != N);

OK.

>  
>        if (i & 1)
>          pthread_mutex_unlock (&mut);
> diff --git a/nptl/tst-cond22.c b/nptl/tst-cond22.c
> index bd978e5..64f19ea 100644
> --- a/nptl/tst-cond22.c
> +++ b/nptl/tst-cond22.c
> @@ -106,10 +106,11 @@ do_test (void)
>        status = 1;
>      }
>  
> -  printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
> -	  c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
> -	  c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
> -	  c.__data.__nwaiters, c.__data.__broadcast_seq);
> +  printf ("cond = { %llu, %llu, %u/%u/%u, %u/%u/%u, %u, %u }\n",
> +	  c.__data.__wseq, c.__data.__g1_start,
> +	  c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
> +	  c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
> +	  c.__data.__g1_orig_size, c.__data.__wrefs);

OK.

>  
>    if (pthread_create (&th, NULL, tf, (void *) 1l) != 0)
>      {
> @@ -148,10 +149,11 @@ do_test (void)
>        status = 1;
>      }
>  
> -  printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
> -	  c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
> -	  c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
> -	  c.__data.__nwaiters, c.__data.__broadcast_seq);
> +  printf ("cond = { %llu, %llu, %u/%u/%u, %u/%u/%u, %u, %u }\n",
> +	  c.__data.__wseq, c.__data.__g1_start,
> +	  c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
> +	  c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
> +	  c.__data.__g1_orig_size, c.__data.__wrefs);

OK.

>  
>    return status;
>  }
> diff --git a/sysdeps/aarch64/nptl/bits/pthreadtypes.h b/sysdeps/aarch64/nptl/bits/pthreadtypes.h
> index 13984a7..87c4804 100644
> --- a/sysdeps/aarch64/nptl/bits/pthreadtypes.h
> +++ b/sysdeps/aarch64/nptl/bits/pthreadtypes.h
> @@ -90,17 +90,32 @@ typedef union
>  {
>    struct
>    {
> -    int __lock;
> -    unsigned int __futex;
> -    __extension__ unsigned long long int __total_seq;
> -    __extension__ unsigned long long int __wakeup_seq;
> -    __extension__ unsigned long long int __woken_seq;
> -    void *__mutex;
> -    unsigned int __nwaiters;
> -    unsigned int __broadcast_seq;
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __wseq;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __wseq32;
> +    };
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __g1_start;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __g1_start32;
> +    };
> +    unsigned int __g_refs[2];
> +    unsigned int __g_size[2];
> +    unsigned int __g1_orig_size;
> +    unsigned int __wrefs;
> +    unsigned int __g_signals[2];
> +#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
> +#define __PTHREAD_COND_SHARED_MASK 1
>    } __data;
>    char __size[__SIZEOF_PTHREAD_COND_T];
> -  long int __align;
> +  __extension__ long long int __align;

OK. Same size and alignment, so it's fine.

>  } pthread_cond_t;
>  
>  typedef union
> diff --git a/sysdeps/arm/nptl/bits/pthreadtypes.h b/sysdeps/arm/nptl/bits/pthreadtypes.h
> index afb5392..3e1f451 100644
> --- a/sysdeps/arm/nptl/bits/pthreadtypes.h
> +++ b/sysdeps/arm/nptl/bits/pthreadtypes.h
> @@ -93,14 +93,29 @@ typedef union
>  {
>    struct
>    {
> -    int __lock;
> -    unsigned int __futex;
> -    __extension__ unsigned long long int __total_seq;
> -    __extension__ unsigned long long int __wakeup_seq;
> -    __extension__ unsigned long long int __woken_seq;
> -    void *__mutex;
> -    unsigned int __nwaiters;
> -    unsigned int __broadcast_seq;
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __wseq;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __wseq32;
> +    };
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __g1_start;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __g1_start32;
> +    };
> +    unsigned int __g_refs[2];
> +    unsigned int __g_size[2];
> +    unsigned int __g1_orig_size;
> +    unsigned int __wrefs;
> +    unsigned int __g_signals[2];
> +#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
> +#define __PTHREAD_COND_SHARED_MASK 1

OK.

>    } __data;
>    char __size[__SIZEOF_PTHREAD_COND_T];
>    __extension__ long long int __align;
> diff --git a/sysdeps/ia64/nptl/bits/pthreadtypes.h b/sysdeps/ia64/nptl/bits/pthreadtypes.h
> index f2e6dac..a892fe0 100644
> --- a/sysdeps/ia64/nptl/bits/pthreadtypes.h
> +++ b/sysdeps/ia64/nptl/bits/pthreadtypes.h
> @@ -90,17 +90,32 @@ typedef union
>  {
>    struct
>    {
> -    int __lock;
> -    unsigned int __futex;
> -    __extension__ unsigned long long int __total_seq;
> -    __extension__ unsigned long long int __wakeup_seq;
> -    __extension__ unsigned long long int __woken_seq;
> -    void *__mutex;
> -    unsigned int __nwaiters;
> -    unsigned int __broadcast_seq;
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __wseq;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __wseq32;
> +    };
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __g1_start;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __g1_start32;
> +    };
> +    unsigned int __g_refs[2];
> +    unsigned int __g_size[2];
> +    unsigned int __g1_orig_size;
> +    unsigned int __wrefs;
> +    unsigned int __g_signals[2];
> +#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
> +#define __PTHREAD_COND_SHARED_MASK 1
>    } __data;
>    char __size[__SIZEOF_PTHREAD_COND_T];
> -  long int __align;
> +  __extension__ long long int __align;

OK. Same alignment and size, so it will be fine.

>  } pthread_cond_t;
>  
>  typedef union
> diff --git a/sysdeps/m68k/nptl/bits/pthreadtypes.h b/sysdeps/m68k/nptl/bits/pthreadtypes.h
> index d8faa7a..4a86878 100644
> --- a/sysdeps/m68k/nptl/bits/pthreadtypes.h
> +++ b/sysdeps/m68k/nptl/bits/pthreadtypes.h
> @@ -88,19 +88,35 @@ typedef union
>  
>  
>  /* Data structure for conditional variable handling.  The structure of
> -   the attribute type is deliberately not exposed.  */
> +   the attribute type is not exposed on purpose.  */
>  typedef union
>  {
>    struct
>    {
> -    int __lock __attribute__ ((__aligned__ (4)));

This is not OK, but I'll fix it up post-commit. We need to keep this
to maintain the ABI of this structure when embedded in other structures.

> -    unsigned int __futex;
> -    __extension__ unsigned long long int __total_seq;
> -    __extension__ unsigned long long int __wakeup_seq;
> -    __extension__ unsigned long long int __woken_seq;
> -    void *__mutex;
> -    unsigned int __nwaiters;
> -    unsigned int __broadcast_seq;
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __wseq;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __wseq32;
> +    };
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __g1_start;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __g1_start32;
> +    };
> +    /* Enforce proper alignment of fields used as futex words.  */
> +    unsigned int __g_refs[2] __attribute__ ((__aligned__ (4)));
> +    unsigned int __g_size[2];
> +    unsigned int __g1_orig_size;
> +    unsigned int __wrefs;
> +    unsigned int __g_signals[2];
> +#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
> +#define __PTHREAD_COND_SHARED_MASK 1

OK.

>    } __data;
>    char __size[__SIZEOF_PTHREAD_COND_T];
>    __extension__ long long int __align;
> diff --git a/sysdeps/microblaze/nptl/bits/pthreadtypes.h b/sysdeps/microblaze/nptl/bits/pthreadtypes.h
> index 9e9e307..acbb6ff 100644
> --- a/sysdeps/microblaze/nptl/bits/pthreadtypes.h
> +++ b/sysdeps/microblaze/nptl/bits/pthreadtypes.h
> @@ -91,14 +91,29 @@ typedef union
>  {
>    struct
>    {
> -    int __lock;
> -    unsigned int __futex;
> -    __extension__ unsigned long long int __total_seq;
> -    __extension__ unsigned long long int __wakeup_seq;
> -    __extension__ unsigned long long int __woken_seq;
> -    void *__mutex;
> -    unsigned int __nwaiters;
> -    unsigned int __broadcast_seq;
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __wseq;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __wseq32;
> +    };
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __g1_start;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __g1_start32;
> +    };
> +    unsigned int __g_refs[2];
> +    unsigned int __g_size[2];
> +    unsigned int __g1_orig_size;
> +    unsigned int __wrefs;
> +    unsigned int __g_signals[2];
> +#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
> +#define __PTHREAD_COND_SHARED_MASK 1

OK.

>    } __data;
>    char __size[__SIZEOF_PTHREAD_COND_T];
>    __extension__ long long int __align;
> diff --git a/sysdeps/mips/nptl/bits/pthreadtypes.h b/sysdeps/mips/nptl/bits/pthreadtypes.h
> index 68ed94b..6e16292 100644
> --- a/sysdeps/mips/nptl/bits/pthreadtypes.h
> +++ b/sysdeps/mips/nptl/bits/pthreadtypes.h
> @@ -117,19 +117,34 @@ typedef union
>  
>  
>  /* Data structure for conditional variable handling.  The structure of
> -   the attribute type is deliberately not exposed.  */
> +   the attribute type is not exposed on purpose.  */
>  typedef union
>  {
>    struct
>    {
> -    int __lock;
> -    unsigned int __futex;
> -    __extension__ unsigned long long int __total_seq;
> -    __extension__ unsigned long long int __wakeup_seq;
> -    __extension__ unsigned long long int __woken_seq;
> -    void *__mutex;
> -    unsigned int __nwaiters;
> -    unsigned int __broadcast_seq;
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __wseq;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __wseq32;
> +    };
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __g1_start;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __g1_start32;
> +    };
> +    unsigned int __g_refs[2];
> +    unsigned int __g_size[2];
> +    unsigned int __g1_orig_size;
> +    unsigned int __wrefs;
> +    unsigned int __g_signals[2];
> +#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
> +#define __PTHREAD_COND_SHARED_MASK 1

OK.

>    } __data;
>    char __size[__SIZEOF_PTHREAD_COND_T];
>    __extension__ long long int __align;
> diff --git a/sysdeps/nios2/nptl/bits/pthreadtypes.h b/sysdeps/nios2/nptl/bits/pthreadtypes.h
> index 76076d0..e698bac 100644
> --- a/sysdeps/nios2/nptl/bits/pthreadtypes.h
> +++ b/sysdeps/nios2/nptl/bits/pthreadtypes.h
> @@ -88,19 +88,34 @@ typedef union
>  
>  
>  /* Data structure for conditional variable handling.  The structure of
> -   the attribute type is deliberately not exposed.  */
> +   the attribute type is not exposed on purpose.  */
>  typedef union
>  {
>    struct
>    {
> -    int __lock;
> -    unsigned int __futex;
> -    __extension__ unsigned long long int __total_seq;
> -    __extension__ unsigned long long int __wakeup_seq;
> -    __extension__ unsigned long long int __woken_seq;
> -    void *__mutex;
> -    unsigned int __nwaiters;
> -    unsigned int __broadcast_seq;
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __wseq;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __wseq32;
> +    };
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __g1_start;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __g1_start32;
> +    };
> +    unsigned int __g_refs[2];
> +    unsigned int __g_size[2];
> +    unsigned int __g1_orig_size;
> +    unsigned int __wrefs;
> +    unsigned int __g_signals[2];
> +#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
> +#define __PTHREAD_COND_SHARED_MASK 1

OK.

>    } __data;
>    char __size[__SIZEOF_PTHREAD_COND_T];
>    __extension__ long long int __align;
> diff --git a/sysdeps/nptl/internaltypes.h b/sysdeps/nptl/internaltypes.h
> index 203c548..31e5a43 100644
> --- a/sysdeps/nptl/internaltypes.h
> +++ b/sysdeps/nptl/internaltypes.h
> @@ -68,20 +68,13 @@ struct pthread_condattr
>  {
>    /* Combination of values:
>  
> -     Bit 0  : flag whether conditional variable will be sharable between
> -	      processes.
> -
> -     Bit 1-7: clock ID.  */
> +     Bit 0                : flag whether conditional variable will be
> +                            sharable between processes.
> +     Bit 1-COND_CLOCK_BITS: Clock ID.  COND_CLOCK_BITS is the number of bits
> +                            needed to represent the ID of the clock.  */

OK.

>    int value;
>  };
> -
> -
> -/* The __NWAITERS field is used as a counter and to house the number
> -   of bits for other purposes.  COND_CLOCK_BITS is the number
> -   of bits needed to represent the ID of the clock.  COND_NWAITERS_SHIFT
> -   is the number of bits reserved for other purposes like the clock.  */
> -#define COND_CLOCK_BITS		1
> -#define COND_NWAITERS_SHIFT	1
> +#define COND_CLOCK_BITS	1

OK. We support only two clocks (realtime/monotonic).

>  
>  
>  /* Read-write lock variable attribute data structure.  */
> diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
> index fd0894e..c122446 100644
> --- a/sysdeps/nptl/pthread.h
> +++ b/sysdeps/nptl/pthread.h
> @@ -183,7 +183,7 @@ enum
>  
>  
>  /* Conditional variable handling.  */
> -#define PTHREAD_COND_INITIALIZER { { 0, 0, 0, 0, 0, (void *) 0, 0, 0 } }
> +#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } }

OK. Verified it's all zero :-)

>  
>  
>  /* Cleanup buffers */
> diff --git a/sysdeps/s390/nptl/bits/pthreadtypes.h b/sysdeps/s390/nptl/bits/pthreadtypes.h
> index 40d10fe..fb8daea 100644
> --- a/sysdeps/s390/nptl/bits/pthreadtypes.h
> +++ b/sysdeps/s390/nptl/bits/pthreadtypes.h
> @@ -142,14 +142,29 @@ typedef union
>  {
>    struct
>    {
> -    int __lock;
> -    unsigned int __futex;
> -    __extension__ unsigned long long int __total_seq;
> -    __extension__ unsigned long long int __wakeup_seq;
> -    __extension__ unsigned long long int __woken_seq;
> -    void *__mutex;
> -    unsigned int __nwaiters;
> -    unsigned int __broadcast_seq;
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __wseq;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __wseq32;
> +    };
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __g1_start;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __g1_start32;
> +    };
> +    unsigned int __g_refs[2];
> +    unsigned int __g_size[2];
> +    unsigned int __g1_orig_size;
> +    unsigned int __wrefs;
> +    unsigned int __g_signals[2];
> +#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
> +#define __PTHREAD_COND_SHARED_MASK 1

OK.

>    } __data;
>    char __size[__SIZEOF_PTHREAD_COND_T];
>    __extension__ long long int __align;
> diff --git a/sysdeps/sh/nptl/bits/pthreadtypes.h b/sysdeps/sh/nptl/bits/pthreadtypes.h
> index 13fbd73..0b67bd9 100644
> --- a/sysdeps/sh/nptl/bits/pthreadtypes.h
> +++ b/sysdeps/sh/nptl/bits/pthreadtypes.h
> @@ -93,14 +93,29 @@ typedef union
>  {
>    struct
>    {
> -    int __lock;
> -    unsigned int __futex;
> -    __extension__ unsigned long long int __total_seq;
> -    __extension__ unsigned long long int __wakeup_seq;
> -    __extension__ unsigned long long int __woken_seq;
> -    void *__mutex;
> -    unsigned int __nwaiters;
> -    unsigned int __broadcast_seq;
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __wseq;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __wseq32;
> +    };
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __g1_start;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __g1_start32;
> +    };
> +    unsigned int __g_refs[2];
> +    unsigned int __g_size[2];
> +    unsigned int __g1_orig_size;
> +    unsigned int __wrefs;
> +    unsigned int __g_signals[2];
> +#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
> +#define __PTHREAD_COND_SHARED_MASK 1

OK.

>    } __data;
>    char __size[__SIZEOF_PTHREAD_COND_T];
>    __extension__ long long int __align;
> diff --git a/sysdeps/tile/nptl/bits/pthreadtypes.h b/sysdeps/tile/nptl/bits/pthreadtypes.h
> index 7d68650..eb8d132 100644
> --- a/sysdeps/tile/nptl/bits/pthreadtypes.h
> +++ b/sysdeps/tile/nptl/bits/pthreadtypes.h
> @@ -122,14 +122,29 @@ typedef union
>  {
>    struct
>    {
> -    int __lock;
> -    unsigned int __futex;
> -    __extension__ unsigned long long int __total_seq;
> -    __extension__ unsigned long long int __wakeup_seq;
> -    __extension__ unsigned long long int __woken_seq;
> -    void *__mutex;
> -    unsigned int __nwaiters;
> -    unsigned int __broadcast_seq;
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __wseq;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __wseq32;
> +    };
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __g1_start;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __g1_start32;
> +    };
> +    unsigned int __g_refs[2];
> +    unsigned int __g_size[2];
> +    unsigned int __g1_orig_size;
> +    unsigned int __wrefs;
> +    unsigned int __g_signals[2];
> +#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
> +#define __PTHREAD_COND_SHARED_MASK 1

OK.

>    } __data;
>    char __size[__SIZEOF_PTHREAD_COND_T];
>    __extension__ long long int __align;
> diff --git a/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h b/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
> index 1a1779b..6bf9cb7 100644
> --- a/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
> +++ b/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
> @@ -84,19 +84,34 @@ typedef union
>  
>  
>  /* Data structure for conditional variable handling.  The structure of
> -   the attribute type is deliberately not exposed.  */
> +   the attribute type is not exposed on purpose.  */
>  typedef union
>  {
>    struct
>    {
> -    int __lock;
> -    unsigned int __futex;
> -    __extension__ unsigned long long int __total_seq;
> -    __extension__ unsigned long long int __wakeup_seq;
> -    __extension__ unsigned long long int __woken_seq;
> -    void *__mutex;
> -    unsigned int __nwaiters;
> -    unsigned int __broadcast_seq;
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __wseq;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __wseq32;
> +    };
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __g1_start;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __g1_start32;
> +    };
> +    unsigned int __g_refs[2];
> +    unsigned int __g_size[2];
> +    unsigned int __g1_orig_size;
> +    unsigned int __wrefs;
> +    unsigned int __g_signals[2];
> +#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
> +#define __PTHREAD_COND_SHARED_MASK 1

OK.

>    } __data;
>    char __size[__SIZEOF_PTHREAD_COND_T];
>    __extension__ long long int __align;
> diff --git a/sysdeps/unix/sysv/linux/hppa/internaltypes.h b/sysdeps/unix/sysv/linux/hppa/internaltypes.h
> index 651ce2e..d649657 100644
> --- a/sysdeps/unix/sysv/linux/hppa/internaltypes.h
> +++ b/sysdeps/unix/sysv/linux/hppa/internaltypes.h
> @@ -46,32 +46,38 @@ fails because __initializer is zero, and the structure will be used as
>  is correctly.  */
>  
>  #define cond_compat_clear(var) \
> -({											\
> -  int tmp = 0;										\
> -  var->__data.__lock = 0;								\
> -  var->__data.__futex = 0;								\
> -  var->__data.__mutex = NULL;								\
> -  /* Clear __initializer last, to indicate initialization is done.  */			\
> -  __asm__ __volatile__ ("stw,ma %1,0(%0)"						\
> -			: : "r" (&var->__data.__initializer), "r" (tmp) : "memory");	\
> +({									\
> +  int tmp = 0;								\
> +  var->__data.__wseq = 0;						\
> +  var->__data.__signals_sent = 0;					\
> +  var->__data.__confirmed = 0;						\
> +  var->__data.__generation = 0;						\
> +  var->__data.__mutex = NULL;						\
> +  var->__data.__quiescence_waiters = 0;					\
> +  var->__data.__clockid = 0;						\
> +  /* Clear __initializer last, to indicate initialization is done.  */	\
> +  /* This synchronizes-with the acquire load below.  */			\
> +  atomic_store_release (&var->__data.__initializer, 0);			\

OK. Thanks, yes, the above was only a compiler barrier, and we do need a acq/rel pair here.

>  })
>  
>  #define cond_compat_check_and_clear(var) \
>  ({								\
> -  int ret;							\
> -  volatile int *value = &var->__data.__initializer;		\
> -  if ((ret = atomic_compare_and_exchange_val_acq(value, 2, 1)))	\
> +  int v;							\
> +  int *value = &var->__data.__initializer;			\
> +  /* This synchronizes-with the release store above.  */	\
> +  while ((v = atomic_load_acquire (value)) != 0)		\
>      {								\
> -      if (ret == 1)						\
> +      if (v == 1						\
> +	  /* Relaxed MO is fine; it only matters who's first.  */        \
> +	  && atomic_compare_exchange_acquire_weak_relaxed (value, 1, 2)) \
>  	{							\
> -	  /* Initialize structure.  */				\
> +	  /* We're first; initialize structure.  */		\
>  	  cond_compat_clear (var);				\
> +	  break;						\
>  	}							\
>        else							\
> -        {							\
> -	  /* Yield until structure is initialized.  */		\
> -	  while (*value == 2) sched_yield ();			\
> -        }							\
> +	/* Yield before we re-check initialization status.  */	\
> +	sched_yield ();						\

OK. This looks good to me, the point is to approximate a pthread_once but
without the space required by the actual pthread_once algorithm.

>      }								\
>  })
>  
> diff --git a/sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c b/sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c
> deleted file mode 100644
> index ec6fd23..0000000
> --- a/sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c
> +++ /dev/null
> @@ -1,41 +0,0 @@
> -/* Copyright (C) 2009-2016 Free Software Foundation, Inc.
> -   This file is part of the GNU C Library.
> -   Contributed by Carlos O'Donell <carlos@codesourcery.com>, 2009.
> -
> -   The GNU C Library is free software; you can redistribute it and/or
> -   modify it under the terms of the GNU Lesser General Public
> -   License as published by the Free Software Foundation; either
> -   version 2.1 of the License, or (at your option) any later version.
> -
> -   The GNU C Library is distributed in the hope that it will be useful,
> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> -   Lesser General Public License for more details.
> -
> -   You should have received a copy of the GNU Lesser General Public
> -   License along with the GNU C Library.  If not, see
> -   <http://www.gnu.org/licenses/>.  */
> -
> -#ifndef INCLUDED_SELF
> -# define INCLUDED_SELF
> -# include <pthread_cond_timedwait.c>
> -#else
> -# include <pthread.h>
> -# include <pthreadP.h>
> -# include <internaltypes.h>
> -# include <shlib-compat.h>
> -int
> -__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
> -			  const struct timespec *abstime)
> -{
> -  cond_compat_check_and_clear (cond);
> -  return __pthread_cond_timedwait_internal (cond, mutex, abstime);
> -}
> -versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
> -                  GLIBC_2_3_2);
> -# undef versioned_symbol
> -# define versioned_symbol(lib, local, symbol, version)
> -# undef __pthread_cond_timedwait
> -# define __pthread_cond_timedwait __pthread_cond_timedwait_internal
> -# include_next <pthread_cond_timedwait.c>
> -#endif

OK. I'll double check this works on hppa in January.

> diff --git a/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c b/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c
> index 8f02831..0611f7d 100644
> --- a/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c
> +++ b/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c
> @@ -32,9 +32,22 @@ __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
>  }
>  versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
>                    GLIBC_2_3_2);
> +int
> +__pthread_cond_timedwait (cond, mutex, abstime)
> +     pthread_cond_t *cond;
> +     pthread_mutex_t *mutex;
> +     const struct timespec *abstime;
> +{
> +  cond_compat_check_and_clear (cond);
> +  return __pthread_cond_timedwait_internal (cond, mutex, abstime);
> +}
> +versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
> +                  GLIBC_2_3_2);

OK. Looks good.

>  # undef versioned_symbol
>  # define versioned_symbol(lib, local, symbol, version)
>  # undef __pthread_cond_wait
>  # define __pthread_cond_wait __pthread_cond_wait_internal
> +# undef __pthread_cond_timedwait
> +# define __pthread_cond_timedwait __pthread_cond_timedwait_internal

OK.

>  # include_next <pthread_cond_wait.c>
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S
> deleted file mode 100644
> index f697e5b..0000000
> --- a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S
> +++ /dev/null

OK. Remove assembly implementation.

> diff --git a/sysdeps/unix/sysv/linux/i386/pthread_cond_broadcast.S b/sysdeps/unix/sysv/linux/i386/pthread_cond_broadcast.S
> deleted file mode 100644
> index 5996688..0000000
> --- a/sysdeps/unix/sysv/linux/i386/pthread_cond_broadcast.S
> +++ /dev/null
> @@ -1,241 +0,0 @@

OK. Removed assembly implementation.

> diff --git a/sysdeps/unix/sysv/linux/i386/pthread_cond_signal.S b/sysdeps/unix/sysv/linux/i386/pthread_cond_signal.S
> deleted file mode 100644
> index 0038775..0000000
> --- a/sysdeps/unix/sysv/linux/i386/pthread_cond_signal.S
> +++ /dev/null

OK. Removed assembly implementation.

> diff --git a/sysdeps/unix/sysv/linux/i386/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/i386/pthread_cond_timedwait.S
> deleted file mode 100644
> index 6256376..0000000
> --- a/sysdeps/unix/sysv/linux/i386/pthread_cond_timedwait.S
> +++ /dev/null
> @@ -1,974 +0,0 @@

OK. Removed assembly implmentation.

> diff --git a/sysdeps/unix/sysv/linux/i386/pthread_cond_wait.S b/sysdeps/unix/sysv/linux/i386/pthread_cond_wait.S
> deleted file mode 100644
> index 5016718..0000000
> --- a/sysdeps/unix/sysv/linux/i386/pthread_cond_wait.S
> +++ /dev/null

OK. Removed assembly implementation.

> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
> index 345e79a..183e480 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
> @@ -123,19 +123,34 @@ typedef union
>  
>  
>  /* Data structure for conditional variable handling.  The structure of
> -   the attribute type is deliberately not exposed.  */
> +   the attribute type is not exposed on purpose.  */
>  typedef union
>  {
>    struct
>    {
> -    int __lock;
> -    unsigned int __futex;
> -    __extension__ unsigned long long int __total_seq;
> -    __extension__ unsigned long long int __wakeup_seq;
> -    __extension__ unsigned long long int __woken_seq;
> -    void *__mutex;
> -    unsigned int __nwaiters;
> -    unsigned int __broadcast_seq;
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __wseq;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __wseq32;
> +    };
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __g1_start;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __g1_start32;
> +    };
> +    unsigned int __g_refs[2];
> +    unsigned int __g_size[2];
> +    unsigned int __g1_orig_size;
> +    unsigned int __wrefs;
> +    unsigned int __g_signals[2];
> +#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
> +#define __PTHREAD_COND_SHARED_MASK 1

OK.

>    } __data;
>    char __size[__SIZEOF_PTHREAD_COND_T];
>    __extension__ long long int __align;
> diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
> deleted file mode 100644
> index de455dd..0000000
> --- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
> +++ /dev/null

OK. Removed assembly implementation.

> diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
> deleted file mode 100644
> index da14bc3..0000000
> --- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
> +++ /dev/null

OK. Removed asesmbly implementation.

> diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
> deleted file mode 100644
> index 82ffa1a..0000000
> --- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
> +++ /dev/null

OK. Removed assembly implementation.

> diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
> deleted file mode 100644
> index c82f37b..0000000
> --- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
> +++ /dev/null

OK. Removed assembly implementation.

> diff --git a/sysdeps/x86/bits/pthreadtypes.h b/sysdeps/x86/bits/pthreadtypes.h
> index 16b8f4f..3f23b48 100644
> --- a/sysdeps/x86/bits/pthreadtypes.h
> +++ b/sysdeps/x86/bits/pthreadtypes.h
> @@ -140,14 +140,29 @@ typedef union
>  {
>    struct
>    {
> -    int __lock;
> -    unsigned int __futex;
> -    __extension__ unsigned long long int __total_seq;
> -    __extension__ unsigned long long int __wakeup_seq;
> -    __extension__ unsigned long long int __woken_seq;
> -    void *__mutex;
> -    unsigned int __nwaiters;
> -    unsigned int __broadcast_seq;
> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __wseq;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __wseq32;
> +    };

OK.

> +    __extension__ union
> +    {
> +      __extension__ unsigned long long int __g1_start;
> +      struct {
> +	unsigned int __low;
> +	unsigned int __high;
> +      } __g1_start32;
> +    };

OK.

> +    unsigned int __g_refs[2];
> +    unsigned int __g_size[2];
> +    unsigned int __g1_orig_size;
> +    unsigned int __wrefs;
> +    unsigned int __g_signals[2];

OK.

> +#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
> +#define __PTHREAD_COND_SHARED_MASK 1

OK.

>    } __data;
>    char __size[__SIZEOF_PTHREAD_COND_T];
>    __extension__ long long int __align;

Cheers,
Carlos.
Joseph Myers Dec. 31, 2016, 5:37 p.m. UTC | #2
In addition to hppa (as expected), it appears the build is broken for 
sparcv9 (previous discussion said it was broken for pre-v9, did the 
expected breakage change as a result of other sparc changes?).

https://sourceware.org/ml/libc-testresults/2016-q4/msg00093.html

For sparc64-linux-gnu I see

pthread_cond_init.c: In function '__pthread_cond_init':
pthread_cond_init.c:38:17: error: 'struct <anonymous>' has no member named 
'__wrefs'
     cond->__data.__wrefs |= __PTHREAD_COND_SHARED_MASK;
                 ^
pthread_cond_init.c:44:17: error: 'struct <anonymous>' has no member named 
'__wrefs'
     cond->__data.__wrefs |= __PTHREAD_COND_CLOCK_MONOTONIC_MASK;
                 ^
and various such errors for sparcv9-linux-gnu.
Carlos O'Donell Jan. 2, 2017, 3:56 a.m. UTC | #3
On 12/31/2016 12:37 PM, Joseph Myers wrote:
> In addition to hppa (as expected), it appears the build is broken for 
> sparcv9 (previous discussion said it was broken for pre-v9, did the 
> expected breakage change as a result of other sparc changes?).
> 
> https://sourceware.org/ml/libc-testresults/2016-q4/msg00093.html
> 
> For sparc64-linux-gnu I see
> 
> pthread_cond_init.c: In function '__pthread_cond_init':
> pthread_cond_init.c:38:17: error: 'struct <anonymous>' has no member named 
> '__wrefs'
>      cond->__data.__wrefs |= __PTHREAD_COND_SHARED_MASK;
>                  ^
> pthread_cond_init.c:44:17: error: 'struct <anonymous>' has no member named 
> '__wrefs'
>      cond->__data.__wrefs |= __PTHREAD_COND_CLOCK_MONOTONIC_MASK;
>                  ^
> and various such errors for sparcv9-linux-gnu.
 
My opinion is that this has to get fixed by the ports maintainer
for SPARC, just like I'll fix this for hppa in the coming week.

You need to adapt the pthreadtypes.h structure definition
to match the same changes being done to the other architectures.
Mike Frysinger Feb. 10, 2017, 9:18 p.m. UTC | #4
On 01 Jan 2017 22:56, Carlos O'Donell wrote:
> My opinion is that this has to get fixed by the ports maintainer
> for SPARC, just like I'll fix this for hppa in the coming week.
> 
> You need to adapt the pthreadtypes.h structure definition
> to match the same changes being done to the other architectures.

did you have a patch for hppa ?  do we really care about linuxthreads
anymore ?  i'd point out we've already broken ABI once since then (the
signal number changes), so scuttling linuxthreads stuff too sounds fine
to me.
-mike
Florian Weimer Feb. 11, 2017, 12:16 p.m. UTC | #5
On 02/10/2017 10:18 PM, Mike Frysinger wrote:
> On 01 Jan 2017 22:56, Carlos O'Donell wrote:
>> My opinion is that this has to get fixed by the ports maintainer
>> for SPARC, just like I'll fix this for hppa in the coming week.
>>
>> You need to adapt the pthreadtypes.h structure definition
>> to match the same changes being done to the other architectures.
>
> did you have a patch for hppa ?  do we really care about linuxthreads
> anymore ?

LinuxThreads support is gone everywhere, but this doesn't mean we don't 
have any ABIs which are influenced by LinuxThreads.  The ABI 
compatibility between LinuxThreads and NPTL made application binaries 
portable across kernels.  So NPTL picked up where LinuxThreads left. 
Most of its structures are defined in public headers in such a way that 
their sizes are exposed, and there are no allocation functions for them, 
so size and alignment are essentially fixed today.

I'm not sure why this is relevant to HPPA in particular, though.

Thanks,
Florian
Adhemerval Zanella Feb. 11, 2017, 12:38 p.m. UTC | #6
On 11/02/2017 10:16, Florian Weimer wrote:
> On 02/10/2017 10:18 PM, Mike Frysinger wrote:
>> On 01 Jan 2017 22:56, Carlos O'Donell wrote:
>>> My opinion is that this has to get fixed by the ports maintainer
>>> for SPARC, just like I'll fix this for hppa in the coming week.
>>>
>>> You need to adapt the pthreadtypes.h structure definition
>>> to match the same changes being done to the other architectures.
>>
>> did you have a patch for hppa ?  do we really care about linuxthreads
>> anymore ?
> 
> LinuxThreads support is gone everywhere, but this doesn't mean we don't have any ABIs which are influenced by LinuxThreads.  The ABI compatibility between LinuxThreads and NPTL made application binaries portable across kernels.  So NPTL picked up where LinuxThreads left. Most of its structures are defined in public headers in such a way that their sizes are exposed, and there are no allocation functions for them, so size and alignment are essentially fixed today.
> 
> I'm not sure why this is relevant to HPPA in particular, though.
> 
> Thanks,
> Florian

At least on an hppa environment I have access, just removing the own hppa
implementation seems to not show any regressions. I think we just need to
get rid of this old and ununsed (and broken) interfaces.
Mike Frysinger Feb. 11, 2017, 6:24 p.m. UTC | #7
On 11 Feb 2017 13:16, Florian Weimer wrote:
> On 02/10/2017 10:18 PM, Mike Frysinger wrote:
> > On 01 Jan 2017 22:56, Carlos O'Donell wrote:
> >> My opinion is that this has to get fixed by the ports maintainer
> >> for SPARC, just like I'll fix this for hppa in the coming week.
> >>
> >> You need to adapt the pthreadtypes.h structure definition
> >> to match the same changes being done to the other architectures.
> >
> > did you have a patch for hppa ?  do we really care about linuxthreads
> > anymore ?
> 
> LinuxThreads support is gone everywhere, but this doesn't mean we don't 
> have any ABIs which are influenced by LinuxThreads.  The ABI 
> compatibility between LinuxThreads and NPTL made application binaries 
> portable across kernels.  So NPTL picked up where LinuxThreads left. 
> Most of its structures are defined in public headers in such a way that 
> their sizes are exposed, and there are no allocation functions for them, 
> so size and alignment are essentially fixed today.
> 
> I'm not sure why this is relevant to HPPA in particular, though.

i'm familiar with the background of linuxthreads->nptl.  hppa took quite
a while to make the nptl migration because of backwards compat with the
linuxthreads abi.

my counter point is that we actively broke the hppa kernel abi wrt signal
numbering to the point where you have to recompile glibc and apps in order
for code to work.  that happened after the nptl transition which means we
don't have any code that cares about the linuxthreads abi anymore.

i haven't looked closer to see if the abi is also locked in on the nptl
side though in which case we can't.
-mike
Florian Weimer Feb. 13, 2017, 11:35 a.m. UTC | #8
On 02/11/2017 07:24 PM, Mike Frysinger wrote:
> i'm familiar with the background of linuxthreads->nptl.  hppa took quite
> a while to make the nptl migration because of backwards compat with the
> linuxthreads abi.
>
> my counter point is that we actively broke the hppa kernel abi wrt signal
> numbering to the point where you have to recompile glibc and apps in order
> for code to work.  that happened after the nptl transition which means we
> don't have any code that cares about the linuxthreads abi anymore.
>
> i haven't looked closer to see if the abi is also locked in on the nptl
> side though in which case we can't.

HPPA uses public struct definitions which have non-default alignment, so 
we can't use the generic definitions without changing ABI and struct 
layout in user-defined structs which embed those structs.

The LinuxThreads/NPTL history does not matter at this point.

Thanks,
Florian
diff mbox

Patch

commit 1846a30fb9728dbc22730e56a9eaa3a996a4ef08
Author: Torvald Riegel <triegel@redhat.com>
Date:   Wed May 25 23:43:36 2016 +0200

    New condvar implementation that provides stronger ordering guarantees.
    
    This is a new implementation for condition variables, required
    after http://austingroupbugs.net/view.php?id=609 to fix bug 13165.  In
    essence, we need to be stricter in which waiters a signal or broadcast
    is required to wake up; this couldn't be solved using the old algorithm.
    ISO C++ made a similar clarification, so this also fixes a bug in
    current libstdc++, for example.
    
    We can't use the old algorithm anymore because futexes do not guarantee
    to wake in FIFO order.  Thus, when we wake, we can't simply let any
    waiter grab a signal, but we need to ensure that one of the waiters
    happening before the signal is woken up.  This is something the previous
    algorithm violated (see bug 13165).
    
    There's another issue specific to condvars: ABA issues on the underlying
    futexes.  Unlike mutexes that have just three states, or semaphores that
    have no tokens or a limited number of them, the state of a condvar is
    the *order* of the waiters.  A waiter on a semaphore can grab a token
    whenever one is available; a condvar waiter must only consume a signal
    if it is eligible to do so as determined by the relative order of the
    waiter and the signal.
    Therefore, this new algorithm maintains two groups of waiters: Those
    eligible to consume signals (G1), and those that have to wait until
    previous waiters have consumed signals (G2).  Once G1 is empty, G2
    becomes the new G1.  64b counters are used to avoid ABA issues.
    
    This condvar doesn't yet use a requeue optimization (ie, on a broadcast,
    waking just one thread and requeueing all others on the futex of the
    mutex supplied by the program).  I don't think doing the requeue is
    necessarily the right approach (but I haven't done real measurements
    yet):
    * If a program expects to wake many threads at the same time and make
    that scalable, a condvar isn't great anyway because of how it requires
    waiters to operate mutually exclusive (due to the mutex usage).  Thus, a
    thundering herd problem is a scalability problem with or without the
    optimization.  Using something like a semaphore might be more
    appropriate in such a case.
    * The scalability problem is actually at the mutex side; the condvar
    could help (and it tries to with the requeue optimization), but it
    should be the mutex who decides how that is done, and whether it is done
    at all.
    * Forcing all but one waiter into the kernel-side wait queue of the
    mutex prevents/avoids the use of lock elision on the mutex.  Thus, it
    prevents the only cure against the underlying scalability problem
    inherent to condvars.
    * If condvars use short critical sections (ie, hold the mutex just to
    check a binary flag or such), which they should do ideally, then forcing
    all those waiter to proceed serially with kernel-based hand-off (ie,
    futex ops in the mutex' contended state, via the futex wait queues) will
    be less efficient than just letting a scalable mutex implementation take
    care of it.  Our current mutex impl doesn't employ spinning at all, but
    if critical sections are short, spinning can be much better.
    * Doing the requeue stuff requires all waiters to always drive the mutex
    into the contended state.  This leads to each waiter having to call
    futex_wake after lock release, even if this wouldn't be necessary.
    
    	[BZ #13165]
    	* nptl/pthread_cond_broadcast.c (__pthread_cond_broadcast): Rewrite to
    	use new algorithm.
    	* nptl/pthread_cond_destroy.c (__pthread_cond_destroy): Likewise.
    	* nptl/pthread_cond_init.c (__pthread_cond_init): Likewise.
    	* nptl/pthread_cond_signal.c (__pthread_cond_signal): Likewise.
    	* nptl/pthread_cond_wait.c (__pthread_cond_wait): Likewise.
    	(__pthread_cond_timedwait): Move here from pthread_cond_timedwait.c.
    	(__condvar_confirm_wakeup, __condvar_cancel_waiting,
    	__condvar_cleanup_waiting, __condvar_dec_grefs,
    	__pthread_cond_wait_common): New.
    	(__condvar_cleanup): Remove.
    	* npt/pthread_condattr_getclock.c (pthread_condattr_getclock): Adapt.
    	* npt/pthread_condattr_setclock.c (pthread_condattr_setclock):
    	Likewise.
    	* npt/pthread_condattr_getpshared.c (pthread_condattr_getpshared):
    	Likewise.
    	* npt/pthread_condattr_init.c (pthread_condattr_init): Likewise.
    	* nptl/tst-cond1.c: Add comment.
    	* nptl/tst-cond20.c (do_test): Adapt.
    	* nptl/tst-cond22.c (do_test): Likewise.
    	* sysdeps/aarch64/nptl/bits/pthreadtypes.h (pthread_cond_t): Adapt
    	structure.
    	* sysdeps/arm/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
    	* sysdeps/ia64/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
    	* sysdeps/m68k/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
    	* sysdeps/microblaze/nptl/bits/pthreadtypes.h (pthread_cond_t):
    	Likewise.
    	* sysdeps/mips/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
    	* sysdeps/nios2/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
    	* sysdeps/s390/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
    	* sysdeps/sh/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
    	* sysdeps/tile/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise.
    	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t):
    	Likewise.
    	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h (pthread_cond_t):
    	Likewise.
    	* sysdeps/x86/bits/pthreadtypes.h (pthread_cond_t): Likewise.
    	* sysdeps/nptl/internaltypes.h (COND_NWAITERS_SHIFT): Remove.
    	(COND_CLOCK_BITS): Adapt.
    	* sysdeps/nptl/pthread.h (PTHREAD_COND_INITIALIZER): Adapt.
    	* sysdeps/unix/sysv/linux/hppa/internaltypes.h (cond_compat_clear,
    	cond_compat_check_and_clear): Adapt.
    	* sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c: Remove file ...
    	* sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c
    	(__pthread_cond_timedwait): ... and move here.
    	* nptl/DESIGN-condvar.txt: Remove file.
    	* nptl/lowlevelcond.sym: Likewise.
    	* nptl/pthread_cond_timedwait.c: Likewise.
    	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S: Likewise.
    	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise.
    	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise.
    	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise.
    	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise.

diff --git a/nptl/DESIGN-condvar.txt b/nptl/DESIGN-condvar.txt
deleted file mode 100644
index 4845251..0000000
--- a/nptl/DESIGN-condvar.txt
+++ /dev/null
@@ -1,134 +0,0 @@ 
-Conditional Variable pseudocode.
-================================
-
-       int pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *mutex);
-       int pthread_cond_signal    (pthread_cond_t *cv);
-       int pthread_cond_broadcast (pthread_cond_t *cv);
-
-struct pthread_cond_t {
-
-   unsigned int cond_lock;
-
-         internal mutex
-
-   uint64_t total_seq;
-
-     Total number of threads using the conditional variable.
-
-   uint64_t wakeup_seq;
-
-     sequence number for next wakeup.
-
-   uint64_t woken_seq;
-
-     sequence number of last woken thread.
-
-   uint32_t broadcast_seq;
-
-}
-
-
-struct cv_data {
-
-   pthread_cond_t *cv;
-
-   uint32_t bc_seq
-
-}
-
-
-
-cleanup_handler(cv_data)
-{
-  cv = cv_data->cv;
-  lll_lock(cv->lock);
-
-  if (cv_data->bc_seq == cv->broadcast_seq) {
-    ++cv->wakeup_seq;
-    ++cv->woken_seq;
-  }
-
-  /* make sure no signal gets lost.  */
-  FUTEX_WAKE(cv->wakeup_seq, ALL);
-
-  lll_unlock(cv->lock);
-}
-
-
-cond_timedwait(cv, mutex, timeout):
-{
-   lll_lock(cv->lock);
-   mutex_unlock(mutex);
-
-   cleanup_push
-
-   ++cv->total_seq;
-   val = seq =  cv->wakeup_seq;
-   cv_data.bc = cv->broadcast_seq;
-   cv_data.cv = cv;
-
-   while (1) {
-
-     lll_unlock(cv->lock);
-
-     enable_async(&cv_data);
-
-     ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout);
-
-     restore_async
-
-     lll_lock(cv->lock);
-
-     if (bc != cv->broadcast_seq)
-       goto bc_out;
-
-     val = cv->wakeup_seq;
-
-     if (val != seq && cv->woken_seq != val) {
-       ret = 0;
-       break;
-     }
-
-     if (ret == TIMEDOUT) {
-       ++cv->wakeup_seq;
-       break;
-     }
-   }
-
-   ++cv->woken_seq;
-
- bc_out:
-   lll_unlock(cv->lock);
-
-   cleanup_pop
-
-   mutex_lock(mutex);
-
-   return ret;
-}
-
-cond_signal(cv)
-{
-   lll_lock(cv->lock);
-
-   if (cv->total_seq > cv->wakeup_seq) {
-     ++cv->wakeup_seq;
-     FUTEX_WAKE(cv->wakeup_seq, 1);
-   }
-
-   lll_unlock(cv->lock);
-}
-
-cond_broadcast(cv)
-{
-   lll_lock(cv->lock);
-
-   if (cv->total_seq > cv->wakeup_seq) {
-     cv->wakeup_seq = cv->total_seq;
-     cv->woken_seq = cv->total_seq;
-     ++cv->broadcast_seq;
-     FUTEX_WAKE(cv->wakeup_seq, ALL);
-   }
-
-   lll_unlock(cv->lock);
-}
diff --git a/nptl/Makefile b/nptl/Makefile
index e0bc1b7..cbd7f4b 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -71,7 +71,7 @@  libpthread-routines = nptl-init vars events version pt-interp \
 		      pthread_rwlockattr_getkind_np \
 		      pthread_rwlockattr_setkind_np \
 		      pthread_cond_init pthread_cond_destroy \
-		      pthread_cond_wait pthread_cond_timedwait \
+		      pthread_cond_wait \
 		      pthread_cond_signal pthread_cond_broadcast \
 		      old_pthread_cond_init old_pthread_cond_destroy \
 		      old_pthread_cond_wait old_pthread_cond_timedwait \
@@ -181,7 +181,6 @@  CFLAGS-pthread_timedjoin.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-pthread_once.c = $(uses-callbacks) -fexceptions \
 			-fasynchronous-unwind-tables
 CFLAGS-pthread_cond_wait.c = -fexceptions -fasynchronous-unwind-tables
-CFLAGS-pthread_cond_timedwait.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-sem_wait.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-sem_timedwait.c = -fexceptions -fasynchronous-unwind-tables
 
@@ -302,8 +301,7 @@  test-xfail-tst-once5 = yes
 # Files which must not be linked with libpthread.
 tests-nolibpthread = tst-unload
 
-gen-as-const-headers = pthread-errnos.sym \
-		       lowlevelcond.sym lowlevelrwlock.sym \
+gen-as-const-headers = pthread-errnos.sym lowlevelrwlock.sym \
 		       unwindbuf.sym \
 		       lowlevelrobustlock.sym pthread-pi-defines.sym
 
diff --git a/nptl/lowlevelcond.sym b/nptl/lowlevelcond.sym
deleted file mode 100644
index 18e1ada..0000000
--- a/nptl/lowlevelcond.sym
+++ /dev/null
@@ -1,16 +0,0 @@ 
-#include <stddef.h>
-#include <sched.h>
-#include <bits/pthreadtypes.h>
-#include <internaltypes.h>
-
---
-
-cond_lock	offsetof (pthread_cond_t, __data.__lock)
-cond_futex	offsetof (pthread_cond_t, __data.__futex)
-cond_nwaiters	offsetof (pthread_cond_t, __data.__nwaiters)
-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)
-nwaiters_shift	COND_NWAITERS_SHIFT
diff --git a/nptl/pthread_cond_broadcast.c b/nptl/pthread_cond_broadcast.c
index 552fd42..87c0755 100644
--- a/nptl/pthread_cond_broadcast.c
+++ b/nptl/pthread_cond_broadcast.c
@@ -19,72 +19,71 @@ 
 #include <endian.h>
 #include <errno.h>
 #include <sysdep.h>
-#include <lowlevellock.h>
+#include <futex-internal.h>
 #include <pthread.h>
 #include <pthreadP.h>
 #include <stap-probe.h>
+#include <atomic.h>
 
 #include <shlib-compat.h>
-#include <kernel-features.h>
 
+#include "pthread_cond_common.c"
 
+
+/* We do the following steps from __pthread_cond_signal in one critical
+   section: (1) signal all waiters in G1, (2) close G1 so that it can become
+   the new G2 and make G2 the new G1, and (3) signal all waiters in the new
+   G1.  We don't need to do all these steps if there are no waiters in G1
+   and/or G2.  See __pthread_cond_signal for further details.  */
 int
 __pthread_cond_broadcast (pthread_cond_t *cond)
 {
   LIBC_PROBE (cond_broadcast, 1, cond);
 
-  int pshared = (cond->__data.__mutex == (void *) ~0l)
-		? LLL_SHARED : LLL_PRIVATE;
-  /* Make sure we are alone.  */
-  lll_lock (cond->__data.__lock, pshared);
+  unsigned int wrefs = atomic_load_relaxed (&cond->__data.__wrefs);
+  if (wrefs >> 3 == 0)
+    return 0;
+  int private = __condvar_get_private (wrefs);
+
+  __condvar_acquire_lock (cond, private);
 
-  /* Are there any waiters to be woken?  */
-  if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
+  unsigned long long int wseq = __condvar_load_wseq_relaxed (cond);
+  unsigned int g2 = wseq & 1;
+  unsigned int g1 = g2 ^ 1;
+  wseq >>= 1;
+  bool do_futex_wake = false;
+
+  /* Step (1): signal all waiters remaining in G1.  */
+  if (cond->__data.__g_size[g1] != 0)
     {
-      /* 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_unlock (cond->__data.__lock, pshared);
-
-      /* Wake everybody.  */
-      pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
-
-      /* Do not use requeue for pshared condvars.  */
-      if (mut == (void *) ~0l
-	  || PTHREAD_MUTEX_PSHARED (mut) & PTHREAD_MUTEX_PSHARED_BIT)
-	goto wake_all;
-
-#if (defined lll_futex_cmp_requeue_pi \
-     && defined __ASSUME_REQUEUE_PI)
-      if (USE_REQUEUE_PI (mut))
-	{
-	  if (lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, INT_MAX,
-					&mut->__data.__lock, futex_val,
-					LLL_PRIVATE) == 0)
-	    return 0;
-	}
-      else
-#endif
-	/* 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, LLL_PRIVATE), 0))
-	  return 0;
-
-wake_all:
-      lll_futex_wake (&cond->__data.__futex, INT_MAX, pshared);
-      return 0;
+      /* Add as many signals as the remaining size of the group.  */
+      atomic_fetch_add_relaxed (cond->__data.__g_signals + g1,
+				cond->__data.__g_size[g1] << 1);
+      cond->__data.__g_size[g1] = 0;
+
+      /* We need to wake G1 waiters before we quiesce G1 below.  */
+      /* TODO Only set it if there are indeed futex waiters.  We could
+	 also try to move this out of the critical section in cases when
+	 G2 is empty (and we don't need to quiesce).  */
+      futex_wake (cond->__data.__g_signals + g1, INT_MAX, private);
     }
 
-  /* We are done.  */
-  lll_unlock (cond->__data.__lock, pshared);
+  /* G1 is complete.  Step (2) is next unless there are no waiters in G2, in
+     which case we can stop.  */
+  if (__condvar_quiesce_and_switch_g1 (cond, wseq, &g1, private))
+    {
+      /* Step (3): Send signals to all waiters in the old G2 / new G1.  */
+      atomic_fetch_add_relaxed (cond->__data.__g_signals + g1,
+				cond->__data.__g_size[g1] << 1);
+      cond->__data.__g_size[g1] = 0;
+      /* TODO Only set it if there are indeed futex waiters.  */
+      do_futex_wake = true;
+    }
+
+  __condvar_release_lock (cond, private);
+
+  if (do_futex_wake)
+    futex_wake (cond->__data.__g_signals + g1, INT_MAX, private);
 
   return 0;
 }
diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c
new file mode 100644
index 0000000..b374396
--- /dev/null
+++ b/nptl/pthread_cond_common.c
@@ -0,0 +1,466 @@ 
+/* pthread_cond_common -- shared code for condition variable.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <atomic.h>
+#include <stdint.h>
+#include <pthread.h>
+#include <libc-internal.h>
+
+/* We need 3 least-significant bits on __wrefs for something else.  */
+#define __PTHREAD_COND_MAX_GROUP_SIZE ((unsigned) 1 << 29)
+
+#if __HAVE_64B_ATOMICS == 1
+
+static uint64_t __attribute__ ((unused))
+__condvar_load_wseq_relaxed (pthread_cond_t *cond)
+{
+  return atomic_load_relaxed (&cond->__data.__wseq);
+}
+
+static uint64_t __attribute__ ((unused))
+__condvar_fetch_add_wseq_acquire (pthread_cond_t *cond, unsigned int val)
+{
+  return atomic_fetch_add_acquire (&cond->__data.__wseq, val);
+}
+
+static uint64_t __attribute__ ((unused))
+__condvar_fetch_xor_wseq_release (pthread_cond_t *cond, unsigned int val)
+{
+  return atomic_fetch_xor_release (&cond->__data.__wseq, val);
+}
+
+static uint64_t __attribute__ ((unused))
+__condvar_load_g1_start_relaxed (pthread_cond_t *cond)
+{
+  return atomic_load_relaxed (&cond->__data.__g1_start);
+}
+
+static void __attribute__ ((unused))
+__condvar_add_g1_start_relaxed (pthread_cond_t *cond, unsigned int val)
+{
+  atomic_store_relaxed (&cond->__data.__g1_start,
+      atomic_load_relaxed (&cond->__data.__g1_start) + val);
+}
+
+#else
+
+/* We use two 64b counters: __wseq and __g1_start.  They are monotonically
+   increasing and single-writer-multiple-readers counters, so we can implement
+   load, fetch-and-add, and fetch-and-xor operations even when we just have
+   32b atomics.  Values we add or xor are less than or equal to 1<<31 (*),
+   so we only have to make overflow-and-addition atomic wrt. to concurrent
+   load operations and xor operations.  To do that, we split each counter into
+   two 32b values of which we reserve the MSB of each to represent an
+   overflow from the lower-order half to the higher-order half.
+
+   In the common case, the state is (higher-order / lower-order half, and . is
+   basically concatenation of the bits):
+   0.h     / 0.l  = h.l
+
+   When we add a value of x that overflows (i.e., 0.l + x == 1.L), we run the
+   following steps S1-S4 (the values these represent are on the right-hand
+   side):
+   S1:  0.h     / 1.L == (h+1).L
+   S2:  1.(h+1) / 1.L == (h+1).L
+   S3:  1.(h+1) / 0.L == (h+1).L
+   S4:  0.(h+1) / 0.L == (h+1).L
+   If the LSB of the higher-order half is set, readers will ignore the
+   overflow bit in the lower-order half.
+
+   To get an atomic snapshot in load operations, we exploit that the
+   higher-order half is monotonically increasing; if we load a value V from
+   it, then read the lower-order half, and then read the higher-order half
+   again and see the same value V, we know that both halves have existed in
+   the sequence of values the full counter had.  This is similar to the
+   validated reads in the time-based STMs in GCC's libitm (e.g.,
+   method_ml_wt).
+
+   The xor operation needs to be an atomic read-modify-write.  The write
+   itself is not an issue as it affects just the lower-order half but not bits
+   used in the add operation.  To make the full fetch-and-xor atomic, we
+   exploit that concurrently, the value can increase by at most 1<<31 (*): The
+   xor operation is only called while having acquired the lock, so not more
+   than __PTHREAD_COND_MAX_GROUP_SIZE waiters can enter concurrently and thus
+   increment __wseq.  Therefore, if the xor operation observes a value of
+   __wseq, then the value it applies the modification to later on can be
+   derived (see below).
+
+   One benefit of this scheme is that this makes load operations
+   obstruction-free because unlike if we would just lock the counter, readers
+   can almost always interpret a snapshot of each halves.  Readers can be
+   forced to read a new snapshot when the read is concurrent with an overflow.
+   However, overflows will happen infrequently, so load operations are
+   practically lock-free.
+
+   (*) The highest value we add is __PTHREAD_COND_MAX_GROUP_SIZE << 2 to
+   __g1_start (the two extra bits are for the lock in the two LSBs of
+   __g1_start).  */
+
+typedef struct
+{
+  unsigned int low;
+  unsigned int high;
+} _condvar_lohi;
+
+static uint64_t
+__condvar_fetch_add_64_relaxed (_condvar_lohi *lh, unsigned int op)
+{
+  /* S1. Note that this is an atomic read-modify-write so it extends the
+     release sequence of release MO store at S3.  */
+  unsigned int l = atomic_fetch_add_relaxed (&lh->low, op);
+  unsigned int h = atomic_load_relaxed (&lh->high);
+  uint64_t result = ((uint64_t) h << 31) | l;
+  l += op;
+  if ((l >> 31) > 0)
+    {
+      /* Overflow.  Need to increment higher-order half.  Note that all
+	 add operations are ordered in happens-before.  */
+      h++;
+      /* S2. Release MO to synchronize with the loads of the higher-order half
+	 in the load operation.  See __condvar_load_64_relaxed.  */
+      atomic_store_release (&lh->high, h | ((unsigned int) 1 << 31));
+      l ^= (unsigned int) 1 << 31;
+      /* S3.  See __condvar_load_64_relaxed.  */
+      atomic_store_release (&lh->low, l);
+      /* S4.  Likewise.  */
+      atomic_store_release (&lh->high, h);
+    }
+  return result;
+}
+
+static uint64_t
+__condvar_load_64_relaxed (_condvar_lohi *lh)
+{
+  unsigned int h, l, h2;
+  do
+    {
+      /* This load and the second one below to the same location read from the
+	 stores in the overflow handling of the add operation or the
+	 initializing stores (which is a simple special case because
+	 initialization always completely happens before further use).
+	 Because no two stores to the higher-order half write the same value,
+	 the loop ensures that if we continue to use the snapshot, this load
+	 and the second one read from the same store operation.  All candidate
+	 store operations have release MO.
+	 If we read from S2 in the first load, then we will see the value of
+	 S1 on the next load (because we synchronize with S2), or a value
+	 later in modification order.  We correctly ignore the lower-half's
+	 overflow bit in this case.  If we read from S4, then we will see the
+	 value of S3 in the next load (or a later value), which does not have
+	 the overflow bit set anymore.
+	  */
+      h = atomic_load_acquire (&lh->high);
+      /* This will read from the release sequence of S3 (i.e, either the S3
+	 store or the read-modify-writes at S1 following S3 in modification
+	 order).  Thus, the read synchronizes with S3, and the following load
+	 of the higher-order half will read from the matching S2 (or a later
+	 value).
+	 Thus, if we read a lower-half value here that already overflowed and
+	 belongs to an increased higher-order half value, we will see the
+	 latter and h and h2 will not be equal.  */
+      l = atomic_load_acquire (&lh->low);
+      /* See above.  */
+      h2 = atomic_load_relaxed (&lh->high);
+    }
+  while (h != h2);
+  if (((l >> 31) > 0) && ((h >> 31) > 0))
+    l ^= (unsigned int) 1 << 31;
+  return ((uint64_t) (h & ~((unsigned int) 1 << 31)) << 31) + l;
+}
+
+static uint64_t __attribute__ ((unused))
+__condvar_load_wseq_relaxed (pthread_cond_t *cond)
+{
+  return __condvar_load_64_relaxed ((_condvar_lohi *) &cond->__data.__wseq32);
+}
+
+static uint64_t __attribute__ ((unused))
+__condvar_fetch_add_wseq_acquire (pthread_cond_t *cond, unsigned int val)
+{
+  uint64_t r = __condvar_fetch_add_64_relaxed
+      ((_condvar_lohi *) &cond->__data.__wseq32, val);
+  atomic_thread_fence_acquire ();
+  return r;
+}
+
+static uint64_t __attribute__ ((unused))
+__condvar_fetch_xor_wseq_release (pthread_cond_t *cond, unsigned int val)
+{
+  _condvar_lohi *lh = (_condvar_lohi *) &cond->__data.__wseq32;
+  /* First, get the current value.  See __condvar_load_64_relaxed.  */
+  unsigned int h, l, h2;
+  do
+    {
+      h = atomic_load_acquire (&lh->high);
+      l = atomic_load_acquire (&lh->low);
+      h2 = atomic_load_relaxed (&lh->high);
+    }
+  while (h != h2);
+  if (((l >> 31) > 0) && ((h >> 31) == 0))
+    h++;
+  h &= ~((unsigned int) 1 << 31);
+  l &= ~((unsigned int) 1 << 31);
+
+  /* Now modify.  Due to the coherence rules, the prior load will read a value
+     earlier in modification order than the following fetch-xor.
+     This uses release MO to make the full operation have release semantics
+     (all other operations access the lower-order half).  */
+  unsigned int l2 = atomic_fetch_xor_release (&lh->low, val)
+      & ~((unsigned int) 1 << 31);
+  if (l2 < l)
+    /* The lower-order half overflowed in the meantime.  This happened exactly
+       once due to the limit on concurrent waiters (see above).  */
+    h++;
+  return ((uint64_t) h << 31) + l2;
+}
+
+static uint64_t __attribute__ ((unused))
+__condvar_load_g1_start_relaxed (pthread_cond_t *cond)
+{
+  return __condvar_load_64_relaxed
+      ((_condvar_lohi *) &cond->__data.__g1_start32);
+}
+
+static void __attribute__ ((unused))
+__condvar_add_g1_start_relaxed (pthread_cond_t *cond, unsigned int val)
+{
+  ignore_value (__condvar_fetch_add_64_relaxed
+      ((_condvar_lohi *) &cond->__data.__g1_start32, val));
+}
+
+#endif  /* !__HAVE_64B_ATOMICS  */
+
+
+/* The lock that signalers use.  See pthread_cond_wait_common for uses.
+   The lock is our normal three-state lock: not acquired (0) / acquired (1) /
+   acquired-with-futex_wake-request (2).  However, we need to preserve the
+   other bits in the unsigned int used for the lock, and therefore it is a
+   little more complex.  */
+static void __attribute__ ((unused))
+__condvar_acquire_lock (pthread_cond_t *cond, int private)
+{
+  unsigned int s = atomic_load_relaxed (&cond->__data.__g1_orig_size);
+  while ((s & 3) == 0)
+    {
+      if (atomic_compare_exchange_weak_acquire (&cond->__data.__g1_orig_size,
+	  &s, s | 1))
+	return;
+      /* TODO Spinning and back-off.  */
+    }
+  /* We can't change from not acquired to acquired, so try to change to
+     acquired-with-futex-wake-request and do a futex wait if we cannot change
+     from not acquired.  */
+  while (1)
+    {
+      while ((s & 3) != 2)
+	{
+	  if (atomic_compare_exchange_weak_acquire
+	      (&cond->__data.__g1_orig_size, &s, (s & ~(unsigned int) 3) | 2))
+	    {
+	      if ((s & 3) == 0)
+		return;
+	      break;
+	    }
+	  /* TODO Back off.  */
+	}
+      futex_wait_simple (&cond->__data.__g1_orig_size,
+	  (s & ~(unsigned int) 3) | 2, private);
+      /* Reload so we see a recent value.  */
+      s = atomic_load_relaxed (&cond->__data.__g1_orig_size);
+    }
+}
+
+/* See __condvar_acquire_lock.  */
+static void __attribute__ ((unused))
+__condvar_release_lock (pthread_cond_t *cond, int private)
+{
+  if ((atomic_fetch_and_release (&cond->__data.__g1_orig_size,
+				 ~(unsigned int) 3) & 3)
+      == 2)
+    futex_wake (&cond->__data.__g1_orig_size, 1, private);
+}
+
+/* Only use this when having acquired the lock.  */
+static unsigned int __attribute__ ((unused))
+__condvar_get_orig_size (pthread_cond_t *cond)
+{
+  return atomic_load_relaxed (&cond->__data.__g1_orig_size) >> 2;
+}
+
+/* Only use this when having acquired the lock.  */
+static void __attribute__ ((unused))
+__condvar_set_orig_size (pthread_cond_t *cond, unsigned int size)
+{
+  /* We have acquired the lock, but might get one concurrent update due to a
+     lock state change from acquired to acquired-with-futex_wake-request.
+     The store with relaxed MO is fine because there will be no further
+     changes to the lock bits nor the size, and we will subsequently release
+     the lock with release MO.  */
+  unsigned int s;
+  s = (atomic_load_relaxed (&cond->__data.__g1_orig_size) & 3)
+      | (size << 2);
+  if ((atomic_exchange_relaxed (&cond->__data.__g1_orig_size, s) & 3)
+      != (s & 3))
+    atomic_store_relaxed (&cond->__data.__g1_orig_size, (size << 2) | 2);
+}
+
+/* Returns FUTEX_SHARED or FUTEX_PRIVATE based on the provided __wrefs
+   value.  */
+static int __attribute__ ((unused))
+__condvar_get_private (int flags)
+{
+  if ((flags & __PTHREAD_COND_SHARED_MASK) == 0)
+    return FUTEX_PRIVATE;
+  else
+    return FUTEX_SHARED;
+}
+
+/* This closes G1 (whose index is in G1INDEX), waits for all futex waiters to
+   leave G1, converts G1 into a fresh G2, and then switches group roles so that
+   the former G2 becomes the new G1 ending at the current __wseq value when we
+   eventually make the switch (WSEQ is just an observation of __wseq by the
+   signaler).
+   If G2 is empty, it will not switch groups because then it would create an
+   empty G1 which would require switching groups again on the next signal.
+   Returns false iff groups were not switched because G2 was empty.  */
+static bool __attribute__ ((unused))
+__condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
+    unsigned int *g1index, int private)
+{
+  const unsigned int maxspin = 0;
+  unsigned int g1 = *g1index;
+
+  /* If there is no waiter in G2, we don't do anything.  The expression may
+     look odd but remember that __g_size might hold a negative value, so
+     putting the expression this way avoids relying on implementation-defined
+     behavior.
+     Note that this works correctly for a zero-initialized condvar too.  */
+  unsigned int old_orig_size = __condvar_get_orig_size (cond);
+  uint64_t old_g1_start = __condvar_load_g1_start_relaxed (cond) >> 1;
+  if (((unsigned) (wseq - old_g1_start - old_orig_size)
+	  + cond->__data.__g_size[g1 ^ 1]) == 0)
+	return false;
+
+  /* Now try to close and quiesce G1.  We have to consider the following kinds
+     of waiters:
+     * Waiters from less recent groups than G1 are not affected because
+       nothing will change for them apart from __g1_start getting larger.
+     * New waiters arriving concurrently with the group switching will all go
+       into G2 until we atomically make the switch.  Waiters existing in G2
+       are not affected.
+     * Waiters in G1 will be closed out immediately by setting a flag in
+       __g_signals, which will prevent waiters from blocking using a futex on
+       __g_signals and also notifies them that the group is closed.  As a
+       result, they will eventually remove their group reference, allowing us
+       to close switch group roles.  */
+
+  /* First, set the closed flag on __g_signals.  This tells waiters that are
+     about to wait that they shouldn't do that anymore.  This basically
+     serves as an advance notificaton of the upcoming change to __g1_start;
+     waiters interpret it as if __g1_start was larger than their waiter
+     sequence position.  This allows us to change __g1_start after waiting
+     for all existing waiters with group references to leave, which in turn
+     makes recovery after stealing a signal simpler because it then can be
+     skipped if __g1_start indicates that the group is closed (otherwise,
+     we would have to recover always because waiters don't know how big their
+     groups are).  Relaxed MO is fine.  */
+  atomic_fetch_or_relaxed (cond->__data.__g_signals + g1, 1);
+
+  /* Wait until there are no group references anymore.  The fetch-or operation
+     injects us into the modification order of __g_refs; release MO ensures
+     that waiters incrementing __g_refs after our fetch-or see the previous
+     changes to __g_signals and to __g1_start that had to happen before we can
+     switch this G1 and alias with an older group (we have two groups, so
+     aliasing requires switching group roles twice).  Note that nobody else
+     can have set the wake-request flag, so we do not have to act upon it.
+
+     Also note that it is harmless if older waiters or waiters from this G1
+     get a group reference after we have quiesced the group because it will
+     remain closed for them either because of the closed flag in __g_signals
+     or the later update to __g1_start.  New waiters will never arrive here
+     but instead continue to go into the still current G2.  */
+  unsigned r = atomic_fetch_or_release (cond->__data.__g_refs + g1, 0);
+  while ((r >> 1) > 0)
+    {
+      for (unsigned int spin = maxspin; ((r >> 1) > 0) && (spin > 0); spin--)
+	{
+	  /* TODO Back off.  */
+	  r = atomic_load_relaxed (cond->__data.__g_refs + g1);
+	}
+      if ((r >> 1) > 0)
+	{
+	  /* There is still a waiter after spinning.  Set the wake-request
+	     flag and block.  Relaxed MO is fine because this is just about
+	     this futex word.  */
+	  r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1);
+
+	  if ((r >> 1) > 0)
+	    futex_wait_simple (cond->__data.__g_refs + g1, r, private);
+	  /* Reload here so we eventually see the most recent value even if we
+	     do not spin.   */
+	  r = atomic_load_relaxed (cond->__data.__g_refs + g1);
+	}
+    }
+  /* Acquire MO so that we synchronize with the release operation that waiters
+     use to decrement __g_refs and thus happen after the waiters we waited
+     for.  */
+  atomic_thread_fence_acquire ();
+
+  /* Update __g1_start, which finishes closing this group.  The value we add
+     will never be negative because old_orig_size can only be zero when we
+     switch groups the first time after a condvar was initialized, in which
+     case G1 will be at index 1 and we will add a value of 1.  See above for
+     why this takes place after waiting for quiescence of the group.
+     Relaxed MO is fine because the change comes with no additional
+     constraints that others would have to observe.  */
+  __condvar_add_g1_start_relaxed (cond,
+      (old_orig_size << 1) + (g1 == 1 ? 1 : - 1));
+
+  /* Now reopen the group, thus enabling waiters to again block using the
+     futex controlled by __g_signals.  Release MO so that observers that see
+     no signals (and thus can block) also see the write __g1_start and thus
+     that this is now a new group (see __pthread_cond_wait_common for the
+     matching acquire MO loads).  */
+  atomic_store_release (cond->__data.__g_signals + g1, 0);
+
+  /* At this point, the old G1 is now a valid new G2 (but not in use yet).
+     No old waiter can neither grab a signal nor acquire a reference without
+     noticing that __g1_start is larger.
+     We can now publish the group switch by flipping the G2 index in __wseq.
+     Release MO so that this synchronizes with the acquire MO operation
+     waiters use to obtain a position in the waiter sequence.  */
+  wseq = __condvar_fetch_xor_wseq_release (cond, 1) >> 1;
+  g1 ^= 1;
+  *g1index ^= 1;
+
+  /* These values are just observed by signalers, and thus protected by the
+     lock.  */
+  unsigned int orig_size = wseq - (old_g1_start + old_orig_size);
+  __condvar_set_orig_size (cond, orig_size);
+  /* Use and addition to not loose track of cancellations in what was
+     previously G2.  */
+  cond->__data.__g_size[g1] += orig_size;
+
+  /* The new G1's size may be zero because of cancellations during its time
+     as G2.  If this happens, there are no waiters that have to receive a
+     signal, so we do not need to add any and return false.  */
+  if (cond->__data.__g_size[g1] == 0)
+    return false;
+
+  return true;
+}
diff --git a/nptl/pthread_cond_destroy.c b/nptl/pthread_cond_destroy.c
index 1acd804..5845c6a 100644
--- a/nptl/pthread_cond_destroy.c
+++ b/nptl/pthread_cond_destroy.c
@@ -20,66 +20,42 @@ 
 #include <shlib-compat.h>
 #include "pthreadP.h"
 #include <stap-probe.h>
-
-
+#include <atomic.h>
+#include <futex-internal.h>
+
+#include "pthread_cond_common.c"
+
+/* See __pthread_cond_wait for a high-level description of the algorithm.
+
+   A correct program must make sure that no waiters are blocked on the condvar
+   when it is destroyed, and that there are no concurrent signals or
+   broadcasts.  To wake waiters reliably, the program must signal or
+   broadcast while holding the mutex or after having held the mutex.  It must
+   also ensure that no signal or broadcast are still pending to unblock
+   waiters; IOW, because waiters can wake up spuriously, the program must
+   effectively ensure that destruction happens after the execution of those
+   signal or broadcast calls.
+   Thus, we can assume that all waiters that are still accessing the condvar
+   have been woken.  We wait until they have confirmed to have woken up by
+   decrementing __wrefs.  */
 int
 __pthread_cond_destroy (pthread_cond_t *cond)
 {
-  int pshared = (cond->__data.__mutex == (void *) ~0l)
-		? LLL_SHARED : LLL_PRIVATE;
-
   LIBC_PROBE (cond_destroy, 1, cond);
 
-  /* Make sure we are alone.  */
-  lll_lock (cond->__data.__lock, pshared);
-
-  if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
-    {
-      /* If there are still some waiters which have not been
-	 woken up, this is an application bug.  */
-      lll_unlock (cond->__data.__lock, pshared);
-      return EBUSY;
-    }
-
-  /* Tell pthread_cond_*wait that this condvar is being destroyed.  */
-  cond->__data.__total_seq = -1ULL;
-
-  /* If there are waiters which have been already signalled or
-     broadcasted, but still are using the pthread_cond_t structure,
-     pthread_cond_destroy needs to wait for them.  */
-  unsigned int nwaiters = cond->__data.__nwaiters;
-
-  if (nwaiters >= (1 << COND_NWAITERS_SHIFT))
+  /* Set the wake request flag.  We could also spin, but destruction that is
+     concurrent with still-active waiters is probably neither common nor
+     performance critical.  Acquire MO to synchronize with waiters confirming
+     that they finished.  */
+  unsigned int wrefs = atomic_fetch_or_acquire (&cond->__data.__wrefs, 4);
+  int private = __condvar_get_private (wrefs);
+  while (wrefs >> 3 != 0)
     {
-      /* Wake everybody on the associated mutex in case there are
-	 threads that have been requeued to it.
-	 Without this, pthread_cond_destroy could block potentially
-	 for a long time or forever, as it would depend on other
-	 thread's using the mutex.
-	 When all threads waiting on the mutex are woken up, pthread_cond_wait
-	 only waits for threads to acquire and release the internal
-	 condvar lock.  */
-      if (cond->__data.__mutex != NULL
-	  && cond->__data.__mutex != (void *) ~0l)
-	{
-	  pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
-	  lll_futex_wake (&mut->__data.__lock, INT_MAX,
-			  PTHREAD_MUTEX_PSHARED (mut));
-	}
-
-      do
-	{
-	  lll_unlock (cond->__data.__lock, pshared);
-
-	  lll_futex_wait (&cond->__data.__nwaiters, nwaiters, pshared);
-
-	  lll_lock (cond->__data.__lock, pshared);
-
-	  nwaiters = cond->__data.__nwaiters;
-	}
-      while (nwaiters >= (1 << COND_NWAITERS_SHIFT));
+      futex_wait_simple (&cond->__data.__wrefs, wrefs, private);
+      /* See above.  */
+      wrefs = atomic_load_acquire (&cond->__data.__wrefs);
     }
-
+  /* The memory the condvar occupies can now be reused.  */
   return 0;
 }
 versioned_symbol (libpthread, __pthread_cond_destroy,
diff --git a/nptl/pthread_cond_init.c b/nptl/pthread_cond_init.c
index 9023370..cdd9b7d 100644
--- a/nptl/pthread_cond_init.c
+++ b/nptl/pthread_cond_init.c
@@ -19,25 +19,25 @@ 
 #include <shlib-compat.h>
 #include "pthreadP.h"
 #include <stap-probe.h>
+#include <string.h>
 
 
+/* See __pthread_cond_wait for details.  */
 int
 __pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
 {
   struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr;
 
-  cond->__data.__lock = LLL_LOCK_INITIALIZER;
-  cond->__data.__futex = 0;
-  cond->__data.__nwaiters = (icond_attr != NULL
-			     ? ((icond_attr->value >> 1)
-				& ((1 << COND_NWAITERS_SHIFT) - 1))
-			     : CLOCK_REALTIME);
-  cond->__data.__total_seq = 0;
-  cond->__data.__wakeup_seq = 0;
-  cond->__data.__woken_seq = 0;
-  cond->__data.__mutex = (icond_attr == NULL || (icond_attr->value & 1) == 0
-			  ? NULL : (void *) ~0l);
-  cond->__data.__broadcast_seq = 0;
+  memset (cond, 0, sizeof (pthread_cond_t));
+  /* Iff not equal to ~0l, this is a PTHREAD_PROCESS_PRIVATE condvar.  */
+  if (icond_attr != NULL && (icond_attr->value & 1) != 0)
+    cond->__data.__wrefs |= __PTHREAD_COND_SHARED_MASK;
+  int clockid = (icond_attr != NULL
+		 ? ((icond_attr->value >> 1) & ((1 << COND_CLOCK_BITS) - 1))
+		 : CLOCK_REALTIME);
+  /* If 0, CLOCK_REALTIME is used; CLOCK_MONOTONIC otherwise.  */
+  if (clockid != CLOCK_REALTIME)
+    cond->__data.__wrefs |= __PTHREAD_COND_CLOCK_MONOTONIC_MASK;
 
   LIBC_PROBE (cond_init, 2, cond, cond_attr);
 
diff --git a/nptl/pthread_cond_signal.c b/nptl/pthread_cond_signal.c
index b3a6d3d..a95d569 100644
--- a/nptl/pthread_cond_signal.c
+++ b/nptl/pthread_cond_signal.c
@@ -19,62 +19,79 @@ 
 #include <endian.h>
 #include <errno.h>
 #include <sysdep.h>
-#include <lowlevellock.h>
+#include <futex-internal.h>
 #include <pthread.h>
 #include <pthreadP.h>
+#include <atomic.h>
+#include <stdint.h>
 
 #include <shlib-compat.h>
-#include <kernel-features.h>
 #include <stap-probe.h>
 
+#include "pthread_cond_common.c"
 
+/* See __pthread_cond_wait for a high-level description of the algorithm.  */
 int
 __pthread_cond_signal (pthread_cond_t *cond)
 {
-  int pshared = (cond->__data.__mutex == (void *) ~0l)
-		? LLL_SHARED : LLL_PRIVATE;
-
   LIBC_PROBE (cond_signal, 1, cond);
 
-  /* Make sure we are alone.  */
-  lll_lock (cond->__data.__lock, pshared);
-
-  /* Are there any waiters to be woken?  */
-  if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
+  /* First check whether there are waiters.  Relaxed MO is fine for that for
+     the same reasons that relaxed MO is fine when observing __wseq (see
+     below).  */
+  unsigned int wrefs = atomic_load_relaxed (&cond->__data.__wrefs);
+  if (wrefs >> 3 == 0)
+    return 0;
+  int private = __condvar_get_private (wrefs);
+
+  __condvar_acquire_lock (cond, private);
+
+  /* Load the waiter sequence number, which represents our relative ordering
+     to any waiters.  Relaxed MO is sufficient for that because:
+     1) We can pick any position that is allowed by external happens-before
+        constraints.  In particular, if another __pthread_cond_wait call
+        happened before us, this waiter must be eligible for being woken by
+        us.  The only way do establish such a happens-before is by signaling
+        while having acquired the mutex associated with the condvar and
+        ensuring that the signal's critical section happens after the waiter.
+        Thus, the mutex ensures that we see that waiter's __wseq increase.
+     2) Once we pick a position, we do not need to communicate this to the
+        program via a happens-before that we set up: First, any wake-up could
+        be a spurious wake-up, so the program must not interpret a wake-up as
+        an indication that the waiter happened before a particular signal;
+        second, a program cannot detect whether a waiter has not yet been
+        woken (i.e., it cannot distinguish between a non-woken waiter and one
+        that has been woken but hasn't resumed execution yet), and thus it
+        cannot try to deduce that a signal happened before a particular
+        waiter.  */
+  unsigned long long int wseq = __condvar_load_wseq_relaxed (cond);
+  unsigned int g1 = (wseq & 1) ^ 1;
+  wseq >>= 1;
+  bool do_futex_wake = false;
+
+  /* If G1 is still receiving signals, we put the signal there.  If not, we
+     check if G2 has waiters, and if so, quiesce and switch G1 to the former
+     G2; if this results in a new G1 with waiters (G2 might have cancellations
+     already, see __condvar_quiesce_and_switch_g1), we put the signal in the
+     new G1.  */
+  if ((cond->__data.__g_size[g1] != 0)
+      || __condvar_quiesce_and_switch_g1 (cond, wseq, &g1, private))
     {
-      /* Yes.  Mark one of them as woken.  */
-      ++cond->__data.__wakeup_seq;
-      ++cond->__data.__futex;
-
-#if (defined lll_futex_cmp_requeue_pi \
-     && defined __ASSUME_REQUEUE_PI)
-      pthread_mutex_t *mut = cond->__data.__mutex;
-
-      if (USE_REQUEUE_PI (mut)
-	/* This can only really fail with a ENOSYS, since nobody can modify
-	   futex while we have the cond_lock.  */
-	  && lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, 0,
-				       &mut->__data.__lock,
-				       cond->__data.__futex, pshared) == 0)
-	{
-	  lll_unlock (cond->__data.__lock, pshared);
-	  return 0;
-	}
-      else
-#endif
-	/* Wake one.  */
-	if (! __builtin_expect (lll_futex_wake_unlock (&cond->__data.__futex,
-						       1, 1,
-						       &cond->__data.__lock,
-						       pshared), 0))
-	  return 0;
-
-      /* Fallback if neither of them work.  */
-      lll_futex_wake (&cond->__data.__futex, 1, pshared);
+      /* Add a signal.  Relaxed MO is fine because signaling does not need to
+	 establish a happens-before relation (see above).  We do not mask the
+	 release-MO store when initializing a group in
+	 __condvar_quiesce_and_switch_g1 because we use an atomic
+	 read-modify-write and thus extend that store's release sequence.  */
+      atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, 2);
+      cond->__data.__g_size[g1]--;
+      /* TODO Only set it if there are indeed futex waiters.  */
+      do_futex_wake = true;
     }
 
-  /* We are done.  */
-  lll_unlock (cond->__data.__lock, pshared);
+  __condvar_release_lock (cond, private);
+
+  if (do_futex_wake)
+    futex_wake (cond->__data.__g_signals + g1, 1, private);
 
   return 0;
 }
diff --git a/nptl/pthread_cond_timedwait.c b/nptl/pthread_cond_timedwait.c
deleted file mode 100644
index 711a51d..0000000
--- a/nptl/pthread_cond_timedwait.c
+++ /dev/null
@@ -1,268 +0,0 @@ 
-/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <endian.h>
-#include <errno.h>
-#include <sysdep.h>
-#include <lowlevellock.h>
-#include <pthread.h>
-#include <pthreadP.h>
-#include <sys/time.h>
-#include <kernel-features.h>
-
-#include <shlib-compat.h>
-
-#ifndef HAVE_CLOCK_GETTIME_VSYSCALL
-# undef INTERNAL_VSYSCALL
-# define INTERNAL_VSYSCALL INTERNAL_SYSCALL
-# undef INLINE_VSYSCALL
-# define INLINE_VSYSCALL INLINE_SYSCALL
-#else
-# include <libc-vdso.h>
-#endif
-
-/* Cleanup handler, defined in pthread_cond_wait.c.  */
-extern void __condvar_cleanup (void *arg)
-     __attribute__ ((visibility ("hidden")));
-
-struct _condvar_cleanup_buffer
-{
-  int oldtype;
-  pthread_cond_t *cond;
-  pthread_mutex_t *mutex;
-  unsigned int bc_seq;
-};
-
-int
-__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
-			  const struct timespec *abstime)
-{
-  struct _pthread_cleanup_buffer buffer;
-  struct _condvar_cleanup_buffer cbuffer;
-  int result = 0;
-
-  /* Catch invalid parameters.  */
-  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
-    return EINVAL;
-
-  int pshared = (cond->__data.__mutex == (void *) ~0l)
-		? LLL_SHARED : LLL_PRIVATE;
-
-#if (defined lll_futex_timed_wait_requeue_pi \
-     && defined __ASSUME_REQUEUE_PI)
-  int pi_flag = 0;
-#endif
-
-  /* Make sure we are alone.  */
-  lll_lock (cond->__data.__lock, pshared);
-
-  /* Now we can release the mutex.  */
-  int err = __pthread_mutex_unlock_usercnt (mutex, 0);
-  if (err)
-    {
-      lll_unlock (cond->__data.__lock, pshared);
-      return err;
-    }
-
-  /* We have one new user of the condvar.  */
-  ++cond->__data.__total_seq;
-  ++cond->__data.__futex;
-  cond->__data.__nwaiters += 1 << COND_NWAITERS_SHIFT;
-
-  /* Work around the fact that the kernel rejects negative timeout values
-     despite them being valid.  */
-  if (__glibc_unlikely (abstime->tv_sec < 0))
-    goto timeout;
-
-  /* Remember the mutex we are using here.  If there is already a
-     different address store this is a bad user bug.  Do not store
-     anything for pshared condvars.  */
-  if (cond->__data.__mutex != (void *) ~0l)
-    cond->__data.__mutex = mutex;
-
-  /* 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, &cbuffer);
-
-  /* The current values of the wakeup counter.  The "woken" counter
-     must exceed this value.  */
-  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;
-
-  while (1)
-    {
-#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
-     || !defined lll_futex_timed_wait_bitset)
-      struct timespec rt;
-      {
-# ifdef __NR_clock_gettime
-	INTERNAL_SYSCALL_DECL (err);
-	(void) INTERNAL_VSYSCALL (clock_gettime, err, 2,
-				  (cond->__data.__nwaiters
-				   & ((1 << COND_NWAITERS_SHIFT) - 1)),
-				  &rt);
-	/* Convert the absolute timeout value to a relative timeout.  */
-	rt.tv_sec = abstime->tv_sec - rt.tv_sec;
-	rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec;
-# else
-	/* Get the current time.  So far we support only one clock.  */
-	struct timeval tv;
-	(void) __gettimeofday (&tv, NULL);
-
-	/* Convert the absolute timeout value to a relative timeout.  */
-	rt.tv_sec = abstime->tv_sec - tv.tv_sec;
-	rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
-# endif
-      }
-      if (rt.tv_nsec < 0)
-	{
-	  rt.tv_nsec += 1000000000;
-	  --rt.tv_sec;
-	}
-      /* Did we already time out?  */
-      if (__glibc_unlikely (rt.tv_sec < 0))
-	{
-	  if (cbuffer.bc_seq != cond->__data.__broadcast_seq)
-	    goto bc_out;
-
-	  goto timeout;
-	}
-#endif
-
-      unsigned int futex_val = cond->__data.__futex;
-
-      /* Prepare to wait.  Release the condvar futex.  */
-      lll_unlock (cond->__data.__lock, pshared);
-
-      /* Enable asynchronous cancellation.  Required by the standard.  */
-      cbuffer.oldtype = __pthread_enable_asynccancel ();
-
-/* REQUEUE_PI was implemented after FUTEX_CLOCK_REALTIME, so it is sufficient
-   to check just the former.  */
-#if (defined lll_futex_timed_wait_requeue_pi \
-     && defined __ASSUME_REQUEUE_PI)
-      /* If pi_flag remained 1 then it means that we had the lock and the mutex
-	 but a spurious waker raced ahead of us.  Give back the mutex before
-	 going into wait again.  */
-      if (pi_flag)
-	{
-	  __pthread_mutex_cond_lock_adjust (mutex);
-	  __pthread_mutex_unlock_usercnt (mutex, 0);
-	}
-      pi_flag = USE_REQUEUE_PI (mutex);
-
-      if (pi_flag)
-	{
-	  unsigned int clockbit = (cond->__data.__nwaiters & 1
-				   ? 0 : FUTEX_CLOCK_REALTIME);
-	  err = lll_futex_timed_wait_requeue_pi (&cond->__data.__futex,
-						 futex_val, abstime, clockbit,
-						 &mutex->__data.__lock,
-						 pshared);
-	  pi_flag = (err == 0);
-	}
-      else
-#endif
-
-	{
-#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
-     || !defined lll_futex_timed_wait_bitset)
-	  /* Wait until woken by signal or broadcast.  */
-	  err = lll_futex_timed_wait (&cond->__data.__futex,
-				      futex_val, &rt, pshared);
-#else
-	  unsigned int clockbit = (cond->__data.__nwaiters & 1
-				   ? 0 : FUTEX_CLOCK_REALTIME);
-	  err = lll_futex_timed_wait_bitset (&cond->__data.__futex, futex_val,
-					     abstime, clockbit, pshared);
-#endif
-	}
-
-      /* Disable asynchronous cancellation.  */
-      __pthread_disable_asynccancel (cbuffer.oldtype);
-
-      /* We are going to look at shared data again, so get the lock.  */
-      lll_lock (cond->__data.__lock, pshared);
-
-      /* 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)
-	break;
-
-      /* Not woken yet.  Maybe the time expired?  */
-      if (__glibc_unlikely (err == -ETIMEDOUT))
-	{
-	timeout:
-	  /* Yep.  Adjust the counters.  */
-	  ++cond->__data.__wakeup_seq;
-	  ++cond->__data.__futex;
-
-	  /* The error value.  */
-	  result = ETIMEDOUT;
-	  break;
-	}
-    }
-
-  /* Another thread woken up.  */
-  ++cond->__data.__woken_seq;
-
- bc_out:
-
-  cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT;
-
-  /* If pthread_cond_destroy was called on this variable already,
-     notify the pthread_cond_destroy caller all waiters have left
-     and it can be successfully destroyed.  */
-  if (cond->__data.__total_seq == -1ULL
-      && cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT))
-    lll_futex_wake (&cond->__data.__nwaiters, 1, pshared);
-
-  /* We are done with the condvar.  */
-  lll_unlock (cond->__data.__lock, pshared);
-
-  /* The cancellation handling is back to normal, remove the handler.  */
-  __pthread_cleanup_pop (&buffer, 0);
-
-  /* Get the mutex before returning.  */
-#if (defined lll_futex_timed_wait_requeue_pi \
-     && defined __ASSUME_REQUEUE_PI)
-  if (pi_flag)
-    {
-      __pthread_mutex_cond_lock_adjust (mutex);
-      err = 0;
-    }
-  else
-#endif
-    err = __pthread_mutex_cond_lock (mutex);
-
-  return err ?: result;
-}
-
-versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
-		  GLIBC_2_3_2);
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
index 3f62acc..984f01f 100644
--- a/nptl/pthread_cond_wait.c
+++ b/nptl/pthread_cond_wait.c
@@ -19,219 +19,653 @@ 
 #include <endian.h>
 #include <errno.h>
 #include <sysdep.h>
-#include <lowlevellock.h>
+#include <futex-internal.h>
 #include <pthread.h>
 #include <pthreadP.h>
-#include <kernel-features.h>
+#include <sys/time.h>
+#include <atomic.h>
+#include <stdint.h>
+#include <stdbool.h>
 
 #include <shlib-compat.h>
 #include <stap-probe.h>
+#include <time.h>
+
+#include "pthread_cond_common.c"
+
 
 struct _condvar_cleanup_buffer
 {
-  int oldtype;
+  uint64_t wseq;
   pthread_cond_t *cond;
   pthread_mutex_t *mutex;
-  unsigned int bc_seq;
+  int private;
 };
 
 
-void
-__attribute__ ((visibility ("hidden")))
-__condvar_cleanup (void *arg)
+/* Decrease the waiter reference count.  */
+static void
+__condvar_confirm_wakeup (pthread_cond_t *cond, int private)
 {
-  struct _condvar_cleanup_buffer *cbuffer =
-    (struct _condvar_cleanup_buffer *) arg;
-  unsigned int destroying;
-  int pshared = (cbuffer->cond->__data.__mutex == (void *) ~0l)
-		? LLL_SHARED : LLL_PRIVATE;
+  /* If destruction is pending (i.e., the wake-request flag is nonzero) and we
+     are the last waiter (prior value of __wrefs was 1 << 3), then wake any
+     threads waiting in pthread_cond_destroy.  Release MO to synchronize with
+     these threads.  Don't bother clearing the wake-up request flag.  */
+  if ((atomic_fetch_add_release (&cond->__data.__wrefs, -8) >> 2) == 3)
+    futex_wake (&cond->__data.__wrefs, INT_MAX, private);
+}
+
 
-  /* We are going to modify shared data.  */
-  lll_lock (cbuffer->cond->__data.__lock, pshared);
+/* Cancel waiting after having registered as a waiter previously.  SEQ is our
+   position and G is our group index.
+   The goal of cancellation is to make our group smaller if that is still
+   possible.  If we are in a closed group, this is not possible anymore; in
+   this case, we need to send a replacement signal for the one we effectively
+   consumed because the signal should have gotten consumed by another waiter
+   instead; we must not both cancel waiting and consume a signal.
+
+   Must not be called while still holding a reference on the group.
+
+   Returns true iff we consumed a signal.
+
+   On some kind of timeouts, we may be able to pretend that a signal we
+   effectively consumed happened before the timeout (i.e., similarly to first
+   spinning on signals before actually checking whether the timeout has
+   passed already).  Doing this would allow us to skip sending a replacement
+   signal, but this case might happen rarely because the end of the timeout
+   must race with someone else sending a signal.  Therefore, we don't bother
+   trying to optimize this.  */
+static void
+__condvar_cancel_waiting (pthread_cond_t *cond, uint64_t seq, unsigned int g,
+			  int private)
+{
+  bool consumed_signal = false;
 
-  if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq)
+  /* No deadlock with group switching is possible here because we have do
+     not hold a reference on the group.  */
+  __condvar_acquire_lock (cond, private);
+
+  uint64_t g1_start = __condvar_load_g1_start_relaxed (cond) >> 1;
+  if (g1_start > seq)
+    {
+      /* Our group is closed, so someone provided enough signals for it.
+	 Thus, we effectively consumed a signal.  */
+      consumed_signal = true;
+    }
+  else
     {
-      /* This thread is not waiting anymore.  Adjust the sequence counters
-	 appropriately.  We do not increment WAKEUP_SEQ if this would
-	 bump it over the value of TOTAL_SEQ.  This can happen if a thread
-	 was woken and then canceled.  */
-      if (cbuffer->cond->__data.__wakeup_seq
-	  < cbuffer->cond->__data.__total_seq)
+      if (g1_start + __condvar_get_orig_size (cond) <= seq)
+	{
+	  /* We are in the current G2 and thus cannot have consumed a signal.
+	     Reduce its effective size or handle overflow.  Remember that in
+	     G2, unsigned int size is zero or a negative value.  */
+	  if (cond->__data.__g_size[g] + __PTHREAD_COND_MAX_GROUP_SIZE > 0)
+	    {
+	      cond->__data.__g_size[g]--;
+	    }
+	  else
+	    {
+	      /* Cancellations would overflow the maximum group size.  Just
+		 wake up everyone spuriously to create a clean state.  This
+		 also means we do not consume a signal someone else sent.  */
+	      __condvar_release_lock (cond, private);
+	      __pthread_cond_broadcast (cond);
+	      return;
+	    }
+	}
+      else
 	{
-	  ++cbuffer->cond->__data.__wakeup_seq;
-	  ++cbuffer->cond->__data.__futex;
+	  /* We are in current G1.  If the group's size is zero, someone put
+	     a signal in the group that nobody else but us can consume.  */
+	  if (cond->__data.__g_size[g] == 0)
+	    consumed_signal = true;
+	  else
+	    {
+	      /* Otherwise, we decrease the size of the group.  This is
+		 equivalent to atomically putting in a signal just for us and
+		 consuming it right away.  We do not consume a signal sent
+		 by someone else.  We also cannot have consumed a futex
+		 wake-up because if we were cancelled or timed out in a futex
+		 call, the futex will wake another waiter.  */
+	      cond->__data.__g_size[g]--;
+	    }
 	}
-      ++cbuffer->cond->__data.__woken_seq;
     }
 
-  cbuffer->cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT;
+  __condvar_release_lock (cond, private);
 
-  /* If pthread_cond_destroy was called on this variable already,
-     notify the pthread_cond_destroy caller all waiters have left
-     and it can be successfully destroyed.  */
-  destroying = 0;
-  if (cbuffer->cond->__data.__total_seq == -1ULL
-      && cbuffer->cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT))
+  if (consumed_signal)
     {
-      lll_futex_wake (&cbuffer->cond->__data.__nwaiters, 1, pshared);
-      destroying = 1;
+      /* We effectively consumed a signal even though we didn't want to.
+	 Therefore, we need to send a replacement signal.
+	 If we would want to optimize this, we could do what
+	 pthread_cond_signal does right in the critical section above.  */
+      __pthread_cond_signal (cond);
     }
+}
 
-  /* We are done.  */
-  lll_unlock (cbuffer->cond->__data.__lock, pshared);
-
-  /* Wake everybody to make sure no condvar signal gets lost.  */
-  if (! destroying)
-    lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX, pshared);
-
-  /* Get the mutex before returning unless asynchronous cancellation
-     is in effect.  We don't try to get the mutex if we already own it.  */
-  if (!(USE_REQUEUE_PI (cbuffer->mutex))
-      || ((cbuffer->mutex->__data.__lock & FUTEX_TID_MASK)
-	  != THREAD_GETMEM (THREAD_SELF, tid)))
-  {
-    __pthread_mutex_cond_lock (cbuffer->mutex);
-  }
-  else
-    __pthread_mutex_cond_lock_adjust (cbuffer->mutex);
+/* Wake up any signalers that might be waiting.  */
+static void
+__condvar_dec_grefs (pthread_cond_t *cond, unsigned int g, int private)
+{
+  /* Release MO to synchronize-with the acquire load in
+     __condvar_quiesce_and_switch_g1.  */
+  if (atomic_fetch_add_release (cond->__data.__g_refs + g, -2) == 3)
+    {
+      /* Clear the wake-up request flag before waking up.  We do not need more
+	 than relaxed MO and it doesn't matter if we apply this for an aliased
+	 group because we wake all futex waiters right after clearing the
+	 flag.  */
+      atomic_fetch_and_relaxed (cond->__data.__g_refs + g, ~(unsigned int) 1);
+      futex_wake (cond->__data.__g_refs + g, INT_MAX, private);
+    }
 }
 
+/* Clean-up for cancellation of waiters waiting for normal signals.  We cancel
+   our registration as a waiter, confirm we have woken up, and re-acquire the
+   mutex.  */
+static void
+__condvar_cleanup_waiting (void *arg)
+{
+  struct _condvar_cleanup_buffer *cbuffer =
+    (struct _condvar_cleanup_buffer *) arg;
+  pthread_cond_t *cond = cbuffer->cond;
+  unsigned g = cbuffer->wseq & 1;
 
-int
-__pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
+  __condvar_dec_grefs (cond, g, cbuffer->private);
+
+  __condvar_cancel_waiting (cond, cbuffer->wseq >> 1, g, cbuffer->private);
+  /* FIXME With the current cancellation implementation, it is possible that
+     a thread is cancelled after it has returned from a syscall.  This could
+     result in a cancelled waiter consuming a futex wake-up that is then
+     causing another waiter in the same group to not wake up.  To work around
+     this issue until we have fixed cancellation, just add a futex wake-up
+     conservatively.  */
+  futex_wake (cond->__data.__g_signals + g, 1, cbuffer->private);
+
+  __condvar_confirm_wakeup (cond, cbuffer->private);
+
+  /* XXX If locking the mutex fails, should we just stop execution?  This
+     might be better than silently ignoring the error.  */
+  __pthread_mutex_cond_lock (cbuffer->mutex);
+}
+
+/* This condvar implementation guarantees that all calls to signal and
+   broadcast and all of the three virtually atomic parts of each call to wait
+   (i.e., (1) releasing the mutex and blocking, (2) unblocking, and (3) re-
+   acquiring the mutex) happen in some total order that is consistent with the
+   happens-before relations in the calling program.  However, this order does
+   not necessarily result in additional happens-before relations being
+   established (which aligns well with spurious wake-ups being allowed).
+
+   All waiters acquire a certain position in a 64b waiter sequence (__wseq).
+   This sequence determines which waiters are allowed to consume signals.
+   A broadcast is equal to sending as many signals as are unblocked waiters.
+   When a signal arrives, it samples the current value of __wseq with a
+   relaxed-MO load (i.e., the position the next waiter would get).  (This is
+   sufficient because it is consistent with happens-before; the caller can
+   enforce stronger ordering constraints by calling signal while holding the
+   mutex.)  Only waiters with a position less than the __wseq value observed
+   by the signal are eligible to consume this signal.
+
+   This would be straight-forward to implement if waiters would just spin but
+   we need to let them block using futexes.  Futexes give no guarantee of
+   waking in FIFO order, so we cannot reliably wake eligible waiters if we
+   just use a single futex.  Also, futex words are 32b in size, but we need
+   to distinguish more than 1<<32 states because we need to represent the
+   order of wake-up (and thus which waiters are eligible to consume signals);
+   blocking in a futex is not atomic with a waiter determining its position in
+   the waiter sequence, so we need the futex word to reliably notify waiters
+   that they should not attempt to block anymore because they have been
+   already signaled in the meantime.  While an ABA issue on a 32b value will
+   be rare, ignoring it when we are aware of it is not the right thing to do
+   either.
+
+   Therefore, we use a 64b counter to represent the waiter sequence (on
+   architectures which only support 32b atomics, we use a few bits less).
+   To deal with the blocking using futexes, we maintain two groups of waiters:
+   * Group G1 consists of waiters that are all eligible to consume signals;
+     incoming signals will always signal waiters in this group until all
+     waiters in G1 have been signaled.
+   * Group G2 consists of waiters that arrive when a G1 is present and still
+     contains waiters that have not been signaled.  When all waiters in G1
+     are signaled and a new signal arrives, the new signal will convert G2
+     into the new G1 and create a new G2 for future waiters.
+
+   We cannot allocate new memory because of process-shared condvars, so we
+   have just two slots of groups that change their role between G1 and G2.
+   Each has a separate futex word, a number of signals available for
+   consumption, a size (number of waiters in the group that have not been
+   signaled), and a reference count.
+
+   The group reference count is used to maintain the number of waiters that
+   are using the group's futex.  Before a group can change its role, the
+   reference count must show that no waiters are using the futex anymore; this
+   prevents ABA issues on the futex word.
+
+   To represent which intervals in the waiter sequence the groups cover (and
+   thus also which group slot contains G1 or G2), we use a 64b counter to
+   designate the start position of G1 (inclusive), and a single bit in the
+   waiter sequence counter to represent which group slot currently contains
+   G2.  This allows us to switch group roles atomically wrt. waiters obtaining
+   a position in the waiter sequence.  The G1 start position allows waiters to
+   figure out whether they are in a group that has already been completely
+   signaled (i.e., if the current G1 starts at a later position that the
+   waiter's position).  Waiters cannot determine whether they are currently
+   in G2 or G1 -- but they do not have too because all they are interested in
+   is whether there are available signals, and they always start in G2 (whose
+   group slot they know because of the bit in the waiter sequence.  Signalers
+   will simply fill the right group until it is completely signaled and can
+   be closed (they do not switch group roles until they really have to to
+   decrease the likelihood of having to wait for waiters still holding a
+   reference on the now-closed G1).
+
+   Signalers maintain the initial size of G1 to be able to determine where
+   G2 starts (G2 is always open-ended until it becomes G1).  They track the
+   remaining size of a group; when waiters cancel waiting (due to PThreads
+   cancellation or timeouts), they will decrease this remaining size as well.
+
+   To implement condvar destruction requirements (i.e., that
+   pthread_cond_destroy can be called as soon as all waiters have been
+   signaled), waiters increment a reference count before starting to wait and
+   decrement it after they stopped waiting but right before they acquire the
+   mutex associated with the condvar.
+
+   pthread_cond_t thus consists of the following (bits that are used for
+   flags and are not part of the primary value of each field but necessary
+   to make some things atomic or because there was no space for them
+   elsewhere in the data structure):
+
+   __wseq: Waiter sequence counter
+     * LSB is index of current G2.
+     * Waiters fetch-add while having acquire the mutex associated with the
+       condvar.  Signalers load it and fetch-xor it concurrently.
+   __g1_start: Starting position of G1 (inclusive)
+     * LSB is index of current G2.
+     * Modified by signalers while having acquired the condvar-internal lock
+       and observed concurrently by waiters.
+   __g1_orig_size: Initial size of G1
+     * The two least-significant bits represent the condvar-internal lock.
+     * Only accessed while having acquired the condvar-internal lock.
+   __wrefs: Waiter reference counter.
+     * Bit 2 is true if waiters should run futex_wake when they remove the
+       last reference.  pthread_cond_destroy uses this as futex word.
+     * Bit 1 is the clock ID (0 == CLOCK_REALTIME, 1 == CLOCK_MONOTONIC).
+     * Bit 0 is true iff this is a process-shared condvar.
+     * Simple reference count used by both waiters and pthread_cond_destroy.
+   For each of the two groups, we have:
+   __g_refs: Futex waiter reference count.
+     * LSB is true if waiters should run futex_wake when they remove the
+       last reference.
+     * Reference count used by waiters concurrently with signalers that have
+       acquired the condvar-internal lock.
+   __g_signals: The number of signals that can still be consumed.
+     * Used as a futex word by waiters.  Used concurrently by waiters and
+       signalers.
+     * LSB is true iff this group has been completely signaled (i.e., it is
+       closed).
+   __g_size: Waiters remaining in this group (i.e., which have not been
+     signaled yet.
+     * Accessed by signalers and waiters that cancel waiting (both do so only
+       when having acquired the condvar-internal lock.
+     * The size of G2 is always zero because it cannot be determined until
+       the group becomes G1.
+     * Although this is of unsigned type, we rely on using unsigned overflow
+       rules to make this hold effectively negative values too (in
+       particular, when waiters in G2 cancel waiting).
+
+   A PTHREAD_COND_INITIALIZER condvar has all fields set to zero, which yields
+   a condvar that has G2 starting at position 0 and a G1 that is closed.
+
+   Because waiters do not claim ownership of a group right when obtaining a
+   position in __wseq but only reference count the group when using futexes
+   to block, it can happen that a group gets closed before a waiter can
+   increment the reference count.  Therefore, waiters have to check whether
+   their group is already closed using __g1_start.  They also have to perform
+   this check when spinning when trying to grab a signal from __g_signals.
+   Note that for these checks, using relaxed MO to load __g1_start is
+   sufficient because if a waiter can see a sufficiently large value, it could
+   have also consume a signal in the waiters group.
+
+   Waiters try to grab a signal from __g_signals without holding a reference
+   count, which can lead to stealing a signal from a more recent group after
+   their own group was already closed.  They cannot always detect whether they
+   in fact did because they do not know when they stole, but they can
+   conservatively add a signal back to the group they stole from; if they
+   did so unnecessarily, all that happens is a spurious wake-up.  To make this
+   even less likely, __g1_start contains the index of the current g2 too,
+   which allows waiters to check if there aliasing on the group slots; if
+   there wasn't, they didn't steal from the current G1, which means that the
+   G1 they stole from must have been already closed and they do not need to
+   fix anything.
+
+   It is essential that the last field in pthread_cond_t is __g_signals[1]:
+   The previous condvar used a pointer-sized field in pthread_cond_t, so a
+   PTHREAD_COND_INITIALIZER from that condvar implementation might only
+   initialize 4 bytes to zero instead of the 8 bytes we need (i.e., 44 bytes
+   in total instead of the 48 we need).  __g_signals[1] is not accessed before
+   the first group switch (G2 starts at index 0), which will set its value to
+   zero after a harmless fetch-or whose return value is ignored.  This
+   effectively completes initialization.
+
+
+   Limitations:
+   * This condvar isn't designed to allow for more than
+     __PTHREAD_COND_MAX_GROUP_SIZE * (1 << 31) calls to __pthread_cond_wait.
+   * More than __PTHREAD_COND_MAX_GROUP_SIZE concurrent waiters are not
+     supported.
+   * Beyond what is allowed as errors by POSIX or documented, we can also
+     return the following errors:
+     * EPERM if MUTEX is a recursive mutex and the caller doesn't own it.
+     * EOWNERDEAD or ENOTRECOVERABLE when using robust mutexes.  Unlike
+       for other errors, this can happen when we re-acquire the mutex; this
+       isn't allowed by POSIX (which requires all errors to virtually happen
+       before we release the mutex or change the condvar state), but there's
+       nothing we can do really.
+     * When using PTHREAD_MUTEX_PP_* mutexes, we can also return all errors
+       returned by __pthread_tpp_change_priority.  We will already have
+       released the mutex in such cases, so the caller cannot expect to own
+       MUTEX.
+
+   Other notes:
+   * Instead of the normal mutex unlock / lock functions, we use
+     __pthread_mutex_unlock_usercnt(m, 0) / __pthread_mutex_cond_lock(m)
+     because those will not change the mutex-internal users count, so that it
+     can be detected when a condvar is still associated with a particular
+     mutex because there is a waiter blocked on this condvar using this mutex.
+*/
+static __always_inline int
+__pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
+    const struct timespec *abstime)
 {
-  struct _pthread_cleanup_buffer buffer;
-  struct _condvar_cleanup_buffer cbuffer;
+  const int maxspin = 0;
   int err;
-  int pshared = (cond->__data.__mutex == (void *) ~0l)
-		? LLL_SHARED : LLL_PRIVATE;
-
-#if (defined lll_futex_wait_requeue_pi \
-     && defined __ASSUME_REQUEUE_PI)
-  int pi_flag = 0;
-#endif
+  int result = 0;
 
   LIBC_PROBE (cond_wait, 2, cond, mutex);
 
-  /* Make sure we are alone.  */
-  lll_lock (cond->__data.__lock, pshared);
-
-  /* Now we can release the mutex.  */
+  /* Acquire a position (SEQ) in the waiter sequence (WSEQ).  We use an
+     atomic operation because signals and broadcasts may update the group
+     switch without acquiring the mutex.  We do not need release MO here
+     because we do not need to establish any happens-before relation with
+     signalers (see __pthread_cond_signal); modification order alone
+     establishes a total order of waiters/signals.  We do need acquire MO
+     to synchronize with group reinitialization in
+     __condvar_quiesce_and_switch_g1.  */
+  uint64_t wseq = __condvar_fetch_add_wseq_acquire (cond, 2);
+  /* Find our group's index.  We always go into what was G2 when we acquired
+     our position.  */
+  unsigned int g = wseq & 1;
+  uint64_t seq = wseq >> 1;
+
+  /* Increase the waiter reference count.  Relaxed MO is sufficient because
+     we only need to synchronize when decrementing the reference count.  */
+  unsigned int flags = atomic_fetch_add_relaxed (&cond->__data.__wrefs, 8);
+  int private = __condvar_get_private (flags);
+
+  /* Now that we are registered as a waiter, we can release the mutex.
+     Waiting on the condvar must be atomic with releasing the mutex, so if
+     the mutex is used to establish a happens-before relation with any
+     signaler, the waiter must be visible to the latter; thus, we release the
+     mutex after registering as waiter.
+     If releasing the mutex fails, we just cancel our registration as a
+     waiter and confirm that we have woken up.  */
   err = __pthread_mutex_unlock_usercnt (mutex, 0);
-  if (__glibc_unlikely (err))
+  if (__glibc_unlikely (err != 0))
     {
-      lll_unlock (cond->__data.__lock, pshared);
+      __condvar_cancel_waiting (cond, seq, g, private);
+      __condvar_confirm_wakeup (cond, private);
       return err;
     }
 
-  /* We have one new user of the condvar.  */
-  ++cond->__data.__total_seq;
-  ++cond->__data.__futex;
-  cond->__data.__nwaiters += 1 << COND_NWAITERS_SHIFT;
-
-  /* Remember the mutex we are using here.  If there is already a
-     different address store this is a bad user bug.  Do not store
-     anything for pshared condvars.  */
-  if (cond->__data.__mutex != (void *) ~0l)
-    cond->__data.__mutex = mutex;
-
-  /* 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, &cbuffer);
-
-  /* The current values of the wakeup counter.  The "woken" counter
-     must exceed this value.  */
-  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;
+  /* Now wait until a signal is available in our group or it is closed.
+     Acquire MO so that if we observe a value of zero written after group
+     switching in __condvar_quiesce_and_switch_g1, we synchronize with that
+     store and will see the prior update of __g1_start done while switching
+     groups too.  */
+  unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
 
   do
     {
-      unsigned int futex_val = cond->__data.__futex;
-      /* Prepare to wait.  Release the condvar futex.  */
-      lll_unlock (cond->__data.__lock, pshared);
-
-      /* Enable asynchronous cancellation.  Required by the standard.  */
-      cbuffer.oldtype = __pthread_enable_asynccancel ();
-
-#if (defined lll_futex_wait_requeue_pi \
-     && defined __ASSUME_REQUEUE_PI)
-      /* If pi_flag remained 1 then it means that we had the lock and the mutex
-	 but a spurious waker raced ahead of us.  Give back the mutex before
-	 going into wait again.  */
-      if (pi_flag)
+      while (1)
 	{
-	  __pthread_mutex_cond_lock_adjust (mutex);
-	  __pthread_mutex_unlock_usercnt (mutex, 0);
+	  /* Spin-wait first.
+	     Note that spinning first without checking whether a timeout
+	     passed might lead to what looks like a spurious wake-up even
+	     though we should return ETIMEDOUT (e.g., if the caller provides
+	     an absolute timeout that is clearly in the past).  However,
+	     (1) spurious wake-ups are allowed, (2) it seems unlikely that a
+	     user will (ab)use pthread_cond_wait as a check for whether a
+	     point in time is in the past, and (3) spinning first without
+	     having to compare against the current time seems to be the right
+	     choice from a performance perspective for most use cases.  */
+	  unsigned int spin = maxspin;
+	  while (signals == 0 && spin > 0)
+	    {
+	      /* Check that we are not spinning on a group that's already
+		 closed.  */
+	      if (seq < (__condvar_load_g1_start_relaxed (cond) >> 1))
+		goto done;
+
+	      /* TODO Back off.  */
+
+	      /* Reload signals.  See above for MO.  */
+	      signals = atomic_load_acquire (cond->__data.__g_signals + g);
+	      spin--;
+	    }
+
+	  /* If our group will be closed as indicated by the flag on signals,
+	     don't bother grabbing a signal.  */
+	  if (signals & 1)
+	    goto done;
+
+	  /* If there is an available signal, don't block.  */
+	  if (signals != 0)
+	    break;
+
+	  /* No signals available after spinning, so prepare to block.
+	     We first acquire a group reference and use acquire MO for that so
+	     that we synchronize with the dummy read-modify-write in
+	     __condvar_quiesce_and_switch_g1 if we read from that.  In turn,
+	     in this case this will make us see the closed flag on __g_signals
+	     that designates a concurrent attempt to reuse the group's slot.
+	     We use acquire MO for the __g_signals check to make the
+	     __g1_start check work (see spinning above).
+	     Note that the group reference acquisition will not mask the
+	     release MO when decrementing the reference count because we use
+	     an atomic read-modify-write operation and thus extend the release
+	     sequence.  */
+	  atomic_fetch_add_acquire (cond->__data.__g_refs + g, 2);
+	  if (((atomic_load_acquire (cond->__data.__g_signals + g) & 1) != 0)
+	      || (seq < (__condvar_load_g1_start_relaxed (cond) >> 1)))
+	    {
+	      /* Our group is closed.  Wake up any signalers that might be
+		 waiting.  */
+	      __condvar_dec_grefs (cond, g, private);
+	      goto done;
+	    }
+
+	  // Now block.
+	  struct _pthread_cleanup_buffer buffer;
+	  struct _condvar_cleanup_buffer cbuffer;
+	  cbuffer.wseq = wseq;
+	  cbuffer.cond = cond;
+	  cbuffer.mutex = mutex;
+	  cbuffer.private = private;
+	  __pthread_cleanup_push (&buffer, __condvar_cleanup_waiting, &cbuffer);
+
+	  if (abstime == NULL)
+	    {
+	      /* Block without a timeout.  */
+	      err = futex_wait_cancelable (
+		  cond->__data.__g_signals + g, 0, private);
+	    }
+	  else
+	    {
+	      /* Block, but with a timeout.
+		 Work around the fact that the kernel rejects negative timeout
+		 values despite them being valid.  */
+	      if (__glibc_unlikely (abstime->tv_sec < 0))
+	        err = ETIMEDOUT;
+
+	      else if ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0)
+		{
+		  /* CLOCK_MONOTONIC is requested.  */
+		  struct timespec rt;
+		  if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
+		    __libc_fatal ("clock_gettime does not support "
+				  "CLOCK_MONOTONIC");
+		  /* Convert the absolute timeout value to a relative
+		     timeout.  */
+		  rt.tv_sec = abstime->tv_sec - rt.tv_sec;
+		  rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec;
+		  if (rt.tv_nsec < 0)
+		    {
+		      rt.tv_nsec += 1000000000;
+		      --rt.tv_sec;
+		    }
+		  /* Did we already time out?  */
+		  if (__glibc_unlikely (rt.tv_sec < 0))
+		    err = ETIMEDOUT;
+		  else
+		    err = futex_reltimed_wait_cancelable
+			(cond->__data.__g_signals + g, 0, &rt, private);
+		}
+	      else
+		{
+		  /* Use CLOCK_REALTIME.  */
+		  err = futex_abstimed_wait_cancelable
+		      (cond->__data.__g_signals + g, 0, abstime, private);
+		}
+	    }
+
+	  __pthread_cleanup_pop (&buffer, 0);
+
+	  if (__glibc_unlikely (err == ETIMEDOUT))
+	    {
+	      __condvar_dec_grefs (cond, g, private);
+	      /* If we timed out, we effectively cancel waiting.  Note that
+		 we have decremented __g_refs before cancellation, so that a
+		 deadlock between waiting for quiescence of our group in
+		 __condvar_quiesce_and_switch_g1 and us trying to acquire
+		 the lock during cancellation is not possible.  */
+	      __condvar_cancel_waiting (cond, seq, g, private);
+	      result = ETIMEDOUT;
+	      goto done;
+	    }
+	  else
+	    __condvar_dec_grefs (cond, g, private);
+
+	  /* Reload signals.  See above for MO.  */
+	  signals = atomic_load_acquire (cond->__data.__g_signals + g);
 	}
-      pi_flag = USE_REQUEUE_PI (mutex);
 
-      if (pi_flag)
+    }
+  /* Try to grab a signal.  Use acquire MO so that we see an up-to-date value
+     of __g1_start below (see spinning above for a similar case).  In
+     particular, if we steal from a more recent group, we will also see a
+     more recent __g1_start below.  */
+  while (!atomic_compare_exchange_weak_acquire (cond->__data.__g_signals + g,
+						&signals, signals - 2));
+
+  /* We consumed a signal but we could have consumed from a more recent group
+     that aliased with ours due to being in the same group slot.  If this
+     might be the case our group must be closed as visible through
+     __g1_start.  */
+  uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
+  if (seq < (g1_start >> 1))
+    {
+      /* We potentially stole a signal from a more recent group but we do not
+	 know which group we really consumed from.
+	 We do not care about groups older than current G1 because they are
+	 closed; we could have stolen from these, but then we just add a
+	 spurious wake-up for the current groups.
+	 We will never steal a signal from current G2 that was really intended
+	 for G2 because G2 never receives signals (until it becomes G1).  We
+	 could have stolen a signal from G2 that was conservatively added by a
+	 previous waiter that also thought it stole a signal -- but given that
+	 that signal was added unnecessarily, it's not a problem if we steal
+	 it.
+	 Thus, the remaining case is that we could have stolen from the current
+	 G1, where "current" means the __g1_start value we observed.  However,
+	 if the current G1 does not have the same slot index as we do, we did
+	 not steal from it and do not need to undo that.  This is the reason
+	 for putting a bit with G2's index into__g1_start as well.  */
+      if (((g1_start & 1) ^ 1) == g)
 	{
-	  err = lll_futex_wait_requeue_pi (&cond->__data.__futex,
-					   futex_val, &mutex->__data.__lock,
-					   pshared);
-
-	  pi_flag = (err == 0);
+	  /* We have to conservatively undo our potential mistake of stealing
+	     a signal.  We can stop trying to do that when the current G1
+	     changes because other spinning waiters will notice this too and
+	     __condvar_quiesce_and_switch_g1 has checked that there are no
+	     futex waiters anymore before switching G1.
+	     Relaxed MO is fine for the __g1_start load because we need to
+	     merely be able to observe this fact and not have to observe
+	     something else as well.
+	     ??? Would it help to spin for a little while to see whether the
+	     current G1 gets closed?  This might be worthwhile if the group is
+	     small or close to being closed.  */
+	  unsigned int s = atomic_load_relaxed (cond->__data.__g_signals + g);
+	  while (__condvar_load_g1_start_relaxed (cond) == g1_start)
+	    {
+	      /* Try to add a signal.  We don't need to acquire the lock
+		 because at worst we can cause a spurious wake-up.  If the
+		 group is in the process of being closed (LSB is true), this
+		 has an effect similar to us adding a signal.  */
+	      if (((s & 1) != 0)
+		  || atomic_compare_exchange_weak_relaxed
+		       (cond->__data.__g_signals + g, &s, s + 2))
+		{
+		  /* If we added a signal, we also need to add a wake-up on
+		     the futex.  We also need to do that if we skipped adding
+		     a signal because the group is being closed because
+		     while __condvar_quiesce_and_switch_g1 could have closed
+		     the group, it might stil be waiting for futex waiters to
+		     leave (and one of those waiters might be the one we stole
+		     the signal from, which cause it to block using the
+		     futex).  */
+		  futex_wake (cond->__data.__g_signals + g, 1, private);
+		  break;
+		}
+	      /* TODO Back off.  */
+	    }
 	}
-      else
-#endif
-	  /* Wait until woken by signal or broadcast.  */
-	lll_futex_wait (&cond->__data.__futex, futex_val, pshared);
-
-      /* Disable asynchronous cancellation.  */
-      __pthread_disable_asynccancel (cbuffer.oldtype);
-
-      /* We are going to look at shared data again, so get the lock.  */
-      lll_lock (cond->__data.__lock, pshared);
-
-      /* 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;
     }
-  while (val == seq || cond->__data.__woken_seq == val);
 
-  /* Another thread woken up.  */
-  ++cond->__data.__woken_seq;
+ done:
 
- bc_out:
+  /* Confirm that we have been woken.  We do that before acquiring the mutex
+     to allow for execution of pthread_cond_destroy while having acquired the
+     mutex.  */
+  __condvar_confirm_wakeup (cond, private);
 
-  cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT;
-
-  /* If pthread_cond_destroy was called on this varaible already,
-     notify the pthread_cond_destroy caller all waiters have left
-     and it can be successfully destroyed.  */
-  if (cond->__data.__total_seq == -1ULL
-      && cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT))
-    lll_futex_wake (&cond->__data.__nwaiters, 1, pshared);
+  /* Woken up; now re-acquire the mutex.  If this doesn't fail, return RESULT,
+     which is set to ETIMEDOUT if a timeout occured, or zero otherwise.  */
+  err = __pthread_mutex_cond_lock (mutex);
+  /* XXX Abort on errors that are disallowed by POSIX?  */
+  return (err != 0) ? err : result;
+}
 
-  /* We are done with the condvar.  */
-  lll_unlock (cond->__data.__lock, pshared);
 
-  /* The cancellation handling is back to normal, remove the handler.  */
-  __pthread_cleanup_pop (&buffer, 0);
+/* See __pthread_cond_wait_common.  */
+int
+__pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+  return __pthread_cond_wait_common (cond, mutex, NULL);
+}
 
-  /* Get the mutex before returning.  Not needed for PI.  */
-#if (defined lll_futex_wait_requeue_pi \
-     && defined __ASSUME_REQUEUE_PI)
-  if (pi_flag)
-    {
-      __pthread_mutex_cond_lock_adjust (mutex);
-      return 0;
-    }
-  else
-#endif
-    return __pthread_mutex_cond_lock (mutex);
+/* See __pthread_cond_wait_common.  */
+int
+__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
+    const struct timespec *abstime)
+{
+  /* Check parameter validity.  This should also tell the compiler that
+     it can assume that abstime is not NULL.  */
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+  return __pthread_cond_wait_common (cond, mutex, abstime);
 }
 
 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
 		  GLIBC_2_3_2);
+versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
+		  GLIBC_2_3_2);
diff --git a/nptl/pthread_condattr_getclock.c b/nptl/pthread_condattr_getclock.c
index d156302..cecb4aa 100644
--- a/nptl/pthread_condattr_getclock.c
+++ b/nptl/pthread_condattr_getclock.c
@@ -23,6 +23,6 @@  int
 pthread_condattr_getclock (const pthread_condattr_t *attr, clockid_t *clock_id)
 {
   *clock_id = (((((const struct pthread_condattr *) attr)->value) >> 1)
-	       & ((1 << COND_NWAITERS_SHIFT) - 1));
+	       & ((1 << COND_CLOCK_BITS) - 1));
   return 0;
 }
diff --git a/nptl/pthread_condattr_getpshared.c b/nptl/pthread_condattr_getpshared.c
index 5a10f3e..8147966 100644
--- a/nptl/pthread_condattr_getpshared.c
+++ b/nptl/pthread_condattr_getpshared.c
@@ -22,7 +22,8 @@ 
 int
 pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
 {
-  *pshared = ((const struct pthread_condattr *) attr)->value & 1;
+  *pshared = (((const struct pthread_condattr *) attr)->value & 1
+	      ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE);
 
   return 0;
 }
diff --git a/nptl/pthread_condattr_init.c b/nptl/pthread_condattr_init.c
index 0ce42e5..6e5168d 100644
--- a/nptl/pthread_condattr_init.c
+++ b/nptl/pthread_condattr_init.c
@@ -23,7 +23,9 @@ 
 int
 __pthread_condattr_init (pthread_condattr_t *attr)
 {
-  memset (attr, '\0', sizeof (*attr));
+  struct pthread_condattr *iattr = (struct pthread_condattr *) attr;
+  /* Default is not pshared and CLOCK_REALTIME.  */
+  iattr-> value = CLOCK_REALTIME << 1;
 
   return 0;
 }
diff --git a/nptl/pthread_condattr_setclock.c b/nptl/pthread_condattr_setclock.c
index 25e2a17..3cfad84 100644
--- a/nptl/pthread_condattr_setclock.c
+++ b/nptl/pthread_condattr_setclock.c
@@ -18,7 +18,7 @@ 
 
 #include <assert.h>
 #include <errno.h>
-#include <stdbool.h>
+#include <futex-internal.h>
 #include <time.h>
 #include <sysdep.h>
 #include "pthreadP.h"
@@ -33,12 +33,17 @@  pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock_id)
        in the pthread_cond_t structure needs to be adjusted.  */
     return EINVAL;
 
+  /* If we do not support waiting using CLOCK_MONOTONIC, return an error.  */
+  if (clock_id == CLOCK_MONOTONIC
+      && !futex_supports_exact_relative_timeouts())
+    return ENOTSUP;
+
   /* Make sure the value fits in the bits we reserved.  */
-  assert (clock_id < (1 << COND_NWAITERS_SHIFT));
+  assert (clock_id < (1 << COND_CLOCK_BITS));
 
   int *valuep = &((struct pthread_condattr *) attr)->value;
 
-  *valuep = ((*valuep & ~(((1 << COND_NWAITERS_SHIFT) - 1) << 1))
+  *valuep = ((*valuep & ~(((1 << COND_CLOCK_BITS) - 1) << 1))
 	     | (clock_id << 1));
 
   return 0;
diff --git a/nptl/tst-cond1.c b/nptl/tst-cond1.c
index 75ab9c8..509bbd0 100644
--- a/nptl/tst-cond1.c
+++ b/nptl/tst-cond1.c
@@ -73,6 +73,9 @@  do_test (void)
 
   puts ("parent: wait for condition");
 
+  /* This test will fail on spurious wake-ups, which are allowed; however,
+     the current implementation shouldn't produce spurious wake-ups in the
+     scenario we are testing here.  */
   err = pthread_cond_wait (&cond, &mut);
   if (err != 0)
     error (EXIT_FAILURE, err, "parent: cannot wait fir signal");
diff --git a/nptl/tst-cond20.c b/nptl/tst-cond20.c
index 918c4ad..665a66a 100644
--- a/nptl/tst-cond20.c
+++ b/nptl/tst-cond20.c
@@ -96,7 +96,10 @@  do_test (void)
 
   for (i = 0; i < ROUNDS; ++i)
     {
-      pthread_cond_wait (&cond2, &mut);
+      /* Make sure we discard spurious wake-ups.  */
+      do
+	pthread_cond_wait (&cond2, &mut);
+      while (count != N);
 
       if (i & 1)
         pthread_mutex_unlock (&mut);
diff --git a/nptl/tst-cond22.c b/nptl/tst-cond22.c
index bd978e5..64f19ea 100644
--- a/nptl/tst-cond22.c
+++ b/nptl/tst-cond22.c
@@ -106,10 +106,11 @@  do_test (void)
       status = 1;
     }
 
-  printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
-	  c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
-	  c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
-	  c.__data.__nwaiters, c.__data.__broadcast_seq);
+  printf ("cond = { %llu, %llu, %u/%u/%u, %u/%u/%u, %u, %u }\n",
+	  c.__data.__wseq, c.__data.__g1_start,
+	  c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
+	  c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
+	  c.__data.__g1_orig_size, c.__data.__wrefs);
 
   if (pthread_create (&th, NULL, tf, (void *) 1l) != 0)
     {
@@ -148,10 +149,11 @@  do_test (void)
       status = 1;
     }
 
-  printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
-	  c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
-	  c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
-	  c.__data.__nwaiters, c.__data.__broadcast_seq);
+  printf ("cond = { %llu, %llu, %u/%u/%u, %u/%u/%u, %u, %u }\n",
+	  c.__data.__wseq, c.__data.__g1_start,
+	  c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
+	  c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
+	  c.__data.__g1_orig_size, c.__data.__wrefs);
 
   return status;
 }
diff --git a/sysdeps/aarch64/nptl/bits/pthreadtypes.h b/sysdeps/aarch64/nptl/bits/pthreadtypes.h
index 13984a7..87c4804 100644
--- a/sysdeps/aarch64/nptl/bits/pthreadtypes.h
+++ b/sysdeps/aarch64/nptl/bits/pthreadtypes.h
@@ -90,17 +90,32 @@  typedef union
 {
   struct
   {
-    int __lock;
-    unsigned int __futex;
-    __extension__ unsigned long long int __total_seq;
-    __extension__ unsigned long long int __wakeup_seq;
-    __extension__ unsigned long long int __woken_seq;
-    void *__mutex;
-    unsigned int __nwaiters;
-    unsigned int __broadcast_seq;
+    __extension__ union
+    {
+      __extension__ unsigned long long int __wseq;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __wseq32;
+    };
+    __extension__ union
+    {
+      __extension__ unsigned long long int __g1_start;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __g1_start32;
+    };
+    unsigned int __g_refs[2];
+    unsigned int __g_size[2];
+    unsigned int __g1_orig_size;
+    unsigned int __wrefs;
+    unsigned int __g_signals[2];
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
-  long int __align;
+  __extension__ long long int __align;
 } pthread_cond_t;
 
 typedef union
diff --git a/sysdeps/arm/nptl/bits/pthreadtypes.h b/sysdeps/arm/nptl/bits/pthreadtypes.h
index afb5392..3e1f451 100644
--- a/sysdeps/arm/nptl/bits/pthreadtypes.h
+++ b/sysdeps/arm/nptl/bits/pthreadtypes.h
@@ -93,14 +93,29 @@  typedef union
 {
   struct
   {
-    int __lock;
-    unsigned int __futex;
-    __extension__ unsigned long long int __total_seq;
-    __extension__ unsigned long long int __wakeup_seq;
-    __extension__ unsigned long long int __woken_seq;
-    void *__mutex;
-    unsigned int __nwaiters;
-    unsigned int __broadcast_seq;
+    __extension__ union
+    {
+      __extension__ unsigned long long int __wseq;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __wseq32;
+    };
+    __extension__ union
+    {
+      __extension__ unsigned long long int __g1_start;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __g1_start32;
+    };
+    unsigned int __g_refs[2];
+    unsigned int __g_size[2];
+    unsigned int __g1_orig_size;
+    unsigned int __wrefs;
+    unsigned int __g_signals[2];
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   __extension__ long long int __align;
diff --git a/sysdeps/ia64/nptl/bits/pthreadtypes.h b/sysdeps/ia64/nptl/bits/pthreadtypes.h
index f2e6dac..a892fe0 100644
--- a/sysdeps/ia64/nptl/bits/pthreadtypes.h
+++ b/sysdeps/ia64/nptl/bits/pthreadtypes.h
@@ -90,17 +90,32 @@  typedef union
 {
   struct
   {
-    int __lock;
-    unsigned int __futex;
-    __extension__ unsigned long long int __total_seq;
-    __extension__ unsigned long long int __wakeup_seq;
-    __extension__ unsigned long long int __woken_seq;
-    void *__mutex;
-    unsigned int __nwaiters;
-    unsigned int __broadcast_seq;
+    __extension__ union
+    {
+      __extension__ unsigned long long int __wseq;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __wseq32;
+    };
+    __extension__ union
+    {
+      __extension__ unsigned long long int __g1_start;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __g1_start32;
+    };
+    unsigned int __g_refs[2];
+    unsigned int __g_size[2];
+    unsigned int __g1_orig_size;
+    unsigned int __wrefs;
+    unsigned int __g_signals[2];
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
-  long int __align;
+  __extension__ long long int __align;
 } pthread_cond_t;
 
 typedef union
diff --git a/sysdeps/m68k/nptl/bits/pthreadtypes.h b/sysdeps/m68k/nptl/bits/pthreadtypes.h
index d8faa7a..4a86878 100644
--- a/sysdeps/m68k/nptl/bits/pthreadtypes.h
+++ b/sysdeps/m68k/nptl/bits/pthreadtypes.h
@@ -88,19 +88,35 @@  typedef union
 
 
 /* Data structure for conditional variable handling.  The structure of
-   the attribute type is deliberately not exposed.  */
+   the attribute type is not exposed on purpose.  */
 typedef union
 {
   struct
   {
-    int __lock __attribute__ ((__aligned__ (4)));
-    unsigned int __futex;
-    __extension__ unsigned long long int __total_seq;
-    __extension__ unsigned long long int __wakeup_seq;
-    __extension__ unsigned long long int __woken_seq;
-    void *__mutex;
-    unsigned int __nwaiters;
-    unsigned int __broadcast_seq;
+    __extension__ union
+    {
+      __extension__ unsigned long long int __wseq;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __wseq32;
+    };
+    __extension__ union
+    {
+      __extension__ unsigned long long int __g1_start;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __g1_start32;
+    };
+    /* Enforce proper alignment of fields used as futex words.  */
+    unsigned int __g_refs[2] __attribute__ ((__aligned__ (4)));
+    unsigned int __g_size[2];
+    unsigned int __g1_orig_size;
+    unsigned int __wrefs;
+    unsigned int __g_signals[2];
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   __extension__ long long int __align;
diff --git a/sysdeps/microblaze/nptl/bits/pthreadtypes.h b/sysdeps/microblaze/nptl/bits/pthreadtypes.h
index 9e9e307..acbb6ff 100644
--- a/sysdeps/microblaze/nptl/bits/pthreadtypes.h
+++ b/sysdeps/microblaze/nptl/bits/pthreadtypes.h
@@ -91,14 +91,29 @@  typedef union
 {
   struct
   {
-    int __lock;
-    unsigned int __futex;
-    __extension__ unsigned long long int __total_seq;
-    __extension__ unsigned long long int __wakeup_seq;
-    __extension__ unsigned long long int __woken_seq;
-    void *__mutex;
-    unsigned int __nwaiters;
-    unsigned int __broadcast_seq;
+    __extension__ union
+    {
+      __extension__ unsigned long long int __wseq;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __wseq32;
+    };
+    __extension__ union
+    {
+      __extension__ unsigned long long int __g1_start;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __g1_start32;
+    };
+    unsigned int __g_refs[2];
+    unsigned int __g_size[2];
+    unsigned int __g1_orig_size;
+    unsigned int __wrefs;
+    unsigned int __g_signals[2];
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   __extension__ long long int __align;
diff --git a/sysdeps/mips/nptl/bits/pthreadtypes.h b/sysdeps/mips/nptl/bits/pthreadtypes.h
index 68ed94b..6e16292 100644
--- a/sysdeps/mips/nptl/bits/pthreadtypes.h
+++ b/sysdeps/mips/nptl/bits/pthreadtypes.h
@@ -117,19 +117,34 @@  typedef union
 
 
 /* Data structure for conditional variable handling.  The structure of
-   the attribute type is deliberately not exposed.  */
+   the attribute type is not exposed on purpose.  */
 typedef union
 {
   struct
   {
-    int __lock;
-    unsigned int __futex;
-    __extension__ unsigned long long int __total_seq;
-    __extension__ unsigned long long int __wakeup_seq;
-    __extension__ unsigned long long int __woken_seq;
-    void *__mutex;
-    unsigned int __nwaiters;
-    unsigned int __broadcast_seq;
+    __extension__ union
+    {
+      __extension__ unsigned long long int __wseq;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __wseq32;
+    };
+    __extension__ union
+    {
+      __extension__ unsigned long long int __g1_start;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __g1_start32;
+    };
+    unsigned int __g_refs[2];
+    unsigned int __g_size[2];
+    unsigned int __g1_orig_size;
+    unsigned int __wrefs;
+    unsigned int __g_signals[2];
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   __extension__ long long int __align;
diff --git a/sysdeps/nios2/nptl/bits/pthreadtypes.h b/sysdeps/nios2/nptl/bits/pthreadtypes.h
index 76076d0..e698bac 100644
--- a/sysdeps/nios2/nptl/bits/pthreadtypes.h
+++ b/sysdeps/nios2/nptl/bits/pthreadtypes.h
@@ -88,19 +88,34 @@  typedef union
 
 
 /* Data structure for conditional variable handling.  The structure of
-   the attribute type is deliberately not exposed.  */
+   the attribute type is not exposed on purpose.  */
 typedef union
 {
   struct
   {
-    int __lock;
-    unsigned int __futex;
-    __extension__ unsigned long long int __total_seq;
-    __extension__ unsigned long long int __wakeup_seq;
-    __extension__ unsigned long long int __woken_seq;
-    void *__mutex;
-    unsigned int __nwaiters;
-    unsigned int __broadcast_seq;
+    __extension__ union
+    {
+      __extension__ unsigned long long int __wseq;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __wseq32;
+    };
+    __extension__ union
+    {
+      __extension__ unsigned long long int __g1_start;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __g1_start32;
+    };
+    unsigned int __g_refs[2];
+    unsigned int __g_size[2];
+    unsigned int __g1_orig_size;
+    unsigned int __wrefs;
+    unsigned int __g_signals[2];
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   __extension__ long long int __align;
diff --git a/sysdeps/nptl/internaltypes.h b/sysdeps/nptl/internaltypes.h
index 203c548..31e5a43 100644
--- a/sysdeps/nptl/internaltypes.h
+++ b/sysdeps/nptl/internaltypes.h
@@ -68,20 +68,13 @@  struct pthread_condattr
 {
   /* Combination of values:
 
-     Bit 0  : flag whether conditional variable will be sharable between
-	      processes.
-
-     Bit 1-7: clock ID.  */
+     Bit 0                : flag whether conditional variable will be
+                            sharable between processes.
+     Bit 1-COND_CLOCK_BITS: Clock ID.  COND_CLOCK_BITS is the number of bits
+                            needed to represent the ID of the clock.  */
   int value;
 };
-
-
-/* The __NWAITERS field is used as a counter and to house the number
-   of bits for other purposes.  COND_CLOCK_BITS is the number
-   of bits needed to represent the ID of the clock.  COND_NWAITERS_SHIFT
-   is the number of bits reserved for other purposes like the clock.  */
-#define COND_CLOCK_BITS		1
-#define COND_NWAITERS_SHIFT	1
+#define COND_CLOCK_BITS	1
 
 
 /* Read-write lock variable attribute data structure.  */
diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
index fd0894e..c122446 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -183,7 +183,7 @@  enum
 
 
 /* Conditional variable handling.  */
-#define PTHREAD_COND_INITIALIZER { { 0, 0, 0, 0, 0, (void *) 0, 0, 0 } }
+#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } }
 
 
 /* Cleanup buffers */
diff --git a/sysdeps/s390/nptl/bits/pthreadtypes.h b/sysdeps/s390/nptl/bits/pthreadtypes.h
index 40d10fe..fb8daea 100644
--- a/sysdeps/s390/nptl/bits/pthreadtypes.h
+++ b/sysdeps/s390/nptl/bits/pthreadtypes.h
@@ -142,14 +142,29 @@  typedef union
 {
   struct
   {
-    int __lock;
-    unsigned int __futex;
-    __extension__ unsigned long long int __total_seq;
-    __extension__ unsigned long long int __wakeup_seq;
-    __extension__ unsigned long long int __woken_seq;
-    void *__mutex;
-    unsigned int __nwaiters;
-    unsigned int __broadcast_seq;
+    __extension__ union
+    {
+      __extension__ unsigned long long int __wseq;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __wseq32;
+    };
+    __extension__ union
+    {
+      __extension__ unsigned long long int __g1_start;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __g1_start32;
+    };
+    unsigned int __g_refs[2];
+    unsigned int __g_size[2];
+    unsigned int __g1_orig_size;
+    unsigned int __wrefs;
+    unsigned int __g_signals[2];
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   __extension__ long long int __align;
diff --git a/sysdeps/sh/nptl/bits/pthreadtypes.h b/sysdeps/sh/nptl/bits/pthreadtypes.h
index 13fbd73..0b67bd9 100644
--- a/sysdeps/sh/nptl/bits/pthreadtypes.h
+++ b/sysdeps/sh/nptl/bits/pthreadtypes.h
@@ -93,14 +93,29 @@  typedef union
 {
   struct
   {
-    int __lock;
-    unsigned int __futex;
-    __extension__ unsigned long long int __total_seq;
-    __extension__ unsigned long long int __wakeup_seq;
-    __extension__ unsigned long long int __woken_seq;
-    void *__mutex;
-    unsigned int __nwaiters;
-    unsigned int __broadcast_seq;
+    __extension__ union
+    {
+      __extension__ unsigned long long int __wseq;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __wseq32;
+    };
+    __extension__ union
+    {
+      __extension__ unsigned long long int __g1_start;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __g1_start32;
+    };
+    unsigned int __g_refs[2];
+    unsigned int __g_size[2];
+    unsigned int __g1_orig_size;
+    unsigned int __wrefs;
+    unsigned int __g_signals[2];
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   __extension__ long long int __align;
diff --git a/sysdeps/tile/nptl/bits/pthreadtypes.h b/sysdeps/tile/nptl/bits/pthreadtypes.h
index 7d68650..eb8d132 100644
--- a/sysdeps/tile/nptl/bits/pthreadtypes.h
+++ b/sysdeps/tile/nptl/bits/pthreadtypes.h
@@ -122,14 +122,29 @@  typedef union
 {
   struct
   {
-    int __lock;
-    unsigned int __futex;
-    __extension__ unsigned long long int __total_seq;
-    __extension__ unsigned long long int __wakeup_seq;
-    __extension__ unsigned long long int __woken_seq;
-    void *__mutex;
-    unsigned int __nwaiters;
-    unsigned int __broadcast_seq;
+    __extension__ union
+    {
+      __extension__ unsigned long long int __wseq;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __wseq32;
+    };
+    __extension__ union
+    {
+      __extension__ unsigned long long int __g1_start;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __g1_start32;
+    };
+    unsigned int __g_refs[2];
+    unsigned int __g_size[2];
+    unsigned int __g1_orig_size;
+    unsigned int __wrefs;
+    unsigned int __g_signals[2];
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   __extension__ long long int __align;
diff --git a/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h b/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
index 1a1779b..6bf9cb7 100644
--- a/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
+++ b/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
@@ -84,19 +84,34 @@  typedef union
 
 
 /* Data structure for conditional variable handling.  The structure of
-   the attribute type is deliberately not exposed.  */
+   the attribute type is not exposed on purpose.  */
 typedef union
 {
   struct
   {
-    int __lock;
-    unsigned int __futex;
-    __extension__ unsigned long long int __total_seq;
-    __extension__ unsigned long long int __wakeup_seq;
-    __extension__ unsigned long long int __woken_seq;
-    void *__mutex;
-    unsigned int __nwaiters;
-    unsigned int __broadcast_seq;
+    __extension__ union
+    {
+      __extension__ unsigned long long int __wseq;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __wseq32;
+    };
+    __extension__ union
+    {
+      __extension__ unsigned long long int __g1_start;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __g1_start32;
+    };
+    unsigned int __g_refs[2];
+    unsigned int __g_size[2];
+    unsigned int __g1_orig_size;
+    unsigned int __wrefs;
+    unsigned int __g_signals[2];
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   __extension__ long long int __align;
diff --git a/sysdeps/unix/sysv/linux/hppa/internaltypes.h b/sysdeps/unix/sysv/linux/hppa/internaltypes.h
index 651ce2e..d649657 100644
--- a/sysdeps/unix/sysv/linux/hppa/internaltypes.h
+++ b/sysdeps/unix/sysv/linux/hppa/internaltypes.h
@@ -46,32 +46,38 @@  fails because __initializer is zero, and the structure will be used as
 is correctly.  */
 
 #define cond_compat_clear(var) \
-({											\
-  int tmp = 0;										\
-  var->__data.__lock = 0;								\
-  var->__data.__futex = 0;								\
-  var->__data.__mutex = NULL;								\
-  /* Clear __initializer last, to indicate initialization is done.  */			\
-  __asm__ __volatile__ ("stw,ma %1,0(%0)"						\
-			: : "r" (&var->__data.__initializer), "r" (tmp) : "memory");	\
+({									\
+  int tmp = 0;								\
+  var->__data.__wseq = 0;						\
+  var->__data.__signals_sent = 0;					\
+  var->__data.__confirmed = 0;						\
+  var->__data.__generation = 0;						\
+  var->__data.__mutex = NULL;						\
+  var->__data.__quiescence_waiters = 0;					\
+  var->__data.__clockid = 0;						\
+  /* Clear __initializer last, to indicate initialization is done.  */	\
+  /* This synchronizes-with the acquire load below.  */			\
+  atomic_store_release (&var->__data.__initializer, 0);			\
 })
 
 #define cond_compat_check_and_clear(var) \
 ({								\
-  int ret;							\
-  volatile int *value = &var->__data.__initializer;		\
-  if ((ret = atomic_compare_and_exchange_val_acq(value, 2, 1)))	\
+  int v;							\
+  int *value = &var->__data.__initializer;			\
+  /* This synchronizes-with the release store above.  */	\
+  while ((v = atomic_load_acquire (value)) != 0)		\
     {								\
-      if (ret == 1)						\
+      if (v == 1						\
+	  /* Relaxed MO is fine; it only matters who's first.  */        \
+	  && atomic_compare_exchange_acquire_weak_relaxed (value, 1, 2)) \
 	{							\
-	  /* Initialize structure.  */				\
+	  /* We're first; initialize structure.  */		\
 	  cond_compat_clear (var);				\
+	  break;						\
 	}							\
       else							\
-        {							\
-	  /* Yield until structure is initialized.  */		\
-	  while (*value == 2) sched_yield ();			\
-        }							\
+	/* Yield before we re-check initialization status.  */	\
+	sched_yield ();						\
     }								\
 })
 
diff --git a/sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c b/sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c
deleted file mode 100644
index ec6fd23..0000000
--- a/sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c
+++ /dev/null
@@ -1,41 +0,0 @@ 
-/* Copyright (C) 2009-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Carlos O'Donell <carlos@codesourcery.com>, 2009.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#ifndef INCLUDED_SELF
-# define INCLUDED_SELF
-# include <pthread_cond_timedwait.c>
-#else
-# include <pthread.h>
-# include <pthreadP.h>
-# include <internaltypes.h>
-# include <shlib-compat.h>
-int
-__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
-			  const struct timespec *abstime)
-{
-  cond_compat_check_and_clear (cond);
-  return __pthread_cond_timedwait_internal (cond, mutex, abstime);
-}
-versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
-                  GLIBC_2_3_2);
-# undef versioned_symbol
-# define versioned_symbol(lib, local, symbol, version)
-# undef __pthread_cond_timedwait
-# define __pthread_cond_timedwait __pthread_cond_timedwait_internal
-# include_next <pthread_cond_timedwait.c>
-#endif
diff --git a/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c b/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c
index 8f02831..0611f7d 100644
--- a/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c
+++ b/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c
@@ -32,9 +32,22 @@  __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
 }
 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
                   GLIBC_2_3_2);
+int
+__pthread_cond_timedwait (cond, mutex, abstime)
+     pthread_cond_t *cond;
+     pthread_mutex_t *mutex;
+     const struct timespec *abstime;
+{
+  cond_compat_check_and_clear (cond);
+  return __pthread_cond_timedwait_internal (cond, mutex, abstime);
+}
+versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
+                  GLIBC_2_3_2);
 # undef versioned_symbol
 # define versioned_symbol(lib, local, symbol, version)
 # undef __pthread_cond_wait
 # define __pthread_cond_wait __pthread_cond_wait_internal
+# undef __pthread_cond_timedwait
+# define __pthread_cond_timedwait __pthread_cond_timedwait_internal
 # include_next <pthread_cond_wait.c>
 #endif
diff --git a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S
deleted file mode 100644
index f697e5b..0000000
--- a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S
+++ /dev/null
@@ -1,20 +0,0 @@ 
-/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#define HAVE_CMOV 1
-#include "../pthread_cond_timedwait.S"
diff --git a/sysdeps/unix/sysv/linux/i386/pthread_cond_broadcast.S b/sysdeps/unix/sysv/linux/i386/pthread_cond_broadcast.S
deleted file mode 100644
index 5996688..0000000
--- a/sysdeps/unix/sysv/linux/i386/pthread_cond_broadcast.S
+++ /dev/null
@@ -1,241 +0,0 @@ 
-/* Copyright (C) 2002-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-#include <lowlevellock.h>
-#include <lowlevelcond.h>
-#include <kernel-features.h>
-#include <pthread-pi-defines.h>
-#include <pthread-errnos.h>
-#include <stap-probe.h>
-
-	.text
-
-	/* int pthread_cond_broadcast (pthread_cond_t *cond) */
-	.globl	__pthread_cond_broadcast
-	.type	__pthread_cond_broadcast, @function
-	.align	16
-__pthread_cond_broadcast:
-	cfi_startproc
-	pushl	%ebx
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebx, 0)
-	pushl	%esi
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%esi, 0)
-	pushl	%edi
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%edi, 0)
-	pushl	%ebp
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebp, 0)
-	cfi_remember_state
-
-	movl	20(%esp), %ebx
-
-	LIBC_PROBE (cond_broadcast, 1, %edx)
-
-	/* Get internal lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, cond_lock(%ebx)
-#endif
-	jnz	1f
-
-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	wakeup_seq-cond_futex(%ebx), %ebp
-	jna	4f
-
-	/* Cause all currently waiting threads to recognize they are
-	   woken up.  */
-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-cond_futex(%ebx), %edi
-
-	/* Unlock.  */
-	LOCK
-	subl	$1, cond_lock-cond_futex(%ebx)
-	jne	7f
-
-	/* Don't use requeue for pshared condvars.  */
-8:	cmpl	$-1, %edi
-	je	9f
-
-	/* Do not use requeue for pshared condvars.  */
-	testl	$PS_BIT, MUTEX_KIND(%edi)
-	jne	9f
-
-	/* Requeue to a non-robust PI mutex if the PI bit is set and
-	   the robust bit is not set.  */
-	movl	MUTEX_KIND(%edi), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	je	81f
-
-	/* Wake up all threads.  */
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %ecx
-#else
-	movl	%gs:PRIVATE_FUTEX, %ecx
-	orl	$FUTEX_CMP_REQUEUE, %ecx
-#endif
-	movl	$SYS_futex, %eax
-	movl	$0x7fffffff, %esi
-	movl	$1, %edx
-	/* Get the address of the futex involved.  */
-# if MUTEX_FUTEX != 0
-	addl	$MUTEX_FUTEX, %edi
-# 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
-
-6:	xorl	%eax, %eax
-	popl	%ebp
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebp)
-	popl	%edi
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%edi)
-	popl	%esi
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%esi)
-	popl	%ebx
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebx)
-	ret
-
-	cfi_restore_state
-
-81:	movl	$(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
-	movl	$SYS_futex, %eax
-	movl	$0x7fffffff, %esi
-	movl	$1, %edx
-	/* Get the address of the futex involved.  */
-# if MUTEX_FUTEX != 0
-	addl	$MUTEX_FUTEX, %edi
-# endif
-	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
-	jb	6b
-	jmp	9f
-
-	/* Initial locking failed.  */
-1:
-#if cond_lock == 0
-	movl	%ebx, %edx
-#else
-	leal	cond_lock(%ebx), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-	jmp	2b
-
-	.align	16
-	/* Unlock.  */
-4:	LOCK
-	subl	$1, cond_lock-cond_futex(%ebx)
-	je	6b
-
-	/* Unlock in loop requires wakeup.  */
-5:	leal	cond_lock-cond_futex(%ebx), %eax
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_futex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-	jmp	6b
-
-	/* Unlock in loop requires wakeup.  */
-7:	leal	cond_lock-cond_futex(%ebx), %eax
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_futex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-	jmp	8b
-
-9:	/* The futex requeue functionality is not available.  */
-	movl	$0x7fffffff, %edx
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_futex(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE, %ecx
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	jmp	6b
-	cfi_endproc
-	.size	__pthread_cond_broadcast, .-__pthread_cond_broadcast
-versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
-		  GLIBC_2_3_2)
diff --git a/sysdeps/unix/sysv/linux/i386/pthread_cond_signal.S b/sysdeps/unix/sysv/linux/i386/pthread_cond_signal.S
deleted file mode 100644
index 0038775..0000000
--- a/sysdeps/unix/sysv/linux/i386/pthread_cond_signal.S
+++ /dev/null
@@ -1,216 +0,0 @@ 
-/* Copyright (C) 2002-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-#include <lowlevellock.h>
-#include <lowlevelcond.h>
-#include <kernel-features.h>
-#include <pthread-pi-defines.h>
-#include <pthread-errnos.h>
-#include <stap-probe.h>
-
-	.text
-
-	/* int pthread_cond_signal (pthread_cond_t *cond) */
-	.globl	__pthread_cond_signal
-	.type	__pthread_cond_signal, @function
-	.align	16
-__pthread_cond_signal:
-
-	cfi_startproc
-	pushl	%ebx
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebx, 0)
-	pushl	%edi
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%edi, 0)
-	cfi_remember_state
-
-	movl	12(%esp), %edi
-
-	LIBC_PROBE (cond_signal, 1, %edi)
-
-	/* Get internal lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%edi)
-#else
-	cmpxchgl %edx, cond_lock(%edi)
-#endif
-	jnz	1f
-
-2:	leal	cond_futex(%edi), %ebx
-	movl	total_seq+4(%edi), %eax
-	movl	total_seq(%edi), %ecx
-	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	wakeup_seq-cond_futex(%ebx), %ecx
-	jbe	4f
-
-	/* Bump the wakeup number.  */
-3:	addl	$1, wakeup_seq-cond_futex(%ebx)
-	adcl	$0, wakeup_seq-cond_futex+4(%ebx)
-	addl	$1, (%ebx)
-
-	/* Wake up one thread.  */
-	pushl	%esi
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%esi, 0)
-	pushl	%ebp
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebp, 0)
-
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_futex(%ebx)
-	sete	%cl
-	je	8f
-
-	movl	dep_mutex-cond_futex(%ebx), %edx
-	/* Requeue to a non-robust PI mutex if the PI bit is set and
-	   the robust bit is not set.  */
-	movl	MUTEX_KIND(%edx), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	je	9f
-
-8:	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE_OP, %ecx
-	movl	$SYS_futex, %eax
-	movl	$1, %edx
-	movl	$1, %esi
-	movl	$FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %ebp
-	/* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for
-	   sysenter.
-	ENTER_KERNEL  */
-	int	$0x80
-	popl	%ebp
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebp)
-	popl	%esi
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%esi)
-
-	/* For any kind of error, we try again with WAKE.
-	   The general test also covers running on old kernels.  */
-	cmpl	$-4095, %eax
-	jae	7f
-
-6:	xorl	%eax, %eax
-	popl	%edi
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%edi)
-	popl	%ebx
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebx)
-	ret
-
-	cfi_restore_state
-
-9:	movl	$(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
-	movl	$SYS_futex, %eax
-	movl	$1, %edx
-	xorl	%esi, %esi
-	movl	dep_mutex-cond_futex(%ebx), %edi
-	movl	(%ebx), %ebp
-	/* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for
-	   sysenter.
-	ENTER_KERNEL  */
-	int	$0x80
-	popl	%ebp
-	popl	%esi
-
-	leal	-cond_futex(%ebx), %edi
-
-	/* For any kind of error, we try again with WAKE.
-	   The general test also covers running on old kernels.  */
-	cmpl	$-4095, %eax
-	jb	4f
-
-7:
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	orl	$FUTEX_WAKE, %ecx
-
-	movl	$SYS_futex, %eax
-	/* %edx should be 1 already from $FUTEX_WAKE_OP syscall.
-	movl	$1, %edx  */
-	ENTER_KERNEL
-
-	/* Unlock.  Note that at this point %edi always points to
-	   cond_lock.  */
-4:	LOCK
-	subl	$1, (%edi)
-	je	6b
-
-	/* Unlock in loop requires wakeup.  */
-5:	movl	%edi, %eax
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_futex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-	jmp	6b
-
-	/* Initial locking failed.  */
-1:
-#if cond_lock == 0
-	movl	%edi, %edx
-#else
-	leal	cond_lock(%edi), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%edi)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-	jmp	2b
-
-	cfi_endproc
-	.size	__pthread_cond_signal, .-__pthread_cond_signal
-versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
-		  GLIBC_2_3_2)
diff --git a/sysdeps/unix/sysv/linux/i386/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/i386/pthread_cond_timedwait.S
deleted file mode 100644
index 6256376..0000000
--- a/sysdeps/unix/sysv/linux/i386/pthread_cond_timedwait.S
+++ /dev/null
@@ -1,974 +0,0 @@ 
-/* Copyright (C) 2002-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-#include <lowlevellock.h>
-#include <lowlevelcond.h>
-#include <pthread-errnos.h>
-#include <pthread-pi-defines.h>
-#include <kernel-features.h>
-#include <stap-probe.h>
-
-	.text
-
-/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
-			       const struct timespec *abstime)  */
-	.globl	__pthread_cond_timedwait
-	.type	__pthread_cond_timedwait, @function
-	.align	16
-__pthread_cond_timedwait:
-.LSTARTCODE:
-	cfi_startproc
-#ifdef SHARED
-	cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
-			DW.ref.__gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
-#else
-	cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
-#endif
-
-	pushl	%ebp
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebp, 0)
-	pushl	%edi
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%edi, 0)
-	pushl	%esi
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%esi, 0)
-	pushl	%ebx
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebx, 0)
-
-	movl	20(%esp), %ebx
-	movl	28(%esp), %ebp
-
-	LIBC_PROBE (cond_timedwait, 3, %ebx, 24(%esp), %ebp)
-
-	cmpl	$1000000000, 4(%ebp)
-	movl	$EINVAL, %eax
-	jae	18f
-
-	/* Stack frame:
-
-	   esp + 32
-		    +--------------------------+
-	   esp + 24 | timeout value            |
-		    +--------------------------+
-	   esp + 20 | futex pointer            |
-		    +--------------------------+
-	   esp + 16 | pi-requeued flag         |
-		    +--------------------------+
-	   esp + 12 | old broadcast_seq value  |
-		    +--------------------------+
-	   esp +  4 | old wake_seq value       |
-		    +--------------------------+
-	   esp +  0 | old cancellation mode    |
-		    +--------------------------+
-	*/
-
-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
-# ifdef PIC
-	LOAD_PIC_REG (cx)
-	cmpl	$0, __have_futex_clock_realtime@GOTOFF(%ecx)
-# else
-	cmpl	$0, __have_futex_clock_realtime
-# endif
-	je	.Lreltmo
-#endif
-
-	/* Get internal lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, cond_lock(%ebx)
-#endif
-	jnz	1f
-
-	/* Store the reference to the mutex.  If there is already a
-	   different value in there this is a bad user bug.  */
-2:	cmpl	$-1, dep_mutex(%ebx)
-	movl	24(%esp), %eax
-	je	17f
-	movl	%eax, dep_mutex(%ebx)
-
-	/* Unlock the mutex.  */
-17:	xorl	%edx, %edx
-	call	__pthread_mutex_unlock_usercnt
-
-	testl	%eax, %eax
-	jne	16f
-
-	addl	$1, total_seq(%ebx)
-	adcl	$0, total_seq+4(%ebx)
-	addl	$1, cond_futex(%ebx)
-	addl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-#ifdef __ASSUME_FUTEX_CLOCK_REALTIME
-# define FRAME_SIZE 24
-#else
-# define FRAME_SIZE 32
-#endif
-	subl	$FRAME_SIZE, %esp
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-	cfi_remember_state
-
-	/* 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)
-
-	/* Reset the pi-requeued flag.  */
-	movl	$0, 16(%esp)
-
-	cmpl	$0, (%ebp)
-	movl	$-ETIMEDOUT, %esi
-	js	6f
-
-8:	movl	cond_futex(%ebx), %edi
-	movl	%edi, 20(%esp)
-
-	/* Unlock.  */
-	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	jne	3f
-
-.LcleanupSTART:
-4:	call	__pthread_enable_asynccancel
-	movl	%eax, (%esp)
-
-	leal	(%ebp), %esi
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	sete	%cl
-	je	40f
-
-	movl	dep_mutex(%ebx), %edi
-	/* Requeue to a non-robust PI mutex if the PI bit is set and
-	   the robust bit is not set.  */
-	movl	MUTEX_KIND(%edi), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	jne	40f
-
-	movl	$(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
-	/* The following only works like this because we only support
-	   two clocks, represented using a single bit.  */
-	testl	$1, cond_nwaiters(%ebx)
-	/* XXX Need to implement using sete instead of a jump.  */
-	jne	42f
-	orl	$FUTEX_CLOCK_REALTIME, %ecx
-
-42:	movl	20(%esp), %edx
-	addl	$cond_futex, %ebx
-.Ladd_cond_futex_pi:
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	subl	$cond_futex, %ebx
-.Lsub_cond_futex_pi:
-	movl	%eax, %esi
-	/* Set the pi-requeued flag only if the kernel has returned 0. The
-	   kernel does not hold the mutex on ETIMEDOUT or any other error.  */
-	cmpl	$0, %eax
-	sete	16(%esp)
-	je	41f
-
-	/* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns
-	   successfully, it has already locked the mutex for us and the
-	   pi_flag (16(%esp)) is set to denote that fact.  However, if another
-	   thread changed the futex value before we entered the wait, the
-	   syscall may return an EAGAIN and the mutex is not locked.  We go
-	   ahead with a success anyway since later we look at the pi_flag to
-	   decide if we got the mutex or not.  The sequence numbers then make
-	   sure that only one of the threads actually wake up.  We retry using
-	   normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal
-	   and PI futexes don't mix.
-
-	   Note that we don't check for EAGAIN specifically; we assume that the
-	   only other error the futex function could return is EAGAIN (barring
-	   the ETIMEOUT of course, for the timeout case in futex) since
-	   anything else would mean an error in our function.  It is too
-	   expensive to do that check for every call (which is  quite common in
-	   case of a large number of threads), so it has been skipped.  */
-	cmpl	$-ENOSYS, %eax
-	jne	41f
-	xorl	%ecx, %ecx
-
-40:	subl	$1, %ecx
-	movl	$0, 16(%esp)
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAIT_BITSET, %ecx
-	/* The following only works like this because we only support
-	   two clocks, represented using a single bit.  */
-	testl	$1, cond_nwaiters(%ebx)
-	jne	30f
-	orl	$FUTEX_CLOCK_REALTIME, %ecx
-30:
-	movl	20(%esp), %edx
-	movl	$0xffffffff, %ebp
-	addl	$cond_futex, %ebx
-.Ladd_cond_futex:
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	subl	$cond_futex, %ebx
-.Lsub_cond_futex:
-	movl	28+FRAME_SIZE(%esp), %ebp
-	movl	%eax, %esi
-
-41:	movl	(%esp), %eax
-	call	__pthread_disable_asynccancel
-.LcleanupEND:
-
-	/* Lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, cond_lock(%ebx)
-#endif
-	jnz	5f
-
-6:	movl	broadcast_seq(%ebx), %eax
-	cmpl	12(%esp), %eax
-	jne	23f
-
-	movl	woken_seq(%ebx), %eax
-	movl	woken_seq+4(%ebx), %ecx
-
-	movl	wakeup_seq(%ebx), %edi
-	movl	wakeup_seq+4(%ebx), %edx
-
-	cmpl	8(%esp), %edx
-	jne	7f
-	cmpl	4(%esp), %edi
-	je	15f
-
-7:	cmpl	%ecx, %edx
-	jne	9f
-	cmp	%eax, %edi
-	jne	9f
-
-15:	cmpl	$-ETIMEDOUT, %esi
-	je	28f
-
-	/* We need to go back to futex_wait.  If we're using requeue_pi, then
-	   release the mutex we had acquired and go back.  */
-	movl	16(%esp), %edx
-	test	%edx, %edx
-	jz	8b
-
-	/* Adjust the mutex values first and then unlock it.  The unlock
-	   should always succeed or else the kernel did not lock the mutex
-	   correctly.  */
-	movl	dep_mutex(%ebx), %eax
-	call	__pthread_mutex_cond_lock_adjust
-	movl	dep_mutex(%ebx), %eax
-	xorl	%edx, %edx
-	call	__pthread_mutex_unlock_usercnt
-	jmp	8b
-
-28:	addl	$1, wakeup_seq(%ebx)
-	adcl	$0, wakeup_seq+4(%ebx)
-	addl	$1, cond_futex(%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)
-
-24:	subl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	movl	total_seq(%ebx), %eax
-	andl	total_seq+4(%ebx), %eax
-	cmpl	$0xffffffff, %eax
-	jne	25f
-	movl	cond_nwaiters(%ebx), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	25f
-
-	addl	$cond_nwaiters, %ebx
-	movl	$SYS_futex, %eax
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_nwaiters(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE, %ecx
-	movl	$1, %edx
-	ENTER_KERNEL
-	subl	$cond_nwaiters, %ebx
-
-25:	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	jne	10f
-
-11:	movl	24+FRAME_SIZE(%esp), %eax
-	/* With requeue_pi, the mutex lock is held in the kernel.  */
-	movl	16(%esp), %ecx
-	testl	%ecx, %ecx
-	jnz	27f
-
-	call	__pthread_mutex_cond_lock
-26:	addl	$FRAME_SIZE, %esp
-	cfi_adjust_cfa_offset(-FRAME_SIZE)
-
-	/* We return the result of the mutex_lock operation if it failed.  */
-	testl	%eax, %eax
-#ifdef HAVE_CMOV
-	cmovel	%esi, %eax
-#else
-	jne	22f
-	movl	%esi, %eax
-22:
-#endif
-
-18:	popl	%ebx
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebx)
-	popl	%esi
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%esi)
-	popl	%edi
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%edi)
-	popl	%ebp
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebp)
-
-	ret
-
-	cfi_restore_state
-
-27:	call	__pthread_mutex_cond_lock_adjust
-	xorl	%eax, %eax
-	jmp	26b
-
-	cfi_adjust_cfa_offset(-FRAME_SIZE);
-	/* Initial locking failed.  */
-1:
-#if cond_lock == 0
-	movl	%ebx, %edx
-#else
-	leal	cond_lock(%ebx), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-	jmp	2b
-
-	/* The initial unlocking of the mutex failed.  */
-16:
-	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	jne	18b
-
-	movl	%eax, %esi
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-
-	movl	%esi, %eax
-	jmp	18b
-
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-
-	/* Unlock in loop requires wakeup.  */
-3:
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-	jmp	4b
-
-	/* Locking in loop failed.  */
-5:
-#if cond_lock == 0
-	movl	%ebx, %edx
-#else
-	leal	cond_lock(%ebx), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-	jmp	6b
-
-	/* Unlock after loop requires wakeup.  */
-10:
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-	jmp	11b
-
-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
-	cfi_adjust_cfa_offset(-FRAME_SIZE)
-.Lreltmo:
-	/* Get internal lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-# if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-# else
-	cmpxchgl %edx, cond_lock(%ebx)
-# endif
-	jnz	101f
-
-	/* Store the reference to the mutex.  If there is already a
-	   different value in there this is a bad user bug.  */
-102:	cmpl	$-1, dep_mutex(%ebx)
-	movl	24(%esp), %eax
-	je	117f
-	movl	%eax, dep_mutex(%ebx)
-
-	/* Unlock the mutex.  */
-117:	xorl	%edx, %edx
-	call	__pthread_mutex_unlock_usercnt
-
-	testl	%eax, %eax
-	jne	16b
-
-	addl	$1, total_seq(%ebx)
-	adcl	$0, total_seq+4(%ebx)
-	addl	$1, cond_futex(%ebx)
-	addl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-	subl	$FRAME_SIZE, %esp
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-
-	/* 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)
-
-	/* Reset the pi-requeued flag.  */
-	movl	$0, 16(%esp)
-
-	/* Get the current time.  */
-108:	movl	%ebx, %edx
-# ifdef __NR_clock_gettime
-	/* Get the clock number.  */
-	movl	cond_nwaiters(%ebx), %ebx
-	andl	$((1 << nwaiters_shift) - 1), %ebx
-	/* Only clocks 0 and 1 are allowed so far.  Both are handled in the
-	   kernel.  */
-	leal	24(%esp), %ecx
-	movl	$__NR_clock_gettime, %eax
-	ENTER_KERNEL
-	movl	%edx, %ebx
-
-	/* Compute relative timeout.  */
-	movl	(%ebp), %ecx
-	movl	4(%ebp), %edx
-	subl	24(%esp), %ecx
-	subl	28(%esp), %edx
-# else
-	/* Get the current time.  */
-	leal	24(%esp), %ebx
-	xorl	%ecx, %ecx
-	movl	$__NR_gettimeofday, %eax
-	ENTER_KERNEL
-	movl	%edx, %ebx
-
-	/* Compute relative timeout.  */
-	movl	28(%esp), %eax
-	movl	$1000, %edx
-	mul	%edx		/* Milli seconds to nano seconds.  */
-	movl	(%ebp), %ecx
-	movl	4(%ebp), %edx
-	subl	24(%esp), %ecx
-	subl	%eax, %edx
-# endif
-	jns	112f
-	addl	$1000000000, %edx
-	subl	$1, %ecx
-112:	testl	%ecx, %ecx
-	movl	$-ETIMEDOUT, %esi
-	js	106f
-
-	/* Store relative timeout.  */
-121:	movl	%ecx, 24(%esp)
-	movl	%edx, 28(%esp)
-
-	movl	cond_futex(%ebx), %edi
-	movl	%edi, 20(%esp)
-
-	/* Unlock.  */
-	LOCK
-# if cond_lock == 0
-	subl	$1, (%ebx)
-# else
-	subl	$1, cond_lock(%ebx)
-# endif
-	jne	103f
-
-.LcleanupSTART2:
-104:	call	__pthread_enable_asynccancel
-	movl	%eax, (%esp)
-
-	leal	24(%esp), %esi
-# if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-# endif
-	cmpl	$-1, dep_mutex(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-# ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-# else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-# endif
-# if FUTEX_WAIT != 0
-	addl	$FUTEX_WAIT, %ecx
-# endif
-	movl	20(%esp), %edx
-	addl	$cond_futex, %ebx
-.Ladd_cond_futex2:
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	subl	$cond_futex, %ebx
-.Lsub_cond_futex2:
-	movl	%eax, %esi
-
-141:	movl	(%esp), %eax
-	call	__pthread_disable_asynccancel
-.LcleanupEND2:
-
-
-	/* Lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-# if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-# else
-	cmpxchgl %edx, cond_lock(%ebx)
-# endif
-	jnz	105f
-
-106:	movl	broadcast_seq(%ebx), %eax
-	cmpl	12(%esp), %eax
-	jne	23b
-
-	movl	woken_seq(%ebx), %eax
-	movl	woken_seq+4(%ebx), %ecx
-
-	movl	wakeup_seq(%ebx), %edi
-	movl	wakeup_seq+4(%ebx), %edx
-
-	cmpl	8(%esp), %edx
-	jne	107f
-	cmpl	4(%esp), %edi
-	je	115f
-
-107:	cmpl	%ecx, %edx
-	jne	9b
-	cmp	%eax, %edi
-	jne	9b
-
-115:	cmpl	$-ETIMEDOUT, %esi
-	je	28b
-
-	jmp	8b
-
-	cfi_adjust_cfa_offset(-FRAME_SIZE)
-	/* Initial locking failed.  */
-101:
-# if cond_lock == 0
-	movl	%ebx, %edx
-# else
-	leal	cond_lock(%ebx), %edx
-# endif
-# if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-# endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-# if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-# endif
-	call	__lll_lock_wait
-	jmp	102b
-
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-
-	/* Unlock in loop requires wakeup.  */
-103:
-# if cond_lock == 0
-	movl	%ebx, %eax
-# else
-	leal	cond_lock(%ebx), %eax
-# endif
-# if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-# endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-# if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-# endif
-	call	__lll_unlock_wake
-	jmp	104b
-
-	/* Locking in loop failed.  */
-105:
-# if cond_lock == 0
-	movl	%ebx, %edx
-# else
-	leal	cond_lock(%ebx), %edx
-# endif
-# if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-# endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-# if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-# endif
-	call	__lll_lock_wait
-	jmp	106b
-#endif
-
-	.size	__pthread_cond_timedwait, .-__pthread_cond_timedwait
-versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
-		  GLIBC_2_3_2)
-
-
-	.type	__condvar_tw_cleanup2, @function
-__condvar_tw_cleanup2:
-	subl	$cond_futex, %ebx
-	.size	__condvar_tw_cleanup2, .-__condvar_tw_cleanup2
-	.type	__condvar_tw_cleanup, @function
-__condvar_tw_cleanup:
-	movl	%eax, %esi
-
-	/* Get internal lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, cond_lock(%ebx)
-#endif
-	jz	1f
-
-#if cond_lock == 0
-	movl	%ebx, %edx
-#else
-	leal	cond_lock(%ebx), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-
-1:	movl	broadcast_seq(%ebx), %eax
-	cmpl	12(%esp), %eax
-	jne	3f
-
-	/* We increment the wakeup_seq counter only if it is lower than
-	   total_seq.  If this is not the case the thread was woken and
-	   then canceled.  In this case we ignore the signal.  */
-	movl	total_seq(%ebx), %eax
-	movl	total_seq+4(%ebx), %edi
-	cmpl	wakeup_seq+4(%ebx), %edi
-	jb	6f
-	ja	7f
-	cmpl	wakeup_seq(%ebx), %eax
-	jbe	7f
-
-6:	addl	$1, wakeup_seq(%ebx)
-	adcl	$0, wakeup_seq+4(%ebx)
-	addl	$1, cond_futex(%ebx)
-
-7:	addl	$1, woken_seq(%ebx)
-	adcl	$0, woken_seq+4(%ebx)
-
-3:	subl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	xorl	%edi, %edi
-	movl	total_seq(%ebx), %eax
-	andl	total_seq+4(%ebx), %eax
-	cmpl	$0xffffffff, %eax
-	jne	4f
-	movl	cond_nwaiters(%ebx), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	4f
-
-	addl	$cond_nwaiters, %ebx
-	movl	$SYS_futex, %eax
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_nwaiters(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE, %ecx
-	movl	$1, %edx
-	ENTER_KERNEL
-	subl	$cond_nwaiters, %ebx
-	movl	$1, %edi
-
-4:	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	je	2f
-
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-
-	/* Wake up all waiters to make sure no signal gets lost.  */
-2:	testl	%edi, %edi
-	jnz	5f
-	addl	$cond_futex, %ebx
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_futex(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE, %ecx
-	movl	$SYS_futex, %eax
-	movl	$0x7fffffff, %edx
-	ENTER_KERNEL
-
-	/* Lock the mutex only if we don't own it already.  This only happens
-	   in case of PI mutexes, if we got cancelled after a successful
-	   return of the futex syscall and before disabling async
-	   cancellation.  */
-5:	movl	24+FRAME_SIZE(%esp), %eax
-	movl	MUTEX_KIND(%eax), %ebx
-	andl	$(ROBUST_BIT|PI_BIT), %ebx
-	cmpl	$PI_BIT, %ebx
-	jne	8f
-
-	movl	(%eax), %ebx
-	andl	$TID_MASK, %ebx
-	cmpl	%ebx, %gs:TID
-	jne	8f
-	/* We managed to get the lock.  Fix it up before returning.  */
-	call	__pthread_mutex_cond_lock_adjust
-	jmp	9f
-
-8:	call	__pthread_mutex_cond_lock
-
-9:	movl	%esi, (%esp)
-.LcallUR:
-	call	_Unwind_Resume
-	hlt
-.LENDCODE:
-	cfi_endproc
-	.size	__condvar_tw_cleanup, .-__condvar_tw_cleanup
-
-
-	.section .gcc_except_table,"a",@progbits
-.LexceptSTART:
-	.byte	DW_EH_PE_omit			# @LPStart format (omit)
-	.byte	DW_EH_PE_omit			# @TType format (omit)
-	.byte	DW_EH_PE_sdata4			# call-site format
-						# DW_EH_PE_sdata4
-	.uleb128 .Lcstend-.Lcstbegin
-.Lcstbegin:
-	.long	.LcleanupSTART-.LSTARTCODE
-	.long	.Ladd_cond_futex_pi-.LcleanupSTART
-	.long	__condvar_tw_cleanup-.LSTARTCODE
-	.uleb128  0
-	.long	.Ladd_cond_futex_pi-.LSTARTCODE
-	.long	.Lsub_cond_futex_pi-.Ladd_cond_futex_pi
-	.long	__condvar_tw_cleanup2-.LSTARTCODE
-	.uleb128  0
-	.long	.Lsub_cond_futex_pi-.LSTARTCODE
-	.long	.Ladd_cond_futex-.Lsub_cond_futex_pi
-	.long	__condvar_tw_cleanup-.LSTARTCODE
-	.uleb128  0
-	.long	.Ladd_cond_futex-.LSTARTCODE
-	.long	.Lsub_cond_futex-.Ladd_cond_futex
-	.long	__condvar_tw_cleanup2-.LSTARTCODE
-	.uleb128  0
-	.long	.Lsub_cond_futex-.LSTARTCODE
-	.long	.LcleanupEND-.Lsub_cond_futex
-	.long	__condvar_tw_cleanup-.LSTARTCODE
-	.uleb128  0
-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
-	.long	.LcleanupSTART2-.LSTARTCODE
-	.long	.Ladd_cond_futex2-.LcleanupSTART2
-	.long	__condvar_tw_cleanup-.LSTARTCODE
-	.uleb128  0
-	.long	.Ladd_cond_futex2-.LSTARTCODE
-	.long	.Lsub_cond_futex2-.Ladd_cond_futex2
-	.long	__condvar_tw_cleanup2-.LSTARTCODE
-	.uleb128  0
-	.long	.Lsub_cond_futex2-.LSTARTCODE
-	.long	.LcleanupEND2-.Lsub_cond_futex2
-	.long	__condvar_tw_cleanup-.LSTARTCODE
-	.uleb128  0
-#endif
-	.long	.LcallUR-.LSTARTCODE
-	.long	.LENDCODE-.LcallUR
-	.long	0
-	.uleb128  0
-.Lcstend:
-
-
-#ifdef SHARED
-	.hidden DW.ref.__gcc_personality_v0
-	.weak	DW.ref.__gcc_personality_v0
-	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
-	.align	4
-	.type	DW.ref.__gcc_personality_v0, @object
-	.size	DW.ref.__gcc_personality_v0, 4
-DW.ref.__gcc_personality_v0:
-	.long   __gcc_personality_v0
-#endif
diff --git a/sysdeps/unix/sysv/linux/i386/pthread_cond_wait.S b/sysdeps/unix/sysv/linux/i386/pthread_cond_wait.S
deleted file mode 100644
index 5016718..0000000
--- a/sysdeps/unix/sysv/linux/i386/pthread_cond_wait.S
+++ /dev/null
@@ -1,642 +0,0 @@ 
-/* Copyright (C) 2002-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-#include <lowlevellock.h>
-#include <lowlevelcond.h>
-#include <tcb-offsets.h>
-#include <pthread-errnos.h>
-#include <pthread-pi-defines.h>
-#include <kernel-features.h>
-#include <stap-probe.h>
-
-
-	.text
-
-/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */
-	.globl	__pthread_cond_wait
-	.type	__pthread_cond_wait, @function
-	.align	16
-__pthread_cond_wait:
-.LSTARTCODE:
-	cfi_startproc
-#ifdef SHARED
-	cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
-			DW.ref.__gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
-#else
-	cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
-#endif
-
-	pushl	%ebp
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebp, 0)
-	pushl	%edi
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%edi, 0)
-	pushl	%esi
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%esi, 0)
-	pushl	%ebx
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebx, 0)
-
-	xorl	%esi, %esi
-	movl	20(%esp), %ebx
-
-	LIBC_PROBE (cond_wait, 2, 24(%esp), %ebx)
-
-	/* Get internal lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, cond_lock(%ebx)
-#endif
-	jnz	1f
-
-	/* Store the reference to the mutex.  If there is already a
-	   different value in there this is a bad user bug.  */
-2:	cmpl	$-1, dep_mutex(%ebx)
-	movl	24(%esp), %eax
-	je	15f
-	movl	%eax, dep_mutex(%ebx)
-
-	/* Unlock the mutex.  */
-15:	xorl	%edx, %edx
-	call	__pthread_mutex_unlock_usercnt
-
-	testl	%eax, %eax
-	jne	12f
-
-	addl	$1, total_seq(%ebx)
-	adcl	$0, total_seq+4(%ebx)
-	addl	$1, cond_futex(%ebx)
-	addl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-#define FRAME_SIZE 20
-	subl	$FRAME_SIZE, %esp
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-	cfi_remember_state
-
-	/* 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)
-
-	/* Reset the pi-requeued flag.  */
-8:	movl	$0, 16(%esp)
-	movl	cond_futex(%ebx), %ebp
-
-	/* Unlock.  */
-	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	jne	3f
-
-.LcleanupSTART:
-4:	call	__pthread_enable_asynccancel
-	movl	%eax, (%esp)
-
-	xorl	%ecx, %ecx
-	cmpl	$-1, dep_mutex(%ebx)
-	sete	%cl
-	je	18f
-
-	movl	dep_mutex(%ebx), %edi
-	/* Requeue to a non-robust PI mutex if the PI bit is set and
-	   the robust bit is not set.  */
-	movl	MUTEX_KIND(%edi), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	jne	18f
-
-	movl	$(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
-	movl	%ebp, %edx
-	xorl	%esi, %esi
-	addl	$cond_futex, %ebx
-.Ladd_cond_futex_pi:
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	subl	$cond_futex, %ebx
-.Lsub_cond_futex_pi:
-	/* Set the pi-requeued flag only if the kernel has returned 0. The
-	   kernel does not hold the mutex on error.  */
-	cmpl	$0, %eax
-	sete	16(%esp)
-	je	19f
-
-	/* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns
-	   successfully, it has already locked the mutex for us and the
-	   pi_flag (16(%esp)) is set to denote that fact.  However, if another
-	   thread changed the futex value before we entered the wait, the
-	   syscall may return an EAGAIN and the mutex is not locked.  We go
-	   ahead with a success anyway since later we look at the pi_flag to
-	   decide if we got the mutex or not.  The sequence numbers then make
-	   sure that only one of the threads actually wake up.  We retry using
-	   normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal
-	   and PI futexes don't mix.
-
-	   Note that we don't check for EAGAIN specifically; we assume that the
-	   only other error the futex function could return is EAGAIN since
-	   anything else would mean an error in our function.  It is too
-	   expensive to do that check for every call (which is 	quite common in
-	   case of a large number of threads), so it has been skipped.  */
-	cmpl	$-ENOSYS, %eax
-	jne	19f
-	xorl	%ecx, %ecx
-
-18:	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-#if FUTEX_WAIT != 0
-	addl	$FUTEX_WAIT, %ecx
-#endif
-	movl	%ebp, %edx
-	addl	$cond_futex, %ebx
-.Ladd_cond_futex:
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	subl	$cond_futex, %ebx
-.Lsub_cond_futex:
-
-19:	movl	(%esp), %eax
-	call	__pthread_disable_asynccancel
-.LcleanupEND:
-
-	/* Lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, cond_lock(%ebx)
-#endif
-	jnz	5f
-
-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
-	movl	wakeup_seq+4(%ebx), %edx
-
-	cmpl	8(%esp), %edx
-	jne	7f
-	cmpl	4(%esp), %edi
-	je	22f
-
-7:	cmpl	%ecx, %edx
-	jne	9f
-	cmp	%eax, %edi
-	je	22f
-
-9:	addl	$1, woken_seq(%ebx)
-	adcl	$0, woken_seq+4(%ebx)
-
-	/* Unlock */
-16:	subl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	movl	total_seq(%ebx), %eax
-	andl	total_seq+4(%ebx), %eax
-	cmpl	$0xffffffff, %eax
-	jne	17f
-	movl	cond_nwaiters(%ebx), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	17f
-
-	addl	$cond_nwaiters, %ebx
-	movl	$SYS_futex, %eax
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_nwaiters(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE, %ecx
-	movl	$1, %edx
-	ENTER_KERNEL
-	subl	$cond_nwaiters, %ebx
-
-17:	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	jne	10f
-
-	/* With requeue_pi, the mutex lock is held in the kernel.  */
-11:	movl	24+FRAME_SIZE(%esp), %eax
-	movl	16(%esp), %ecx
-	testl	%ecx, %ecx
-	jnz	21f
-
-	call	__pthread_mutex_cond_lock
-20:	addl	$FRAME_SIZE, %esp
-	cfi_adjust_cfa_offset(-FRAME_SIZE);
-
-14:	popl	%ebx
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebx)
-	popl	%esi
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%esi)
-	popl	%edi
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%edi)
-	popl	%ebp
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebp)
-
-	/* We return the result of the mutex_lock operation.  */
-	ret
-
-	cfi_restore_state
-
-21:	call	__pthread_mutex_cond_lock_adjust
-	xorl	%eax, %eax
-	jmp	20b
-
-	cfi_adjust_cfa_offset(-FRAME_SIZE);
-
-	/* We need to go back to futex_wait.  If we're using requeue_pi, then
-	   release the mutex we had acquired and go back.  */
-22:	movl	16(%esp), %edx
-	test	%edx, %edx
-	jz	8b
-
-	/* Adjust the mutex values first and then unlock it.  The unlock
-	   should always succeed or else the kernel did not lock the mutex
-	   correctly.  */
-	movl	dep_mutex(%ebx), %eax
-	call    __pthread_mutex_cond_lock_adjust
-	movl	dep_mutex(%ebx), %eax
-	xorl	%edx, %edx
-	call	__pthread_mutex_unlock_usercnt
-	jmp	8b
-
-	/* Initial locking failed.  */
-1:
-#if cond_lock == 0
-	movl	%ebx, %edx
-#else
-	leal	cond_lock(%ebx), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-	jmp	2b
-
-	/* The initial unlocking of the mutex failed.  */
-12:
-	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	jne	14b
-
-	movl	%eax, %esi
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-
-	movl	%esi, %eax
-	jmp	14b
-
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-
-	/* Unlock in loop requires wakeup.  */
-3:
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-	jmp	4b
-
-	/* Locking in loop failed.  */
-5:
-#if cond_lock == 0
-	movl	%ebx, %edx
-#else
-	leal	cond_lock(%ebx), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-	jmp	6b
-
-	/* Unlock after loop requires wakeup.  */
-10:
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-	jmp	11b
-
-	.size	__pthread_cond_wait, .-__pthread_cond_wait
-versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
-		  GLIBC_2_3_2)
-
-
-	.type	__condvar_w_cleanup2, @function
-__condvar_w_cleanup2:
-	subl	$cond_futex, %ebx
-	.size	__condvar_w_cleanup2, .-__condvar_w_cleanup2
-.LSbl4:
-	.type	__condvar_w_cleanup, @function
-__condvar_w_cleanup:
-	movl	%eax, %esi
-
-	/* Get internal lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, cond_lock(%ebx)
-#endif
-	jz	1f
-
-#if cond_lock == 0
-	movl	%ebx, %edx
-#else
-	leal	cond_lock(%ebx), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-
-1:	movl	broadcast_seq(%ebx), %eax
-	cmpl	12(%esp), %eax
-	jne	3f
-
-	/* We increment the wakeup_seq counter only if it is lower than
-	   total_seq.  If this is not the case the thread was woken and
-	   then canceled.  In this case we ignore the signal.  */
-	movl	total_seq(%ebx), %eax
-	movl	total_seq+4(%ebx), %edi
-	cmpl	wakeup_seq+4(%ebx), %edi
-	jb	6f
-	ja	7f
-	cmpl	wakeup_seq(%ebx), %eax
-	jbe	7f
-
-6:	addl	$1, wakeup_seq(%ebx)
-	adcl	$0, wakeup_seq+4(%ebx)
-	addl	$1, cond_futex(%ebx)
-
-7:	addl	$1, woken_seq(%ebx)
-	adcl	$0, woken_seq+4(%ebx)
-
-3:	subl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	xorl	%edi, %edi
-	movl	total_seq(%ebx), %eax
-	andl	total_seq+4(%ebx), %eax
-	cmpl	$0xffffffff, %eax
-	jne	4f
-	movl	cond_nwaiters(%ebx), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	4f
-
-	addl	$cond_nwaiters, %ebx
-	movl	$SYS_futex, %eax
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_nwaiters(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE, %ecx
-	movl	$1, %edx
-	ENTER_KERNEL
-	subl	$cond_nwaiters, %ebx
-	movl	$1, %edi
-
-4:	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	je	2f
-
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-
-	/* Wake up all waiters to make sure no signal gets lost.  */
-2:	testl	%edi, %edi
-	jnz	5f
-	addl	$cond_futex, %ebx
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_futex(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE, %ecx
-	movl	$SYS_futex, %eax
-	movl	$0x7fffffff, %edx
-	ENTER_KERNEL
-
-	/* Lock the mutex only if we don't own it already.  This only happens
-	   in case of PI mutexes, if we got cancelled after a successful
-	   return of the futex syscall and before disabling async
-	   cancellation.  */
-5:	movl	24+FRAME_SIZE(%esp), %eax
-	movl	MUTEX_KIND(%eax), %ebx
-	andl	$(ROBUST_BIT|PI_BIT), %ebx
-	cmpl	$PI_BIT, %ebx
-	jne	8f
-
-	movl	(%eax), %ebx
-	andl	$TID_MASK, %ebx
-	cmpl	%ebx, %gs:TID
-	jne	8f
-	/* We managed to get the lock.  Fix it up before returning.  */
-	call	__pthread_mutex_cond_lock_adjust
-	jmp	9f
-
-8:	call	__pthread_mutex_cond_lock
-
-9:	movl	%esi, (%esp)
-.LcallUR:
-	call	_Unwind_Resume
-	hlt
-.LENDCODE:
-	cfi_endproc
-	.size	__condvar_w_cleanup, .-__condvar_w_cleanup
-
-
-	.section .gcc_except_table,"a",@progbits
-.LexceptSTART:
-	.byte	DW_EH_PE_omit			# @LPStart format (omit)
-	.byte	DW_EH_PE_omit			# @TType format (omit)
-	.byte	DW_EH_PE_sdata4			# call-site format
-						# DW_EH_PE_sdata4
-	.uleb128 .Lcstend-.Lcstbegin
-.Lcstbegin:
-	.long	.LcleanupSTART-.LSTARTCODE
-	.long	.Ladd_cond_futex_pi-.LcleanupSTART
-	.long	__condvar_w_cleanup-.LSTARTCODE
-	.uleb128  0
-	.long	.Ladd_cond_futex_pi-.LSTARTCODE
-	.long	.Lsub_cond_futex_pi-.Ladd_cond_futex_pi
-	.long	__condvar_w_cleanup2-.LSTARTCODE
-	.uleb128  0
-	.long	.Lsub_cond_futex_pi-.LSTARTCODE
-	.long	.Ladd_cond_futex-.Lsub_cond_futex_pi
-	.long	__condvar_w_cleanup-.LSTARTCODE
-	.uleb128  0
-	.long	.Ladd_cond_futex-.LSTARTCODE
-	.long	.Lsub_cond_futex-.Ladd_cond_futex
-	.long	__condvar_w_cleanup2-.LSTARTCODE
-	.uleb128  0
-	.long	.Lsub_cond_futex-.LSTARTCODE
-	.long	.LcleanupEND-.Lsub_cond_futex
-	.long	__condvar_w_cleanup-.LSTARTCODE
-	.uleb128  0
-	.long	.LcallUR-.LSTARTCODE
-	.long	.LENDCODE-.LcallUR
-	.long	0
-	.uleb128  0
-.Lcstend:
-
-#ifdef SHARED
-	.hidden DW.ref.__gcc_personality_v0
-	.weak   DW.ref.__gcc_personality_v0
-	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
-	.align 4
-	.type   DW.ref.__gcc_personality_v0, @object
-	.size   DW.ref.__gcc_personality_v0, 4
-DW.ref.__gcc_personality_v0:
-	.long   __gcc_personality_v0
-#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
index 345e79a..183e480 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
@@ -123,19 +123,34 @@  typedef union
 
 
 /* Data structure for conditional variable handling.  The structure of
-   the attribute type is deliberately not exposed.  */
+   the attribute type is not exposed on purpose.  */
 typedef union
 {
   struct
   {
-    int __lock;
-    unsigned int __futex;
-    __extension__ unsigned long long int __total_seq;
-    __extension__ unsigned long long int __wakeup_seq;
-    __extension__ unsigned long long int __woken_seq;
-    void *__mutex;
-    unsigned int __nwaiters;
-    unsigned int __broadcast_seq;
+    __extension__ union
+    {
+      __extension__ unsigned long long int __wseq;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __wseq32;
+    };
+    __extension__ union
+    {
+      __extension__ unsigned long long int __g1_start;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __g1_start32;
+    };
+    unsigned int __g_refs[2];
+    unsigned int __g_size[2];
+    unsigned int __g1_orig_size;
+    unsigned int __wrefs;
+    unsigned int __g_signals[2];
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   __extension__ long long int __align;
diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
deleted file mode 100644
index de455dd..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
+++ /dev/null
@@ -1,177 +0,0 @@ 
-/* Copyright (C) 2002-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-#include <lowlevellock.h>
-#include <lowlevelcond.h>
-#include <kernel-features.h>
-#include <pthread-pi-defines.h>
-#include <pthread-errnos.h>
-#include <stap-probe.h>
-
-	.text
-
-	/* int pthread_cond_broadcast (pthread_cond_t *cond) */
-ENTRY(__pthread_cond_broadcast)
-
-	LIBC_PROBE (cond_broadcast, 1, %rdi)
-
-	/* Get internal lock.  */
-	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jnz	1f
-
-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	%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.  */
-	mov	dep_mutex-cond_futex(%rdi), %R8_LP
-
-	/* Unlock.  */
-	LOCK
-	decl	cond_lock-cond_futex(%rdi)
-	jne	7f
-
-8:	cmp	$-1, %R8_LP
-	je	9f
-
-	/* Do not use requeue for pshared condvars.  */
-	testl	$PS_BIT, MUTEX_KIND(%r8)
-	jne	9f
-
-	/* Requeue to a PI mutex if the PI bit is set.  */
-	movl	MUTEX_KIND(%r8), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	je	81f
-
-	/* Wake up all threads.  */
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %esi
-#else
-	movl	%fs:PRIVATE_FUTEX, %esi
-	orl	$FUTEX_CMP_REQUEUE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	movl	$1, %edx
-	movl	$0x7fffffff, %r10d
-	syscall
-
-	/* 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
-
-	/* Wake up all threads.  */
-81:	movl	$(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
-	movl	$SYS_futex, %eax
-	movl	$1, %edx
-	movl	$0x7fffffff, %r10d
-	syscall
-
-	/* 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
-	jb	10b
-	jmp	9f
-
-	.align	16
-	/* Unlock.  */
-4:	LOCK
-	decl	cond_lock-cond_futex(%rdi)
-	jne	5f
-
-6:	xorl	%eax, %eax
-	retq
-
-	/* Initial locking failed.  */
-1:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-#if cond_lock != 0
-	subq	$cond_lock, %rdi
-#endif
-	jmp	2b
-
-	/* Unlock in loop requires wakeup.  */
-5:	addq	$cond_lock-cond_futex, %rdi
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-	jmp	6b
-
-	/* Unlock in loop requires wakeup.  */
-7:	addq	$cond_lock-cond_futex, %rdi
-	cmp	$-1, %R8_LP
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-	subq	$cond_lock-cond_futex, %rdi
-	jmp	8b
-
-9:	/* The futex requeue functionality is not available.  */
-	cmp	$-1, %R8_LP
-	movl	$0x7fffffff, %edx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAKE, %eax
-	movl	$(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
-	cmove	%eax, %esi
-#else
-	movl	$0, %eax
-	movl	%fs:PRIVATE_FUTEX, %esi
-	cmove	%eax, %esi
-	orl	$FUTEX_WAKE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	syscall
-	jmp	10b
-END(__pthread_cond_broadcast)
-
-versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
-		  GLIBC_2_3_2)
diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
deleted file mode 100644
index da14bc3..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
+++ /dev/null
@@ -1,161 +0,0 @@ 
-/* Copyright (C) 2002-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-#include <lowlevellock.h>
-#include <lowlevelcond.h>
-#include <pthread-pi-defines.h>
-#include <kernel-features.h>
-#include <pthread-errnos.h>
-#include <stap-probe.h>
-
-
-	.text
-
-ENTRY(__pthread_cond_signal)
-
-	LIBC_PROBE (cond_signal, 1, %rdi)
-
-	/* Get internal lock.  */
-	movq	%rdi, %r8
-	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jnz	1f
-
-2:	addq	$cond_futex, %rdi
-	movq	total_seq(%r8), %rcx
-	cmpq	wakeup_seq(%r8), %rcx
-	jbe	4f
-
-	/* Bump the wakeup number.  */
-	addq	$1, wakeup_seq(%r8)
-	addl	$1, (%rdi)
-
-	/* Wake up one thread.  */
-	LP_OP(cmp) $-1, dep_mutex(%r8)
-	movl	$FUTEX_WAKE_OP, %esi
-	movl	$1, %edx
-	movl	$SYS_futex, %eax
-	je	8f
-
-	/* Get the address of the mutex used.  */
-	mov     dep_mutex(%r8), %RCX_LP
-	movl	MUTEX_KIND(%rcx), %r11d
-	andl	$(ROBUST_BIT|PI_BIT), %r11d
-	cmpl	$PI_BIT, %r11d
-	je	9f
-
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), %esi
-#else
-	orl	%fs:PRIVATE_FUTEX, %esi
-#endif
-
-8:	movl	$1, %r10d
-#if cond_lock != 0
-	addq	$cond_lock, %r8
-#endif
-	movl	$FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %r9d
-	syscall
-#if cond_lock != 0
-	subq	$cond_lock, %r8
-#endif
-	/* For any kind of error, we try again with WAKE.
-	   The general test also covers running on old kernels.  */
-	cmpq	$-4095, %rax
-	jae	7f
-
-	xorl	%eax, %eax
-	retq
-
-	/* Wake up one thread and requeue none in the PI Mutex case.  */
-9:	movl	$(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
-	movq	%rcx, %r8
-	xorq	%r10, %r10
-	movl	(%rdi), %r9d	// XXX Can this be right?
-	syscall
-
-	leaq	-cond_futex(%rdi), %r8
-
-	/* For any kind of error, we try again with WAKE.
-	   The general test also covers running on old kernels.  */
-	cmpq	$-4095, %rax
-	jb	4f
-
-7:
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %esi
-#else
-	andl	%fs:PRIVATE_FUTEX, %esi
-#endif
-	orl	$FUTEX_WAKE, %esi
-	movl	$SYS_futex, %eax
-	/* %rdx should be 1 already from $FUTEX_WAKE_OP syscall.
-	movl	$1, %edx  */
-	syscall
-
-	/* Unlock.  */
-4:	LOCK
-#if cond_lock == 0
-	decl	(%r8)
-#else
-	decl	cond_lock(%r8)
-#endif
-	jne	5f
-
-6:	xorl	%eax, %eax
-	retq
-
-	/* Initial locking failed.  */
-1:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-#if cond_lock != 0
-	subq	$cond_lock, %rdi
-#endif
-	jmp	2b
-
-	/* Unlock in loop requires wakeup.  */
-5:
-	movq	%r8, %rdi
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-	jmp	6b
-END(__pthread_cond_signal)
-
-versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
-		  GLIBC_2_3_2)
diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
deleted file mode 100644
index 82ffa1a..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+++ /dev/null
@@ -1,623 +0,0 @@ 
-/* Copyright (C) 2002-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-#include <lowlevellock.h>
-#include <lowlevelcond.h>
-#include <pthread-pi-defines.h>
-#include <pthread-errnos.h>
-#include <stap-probe.h>
-
-#include <kernel-features.h>
-
-
-	.text
-
-
-/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
-			       const struct timespec *abstime)  */
-	.globl	__pthread_cond_timedwait
-	.type	__pthread_cond_timedwait, @function
-	.align	16
-__pthread_cond_timedwait:
-.LSTARTCODE:
-	cfi_startproc
-#ifdef SHARED
-	cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
-			DW.ref.__gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
-#else
-	cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
-#endif
-
-	pushq	%r12
-	cfi_adjust_cfa_offset(8)
-	cfi_rel_offset(%r12, 0)
-	pushq	%r13
-	cfi_adjust_cfa_offset(8)
-	cfi_rel_offset(%r13, 0)
-	pushq	%r14
-	cfi_adjust_cfa_offset(8)
-	cfi_rel_offset(%r14, 0)
-	pushq	%r15
-	cfi_adjust_cfa_offset(8)
-	cfi_rel_offset(%r15, 0)
-#define FRAME_SIZE (32+8)
-	subq	$FRAME_SIZE, %rsp
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-	cfi_remember_state
-
-	LIBC_PROBE (cond_timedwait, 3, %rdi, %rsi, %rdx)
-
-	cmpq	$1000000000, 8(%rdx)
-	movl	$EINVAL, %eax
-	jae	48f
-
-	/* Stack frame:
-
-	   rsp + 48
-		    +--------------------------+
-	   rsp + 32 | timeout value            |
-		    +--------------------------+
-	   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    |
-		    +--------------------------+
-	*/
-
-	LP_OP(cmp) $-1, dep_mutex(%rdi)
-
-	/* Prepare structure passed to cancellation handler.  */
-	movq	%rdi, 8(%rsp)
-	movq	%rsi, 16(%rsp)
-	movq	%rdx, %r13
-
-	je	22f
-	mov	%RSI_LP, dep_mutex(%rdi)
-
-22:
-	xorb	%r15b, %r15b
-
-	/* Get internal lock.  */
-	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jnz	31f
-
-	/* Unlock the mutex.  */
-32:	movq	16(%rsp), %rdi
-	xorl	%esi, %esi
-	callq	__pthread_mutex_unlock_usercnt
-
-	testl	%eax, %eax
-	jne	46f
-
-	movq	8(%rsp), %rdi
-	incq	total_seq(%rdi)
-	incl	cond_futex(%rdi)
-	addl	$(1 << nwaiters_shift), cond_nwaiters(%rdi)
-
-	/* Get and store current wakeup_seq value.  */
-	movq	8(%rsp), %rdi
-	movq	wakeup_seq(%rdi), %r9
-	movl	broadcast_seq(%rdi), %edx
-	movq	%r9, 24(%rsp)
-	movl	%edx, 4(%rsp)
-
-	cmpq	$0, (%r13)
-	movq	$-ETIMEDOUT, %r14
-	js	36f
-
-38:	movl	cond_futex(%rdi), %r12d
-
-	/* Unlock.  */
-	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	jne	33f
-
-.LcleanupSTART1:
-34:	callq	__pthread_enable_asynccancel
-	movl	%eax, (%rsp)
-
-	movq	%r13, %r10
-	movl	$FUTEX_WAIT_BITSET, %esi
-	LP_OP(cmp) $-1, dep_mutex(%rdi)
-	je	60f
-
-	mov	dep_mutex(%rdi), %R8_LP
-	/* Requeue to a non-robust PI mutex if the PI bit is set and
-	the robust bit is not set.  */
-	movl	MUTEX_KIND(%r8), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	jne	61f
-
-	movl	$(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
-	xorl	%eax, %eax
-	/* The following only works like this because we only support
-	   two clocks, represented using a single bit.  */
-	testl	$1, cond_nwaiters(%rdi)
-	movl	$FUTEX_CLOCK_REALTIME, %edx
-	cmove	%edx, %eax
-	orl	%eax, %esi
-	movq	%r12, %rdx
-	addq	$cond_futex, %rdi
-	movl	$SYS_futex, %eax
-	syscall
-
-	cmpl	$0, %eax
-	sete	%r15b
-
-#ifdef __ASSUME_REQUEUE_PI
-	jmp	62f
-#else
-	je	62f
-
-	/* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns
-	   successfully, it has already locked the mutex for us and the
-	   pi_flag (%r15b) is set to denote that fact.  However, if another
-	   thread changed the futex value before we entered the wait, the
-	   syscall may return an EAGAIN and the mutex is not locked.  We go
-	   ahead with a success anyway since later we look at the pi_flag to
-	   decide if we got the mutex or not.  The sequence numbers then make
-	   sure that only one of the threads actually wake up.  We retry using
-	   normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal
-	   and PI futexes don't mix.
-
-	   Note that we don't check for EAGAIN specifically; we assume that the
-	   only other error the futex function could return is EAGAIN (barring
-	   the ETIMEOUT of course, for the timeout case in futex) since
-	   anything else would mean an error in our function.  It is too
-	   expensive to do that check for every call (which is  quite common in
-	   case of a large number of threads), so it has been skipped.  */
-	cmpl    $-ENOSYS, %eax
-	jne     62f
-
-	subq	$cond_futex, %rdi
-#endif
-
-61:	movl	$(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi
-60:	xorb	%r15b, %r15b
-	xorl	%eax, %eax
-	/* The following only works like this because we only support
-	   two clocks, represented using a single bit.  */
-	testl	$1, cond_nwaiters(%rdi)
-	movl	$FUTEX_CLOCK_REALTIME, %edx
-	movl	$0xffffffff, %r9d
-	cmove	%edx, %eax
-	orl	%eax, %esi
-	movq	%r12, %rdx
-	addq	$cond_futex, %rdi
-	movl	$SYS_futex, %eax
-	syscall
-62:	movq	%rax, %r14
-
-	movl	(%rsp), %edi
-	callq	__pthread_disable_asynccancel
-.LcleanupEND1:
-
-	/* Lock.  */
-	movq	8(%rsp), %rdi
-	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jne	35f
-
-36:	movl	broadcast_seq(%rdi), %edx
-
-	movq	woken_seq(%rdi), %rax
-
-	movq	wakeup_seq(%rdi), %r9
-
-	cmpl	4(%rsp), %edx
-	jne	53f
-
-	cmpq	24(%rsp), %r9
-	jbe	45f
-
-	cmpq	%rax, %r9
-	ja	39f
-
-45:	cmpq	$-ETIMEDOUT, %r14
-	je	99f
-
-	/* We need to go back to futex_wait.  If we're using requeue_pi, then
-	   release the mutex we had acquired and go back.  */
-	test	%r15b, %r15b
-	jz	38b
-
-	/* Adjust the mutex values first and then unlock it.  The unlock
-	   should always succeed or else the kernel did not lock the
-	   mutex correctly.  */
-	movq	%r8, %rdi
-	callq	__pthread_mutex_cond_lock_adjust
-	xorl	%esi, %esi
-	callq	__pthread_mutex_unlock_usercnt
-	/* Reload cond_var.  */
-	movq	8(%rsp), %rdi
-	jmp	38b
-
-99:	incq	wakeup_seq(%rdi)
-	incl	cond_futex(%rdi)
-	movl	$ETIMEDOUT, %r14d
-	jmp	44f
-
-53:	xorq	%r14, %r14
-	jmp	54f
-
-39:	xorq	%r14, %r14
-44:	incq	woken_seq(%rdi)
-
-54:	subl	$(1 << nwaiters_shift), cond_nwaiters(%rdi)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	cmpq	$0xffffffffffffffff, total_seq(%rdi)
-	jne	55f
-	movl	cond_nwaiters(%rdi), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	55f
-
-	addq	$cond_nwaiters, %rdi
-	LP_OP(cmp) $-1, dep_mutex-cond_nwaiters(%rdi)
-	movl	$1, %edx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAKE, %eax
-	movl	$(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
-	cmove	%eax, %esi
-#else
-	movl	$0, %eax
-	movl	%fs:PRIVATE_FUTEX, %esi
-	cmove	%eax, %esi
-	orl	$FUTEX_WAKE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	syscall
-	subq	$cond_nwaiters, %rdi
-
-55:	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	jne	40f
-
-	/* If requeue_pi is used the kernel performs the locking of the
-	   mutex. */
-41:	movq	16(%rsp), %rdi
-	testb	%r15b, %r15b
-	jnz	64f
-
-	callq	__pthread_mutex_cond_lock
-
-63:	testq	%rax, %rax
-	cmoveq	%r14, %rax
-
-48:	addq	$FRAME_SIZE, %rsp
-	cfi_adjust_cfa_offset(-FRAME_SIZE)
-	popq	%r15
-	cfi_adjust_cfa_offset(-8)
-	cfi_restore(%r15)
-	popq	%r14
-	cfi_adjust_cfa_offset(-8)
-	cfi_restore(%r14)
-	popq	%r13
-	cfi_adjust_cfa_offset(-8)
-	cfi_restore(%r13)
-	popq	%r12
-	cfi_adjust_cfa_offset(-8)
-	cfi_restore(%r12)
-
-	retq
-
-	cfi_restore_state
-
-64:	callq	__pthread_mutex_cond_lock_adjust
-	movq	%r14, %rax
-	jmp	48b
-
-	/* Initial locking failed.  */
-31:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-	jmp	32b
-
-	/* Unlock in loop requires wakeup.  */
-33:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-	jmp	34b
-
-	/* Locking in loop failed.  */
-35:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-#if cond_lock != 0
-	subq	$cond_lock, %rdi
-#endif
-	jmp	36b
-
-	/* Unlock after loop requires wakeup.  */
-40:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-	jmp	41b
-
-	/* The initial unlocking of the mutex failed.  */
-46:	movq	8(%rsp), %rdi
-	movq	%rax, (%rsp)
-	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	jne	47f
-
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-
-47:	movq	(%rsp), %rax
-	jmp	48b
-
-	.size	__pthread_cond_timedwait, .-__pthread_cond_timedwait
-versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
-		  GLIBC_2_3_2)
-
-
-	.align	16
-	.type	__condvar_cleanup2, @function
-__condvar_cleanup2:
-	/* Stack frame:
-
-	   rsp + 72
-		    +--------------------------+
-	   rsp + 64 | %r12                     |
-		    +--------------------------+
-	   rsp + 56 | %r13                     |
-		    +--------------------------+
-	   rsp + 48 | %r14                     |
-		    +--------------------------+
-	   rsp + 24 | unused                   |
-		    +--------------------------+
-	   rsp + 16 | mutex pointer            |
-		    +--------------------------+
-	   rsp +  8 | condvar pointer          |
-		    +--------------------------+
-	   rsp +  4 | old broadcast_seq value  |
-		    +--------------------------+
-	   rsp +  0 | old cancellation mode    |
-		    +--------------------------+
-	*/
-
-	movq	%rax, 24(%rsp)
-
-	/* Get internal lock.  */
-	movq	8(%rsp), %rdi
-	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jz	1f
-
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-#if cond_lock != 0
-	subq	$cond_lock, %rdi
-#endif
-
-1:	movl	broadcast_seq(%rdi), %edx
-	cmpl	4(%rsp), %edx
-	jne	3f
-
-	/* We increment the wakeup_seq counter only if it is lower than
-	   total_seq.  If this is not the case the thread was woken and
-	   then canceled.  In this case we ignore the signal.  */
-	movq	total_seq(%rdi), %rax
-	cmpq	wakeup_seq(%rdi), %rax
-	jbe	6f
-	incq	wakeup_seq(%rdi)
-	incl	cond_futex(%rdi)
-6:	incq	woken_seq(%rdi)
-
-3:	subl	$(1 << nwaiters_shift), cond_nwaiters(%rdi)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	xorq	%r12, %r12
-	cmpq	$0xffffffffffffffff, total_seq(%rdi)
-	jne	4f
-	movl	cond_nwaiters(%rdi), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	4f
-
-	LP_OP(cmp) $-1, dep_mutex(%rdi)
-	leaq	cond_nwaiters(%rdi), %rdi
-	movl	$1, %edx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAKE, %eax
-	movl	$(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
-	cmove	%eax, %esi
-#else
-	movl	$0, %eax
-	movl	%fs:PRIVATE_FUTEX, %esi
-	cmove	%eax, %esi
-	orl	$FUTEX_WAKE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	syscall
-	subq	$cond_nwaiters, %rdi
-	movl	$1, %r12d
-
-4:	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	je	2f
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-
-	/* Wake up all waiters to make sure no signal gets lost.  */
-2:	testq	%r12, %r12
-	jnz	5f
-	addq	$cond_futex, %rdi
-	LP_OP(cmp) $-1, dep_mutex-cond_futex(%rdi)
-	movl	$0x7fffffff, %edx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAKE, %eax
-	movl	$(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
-	cmove	%eax, %esi
-#else
-	movl	$0, %eax
-	movl	%fs:PRIVATE_FUTEX, %esi
-	cmove	%eax, %esi
-	orl	$FUTEX_WAKE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	syscall
-
-	/* Lock the mutex only if we don't own it already.  This only happens
-	   in case of PI mutexes, if we got cancelled after a successful
-	   return of the futex syscall and before disabling async
-	   cancellation.  */
-5:	movq	16(%rsp), %rdi
-	movl	MUTEX_KIND(%rdi), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	jne	7f
-
-	movl	(%rdi), %eax
-	andl	$TID_MASK, %eax
-	cmpl	%eax, %fs:TID
-	jne	7f
-	/* We managed to get the lock.  Fix it up before returning.  */
-	callq	__pthread_mutex_cond_lock_adjust
-	jmp	8f
-
-7:	callq	__pthread_mutex_cond_lock
-
-8:	movq	24(%rsp), %rdi
-	movq	FRAME_SIZE(%rsp), %r15
-	movq	FRAME_SIZE+8(%rsp), %r14
-	movq	FRAME_SIZE+16(%rsp), %r13
-	movq	FRAME_SIZE+24(%rsp), %r12
-.LcallUR:
-	call	_Unwind_Resume
-	hlt
-.LENDCODE:
-	cfi_endproc
-	.size	__condvar_cleanup2, .-__condvar_cleanup2
-
-
-	.section .gcc_except_table,"a",@progbits
-.LexceptSTART:
-	.byte	DW_EH_PE_omit			# @LPStart format
-	.byte	DW_EH_PE_omit			# @TType format
-	.byte	DW_EH_PE_uleb128		# call-site format
-	.uleb128 .Lcstend-.Lcstbegin
-.Lcstbegin:
-	.uleb128 .LcleanupSTART1-.LSTARTCODE
-	.uleb128 .LcleanupEND1-.LcleanupSTART1
-	.uleb128 __condvar_cleanup2-.LSTARTCODE
-	.uleb128  0
-	.uleb128 .LcallUR-.LSTARTCODE
-	.uleb128 .LENDCODE-.LcallUR
-	.uleb128 0
-	.uleb128  0
-.Lcstend:
-
-
-#ifdef SHARED
-	.hidden	DW.ref.__gcc_personality_v0
-	.weak	DW.ref.__gcc_personality_v0
-	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
-	.align	LP_SIZE
-	.type	DW.ref.__gcc_personality_v0, @object
-	.size	DW.ref.__gcc_personality_v0, LP_SIZE
-DW.ref.__gcc_personality_v0:
-	ASM_ADDR __gcc_personality_v0
-#endif
diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
deleted file mode 100644
index c82f37b..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
+++ /dev/null
@@ -1,555 +0,0 @@ 
-/* Copyright (C) 2002-2016 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-#include <lowlevellock.h>
-#include <lowlevelcond.h>
-#include <tcb-offsets.h>
-#include <pthread-pi-defines.h>
-#include <pthread-errnos.h>
-#include <stap-probe.h>
-
-#include <kernel-features.h>
-
-
-	.text
-
-/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */
-	.globl	__pthread_cond_wait
-	.type	__pthread_cond_wait, @function
-	.align	16
-__pthread_cond_wait:
-.LSTARTCODE:
-	cfi_startproc
-#ifdef SHARED
-	cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
-			DW.ref.__gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
-#else
-	cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
-#endif
-
-#define FRAME_SIZE (32+8)
-	leaq	-FRAME_SIZE(%rsp), %rsp
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-
-	/* Stack frame:
-
-	   rsp + 32
-		    +--------------------------+
-	   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    |
-		    +--------------------------+
-	*/
-
-	LIBC_PROBE (cond_wait, 2, %rdi, %rsi)
-
-	LP_OP(cmp) $-1, dep_mutex(%rdi)
-
-	/* Prepare structure passed to cancellation handler.  */
-	movq	%rdi, 8(%rsp)
-	movq	%rsi, 16(%rsp)
-
-	je	15f
-	mov	%RSI_LP, dep_mutex(%rdi)
-
-	/* Get internal lock.  */
-15:	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jne	1f
-
-	/* Unlock the mutex.  */
-2:	movq	16(%rsp), %rdi
-	xorl	%esi, %esi
-	callq	__pthread_mutex_unlock_usercnt
-
-	testl	%eax, %eax
-	jne	12f
-
-	movq	8(%rsp), %rdi
-	incq	total_seq(%rdi)
-	incl	cond_futex(%rdi)
-	addl	$(1 << nwaiters_shift), cond_nwaiters(%rdi)
-
-	/* Get and store current wakeup_seq value.  */
-	movq	8(%rsp), %rdi
-	movq	wakeup_seq(%rdi), %r9
-	movl	broadcast_seq(%rdi), %edx
-	movq	%r9, 24(%rsp)
-	movl	%edx, 4(%rsp)
-
-	/* Unlock.  */
-8:	movl	cond_futex(%rdi), %edx
-	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	jne	3f
-
-.LcleanupSTART:
-4:	callq	__pthread_enable_asynccancel
-	movl	%eax, (%rsp)
-
-	xorq	%r10, %r10
-	LP_OP(cmp) $-1, dep_mutex(%rdi)
-	leaq	cond_futex(%rdi), %rdi
-	movl	$FUTEX_WAIT, %esi
-	je	60f
-
-	mov	dep_mutex-cond_futex(%rdi), %R8_LP
-	/* Requeue to a non-robust PI mutex if the PI bit is set and
-	the robust bit is not set.  */
-	movl	MUTEX_KIND(%r8), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	jne	61f
-
-	movl	$(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
-	movl	$SYS_futex, %eax
-	syscall
-
-	cmpl	$0, %eax
-	sete	%r8b
-
-#ifdef __ASSUME_REQUEUE_PI
-	jmp	62f
-#else
-	je	62f
-
-	/* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns
-	   successfully, it has already locked the mutex for us and the
-	   pi_flag (%r8b) is set to denote that fact.  However, if another
-	   thread changed the futex value before we entered the wait, the
-	   syscall may return an EAGAIN and the mutex is not locked.  We go
-	   ahead with a success anyway since later we look at the pi_flag to
-	   decide if we got the mutex or not.  The sequence numbers then make
-	   sure that only one of the threads actually wake up.  We retry using
-	   normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal
-	   and PI futexes don't mix.
-
-	   Note that we don't check for EAGAIN specifically; we assume that the
-	   only other error the futex function could return is EAGAIN since
-	   anything else would mean an error in our function.  It is too
-	   expensive to do that check for every call (which is 	quite common in
-	   case of a large number of threads), so it has been skipped.  */
-	cmpl	$-ENOSYS, %eax
-	jne	62f
-
-# ifndef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAIT, %esi
-# endif
-#endif
-
-61:
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), %esi
-#else
-	orl	%fs:PRIVATE_FUTEX, %esi
-#endif
-60:	xorb	%r8b, %r8b
-	movl	$SYS_futex, %eax
-	syscall
-
-62:	movl	(%rsp), %edi
-	callq	__pthread_disable_asynccancel
-.LcleanupEND:
-
-	/* Lock.  */
-	movq	8(%rsp), %rdi
-	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jnz	5f
-
-6:	movl	broadcast_seq(%rdi), %edx
-
-	movq	woken_seq(%rdi), %rax
-
-	movq	wakeup_seq(%rdi), %r9
-
-	cmpl	4(%rsp), %edx
-	jne	16f
-
-	cmpq	24(%rsp), %r9
-	jbe	19f
-
-	cmpq	%rax, %r9
-	jna	19f
-
-	incq	woken_seq(%rdi)
-
-	/* Unlock */
-16:	subl	$(1 << nwaiters_shift), cond_nwaiters(%rdi)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	cmpq	$0xffffffffffffffff, total_seq(%rdi)
-	jne	17f
-	movl	cond_nwaiters(%rdi), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	17f
-
-	addq	$cond_nwaiters, %rdi
-	LP_OP(cmp) $-1, dep_mutex-cond_nwaiters(%rdi)
-	movl	$1, %edx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAKE, %eax
-	movl	$(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
-	cmove	%eax, %esi
-#else
-	movl	$0, %eax
-	movl	%fs:PRIVATE_FUTEX, %esi
-	cmove	%eax, %esi
-	orl	$FUTEX_WAKE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	syscall
-	subq	$cond_nwaiters, %rdi
-
-17:	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	jne	10f
-
-	/* If requeue_pi is used the kernel performs the locking of the
-	   mutex. */
-11:	movq	16(%rsp), %rdi
-	testb	%r8b, %r8b
-	jnz	18f
-
-	callq	__pthread_mutex_cond_lock
-
-14:	leaq	FRAME_SIZE(%rsp), %rsp
-	cfi_adjust_cfa_offset(-FRAME_SIZE)
-
-	/* We return the result of the mutex_lock operation.  */
-	retq
-
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-
-18:	callq	__pthread_mutex_cond_lock_adjust
-	xorl	%eax, %eax
-	jmp	14b
-
-	/* We need to go back to futex_wait.  If we're using requeue_pi, then
-	   release the mutex we had acquired and go back.  */
-19:	testb	%r8b, %r8b
-	jz	8b
-
-	/* Adjust the mutex values first and then unlock it.  The unlock
-	   should always succeed or else the kernel did not lock the mutex
-	   correctly.  */
-	movq	16(%rsp), %rdi
-	callq	__pthread_mutex_cond_lock_adjust
-	movq	%rdi, %r8
-	xorl	%esi, %esi
-	callq	__pthread_mutex_unlock_usercnt
-	/* Reload cond_var.  */
-	movq	8(%rsp), %rdi
-	jmp	8b
-
-	/* Initial locking failed.  */
-1:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-	jmp	2b
-
-	/* Unlock in loop requires wakeup.  */
-3:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	/* The call preserves %rdx.  */
-	callq	__lll_unlock_wake
-#if cond_lock != 0
-	subq	$cond_lock, %rdi
-#endif
-	jmp	4b
-
-	/* Locking in loop failed.  */
-5:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-#if cond_lock != 0
-	subq	$cond_lock, %rdi
-#endif
-	jmp	6b
-
-	/* Unlock after loop requires wakeup.  */
-10:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-	jmp	11b
-
-	/* The initial unlocking of the mutex failed.  */
-12:	movq	%rax, %r10
-	movq	8(%rsp), %rdi
-	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	je	13f
-
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-
-13:	movq	%r10, %rax
-	jmp	14b
-
-	.size	__pthread_cond_wait, .-__pthread_cond_wait
-versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
-		  GLIBC_2_3_2)
-
-
-	.align	16
-	.type	__condvar_cleanup1, @function
-	.globl	__condvar_cleanup1
-	.hidden	__condvar_cleanup1
-__condvar_cleanup1:
-	/* Stack frame:
-
-	   rsp + 32
-		    +--------------------------+
-	   rsp + 24 | unused                   |
-		    +--------------------------+
-	   rsp + 16 | mutex pointer            |
-		    +--------------------------+
-	   rsp +  8 | condvar pointer          |
-		    +--------------------------+
-	   rsp +  4 | old broadcast_seq value  |
-		    +--------------------------+
-	   rsp +  0 | old cancellation mode    |
-		    +--------------------------+
-	*/
-
-	movq	%rax, 24(%rsp)
-
-	/* Get internal lock.  */
-	movq	8(%rsp), %rdi
-	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jz	1f
-
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-#if cond_lock != 0
-	subq	$cond_lock, %rdi
-#endif
-
-1:	movl	broadcast_seq(%rdi), %edx
-	cmpl	4(%rsp), %edx
-	jne	3f
-
-	/* We increment the wakeup_seq counter only if it is lower than
-	   total_seq.  If this is not the case the thread was woken and
-	   then canceled.  In this case we ignore the signal.  */
-	movq	total_seq(%rdi), %rax
-	cmpq	wakeup_seq(%rdi), %rax
-	jbe	6f
-	incq	wakeup_seq(%rdi)
-	incl	cond_futex(%rdi)
-6:	incq	woken_seq(%rdi)
-
-3:	subl	$(1 << nwaiters_shift), cond_nwaiters(%rdi)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	xorl	%ecx, %ecx
-	cmpq	$0xffffffffffffffff, total_seq(%rdi)
-	jne	4f
-	movl	cond_nwaiters(%rdi), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	4f
-
-	LP_OP(cmp) $-1, dep_mutex(%rdi)
-	leaq	cond_nwaiters(%rdi), %rdi
-	movl	$1, %edx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAKE, %eax
-	movl	$(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
-	cmove	%eax, %esi
-#else
-	movl	$0, %eax
-	movl	%fs:PRIVATE_FUTEX, %esi
-	cmove	%eax, %esi
-	orl	$FUTEX_WAKE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	syscall
-	subq	$cond_nwaiters, %rdi
-	movl	$1, %ecx
-
-4:	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	je	2f
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	/* The call preserves %rcx.  */
-	callq	__lll_unlock_wake
-
-	/* Wake up all waiters to make sure no signal gets lost.  */
-2:	testl	%ecx, %ecx
-	jnz	5f
-	addq	$cond_futex, %rdi
-	LP_OP(cmp) $-1, dep_mutex-cond_futex(%rdi)
-	movl	$0x7fffffff, %edx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAKE, %eax
-	movl	$(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
-	cmove	%eax, %esi
-#else
-	movl	$0, %eax
-	movl	%fs:PRIVATE_FUTEX, %esi
-	cmove	%eax, %esi
-	orl	$FUTEX_WAKE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	syscall
-
-	/* Lock the mutex only if we don't own it already.  This only happens
-	   in case of PI mutexes, if we got cancelled after a successful
-	   return of the futex syscall and before disabling async
-	   cancellation.  */
-5:	movq	16(%rsp), %rdi
-	movl	MUTEX_KIND(%rdi), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	jne	7f
-
-	movl	(%rdi), %eax
-	andl	$TID_MASK, %eax
-	cmpl	%eax, %fs:TID
-	jne	7f
-	/* We managed to get the lock.  Fix it up before returning.  */
-	callq	__pthread_mutex_cond_lock_adjust
-	jmp	8f
-
-
-7:	callq	__pthread_mutex_cond_lock
-
-8:	movq	24(%rsp), %rdi
-.LcallUR:
-	call	_Unwind_Resume
-	hlt
-.LENDCODE:
-	cfi_endproc
-	.size	__condvar_cleanup1, .-__condvar_cleanup1
-
-
-	.section .gcc_except_table,"a",@progbits
-.LexceptSTART:
-	.byte	DW_EH_PE_omit			# @LPStart format
-	.byte	DW_EH_PE_omit			# @TType format
-	.byte	DW_EH_PE_uleb128		# call-site format
-	.uleb128 .Lcstend-.Lcstbegin
-.Lcstbegin:
-	.uleb128 .LcleanupSTART-.LSTARTCODE
-	.uleb128 .LcleanupEND-.LcleanupSTART
-	.uleb128 __condvar_cleanup1-.LSTARTCODE
-	.uleb128 0
-	.uleb128 .LcallUR-.LSTARTCODE
-	.uleb128 .LENDCODE-.LcallUR
-	.uleb128 0
-	.uleb128 0
-.Lcstend:
-
-
-#ifdef SHARED
-	.hidden	DW.ref.__gcc_personality_v0
-	.weak	DW.ref.__gcc_personality_v0
-	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
-	.align	LP_SIZE
-	.type	DW.ref.__gcc_personality_v0, @object
-	.size	DW.ref.__gcc_personality_v0, LP_SIZE
-DW.ref.__gcc_personality_v0:
-	ASM_ADDR __gcc_personality_v0
-#endif
diff --git a/sysdeps/x86/bits/pthreadtypes.h b/sysdeps/x86/bits/pthreadtypes.h
index 16b8f4f..3f23b48 100644
--- a/sysdeps/x86/bits/pthreadtypes.h
+++ b/sysdeps/x86/bits/pthreadtypes.h
@@ -140,14 +140,29 @@  typedef union
 {
   struct
   {
-    int __lock;
-    unsigned int __futex;
-    __extension__ unsigned long long int __total_seq;
-    __extension__ unsigned long long int __wakeup_seq;
-    __extension__ unsigned long long int __woken_seq;
-    void *__mutex;
-    unsigned int __nwaiters;
-    unsigned int __broadcast_seq;
+    __extension__ union
+    {
+      __extension__ unsigned long long int __wseq;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __wseq32;
+    };
+    __extension__ union
+    {
+      __extension__ unsigned long long int __g1_start;
+      struct {
+	unsigned int __low;
+	unsigned int __high;
+      } __g1_start32;
+    };
+    unsigned int __g_refs[2];
+    unsigned int __g_size[2];
+    unsigned int __g1_orig_size;
+    unsigned int __wrefs;
+    unsigned int __g_signals[2];
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
   } __data;
   char __size[__SIZEOF_PTHREAD_COND_T];
   __extension__ long long int __align;