summary refs log tree commit diff
path: root/include
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2010-06-01 22:53:05 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 13:47:43 -0700
commitbe1bc2889a4db4961ef69f47fb471ecae9f23ade (patch)
treefd6d5e46e69efd9d66e6baa184988461f608f49a /include
parent4e608671674b62e97166f903830d5553e37970e8 (diff)
downloadlinux-be1bc2889a4db4961ef69f47fb471ecae9f23ade.tar.gz
tty: introduce wait_event_interruptible_tty
Calling wait_event_interruptible implicitly
releases the BKL when it sleeps, but we need
to do this explcitly when we have converted
it to a mutex.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Diffstat (limited to 'include')
-rw-r--r--include/linux/tty.h42
1 files changed, 42 insertions, 0 deletions
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 6ead6b60c743..955d72ea71c0 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -607,5 +607,47 @@ static inline void tty_unlock(void) __releases(kernel_lock)
 }
 #define tty_locked()		(kernel_locked())
 
+/*
+ * wait_event_interruptible_tty -- wait for a condition with the tty lock held
+ *
+ * The condition we are waiting for might take a long time to
+ * become true, or might depend on another thread taking the
+ * BTM. In either case, we need to drop the BTM to guarantee
+ * forward progress. This is a leftover from the conversion
+ * from the BKL and should eventually get removed as the BTM
+ * falls out of use.
+ *
+ * Do not use in new code.
+ */
+#define wait_event_interruptible_tty(wq, condition)			\
+({									\
+	int __ret = 0;							\
+	if (!(condition)) {						\
+		__wait_event_interruptible_tty(wq, condition, __ret);	\
+	}								\
+	__ret;								\
+})
+
+#define __wait_event_interruptible_tty(wq, condition, ret)		\
+do {									\
+	DEFINE_WAIT(__wait);						\
+									\
+	for (;;) {							\
+		prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);	\
+		if (condition)						\
+			break;						\
+		if (!signal_pending(current)) {				\
+			tty_unlock();					\
+			schedule();					\
+			tty_lock();					\
+			continue;					\
+		}							\
+		ret = -ERESTARTSYS;					\
+		break;							\
+	}								\
+	finish_wait(&wq, &__wait);					\
+} while (0)
+
+
 #endif /* __KERNEL__ */
 #endif