public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] RFC: futex: make futex_lock_pi interruptible
@ 2009-10-27  0:26 Darren Hart
  2009-10-27  0:32 ` Darren Hart
  0 siblings, 1 reply; 10+ messages in thread
From: Darren Hart @ 2009-10-27  0:26 UTC (permalink / raw)
  To: lkml, , Thomas Gleixner, Peter Zijlstra, Ingo Molnar,
	Eric Dumazet, Dinakar Guniguntala, Stultz, John

>From 9ea67856951c87a03a5177e1382d836622642521 Mon Sep 17 00:00:00 2001
From: Darren Hart <dvhltc@us.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@us.ibm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@elte.hu>
CC: Eric Dumazet <eric.dumazet@gmail.com>
CC: Dinakar Guniguntala <dino@in.ibm.com>
CC: John Stultz <johnstul@us.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

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2009-10-31  0:31 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-27  0:26 [PATCH] RFC: futex: make futex_lock_pi interruptible Darren Hart
2009-10-27  0:32 ` Darren Hart
2009-10-29  8:39   ` Arnd Bergmann
2009-10-30  1:19     ` Darren Hart
2009-10-30  1:45       ` Darren Hart
2009-10-30  9:13         ` Arnd Bergmann
2009-10-30 16:23           ` Darren Hart
2009-10-30 17:39             ` Arnd Bergmann
2009-10-30 17:55         ` Chris Friesen
2009-10-31  0:31           ` Darren Hart

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox