[PATCH-tip v6 17/22] TP-futex: Enable kernel reader lock stealing

From: Waiman Long
Date: Wed Mar 22 2017 - 13:43:59 EST


By default, the TP futexes do not have preference for either readers
or writers. Most reader-writer locks allows users to decide if they
want to prefer readers or writers more.

This patch allows the setting of the prefer-reader mode in the val
argument of the futex system call. If that flag is set, it will
enable kernel reader to steal the lock when the futex is currently
reader-owned and the lock handoff mechanism hasn't been enabled yet.

Signed-off-by: Waiman Long <longman@xxxxxxxxxx>
---
kernel/futex.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/kernel/futex.c b/kernel/futex.c
index 4139843..cacaaf1 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -197,6 +197,7 @@
#define FLAGS_CLOCKRT 0x02
#define FLAGS_HAS_TIMEOUT 0x04
#define FLAGS_TP_USLOCK 0x08 /* Do the locking in userspace */
+#define FLAGS_TP_PREADER 0x08 /* Prefer readers */

enum futex_type {
TYPE_PI = 0,
@@ -4004,6 +4005,20 @@ static noinline int futex_lock(u32 __user *uaddr, unsigned int flags,
goto out_put_state_key;
}

+ /*
+ * For reader, we will try to steal the lock here as if it is the
+ * top waiter without taking the serialization mutex if the handoff
+ * PID hasn't been set and is in prefer-reader mode.
+ */
+ if (shared && (flags & FLAGS_TP_PREADER) && !state->handoff_pid) {
+ ret = futex_trylock(uaddr, vpid, &uval, true);
+ if (ret) {
+ if (ret > 0)
+ ret = TP_LOCK_STOLEN;
+ goto out_put_state_key;
+ }
+ }
+
if (to)
hrtimer_start_expires(&to->timer, HRTIMER_MODE_ABS);

@@ -4219,8 +4234,9 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
#ifdef CONFIG_SMP
case FUTEX_LOCK:
case FUTEX_LOCK_SHARED:
- if (val && (cmd == FUTEX_LOCK))
- flags |= FLAGS_TP_USLOCK;
+ if (val)
+ flags |= (cmd == FUTEX_LOCK) ? FLAGS_TP_USLOCK
+ : FLAGS_TP_PREADER;
return futex_lock(uaddr, flags, timeout,
(cmd == FUTEX_LOCK) ? false : true);
case FUTEX_UNLOCK:
--
1.8.3.1