summary refs log tree commit diff
path: root/nptl
diff options
context:
space:
mode:
Diffstat (limited to 'nptl')
-rw-r--r--nptl/ChangeLog16
-rw-r--r--nptl/Makefile2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S12
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S12
-rw-r--r--nptl/tst-cond-except.c108
5 files changed, 147 insertions, 3 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 2176932501..7c673c0edb 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,19 @@
+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/nptl/Makefile b/nptl/Makefile
index b081b07955..b9c73b3898 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-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 \
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 5f1fd5ddc6..d14d7deb28 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
@@ -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.  */
@@ -638,7 +640,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/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
index 2ae7af2613..366de6938a 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
@@ -141,9 +141,11 @@ __pthread_cond_wait:
 	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
@@ -630,7 +632,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
diff --git a/nptl/tst-cond-except.c b/nptl/tst-cond-except.c
new file mode 100644
index 0000000000..b9871ba864
--- /dev/null
+++ b/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"