summaryrefslogtreecommitdiff
path: root/libc/nptl
diff options
context:
space:
mode:
Diffstat (limited to 'libc/nptl')
-rw-r--r--libc/nptl/ChangeLog81
-rw-r--r--libc/nptl/Makefile13
-rw-r--r--libc/nptl/pthread_create.c4
-rw-r--r--libc/nptl/sysdeps/i386/tls.h2
-rwxr-xr-xlibc/nptl/sysdeps/pthread/configure120
-rw-r--r--libc/nptl/sysdeps/sparc/tls.h4
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S50
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S129
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h2
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h2
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c21
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h2
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h2
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h2
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h2
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S51
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S121
-rw-r--r--libc/nptl/sysdeps/x86_64/configure82
-rw-r--r--libc/nptl/tst-cancel24-static.cc1
-rw-r--r--libc/nptl/tst-cond-except.c108
-rw-r--r--libc/nptl/tst-cond24.c249
-rw-r--r--libc/nptl/tst-cond8-static.c1
-rw-r--r--libc/nptl/tst-mutex8-static.c1
-rw-r--r--libc/nptl/tst-mutexpi8-static.c1
-rw-r--r--libc/nptl/tst-sem11-static.c1
-rw-r--r--libc/nptl/tst-sem12-static.c1
26 files changed, 659 insertions, 394 deletions
diff --git a/libc/nptl/ChangeLog b/libc/nptl/ChangeLog
index 217693250..9eeeeb1bd 100644
--- a/libc/nptl/ChangeLog
+++ b/libc/nptl/ChangeLog
@@ -1,3 +1,84 @@
+2012-10-09 Roland McGrath <roland@hack.frob.com>
+
+ * sysdeps/pthread/configure: Regenerated.
+ * sysdeps/x86_64/configure: Regenerated.
+
+2012-10-05 David S. Miller <davem@davemloft.net>
+
+ [BZ #14568]
+ * sysdeps/sparc/tls.h (DB_THREAD_SELF_INCLUDE): Delete.
+ (DB_THREAD_SELF): Use constants for the register offsets. Correct
+ the case of a 64-bit debugger with a 32-bit inferior.
+
+2012-10-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ [BZ #14557]
+ * Makefile (tests-static): Add tst-cancel24-static,
+ tst-cond8-static tst-mutex8-static, tst-mutexpi8-static,
+ tst-sem11-static and tst-sem12-static.
+ (tests): Likewise.
+ (LDLIBS-tst-cancel24-static): New macro.
+ * tst-cancel24-static.cc: New file.
+ * tst-cond8-static.c: Likewise.
+ * tst-mutex8-static.c: Likewise.
+ * tst-mutexpi8-static.c: Likewise.
+ * tst-sem11-static.c: Likewise.
+ * tst-sem12-static.c: Likewise.
+
+2012-10-05 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ [BZ #14417]
+ * Makefile (tests): New test case tst-cond24.
+ (LDFLAGS-tst-cond24): Link tst-cond24 against librt.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait): Unlock mutex before going back to
+ wait in PI case.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
+ (__pthread_cond_wait): Likewise. Revert handling of EAGAIN
+ return from futex_wait.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait): Unlock mutex before going back to
+ wait in PI case. Set requeue_pi flag only if wait returned 0.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
+ (__pthread_cond_wait): Likewise. Revert handling of EAGAIN
+ return from futex_wait.
+ * tst-cond24.c: New test case.
+
+2012-10-04 Roland McGrath <roland@hack.frob.com>
+
+ * pthread_create.c (start_thread): Use __madvise, not madvise.
+
+2012-10-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/i386/tls.h: Update copyright years.
+
+2012-10-02 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * pthread_create.c (start_thread): Fix clone flag name in
+ comment to CLONE_CHILD_CLEARTID.
+ * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Likewise.
+ * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise.
+ * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise.
+ * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Likewise.
+ * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise.
+
+2012-10-01 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ [BZ #14477]
+ * Makefile (tests): Add tst-cond-except.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait): Mark instructions where %ebx is
+ incremented in PI case.
+ (.gcc_except_table): Add entry to jump to __condvar_tw_cleanup2
+ for the marked PI case instructions.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
+ (__pthread_cond_wait): Mark instructions where %ebx is
+ incremented in PI case.
+ (.gcc_except_table): Add entry to jump to __condvar_w_cleanup2
+ for the marked PI case instructions.
+ * tst-cond-except.c: New test case.
+
2012-09-24 Dmitry V. Levin <ldv@altlinux.org>
* tst-tls6.sh: Add "set -e".
diff --git a/libc/nptl/Makefile b/libc/nptl/Makefile
index 5d781e206..47752f090 100644
--- a/libc/nptl/Makefile
+++ b/libc/nptl/Makefile
@@ -210,7 +210,8 @@ tests = tst-typesizes \
tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
- tst-cond20 tst-cond21 tst-cond22 tst-cond23 \
+ tst-cond20 tst-cond21 tst-cond22 tst-cond23 tst-cond24 \
+ tst-cond-except \
tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \
tst-robust6 tst-robust7 tst-robust8 tst-robust9 \
tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 tst-robustpi5 \
@@ -288,6 +289,7 @@ gen-as-const-headers = pthread-errnos.sym
LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst
+LDFLAGS-tst-cond24 = -lrt
include ../Makeconfig
@@ -368,8 +370,12 @@ link-libc-static := $(common-objpfx)libc.a $(static-gnulib) \
$(common-objpfx)libc.a
tests-static += tst-locale1 tst-locale2 tst-stackguard1-static \
- tst-cancel21-static
-tests += tst-stackguard1-static tst-cancel21-static
+ tst-cancel21-static tst-cancel24-static tst-cond8-static \
+ tst-mutex8-static tst-mutexpi8-static tst-sem11-static \
+ tst-sem12-static
+tests += tst-stackguard1-static tst-cancel21-static tst-cancel24-static \
+ tst-cond8-static tst-mutex8-static tst-mutexpi8-static \
+ tst-sem11-static tst-sem12-static
xtests-static += tst-setuid1-static
# These tests are linked with libc before libpthread
@@ -528,6 +534,7 @@ $(objpfx)tst-rwlock14: $(common-objpfx)rt/librt.a
endif
LDLIBS-tst-cancel24 = $(no-as-needed) -lstdc++
+LDLIBS-tst-cancel24-static = $(LDLIBS-tst-cancel24)
extra-B-pthread.so = -B$(common-objpfx)nptl/
$(objpfx)libpthread.so: $(addprefix $(objpfx),$(crti-objs) $(crtn-objs))
diff --git a/libc/nptl/pthread_create.c b/libc/nptl/pthread_create.c
index 96ca51f4e..44181ea39 100644
--- a/libc/nptl/pthread_create.c
+++ b/libc/nptl/pthread_create.c
@@ -404,7 +404,7 @@ start_thread (void *arg)
#endif
assert (freesize < pd->stackblock_size);
if (freesize > PTHREAD_STACK_MIN)
- madvise (pd->stackblock, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED);
+ __madvise (pd->stackblock, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED);
/* If the thread is detached free the TCB. */
if (IS_DETACHED (pd))
@@ -425,7 +425,7 @@ start_thread (void *arg)
/* We cannot call '_exit' here. '_exit' will terminate the process.
The 'exit' implementation in the kernel will signal when the
- process is really dead since 'clone' got passed the CLONE_CLEARTID
+ process is really dead since 'clone' got passed the CLONE_CHILD_CLEARTID
flag. The 'tid' field in the TCB will be set to zero.
The exit code is zero since in case all threads exit by calling
diff --git a/libc/nptl/sysdeps/i386/tls.h b/libc/nptl/sysdeps/i386/tls.h
index 65497cf92..eb1ca312f 100644
--- a/libc/nptl/sysdeps/i386/tls.h
+++ b/libc/nptl/sysdeps/i386/tls.h
@@ -1,5 +1,5 @@
/* Definition for thread-local data handling. nptl/i386 version.
- Copyright (C) 2002-2007, 2009, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2002-2012 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
diff --git a/libc/nptl/sysdeps/pthread/configure b/libc/nptl/sysdeps/pthread/configure
index 221ce9bbb..7962ed6fc 100755
--- a/libc/nptl/sysdeps/pthread/configure
+++ b/libc/nptl/sysdeps/pthread/configure
@@ -1,123 +1,3 @@
-
-# as_fn_set_status STATUS
-# -----------------------
-# Set $? to STATUS, without forking.
-as_fn_set_status ()
-{
- return $1
-} # as_fn_set_status
-
-# as_fn_exit STATUS
-# -----------------
-# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
-as_fn_exit ()
-{
- set +e
- as_fn_set_status $1
- exit $1
-} # as_fn_exit
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{
- s//\1/
- q
- }
- /^X\/\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\/\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
-
-
- as_lineno_1=$LINENO as_lineno_1a=$LINENO
- as_lineno_2=$LINENO as_lineno_2a=$LINENO
- eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
- test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
- # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
- sed -n '
- p
- /[$]LINENO/=
- ' <$as_myself |
- sed '
- s/[$]LINENO.*/&-/
- t lineno
- b
- :lineno
- N
- :loop
- s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
- t loop
- s/-\n.*//
- ' >$as_me.lineno &&
- chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
-
- # Don't try to exec as it changes $[0], causing all sort of problems
- # (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensitive to this).
- . "./$as_me.lineno"
- # Exit status is that of the last command.
- exit
-}
-
-
-# ac_fn_c_try_compile LINENO
-# --------------------------
-# Try to compile conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_compile ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
- if { { ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_compile") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_compile
# This file is generated from configure.in by Autoconf. DO NOT EDIT!
if test "x$libc_cv_gcc___thread" != xyes; then
diff --git a/libc/nptl/sysdeps/sparc/tls.h b/libc/nptl/sysdeps/sparc/tls.h
index 61cb09f29..cfc9d96c6 100644
--- a/libc/nptl/sysdeps/sparc/tls.h
+++ b/libc/nptl/sysdeps/sparc/tls.h
@@ -117,9 +117,9 @@ register struct pthread *__thread_self __asm__("%g7");
#define THREAD_SELF __thread_self
/* Magic for libthread_db to know how to do THREAD_SELF. */
-# define DB_THREAD_SELF_INCLUDE <sys/ucontext.h>
# define DB_THREAD_SELF \
- REGISTER (32, 32, REG_G7 * 4, 0) REGISTER (64, 64, REG_G7 * 8, 0)
+ REGISTER (32, 32, 10 * 4, 0) \
+ REGISTER (64, __WORDSIZE, (6 * 8) + (__WORDSIZE==64?0:4), 0)
/* Access to data in the thread descriptor is easy. */
#define THREAD_GETMEM(descr, member) \
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
index 5f1fd5ddc..6761c136e 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+++ b/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
@@ -200,9 +200,11 @@ __pthread_cond_timedwait:
42: leal (%ebp), %esi
movl 28(%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. */
@@ -210,8 +212,23 @@ __pthread_cond_timedwait:
sete 24(%esp)
je 41f
- /* Normal and PI futexes dont mix. Use normal futex functions only
- if the kernel does not support the PI futex functions. */
+ /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns
+ successfully, it has already locked the mutex for us and the
+ pi_flag (24(%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
@@ -271,9 +288,24 @@ __pthread_cond_timedwait:
jne 9f
15: cmpl $-ETIMEDOUT, %esi
- jne 8b
+ 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 24(%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
+ xorl %edx, %edx
+ call __pthread_mutex_unlock_usercnt
+ jmp 8b
- addl $1, wakeup_seq(%ebx)
+28: addl $1, wakeup_seq(%ebx)
adcl $0, wakeup_seq+4(%ebx)
addl $1, cond_futex(%ebx)
movl $ETIMEDOUT, %esi
@@ -638,7 +670,15 @@ __condvar_tw_cleanup:
.uleb128 .Lcstend-.Lcstbegin
.Lcstbegin:
.long .LcleanupSTART-.LSTARTCODE
- .long .Ladd_cond_futex-.LcleanupSTART
+ .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
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
index 2ae7af261..0af06acad 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
+++ b/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
@@ -136,25 +136,37 @@ __pthread_cond_wait:
cmpl $PI_BIT, %eax
jne 18f
-90:
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
- cmpl $-EAGAIN, %eax
- je 91f
-
- /* Normal and PI futexes dont mix. Use normal futex functions only
- if the kernel does not support the PI futex functions. */
+ /* 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
@@ -204,12 +216,12 @@ __pthread_cond_wait:
cmpl 8(%esp), %edx
jne 7f
cmpl 4(%esp), %edi
- je 8b
+ je 22f
7: cmpl %ecx, %edx
jne 9f
cmp %eax, %edi
- je 8b
+ je 22f
9: addl $1, woken_seq(%ebx)
adcl $0, woken_seq+4(%ebx)
@@ -285,6 +297,22 @@ __pthread_cond_wait:
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
+ xorl %edx, %edx
+ call __pthread_mutex_unlock_usercnt
+ jmp 8b
+
/* Initial locking failed. */
1:
#if cond_lock == 0
@@ -398,77 +426,6 @@ __pthread_cond_wait:
call __lll_unlock_wake
jmp 11b
-91:
-.LcleanupSTART2:
- /* FUTEX_WAIT_REQUEUE_PI returned EAGAIN. We need to
- call it again. */
-
- /* 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 92f
-
-#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
-
-92:
- /* Increment the cond_futex value again, so it can be used as a new
- expected value. */
- addl $1, cond_futex(%ebx)
- movl cond_futex(%ebx), %ebp
-
- /* Unlock. */
- LOCK
-#if cond_lock == 0
- subl $1, (%ebx)
-#else
- subl $1, cond_lock(%ebx)
-#endif
- je 93f
-#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
-
-93:
- /* Set the rest of SYS_futex args for FUTEX_WAIT_REQUEUE_PI. */
- xorl %ecx, %ecx
- movl dep_mutex(%ebx), %edi
- jmp 90b
-.LcleanupEND2:
-
.size __pthread_cond_wait, .-__pthread_cond_wait
versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
GLIBC_2_3_2)
@@ -630,7 +587,15 @@ __condvar_w_cleanup:
.uleb128 .Lcstend-.Lcstbegin
.Lcstbegin:
.long .LcleanupSTART-.LSTARTCODE
- .long .Ladd_cond_futex-.LcleanupSTART
+ .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
@@ -641,10 +606,6 @@ __condvar_w_cleanup:
.long .LcleanupEND-.Lsub_cond_futex
.long __condvar_w_cleanup-.LSTARTCODE
.uleb128 0
- .long .LcleanupSTART2-.LSTARTCODE
- .long .LcleanupEND2-.LcleanupSTART2
- .long __condvar_w_cleanup-.LSTARTCODE
- .uleb128 0
.long .LcallUR-.LSTARTCODE
.long .LENDCODE-.LcallUR
.long 0
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
index 3d805ff43..7b576ca00 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
+++ b/libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
@@ -544,7 +544,7 @@ LLL_STUB_UNWIND_INFO_END
#define lll_islocked(futex) \
(futex != LLL_LOCK_INITIALIZER)
-/* The kernel notifies a process with uses CLONE_CLEARTID via futex
+/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
wakeup when the clone terminates. The memory location contains the
thread ID while the clone is running and is reset to zero
afterwards.
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h b/libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
index 234e04234..406c290d7 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
+++ b/libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
@@ -288,7 +288,7 @@ extern int __lll_robust_timedlock_wait
1 - taken by one user
>1 - taken by more users */
-/* The kernel notifies a process which uses CLONE_CLEARTID via futex
+/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
wakeup when the clone terminates. The memory location contains the
thread ID while the clone is running and is reset to zero
afterwards. */
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c b/libc/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c
index 4e3d7bd49..52ab53f0a 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c
+++ b/libc/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c
@@ -28,6 +28,7 @@ clear_once_control (void *arg)
{
pthread_once_t *once_control = (pthread_once_t *) arg;
+ __asm __volatile (__lll_rel_instr);
*once_control = 0;
lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
}
@@ -47,15 +48,15 @@ __pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
oldval = *once_control;
if ((oldval & 2) == 0)
*once_control = newval;
- Do this atomically.
+ Do this atomically with an acquire barrier.
*/
newval = __fork_generation | 1;
- __asm __volatile ("1: lwarx %0,0,%3\n"
+ __asm __volatile ("1: lwarx %0,0,%3" MUTEX_HINT_ACQ "\n"
" andi. %1,%0,2\n"
" bne 2f\n"
" stwcx. %4,0,%3\n"
" bne 1b\n"
- "2: isync"
+ "2: " __lll_acq_instr
: "=&r" (oldval), "=&r" (tmp), "=m" (*once_control)
: "r" (once_control), "r" (newval), "m" (*once_control)
: "cr0");
@@ -87,8 +88,18 @@ __pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
pthread_cleanup_pop (0);
- /* Add one to *once_control to take the bottom 2 bits from 01 to 10. */
- atomic_increment (once_control);
+ /* Add one to *once_control to take the bottom 2 bits from 01 to 10.
+ A release barrier is needed to ensure memory written by init_routine
+ is seen in other threads before *once_control changes. */
+ int tmp;
+ __asm __volatile (__lll_rel_instr "\n"
+ "1: lwarx %0,0,%2" MUTEX_HINT_REL "\n"
+ " addi %0,%0,1\n"
+ " stwcx. %0,0,%2\n"
+ " bne- 1b"
+ : "=&b" (tmp), "=m" (*once_control)
+ : "r" (once_control), "m" (*once_control)
+ : "cr0");
/* Wake up all other threads. */
lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h b/libc/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
index eeb7a72e2..97092823d 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
+++ b/libc/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
@@ -329,7 +329,7 @@ __lll_robust_timedlock (int *futex, const struct timespec *abstime,
#define LLL_LOCK_INITIALIZER (0)
#define LLL_LOCK_INITIALIZER_LOCKED (1)
-/* The kernel notifies a process with uses CLONE_CLEARTID via futex
+/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
wakeup when the clone terminates. The memory location contains the
thread ID while the clone is running and is reset to zero
afterwards. */
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h b/libc/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h
index f3ef3883a..cfd8d0cec 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h
+++ b/libc/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h
@@ -389,7 +389,7 @@ extern int __lll_unlock_wake (int *__futex, int private) attribute_hidden;
#define lll_islocked(futex) \
(futex != LLL_LOCK_INITIALIZER)
-/* The kernel notifies a process with uses CLONE_CLEARTID via futex
+/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
wakeup when the clone terminates. The memory location contains the
thread ID while the clone is running and is reset to zero
afterwards. */
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/libc/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
index 73c3327c0..fafb0873f 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
+++ b/libc/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
@@ -268,7 +268,7 @@ __lll_robust_timedlock (int *futex, const struct timespec *abstime,
#define LLL_LOCK_INITIALIZER (0)
#define LLL_LOCK_INITIALIZER_LOCKED (1)
-/* The kernel notifies a process with uses CLONE_CLEARTID via futex
+/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
wakeup when the clone terminates. The memory location contains the
thread ID while the clone is running and is reset to zero
afterwards. */
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
index 3686970f0..5a80ddd8e 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
+++ b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
@@ -560,7 +560,7 @@ LLL_STUB_UNWIND_INFO_END
(futex != LLL_LOCK_INITIALIZER)
-/* The kernel notifies a process with uses CLONE_CLEARTID via futex
+/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
wakeup when the clone terminates. The memory location contains the
thread ID while the clone is running and is reset to zero
afterwards.
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
index a1c8ca87b..b669abb57 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+++ b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
@@ -103,7 +103,7 @@ __pthread_cond_timedwait:
mov %RSI_LP, dep_mutex(%rdi)
22:
- xorl %r15d, %r15d
+ xorb %r15b, %r15b
#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
# ifdef PIC
@@ -190,18 +190,39 @@ __pthread_cond_timedwait:
movl $SYS_futex, %eax
syscall
- movl $1, %r15d
+ cmpl $0, %eax
+ sete %r15b
+
#ifdef __ASSUME_REQUEUE_PI
jmp 62f
#else
- cmpq $-4095, %rax
- jnae 62f
+ 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: xorl %r15d, %r15d
+60: xorb %r15b, %r15b
xorl %eax, %eax
/* The following only works like this because we only support
two clocks, represented using a single bit. */
@@ -248,7 +269,23 @@ __pthread_cond_timedwait:
ja 39f
45: cmpq $-ETIMEDOUT, %r14
- jne 38b
+ 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)
@@ -298,7 +335,7 @@ __pthread_cond_timedwait:
/* If requeue_pi is used the kernel performs the locking of the
mutex. */
41: movq 16(%rsp), %rdi
- testl %r15d, %r15d
+ testb %r15b, %r15b
jnz 64f
callq __pthread_mutex_cond_lock
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
index 61948523a..ec403cd9b 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
+++ b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
@@ -136,19 +136,36 @@ __pthread_cond_wait:
cmpl $PI_BIT, %eax
jne 61f
-90:
movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
movl $SYS_futex, %eax
syscall
- movl $1, %r8d
- cmpq $-EAGAIN, %rax
- je 91f
+ cmpl $0, %eax
+ sete %r8b
+
#ifdef __ASSUME_REQUEUE_PI
jmp 62f
#else
- cmpq $-4095, %rax
- jnae 62f
+ 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
@@ -161,7 +178,7 @@ __pthread_cond_wait:
#else
orl %fs:PRIVATE_FUTEX, %esi
#endif
-60: xorl %r8d, %r8d
+60: xorb %r8b, %r8b
movl $SYS_futex, %eax
syscall
@@ -191,10 +208,10 @@ __pthread_cond_wait:
jne 16f
cmpq 24(%rsp), %r9
- jbe 8b
+ jbe 19f
cmpq %rax, %r9
- jna 8b
+ jna 19f
incq woken_seq(%rdi)
@@ -236,7 +253,7 @@ __pthread_cond_wait:
/* If requeue_pi is used the kernel performs the locking of the
mutex. */
11: movq 16(%rsp), %rdi
- testl %r8d, %r8d
+ testb %r8b, %r8b
jnz 18f
callq __pthread_mutex_cond_lock
@@ -253,6 +270,23 @@ __pthread_cond_wait:
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
@@ -331,69 +365,6 @@ __pthread_cond_wait:
13: movq %r10, %rax
jmp 14b
-91:
-.LcleanupSTART2:
- /* FUTEX_WAIT_REQUEUE_PI returned EAGAIN. We need to
- call it again. */
- movq 8(%rsp), %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
- jz 92f
-
-#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
-92:
- /* Increment the cond_futex value again, so it can be used as a new
- expected value. */
- incl cond_futex(%rdi)
- movl cond_futex(%rdi), %edx
-
- /* Release internal lock. */
- LOCK
-#if cond_lock == 0
- decl (%rdi)
-#else
- decl cond_lock(%rdi)
-#endif
- jz 93f
-
-#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
-93:
- /* Set the rest of SYS_futex args for FUTEX_WAIT_REQUEUE_PI. */
- xorq %r10, %r10
- mov dep_mutex(%rdi), %R8_LP
- leaq cond_futex(%rdi), %rdi
- jmp 90b
-.LcleanupEND2:
-
.size __pthread_cond_wait, .-__pthread_cond_wait
versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
GLIBC_2_3_2)
@@ -547,10 +518,6 @@ __condvar_cleanup1:
.uleb128 .LcleanupEND-.LcleanupSTART
.uleb128 __condvar_cleanup1-.LSTARTCODE
.uleb128 0
- .uleb128 .LcleanupSTART2-.LSTARTCODE
- .uleb128 .LcleanupEND2-.LcleanupSTART2
- .uleb128 __condvar_cleanup1-.LSTARTCODE
- .uleb128 0
.uleb128 .LcallUR-.LSTARTCODE
.uleb128 .LENDCODE-.LcallUR
.uleb128 0
diff --git a/libc/nptl/sysdeps/x86_64/configure b/libc/nptl/sysdeps/x86_64/configure
index ee047153c..8e5bcacaf 100644
--- a/libc/nptl/sysdeps/x86_64/configure
+++ b/libc/nptl/sysdeps/x86_64/configure
@@ -1,85 +1,3 @@
-
-# as_fn_set_status STATUS
-# -----------------------
-# Set $? to STATUS, without forking.
-as_fn_set_status ()
-{
- return $1
-} # as_fn_set_status
-
-# as_fn_exit STATUS
-# -----------------
-# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
-as_fn_exit ()
-{
- set +e
- as_fn_set_status $1
- exit $1
-} # as_fn_exit
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{
- s//\1/
- q
- }
- /^X\/\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\/\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
-
-
- as_lineno_1=$LINENO as_lineno_1a=$LINENO
- as_lineno_2=$LINENO as_lineno_2a=$LINENO
- eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
- test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
- # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
- sed -n '
- p
- /[$]LINENO/=
- ' <$as_myself |
- sed '
- s/[$]LINENO.*/&-/
- t lineno
- b
- :lineno
- N
- :loop
- s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
- t loop
- s/-\n.*//
- ' >$as_me.lineno &&
- chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
-
- # Don't try to exec as it changes $[0], causing all sort of problems
- # (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensitive to this).
- . "./$as_me.lineno"
- # Exit status is that of the last command.
- exit
-}
-
# This file is generated from configure.in by Autoconf. DO NOT EDIT!
# Local configure fragment for sysdeps/i386.
diff --git a/libc/nptl/tst-cancel24-static.cc b/libc/nptl/tst-cancel24-static.cc
new file mode 100644
index 000000000..3f97de5d5
--- /dev/null
+++ b/libc/nptl/tst-cancel24-static.cc
@@ -0,0 +1 @@
+#include "tst-cancel24.cc"
diff --git a/libc/nptl/tst-cond-except.c b/libc/nptl/tst-cond-except.c
new file mode 100644
index 000000000..b9871ba86
--- /dev/null
+++ b/libc/nptl/tst-cond-except.c
@@ -0,0 +1,108 @@
+/* Verify that exception table for pthread_cond_wait is correct.
+ Copyright (C) 2012 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 <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+pthread_mutex_t mutex;
+pthread_cond_t cond;
+
+#define CHECK_RETURN_VAL_OR_FAIL(ret,str) \
+ ({ if ((ret) != 0) \
+ { \
+ printf ("%s failed: %s\n", (str), strerror (ret)); \
+ ret = 1; \
+ goto out; \
+ } \
+ })
+
+
+void
+clean (void *arg)
+{
+ puts ("clean: Unlocking mutex...");
+ pthread_mutex_unlock ((pthread_mutex_t *) arg);
+ puts ("clean: Mutex unlocked...");
+}
+
+void *
+thr (void *arg)
+{
+ int ret = 0;
+ pthread_mutexattr_t mutexAttr;
+ ret = pthread_mutexattr_init (&mutexAttr);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutexattr_init");
+
+ ret = pthread_mutexattr_setprotocol (&mutexAttr, PTHREAD_PRIO_INHERIT);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutexattr_setprotocol");
+
+ ret = pthread_mutex_init (&mutex, &mutexAttr);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutex_init");
+
+ ret = pthread_cond_init (&cond, 0);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cond_init");
+
+ puts ("th: Init done, entering wait...");
+
+ pthread_cleanup_push (clean, (void *) &mutex);
+ ret = pthread_mutex_lock (&mutex);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutex_lock");
+ while (1)
+ {
+ ret = pthread_cond_wait (&cond, &mutex);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cond_wait");
+ }
+ pthread_cleanup_pop (1);
+
+out:
+ return (void *)ret;
+}
+
+int
+do_test ()
+{
+ pthread_t thread;
+ int ret = 0;
+ void *thr_ret = 0;
+ ret = pthread_create (&thread, 0, thr, &thr_ret);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_create");
+
+ puts ("main: Thread created, waiting a bit...");
+ sleep (2);
+
+ puts ("main: Cancelling thread...");
+ ret = pthread_cancel (thread);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cancel");
+
+ puts ("main: Joining th...");
+ ret = pthread_join (thread, NULL);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_join");
+
+ if (thr_ret != NULL)
+ return 1;
+
+ puts ("main: Joined thread, done!");
+
+out:
+ return ret;
+}
+
+#define TIMEOUT 5
+#include "../test-skeleton.c"
diff --git a/libc/nptl/tst-cond24.c b/libc/nptl/tst-cond24.c
new file mode 100644
index 000000000..2eb2df1a3
--- /dev/null
+++ b/libc/nptl/tst-cond24.c
@@ -0,0 +1,249 @@
+/* Verify that condition variables synchronized by PI mutexes don't hang.
+ Copyright (C) 2012 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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define THREADS_NUM 5
+#define MAXITER 50000
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mutex_attr;
+static pthread_cond_t cond;
+static pthread_t threads[THREADS_NUM];
+static int pending = 0;
+
+typedef void * (*threadfunc) (void *);
+
+void *
+thread_fun_timed (void *arg)
+{
+ int *ret = arg;
+ int rv, i;
+
+ printf ("Started thread_fun_timed[%d]\n", *ret);
+
+ for (i = 0; i < MAXITER / THREADS_NUM; i++)
+ {
+ rv = pthread_mutex_lock (&mutex);
+ if (rv)
+ {
+ printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv);
+ *ret = 1;
+ goto out;
+ }
+
+ while (!pending)
+ {
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += 20;
+ rv = pthread_cond_timedwait (&cond, &mutex, &ts);
+
+ /* There should be no timeout either. */
+ if (rv)
+ {
+ printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv);
+ *ret = 1;
+ goto out;
+ }
+ }
+
+ pending--;
+
+ rv = pthread_mutex_unlock (&mutex);
+ if (rv)
+ {
+ printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv);
+ *ret = 1;
+ goto out;
+ }
+ }
+
+ *ret = 0;
+
+out:
+ return ret;
+}
+
+void *
+thread_fun (void *arg)
+{
+ int *ret = arg;
+ int rv, i;
+
+ printf ("Started thread_fun[%d]\n", *ret);
+
+ for (i = 0; i < MAXITER / THREADS_NUM; i++)
+ {
+ rv = pthread_mutex_lock (&mutex);
+ if (rv)
+ {
+ printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv);
+ *ret = 1;
+ goto out;
+ }
+
+ while (!pending)
+ {
+ rv = pthread_cond_wait (&cond, &mutex);
+
+ if (rv)
+ {
+ printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv);
+ *ret = 1;
+ goto out;
+ }
+ }
+
+ pending--;
+
+ rv = pthread_mutex_unlock (&mutex);
+ if (rv)
+ {
+ printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv);
+ *ret = 1;
+ goto out;
+ }
+ }
+
+ *ret = 0;
+
+out:
+ return ret;
+}
+
+static int
+do_test_wait (threadfunc f)
+{
+ int i;
+ int rv;
+ int counter = 0;
+ int retval[THREADS_NUM];
+
+ puts ("Starting test");
+
+ rv = pthread_mutexattr_init (&mutex_attr);
+ if (rv)
+ {
+ printf ("pthread_mutexattr_init: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+
+ rv = pthread_mutexattr_setprotocol (&mutex_attr, PTHREAD_PRIO_INHERIT);
+ if (rv)
+ {
+ printf ("pthread_mutexattr_setprotocol: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+
+ rv = pthread_mutex_init (&mutex, &mutex_attr);
+ if (rv)
+ {
+ printf ("pthread_mutex_init: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+
+ rv = pthread_cond_init (&cond, NULL);
+ if (rv)
+ {
+ printf ("pthread_cond_init: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+
+ for (i = 0; i < THREADS_NUM; i++)
+ {
+ retval[i] = i;
+ rv = pthread_create (&threads[i], NULL, f, &retval[i]);
+ if (rv)
+ {
+ printf ("pthread_create: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+ }
+
+ for (; counter < MAXITER; counter++)
+ {
+ rv = pthread_mutex_lock (&mutex);
+ if (rv)
+ {
+ printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+
+ if (!(counter % 100))
+ printf ("counter: %d\n", counter);
+ pending += 1;
+
+ rv = pthread_cond_signal (&cond);
+ if (rv)
+ {
+ printf ("pthread_cond_signal: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+
+ rv = pthread_mutex_unlock (&mutex);
+ if (rv)
+ {
+ printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+ }
+
+ for (i = 0; i < THREADS_NUM; i++)
+ {
+ void *ret;
+ rv = pthread_join (threads[i], &ret);
+ if (rv)
+ {
+ printf ("pthread_join: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+ if (ret && *(int *)ret)
+ {
+ printf ("Thread %d returned with an error\n", i);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+do_test (void)
+{
+ puts ("Testing pthread_cond_wait");
+ int ret = do_test_wait (thread_fun);
+ if (ret)
+ return ret;
+
+ puts ("Testing pthread_cond_timedwait");
+ return do_test_wait (thread_fun_timed);
+}
+
+#define TIMEOUT 10
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/libc/nptl/tst-cond8-static.c b/libc/nptl/tst-cond8-static.c
new file mode 100644
index 000000000..fed35db60
--- /dev/null
+++ b/libc/nptl/tst-cond8-static.c
@@ -0,0 +1 @@
+#include "tst-cond8.c"
diff --git a/libc/nptl/tst-mutex8-static.c b/libc/nptl/tst-mutex8-static.c
new file mode 100644
index 000000000..d69ed49ad
--- /dev/null
+++ b/libc/nptl/tst-mutex8-static.c
@@ -0,0 +1 @@
+#include "tst-mutex8.c"
diff --git a/libc/nptl/tst-mutexpi8-static.c b/libc/nptl/tst-mutexpi8-static.c
new file mode 100644
index 000000000..869e6df95
--- /dev/null
+++ b/libc/nptl/tst-mutexpi8-static.c
@@ -0,0 +1 @@
+#include "tst-mutexpi8.c"
diff --git a/libc/nptl/tst-sem11-static.c b/libc/nptl/tst-sem11-static.c
new file mode 100644
index 000000000..09b769807
--- /dev/null
+++ b/libc/nptl/tst-sem11-static.c
@@ -0,0 +1 @@
+#include "tst-sem11.c"
diff --git a/libc/nptl/tst-sem12-static.c b/libc/nptl/tst-sem12-static.c
new file mode 100644
index 000000000..c06349f2b
--- /dev/null
+++ b/libc/nptl/tst-sem12-static.c
@@ -0,0 +1 @@
+#include "tst-sem12.c"