This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] Fix generic __lll_robust_timedlock_wait to check for timeout (bug 20263)
- From: Andreas Schwab <schwab at suse dot de>
- To: libc-alpha at sourceware dot org
- Date: Mon, 20 Jun 2016 16:05:41 +0200
- Subject: [PATCH] Fix generic __lll_robust_timedlock_wait to check for timeout (bug 20263)
- Authentication-results: sourceware.org; auth=none
When commit 8f86154 added support for FUTEX_WAIT_BITSET it didn't add a
check for timeout from lll_futex_timed_wait_bitset in
__lll_robust_timedlock_wait. This only became a problem once glibc is
configured for kernel >= 2.6.29 (which is now always the case). Since
__ASSUME_FUTEX_CLOCK_REALTIME is now always defined the fallback code is
no longer needed. Tested on aarch64.
Andreas.
[BZ #20263]
* nptl/lowlevelrobustlock.c (__lll_robust_timedlock_wait): Check
for ETIMEDOUT or EINVAL.
[__ASSUME_FUTEX_CLOCK_REALTIME]: Remove conditional code.
* nptl/tst-robust10.c: New test.
* nptl/Makefile (tests): Add tst-robust10.
---
nptl/Makefile | 2 +-
nptl/lowlevelrobustlock.c | 34 ++------------
nptl/tst-robust10.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 115 insertions(+), 31 deletions(-)
create mode 100644 nptl/tst-robust10.c
diff --git a/nptl/Makefile b/nptl/Makefile
index e0bc1b7..28f6d5a 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -290,7 +290,7 @@ tests = tst-typesizes \
tst-initializers1 $(addprefix tst-initializers1-,\
c89 gnu89 c99 gnu99 c11 gnu11) \
tst-bad-schedattr \
- tst-thread_local1 tst-mutex-errorcheck
+ tst-thread_local1 tst-mutex-errorcheck tst-robust10
xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \
tst-mutexpp1 tst-mutexpp6 tst-mutexpp10
test-srcs = tst-oddstacklimit
diff --git a/nptl/lowlevelrobustlock.c b/nptl/lowlevelrobustlock.c
index 3b988b2..2083979 100644
--- a/nptl/lowlevelrobustlock.c
+++ b/nptl/lowlevelrobustlock.c
@@ -21,7 +21,6 @@
#include <lowlevellock.h>
#include <sys/time.h>
#include <pthreadP.h>
-#include <kernel-features.h>
int
@@ -81,28 +80,6 @@ __lll_robust_timedlock_wait (int *futex, const struct timespec *abstime,
do
{
-#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
- || !defined lll_futex_timed_wait_bitset)
- struct timeval tv;
- struct timespec rt;
-
- /* Get the current time. */
- (void) __gettimeofday (&tv, NULL);
-
- /* Compute relative timeout. */
- rt.tv_sec = abstime->tv_sec - tv.tv_sec;
- rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
- if (rt.tv_nsec < 0)
- {
- rt.tv_nsec += 1000000000;
- --rt.tv_sec;
- }
-
- /* Already timed out? */
- if (rt.tv_sec < 0)
- return ETIMEDOUT;
-#endif
-
/* If the owner died, return the present value of the futex. */
if (__glibc_unlikely (oldval & FUTEX_OWNER_DIED))
return oldval;
@@ -114,13 +91,10 @@ __lll_robust_timedlock_wait (int *futex, const struct timespec *abstime,
continue;
/* If *futex == 2, wait until woken or timeout. */
-#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
- || !defined lll_futex_timed_wait_bitset)
- lll_futex_timed_wait (futex, newval, &rt, private);
-#else
- lll_futex_timed_wait_bitset (futex, newval, abstime,
- FUTEX_CLOCK_REALTIME, private);
-#endif
+ int err = lll_futex_timed_wait_bitset (futex, newval, abstime,
+ FUTEX_CLOCK_REALTIME, private);
+ if (err == -ETIMEDOUT || err == -EINVAL)
+ return -err;
try:
;
diff --git a/nptl/tst-robust10.c b/nptl/tst-robust10.c
new file mode 100644
index 0000000..6d9e502
--- /dev/null
+++ b/nptl/tst-robust10.c
@@ -0,0 +1,110 @@
+/* Test that pthread_mutex_timedlock properly times out.
+ 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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+pthread_mutex_t mutex;
+
+static void *
+thr (void *arg)
+{
+ struct timespec abstime;
+ clock_gettime (CLOCK_REALTIME, &abstime);
+ abstime.tv_sec += 1;
+ int ret = pthread_mutex_timedlock (&mutex, &abstime);
+ if (ret == 0)
+ {
+ puts ("mutex_timedlock didn't fail");
+ exit (1);
+ }
+ if (ret != ETIMEDOUT)
+ {
+ printf ("mutex_timedlock failed: %s\n", strerror (ret));
+ exit (1);
+ }
+
+ return 0;
+}
+
+static int
+do_test (void)
+{
+ pthread_t pt;
+ pthread_mutexattr_t ma;
+
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 0;
+ }
+ if (pthread_mutexattr_setrobust_np (&ma, PTHREAD_MUTEX_ROBUST_NP) != 0)
+ {
+ puts ("mutexattr_setrobust failed");
+ return 1;
+ }
+ if (pthread_mutex_init (&mutex, &ma))
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_destroy (&ma))
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&mutex))
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_create (&pt, NULL, thr, NULL))
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ if (pthread_join (pt, NULL))
+ {
+ puts ("pthread_join failed");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (&mutex))
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (&mutex))
+ {
+ puts ("mutex_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--
2.9.0
--
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."