summaryrefslogtreecommitdiff
path: root/drivers/char
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2010-08-06 23:40:30 +0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-11 00:47:44 +0400
commitb07471fa51358ce64cc25e1501544502362e4404 (patch)
tree0bd1889eb3cbabe51f15cc5e971f9644cdced0f3 /drivers/char
parentddcd9fb66ae7f448b517242c10a31d4e17bcad45 (diff)
downloadlinux-b07471fa51358ce64cc25e1501544502362e4404.tar.xz
tty: implement BTM as mutex instead of BKL
The tty locking now follows the rules for mutexes, so we can replace the BKL usage with a new subsystem wide mutex. Using a regular mutex here will change the behaviour when blocked on the BTM from spinning to sleeping, but that should not be visible to the user. Using the mutex also means that all the BTM is now covered by lockdep. 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 'drivers/char')
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/tty_mutex.c47
2 files changed, 48 insertions, 0 deletions
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 273cee1cc77b..dc9641660605 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -9,6 +9,7 @@ FONTMAPFILE = cp437.uni
obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o
+obj-y += tty_mutex.o
obj-$(CONFIG_LEGACY_PTYS) += pty.o
obj-$(CONFIG_UNIX98_PTYS) += pty.o
obj-y += misc.o
diff --git a/drivers/char/tty_mutex.c b/drivers/char/tty_mutex.c
new file mode 100644
index 000000000000..133697540c73
--- /dev/null
+++ b/drivers/char/tty_mutex.c
@@ -0,0 +1,47 @@
+/*
+ * drivers/char/tty_lock.c
+ */
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+#include <linux/semaphore.h>
+#include <linux/sched.h>
+
+/*
+ * The 'big tty mutex'
+ *
+ * This mutex is taken and released by tty_lock() and tty_unlock(),
+ * replacing the older big kernel lock.
+ * It can no longer be taken recursively, and does not get
+ * released implicitly while sleeping.
+ *
+ * Don't use in new code.
+ */
+static DEFINE_MUTEX(big_tty_mutex);
+struct task_struct *__big_tty_mutex_owner;
+EXPORT_SYMBOL_GPL(__big_tty_mutex_owner);
+
+/*
+ * Getting the big tty mutex.
+ */
+void __lockfunc tty_lock(void)
+{
+ struct task_struct *task = current;
+
+ WARN_ON(__big_tty_mutex_owner == task);
+
+ mutex_lock(&big_tty_mutex);
+ __big_tty_mutex_owner = task;
+}
+EXPORT_SYMBOL(tty_lock);
+
+void __lockfunc tty_unlock(void)
+{
+ struct task_struct *task = current;
+
+ WARN_ON(__big_tty_mutex_owner != task);
+ __big_tty_mutex_owner = NULL;
+
+ mutex_unlock(&big_tty_mutex);
+}
+EXPORT_SYMBOL(tty_unlock);