[RFC,1/3] nptl: Introduce futex_lock_pi2()
Checks
Context |
Check |
Description |
dj/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
Commit Message
This variant of futex_lock() has support for selectable clocks and priority
inheritance. The underlying FUTEX_LOCK_PI2 operation has been recently
introduced into the Linux kernel.
It can be used for implementing pthread_mutex_clocklock(MONOTONIC)/PI.
Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
---
sysdeps/nptl/futex-internal.h | 77 +++++++++++++++++++++++++++++++
sysdeps/nptl/lowlevellock-futex.h | 1 +
2 files changed, 78 insertions(+)
@@ -295,6 +295,83 @@ futex_lock_pi64 (int *futex_word, const struct __timespec64 *abstime,
}
}
+/* The operation checks the value of the futex, if the value is 0, then
+ it is atomically set to the caller's thread ID. If the futex value is
+ nonzero, it is atomically sets the FUTEX_WAITERS bit, which signals wrt
+ other futex owner that it cannot unlock the futex in user space by
+ atomically by setting its value to 0.
+
+ If more than one wait operations is issued, the enqueueing of the waiters
+ are done in descending priority order.
+
+ The ABSTIME arguments provides an absolute timeout (measured against the
+ CLOCK_REALTIME or CLOCK_MONOTONIC clock). If TIMEOUT is NULL, the operation
+ will block indefinitely.
+
+ Returns:
+
+ - 0 if woken by a PI unlock operation or spuriously.
+ - EAGAIN if the futex owner thread ID is about to exit, but has not yet
+ handled the state cleanup.
+ - EDEADLK if the futex is already locked by the caller.
+ - ESRCH if the thread ID int he futex does not exist.
+ - EINVAL is the state is corrupted or if there is a waiter on the
+ futex or if the clockid is invalid.
+ - ETIMEDOUT if the ABSTIME expires.
+ - ENOSYS if FUTEX_LOCK_PI2 is not available.
+*/
+static __always_inline int
+futex_lock_pi2_64 (int *futex_word, clockid_t clockid,
+ const struct __timespec64 *abstime,
+ int private)
+{
+ unsigned int clockbit;
+
+ if (! lll_futex_supported_clockid (clockid))
+ return EINVAL;
+
+ clockbit = (clockid == CLOCK_REALTIME) ? FUTEX_CLOCK_REALTIME : 0;
+ int op = __lll_private_flag (FUTEX_LOCK_PI2 | clockbit, private);
+
+ int err = INTERNAL_SYSCALL_CALL (futex_time64, futex_word, op,
+ 0, abstime);
+#ifndef __ASSUME_TIME64_SYSCALLS
+ if (err == -ENOSYS)
+ {
+ if (abstime != NULL && ! in_time_t_range (abstime->tv_sec))
+ return EOVERFLOW;
+
+ struct timespec ts32;
+ if (abstime != NULL)
+ ts32 = valid_timespec64_to_timespec (*abstime);
+
+ err = INTERNAL_SYSCALL_CALL (futex, futex_word, op, 0,
+ abstime != NULL ? &ts32 : NULL);
+ }
+#endif
+ switch (err)
+ {
+ case 0:
+ case -EAGAIN:
+ case -EINTR:
+ case -ETIMEDOUT:
+ case -ESRCH:
+ case -EDEADLK:
+ case -ENOSYS: /* Futex lock pi 2 is not available on this kernel. */
+ case -EINVAL: /* This indicates either state corruption or that the kernel
+ found a waiter on futex address which is waiting via
+ FUTEX_WAIT or FUTEX_WAIT_BITSET. This is reported on
+ some futex_lock_pi usage (pthread_mutex_timedlock for
+ instance). */
+ return -err;
+
+ case -EFAULT: /* Must have been caused by a glibc or application bug. */
+ /* No other errors are documented at this time. */
+ default:
+ futex_fatal_error ();
+ }
+}
+
/* Wakes the top priority waiter that called a futex_lock_pi operation on
the futex.
@@ -38,6 +38,7 @@
#define FUTEX_WAKE_BITSET 10
#define FUTEX_WAIT_REQUEUE_PI 11
#define FUTEX_CMP_REQUEUE_PI 12
+#define FUTEX_LOCK_PI2 13
#define FUTEX_PRIVATE_FLAG 128
#define FUTEX_CLOCK_REALTIME 256