Release mutex before going back to wait for PI mutexes (#552960).
This commit is contained in:
parent
fab85b902e
commit
cdb17b58a8
|
@ -0,0 +1,724 @@
|
|||
diff --git a/nptl/Makefile b/nptl/Makefile
|
||||
index 6f2b66c..16ba845 100644
|
||||
--- a/nptl/Makefile
|
||||
+++ b/nptl/Makefile
|
||||
@@ -206,7 +206,7 @@ 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-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 \
|
||||
@@ -274,6 +274,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
|
||||
|
||||
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
|
||||
index 5f1fd5d..a2679ef 100644
|
||||
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
|
||||
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
|
||||
@@ -271,9 +271,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
|
||||
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
|
||||
index 2ae7af2..fe6a69c 100644
|
||||
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
|
||||
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
|
||||
@@ -136,7 +136,6 @@ __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
|
||||
@@ -150,9 +149,6 @@ __pthread_cond_wait:
|
||||
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. */
|
||||
cmpl $-ENOSYS, %eax
|
||||
@@ -204,12 +200,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 +281,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 +410,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)
|
||||
@@ -641,10 +582,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/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
|
||||
index a1c8ca8..21ccb7a 100644
|
||||
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
|
||||
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
|
||||
@@ -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,36 @@ __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
|
||||
+
|
||||
+ /* If we raced for the futex with someone else, the syscall may return
|
||||
+ an EAGAIN. Act as if you did a regular FUTEX_WAIT and returned
|
||||
+ successfully from it. Let the sequence numbers hold you back if
|
||||
+ you were not supposed to be woken up. That way, you don't forget
|
||||
+ to take the mutex lock on your way out. We retry using normal
|
||||
+ futex functions 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 +266,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 +332,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/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
|
||||
index 6194852..84c5fef 100644
|
||||
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
|
||||
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
|
||||
@@ -136,19 +136,33 @@ __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
|
||||
+
|
||||
+ /* If we raced for the futex with someone else, the syscall may return
|
||||
+ an EAGAIN. Act as if you did a regular FUTEX_WAIT and returned
|
||||
+ successfully from it. Let the sequence numbers hold you back if
|
||||
+ you were not supposed to be woken up. That way, you don't forget
|
||||
+ to take the mutex lock on your way out. We retry using normal
|
||||
+ futex functions 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 +175,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 +205,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 +250,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 +267,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 +362,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 +515,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/nptl/tst-cond24.c b/nptl/tst-cond24.c
|
||||
new file mode 100644
|
||||
index 0000000..2eb2df1
|
||||
--- /dev/null
|
||||
+++ b/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"
|
14
glibc.spec
14
glibc.spec
|
@ -27,7 +27,7 @@
|
|||
Summary: The GNU libc libraries
|
||||
Name: glibc
|
||||
Version: %{glibcversion}
|
||||
Release: 16%{?dist}
|
||||
Release: 17%{?dist}
|
||||
# GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries.
|
||||
# Things that are linked directly into dynamically linked programs
|
||||
# and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional
|
||||
|
@ -63,7 +63,8 @@ Patch0001: %{name}-stap.patch
|
|||
|
||||
# Reverting an upstream patch. I don't think this has been discussed
|
||||
# upstream yet.
|
||||
Patch0002: %{name}-rh769421.patch
|
||||
# rh552960 now does this and adds a real fix.
|
||||
# Patch0002: %{name}-rh769421.patch
|
||||
|
||||
# Not likely to be accepted upstream
|
||||
Patch0003: %{name}-rh787201.patch
|
||||
|
@ -195,6 +196,9 @@ Patch2028: %{name}-rh767693-2.patch
|
|||
# Upstream BZ 11438
|
||||
Patch2037: %{name}-fedora-gai-rfc1918.patch
|
||||
|
||||
# Upstream BZ 14417
|
||||
Patch2070: %{name}-rh552960.patch
|
||||
|
||||
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
Obsoletes: glibc-profile < 2.4
|
||||
Obsoletes: nss_db
|
||||
|
@ -419,7 +423,7 @@ package or when debugging this package.
|
|||
%setup -q -n %{glibcsrcdir} -b1
|
||||
|
||||
%patch0001 -E -p1
|
||||
%patch0002 -p1
|
||||
#%patch0002 -p1
|
||||
%patch0003 -p1
|
||||
%patch0004 -p1
|
||||
%patch0005 -p1
|
||||
|
@ -483,6 +487,7 @@ package or when debugging this package.
|
|||
%patch0066 -p1
|
||||
%patch0067 -p1
|
||||
%patch0069 -p1
|
||||
%patch2070 -p1
|
||||
|
||||
# On powerpc32, hp timing is only available in power4/power6
|
||||
# libs, not in base, so pre-power4 dynamic linker is incompatible
|
||||
|
@ -1277,6 +1282,9 @@ rm -f *.filelist*
|
|||
%endif
|
||||
|
||||
%changelog
|
||||
* Fri Sep 28 2012 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.16.90-17
|
||||
- Release mutex before going back to wait for PI mutexes (#552960).
|
||||
|
||||
* Tue Sep 25 2012 Jeff Law <law@redhat.com> - 2.16.90-16
|
||||
- Resync with upstream sources.
|
||||
|
||||
|
|
Loading…
Reference in New Issue