|
|
ce426f |
commit c2f5813ae0a68f6c6d69e66dac2da6e46b9df034
|
|
|
ce426f |
Author: Joseph Myers <joseph@codesourcery.com>
|
|
|
ce426f |
Date: Wed Mar 18 17:05:38 2015 +0000
|
|
|
ce426f |
|
|
|
ce426f |
Make sem_timedwait use FUTEX_CLOCK_REALTIME (bug 18138).
|
|
|
ce426f |
|
|
|
ce426f |
sem_timedwait converts absolute timeouts to relative to pass them to
|
|
|
ce426f |
the futex syscall. (Before the recent reimplementation, on x86_64 it
|
|
|
ce426f |
used FUTEX_CLOCK_REALTIME, but not on other architectures.)
|
|
|
ce426f |
|
|
|
ce426f |
Correctly implementing POSIX requirements, however, requires use of
|
|
|
ce426f |
FUTEX_CLOCK_REALTIME; passing a relative timeout to the kernel does
|
|
|
ce426f |
not conform to POSIX. The POSIX specification for sem_timedwait says
|
|
|
ce426f |
"The timeout shall be based on the CLOCK_REALTIME clock.". The POSIX
|
|
|
ce426f |
specification for clock_settime says "If the value of the
|
|
|
ce426f |
CLOCK_REALTIME clock is set via clock_settime(), the new value of the
|
|
|
ce426f |
clock shall be used to determine the time of expiration for absolute
|
|
|
ce426f |
time services based upon the CLOCK_REALTIME clock. This applies to the
|
|
|
ce426f |
time at which armed absolute timers expire. If the absolute time
|
|
|
ce426f |
requested at the invocation of such a time service is before the new
|
|
|
ce426f |
value of the clock, the time service shall expire immediately as if
|
|
|
ce426f |
the clock had reached the requested time normally.". If a relative
|
|
|
ce426f |
timeout is passed to the kernel, it is interpreted according to the
|
|
|
ce426f |
CLOCK_MONOTONIC clock, and so fails to meet that POSIX requirement in
|
|
|
ce426f |
the event of clock changes.
|
|
|
ce426f |
|
|
|
ce426f |
This patch makes sem_timedwait use lll_futex_timed_wait_bitset with
|
|
|
ce426f |
FUTEX_CLOCK_REALTIME when possible, as done in some other places in
|
|
|
ce426f |
NPTL. FUTEX_CLOCK_REALTIME is always available for supported Linux
|
|
|
ce426f |
kernel versions; unavailability of lll_futex_timed_wait_bitset is only
|
|
|
ce426f |
an issue for hppa (an issue noted in
|
|
|
ce426f |
<https://sourceware.org/glibc/wiki/PortStatus>, and fixed by the
|
|
|
ce426f |
unreviewed
|
|
|
ce426f |
<https://sourceware.org/ml/libc-alpha/2014-12/msg00655.html> that
|
|
|
ce426f |
removes the hppa lowlevellock.h completely).
|
|
|
ce426f |
|
|
|
ce426f |
In the FUTEX_CLOCK_REALTIME case, the glibc code still needs to check
|
|
|
ce426f |
for negative tv_sec and handle that as timeout, because the Linux
|
|
|
ce426f |
kernel returns EINVAL not ETIMEDOUT for that case, so resulting in
|
|
|
ce426f |
failures of nptl/tst-abstime and nptl/tst-sem13 in the absence of that
|
|
|
ce426f |
check. If we're trying to distinguish between Linux-specific and
|
|
|
ce426f |
generic-futex NPTL code, I suppose having this in an nptl/ file isn't
|
|
|
ce426f |
ideal, but there doesn't seem to be any better place at present.
|
|
|
ce426f |
|
|
|
ce426f |
It's not possible to add a testcase for this issue to the testsuite
|
|
|
ce426f |
because of the requirement to change the system clock as part of a
|
|
|
ce426f |
test (this is a case where testing would require some form of
|
|
|
ce426f |
container, with root in that container, and one whose CLOCK_REALTIME
|
|
|
ce426f |
is isolated from that of the host; I'm not sure what forms of
|
|
|
ce426f |
containers, short of a full virtual machine, provide that clock
|
|
|
ce426f |
isolation).
|
|
|
ce426f |
|
|
|
ce426f |
Tested for x86_64. Also tested for powerpc with the testcase included
|
|
|
ce426f |
in the bug.
|
|
|
ce426f |
|
|
|
ce426f |
[BZ #18138]
|
|
|
ce426f |
* nptl/sem_waitcommon.c: Include <kernel-features.h>.
|
|
|
ce426f |
(futex_abstimed_wait)
|
|
|
ce426f |
[__ASSUME_FUTEX_CLOCK_REALTIME && lll_futex_timed_wait_bitset]:
|
|
|
ce426f |
Use lll_futex_timed_wait_bitset with FUTEX_CLOCK_REALTIME instead
|
|
|
ce426f |
of lll_futex_timed_wait.
|
|
|
ce426f |
|
|
|
ce426f |
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_waitcommon.c
|
|
|
ce426f |
===================================================================
|
|
|
ce426f |
--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/sem_waitcommon.c
|
|
|
ce426f |
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/sem_waitcommon.c
|
|
|
ce426f |
@@ -17,6 +17,7 @@
|
|
|
ce426f |
License along with the GNU C Library; if not, see
|
|
|
ce426f |
<http://www.gnu.org/licenses/>. */
|
|
|
ce426f |
|
|
|
ce426f |
+#include <kernel-features.h>
|
|
|
ce426f |
#include <errno.h>
|
|
|
ce426f |
#include <sysdep.h>
|
|
|
ce426f |
#include <lowlevellock.h>
|
|
|
ce426f |
@@ -45,6 +46,13 @@ futex_abstimed_wait (unsigned int* futex
|
|
|
ce426f |
}
|
|
|
ce426f |
else
|
|
|
ce426f |
{
|
|
|
ce426f |
+#if (defined __ASSUME_FUTEX_CLOCK_REALTIME \
|
|
|
ce426f |
+ && defined lll_futex_timed_wait_bitset)
|
|
|
ce426f |
+ /* The Linux kernel returns EINVAL for this, but in userspace
|
|
|
ce426f |
+ such a value is valid. */
|
|
|
ce426f |
+ if (abstime->tv_sec < 0)
|
|
|
ce426f |
+ return ETIMEDOUT;
|
|
|
ce426f |
+#else
|
|
|
ce426f |
struct timeval tv;
|
|
|
ce426f |
struct timespec rt;
|
|
|
ce426f |
int sec, nsec;
|
|
|
ce426f |
@@ -68,9 +76,16 @@ futex_abstimed_wait (unsigned int* futex
|
|
|
ce426f |
/* Do wait. */
|
|
|
ce426f |
rt.tv_sec = sec;
|
|
|
ce426f |
rt.tv_nsec = nsec;
|
|
|
ce426f |
+#endif
|
|
|
ce426f |
if (cancel)
|
|
|
ce426f |
oldtype = __pthread_enable_asynccancel ();
|
|
|
ce426f |
+#if (defined __ASSUME_FUTEX_CLOCK_REALTIME \
|
|
|
ce426f |
+ && defined lll_futex_timed_wait_bitset)
|
|
|
ce426f |
+ err = lll_futex_timed_wait_bitset (futex, expected, abstime,
|
|
|
ce426f |
+ FUTEX_CLOCK_REALTIME, private);
|
|
|
ce426f |
+#else
|
|
|
ce426f |
err = lll_futex_timed_wait (futex, expected, &rt, private);
|
|
|
ce426f |
+#endif
|
|
|
ce426f |
if (cancel)
|
|
|
ce426f |
__pthread_disable_asynccancel (oldtype);
|
|
|
ce426f |
}
|