blob: 9561393e9509c93dd8231e495da13526275da793 [file] [log] [blame]
From d66b51582f975cab5a77f81a3f062356e5783e94 Mon Sep 17 00:00:00 2001
From: Ingo Molnar <mingo@elte.hu>
Date: Fri, 3 Jul 2009 08:44:02 -0500
Subject: [PATCH] printk: might sleep workaround
commit ee7503ec41dd08a6456e70ac3a6df74e539762df in tip.
PREEMPT_RT suffers from the on going problem of running
printk in atomic operations. It is very advantageous to do so
but with PREEMPT_RT making spin_locks sleep, it can also be
devastating.
This patch does not solve the problem of printk sleeping in
an atomic operation. This patch just makes printk not report
that it is. Of course if printk does report that it's sleeping
in an atomic operation, then that printing of the report will
also print a report, and you go into recursive hell.
We need to really sit down and solve the real issue here.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 1552624..5ceabb5 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1636,11 +1636,24 @@ struct task_struct {
unsigned long memsw_bytes; /* uncharged mem+swap usage */
} memcg_batch;
#endif
+#ifdef CONFIG_PREEMPT_RT
+ /*
+ * Temporary hack, until we find a solution to
+ * handle printk in atomic operations.
+ */
+ int in_printk;
+#endif
};
/* Future-safe accessor for struct task_struct's cpus_allowed. */
#define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed)
+#ifdef CONFIG_PREEMPT_RT
+# define set_printk_might_sleep(x) do { current->in_printk = x; } while(0)
+#else
+# define set_printk_might_sleep(x) do { } while(0)
+#endif
+
/*
* Priority of a process goes from 0..MAX_PRIO-1, valid RT
* priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
diff --git a/kernel/printk.c b/kernel/printk.c
index 6c97e02..34adc5f 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -431,8 +431,11 @@ static void __call_console_drivers(unsigned start, unsigned end)
for_each_console(con) {
if ((con->flags & CON_ENABLED) && con->write &&
(cpu_online(raw_smp_processor_id()) ||
- (con->flags & CON_ANYTIME)))
+ (con->flags & CON_ANYTIME))) {
+ set_printk_might_sleep(1);
con->write(con, &LOG_BUF(start), end - start);
+ set_printk_might_sleep(0);
+ }
}
}
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index 900f11c..dfbae19 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -678,7 +678,9 @@ static inline void
rt_spin_lock_fastlock(struct rt_mutex *lock,
void (*slowfn)(struct rt_mutex *lock))
{
- might_sleep();
+ /* Temporary HACK! */
+ if (!current->in_printk)
+ might_sleep();
if (likely(rt_mutex_cmpxchg(lock, NULL, current)))
rt_mutex_deadlock_account_lock(lock, current);
--
1.7.1.1