[RFC,2/3] nptl: Use futex_lock_pi2()
Checks
Context |
Check |
Description |
dj/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
Commit Message
Use futex_lock_pi2() by default, because it supports selectable clocks.
On older kernels futex_lock_pi2() will return ENOSYS. Fallback to
futex_lock_pi() and don't support CLOCK_MONOTONIC then.
Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
---
nptl/pthread_mutex_timedlock.c | 24 ++++++++++++++++++------
sysdeps/nptl/futex-internal.h | 17 +++++++++++++++++
2 files changed, 35 insertions(+), 6 deletions(-)
@@ -300,11 +300,15 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
{
- /* Currently futex FUTEX_LOCK_PI operation only provides support for
- CLOCK_REALTIME and trying to emulate by converting a
- CLOCK_MONOTONIC to CLOCK_REALTIME will take in account possible
- changes to the wall clock. */
- if (__glibc_unlikely (clockid != CLOCK_REALTIME))
+ /* Currently futex FUTEX_LOCK_PI operation only provides support for
+ CLOCK_REALTIME and trying to emulate by converting a
+ CLOCK_MONOTONIC to CLOCK_REALTIME will take in account possible
+ changes to the wall clock.
+
+ However, newer Linux kernels support FUTEX_LOCK_PI2 with selectable
+ clock support. */
+ if (__glibc_unlikely (! futex_lockpi2_supported () &&
+ clockid != CLOCK_REALTIME))
return EINVAL;
int kind, robust;
@@ -370,7 +374,15 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,
int private = (robust
? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
: PTHREAD_MUTEX_PSHARED (mutex));
- int e = futex_lock_pi64 (&mutex->__data.__lock, abstime, private);
+ int e = futex_lock_pi2_64 (&mutex->__data.__lock, clockid, abstime,
+ private);
+
+ /* Use futex futex_lock_pi2() by default. This doesn't work for
+ older kernels. So fallback to futex_lock_pi() then. The clockid
+ is checked above already. */
+ if (__glibc_unlikely (e == ENOSYS))
+ e = futex_lock_pi64 (&mutex->__data.__lock, abstime, private);
+
if (e == ETIMEDOUT)
return ETIMEDOUT;
else if (e == ESRCH || e == EDEADLK)
@@ -372,6 +372,23 @@ futex_lock_pi2_64 (int *futex_word, clockid_t clockid,
}
}
+/* Checks whether FUTEX_LOCK_PI2 operation is available on the running Linux
+ kernel. FUTEX_LOCK_PI2 has been introduced on newer kernel versions.
+
+ Returns true if FUTEX_LOCK_PI2 is available, false otherwise. */
+static __always_inline bool
+futex_lockpi2_supported (void)
+{
+ int err = INTERNAL_SYSCALL_CALL (futex_time64, NULL, FUTEX_LOCK_PI2, 0, NULL);
+
+#ifndef __ASSUME_TIME64_SYSCALLS
+ if (err == -ENOSYS)
+ err = INTERNAL_SYSCALL_CALL (futex, NULL, FUTEX_LOCK_PI2, 0, NULL);
+#endif
+
+ return err != -ENOSYS;
+}
+
/* Wakes the top priority waiter that called a futex_lock_pi operation on
the futex.