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 <long...@redhat.com>
---
 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

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to