lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Mon, 26 Oct 2009 17:26:37 -0700
From:	Darren Hart <dvhltc@...ibm.com>
To:	"lkml, " <linux-kernel@...r.kernel.org>,
	Thomas Gleixner <tglx@...utronix.de>,
	Peter Zijlstra <peterz@...radead.org>,
	Ingo Molnar <mingo@...e.hu>,
	Eric Dumazet <eric.dumazet@...il.com>,
	Dinakar Guniguntala <dino@...ibm.com>,
	"Stultz, John" <johnstul@...ibm.com>
Subject: [PATCH] RFC: futex: make futex_lock_pi interruptible

>From 9ea67856951c87a03a5177e1382d836622642521 Mon Sep 17 00:00:00 2001
From: Darren Hart <dvhltc@...ibm.com>
Date: Mon, 26 Oct 2009 17:15:54 -0700
Subject: [PATCH] RFC: futex: make futex_lock_pi interruptible

NOT FOR INCLUSION

Interruptible locking constructs can currently be implemented in
userspace using condvars and mutexes. However, if FIFO ordered wakeup
and Priority Inheritance are requirements, the sleeping kernel call must
be interruptible. The following patch implements this by allowing
futex_lock_pi() to be interrupted if the new FUTEX_INTERRUPTIBLE opcode
flag is set (rather than perform a syscall restart).

An alternative approach might be to implement a new FUTEX_CANCEL opcode
and return -ECANCELED. This is slightly more complicated to use from
userspace I believe, but not overly so.

A final patch would also need to add support to FUTEX_WAIT. Before I do,
I wanted to get some opinions on this approach.

Signed-off-by: Darren Hart <dvhltc@...ibm.com>
Cc: Thomas Gleixner <tglx@...utronix.de>
Cc: Peter Zijlstra <peterz@...radead.org>
Cc: Ingo Molnar <mingo@...e.hu>
CC: Eric Dumazet <eric.dumazet@...il.com>
CC: Dinakar Guniguntala <dino@...ibm.com>
CC: John Stultz <johnstul@...ibm.com>
---
 include/linux/futex.h |    3 ++-
 kernel/futex.c        |   20 ++++++++++++++------
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/include/linux/futex.h b/include/linux/futex.h
index 34956c8..f1a4f89 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -28,7 +28,8 @@ union ktime;
 
 #define FUTEX_PRIVATE_FLAG	128
 #define FUTEX_CLOCK_REALTIME	256
-#define FUTEX_CMD_MASK		~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
+#define FUTEX_INTERRUPTIBLE	512
+#define FUTEX_CMD_MASK		~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME | FUTEX_INTERRUPTIBLE)
 
 #define FUTEX_WAIT_PRIVATE	(FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
 #define FUTEX_WAKE_PRIVATE	(FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
diff --git a/kernel/futex.c b/kernel/futex.c
index 7c4a6ac..d41c55c 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -1834,8 +1834,8 @@ static long futex_wait_restart(struct restart_block *restart)
  * if there are waiters then it will block, it does PI, etc. (Due to
  * races the kernel might see a 0 value of the futex too.)
  */
-static int futex_lock_pi(u32 __user *uaddr, int fshared,
-			 int detect, ktime_t *time, int trylock)
+static int futex_lock_pi(u32 __user *uaddr, int fshared, int detect,
+			 ktime_t *time, int trylock, int interruptible)
 {
 	struct hrtimer_sleeper timeout, *to = NULL;
 	struct futex_hash_bucket *hb;
@@ -1937,7 +1937,11 @@ out_put_key:
 out:
 	if (to)
 		destroy_hrtimer_on_stack(&to->timer);
-	return ret != -EINTR ? ret : -ERESTARTNOINTR;
+
+	if (interruptible)
+		return ret;
+	else
+		return ret != -EINTR ? ret : -ERESTARTNOINTR;
 
 uaddr_faulted:
 	queue_unlock(&q, hb);
@@ -2489,7 +2493,7 @@ void exit_robust_list(struct task_struct *curr)
 long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
 		u32 __user *uaddr2, u32 val2, u32 val3)
 {
-	int clockrt, ret = -ENOSYS;
+	int clockrt, interruptible, ret = -ENOSYS;
 	int cmd = op & FUTEX_CMD_MASK;
 	int fshared = 0;
 
@@ -2500,6 +2504,8 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
 	if (clockrt && cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI)
 		return -ENOSYS;
 
+	interruptible = op & FUTEX_INTERRUPTIBLE;
+
 	switch (cmd) {
 	case FUTEX_WAIT:
 		val3 = FUTEX_BITSET_MATCH_ANY;
@@ -2523,7 +2529,8 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
 		break;
 	case FUTEX_LOCK_PI:
 		if (futex_cmpxchg_enabled)
-			ret = futex_lock_pi(uaddr, fshared, val, timeout, 0);
+			ret = futex_lock_pi(uaddr, fshared, val, timeout, 0,
+					    interruptible);
 		break;
 	case FUTEX_UNLOCK_PI:
 		if (futex_cmpxchg_enabled)
@@ -2531,7 +2538,8 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
 		break;
 	case FUTEX_TRYLOCK_PI:
 		if (futex_cmpxchg_enabled)
-			ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1);
+			ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1,
+					    interruptible);
 		break;
 	case FUTEX_WAIT_REQUEUE_PI:
 		val3 = FUTEX_BITSET_MATCH_ANY;
-- 
1.6.0.4
-- 
Darren Hart
IBM Linux Technology Center
Real-Time Linux Team
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists