Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

futex: Provide FUTEX_LOCK_PI2 to support clock selection

The FUTEX_LOCK_PI futex operand uses a CLOCK_REALTIME based absolute
timeout since it was implemented, but it does not require that the
FUTEX_CLOCK_REALTIME flag is set, because that was introduced later.

In theory as none of the user space implementations can set the
FUTEX_CLOCK_REALTIME flag on this operand, it would be possible to
creatively abuse it and make the meaning invers, i.e. select CLOCK_REALTIME
when not set and CLOCK_MONOTONIC when set. But that's a nasty hackery.

Another option would be to have a new FUTEX_CLOCK_MONOTONIC flag only for
FUTEX_LOCK_PI, but that's also awkward because it does not allow libraries
to handle the timeout clock selection consistently.

So provide a new FUTEX_LOCK_PI2 operand which implements the timeout
semantics which the other operands use and leave FUTEX_LOCK_PI alone.

Reported-by: Kurt Kanzenbach <kurt@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20210422194705.440773992@linutronix.de

authored by

Thomas Gleixner and committed by
Peter Zijlstra
bf22a697 e112c413

+8 -1
+2
include/uapi/linux/futex.h
··· 21 21 #define FUTEX_WAKE_BITSET 10 22 22 #define FUTEX_WAIT_REQUEUE_PI 11 23 23 #define FUTEX_CMP_REQUEUE_PI 12 24 + #define FUTEX_LOCK_PI2 13 24 25 25 26 #define FUTEX_PRIVATE_FLAG 128 26 27 #define FUTEX_CLOCK_REALTIME 256 ··· 33 32 #define FUTEX_CMP_REQUEUE_PRIVATE (FUTEX_CMP_REQUEUE | FUTEX_PRIVATE_FLAG) 34 33 #define FUTEX_WAKE_OP_PRIVATE (FUTEX_WAKE_OP | FUTEX_PRIVATE_FLAG) 35 34 #define FUTEX_LOCK_PI_PRIVATE (FUTEX_LOCK_PI | FUTEX_PRIVATE_FLAG) 35 + #define FUTEX_LOCK_PI2_PRIVATE (FUTEX_LOCK_PI2 | FUTEX_PRIVATE_FLAG) 36 36 #define FUTEX_UNLOCK_PI_PRIVATE (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG) 37 37 #define FUTEX_TRYLOCK_PI_PRIVATE (FUTEX_TRYLOCK_PI | FUTEX_PRIVATE_FLAG) 38 38 #define FUTEX_WAIT_BITSET_PRIVATE (FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG)
+6 -1
kernel/futex.c
··· 3707 3707 3708 3708 if (op & FUTEX_CLOCK_REALTIME) { 3709 3709 flags |= FLAGS_CLOCKRT; 3710 - if (cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI) 3710 + if (cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI && 3711 + cmd != FUTEX_LOCK_PI2) 3711 3712 return -ENOSYS; 3712 3713 } 3713 3714 3714 3715 switch (cmd) { 3715 3716 case FUTEX_LOCK_PI: 3717 + case FUTEX_LOCK_PI2: 3716 3718 case FUTEX_UNLOCK_PI: 3717 3719 case FUTEX_TRYLOCK_PI: 3718 3720 case FUTEX_WAIT_REQUEUE_PI: ··· 3742 3740 return futex_wake_op(uaddr, flags, uaddr2, val, val2, val3); 3743 3741 case FUTEX_LOCK_PI: 3744 3742 flags |= FLAGS_CLOCKRT; 3743 + fallthrough; 3744 + case FUTEX_LOCK_PI2: 3745 3745 return futex_lock_pi(uaddr, flags, timeout, 0); 3746 3746 case FUTEX_UNLOCK_PI: 3747 3747 return futex_unlock_pi(uaddr, flags); ··· 3764 3760 switch (cmd) { 3765 3761 case FUTEX_WAIT: 3766 3762 case FUTEX_LOCK_PI: 3763 + case FUTEX_LOCK_PI2: 3767 3764 case FUTEX_WAIT_BITSET: 3768 3765 case FUTEX_WAIT_REQUEUE_PI: 3769 3766 return true;