]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
printk: robustify printk
authorPeter Zijlstra <a.p.zijlstra@chello.nl>
Fri, 8 Aug 2008 19:47:09 +0000 (21:47 +0200)
committerIngo Molnar <mingo@elte.hu>
Mon, 11 Aug 2008 11:46:53 +0000 (13:46 +0200)
Avoid deadlocks against rq->lock and xtime_lock by deferring the klogd
wakeup by polling from the timer tick.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
include/linux/kernel.h
kernel/printk.c
kernel/time/tick-sched.c
kernel/timer.c

index aaa998f65c7af93e8a0e715e5bef0ca5ef067ece..113ac8d0425f5c7c6cbf4384082ea5d429690ec4 100644 (file)
@@ -200,6 +200,8 @@ extern struct ratelimit_state printk_ratelimit_state;
 extern int printk_ratelimit(void);
 extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
                                   unsigned int interval_msec);
+extern void printk_tick(void);
+extern int printk_needs_cpu(int);
 #else
 static inline int vprintk(const char *s, va_list args)
        __attribute__ ((format (printf, 1, 0)));
@@ -211,6 +213,8 @@ static inline int printk_ratelimit(void) { return 0; }
 static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \
                                          unsigned int interval_msec)   \
                { return false; }
+static inline void printk_tick(void) { }
+static inline int printk_needs_cpu(int) { return 0; }
 #endif
 
 extern void asmlinkage __attribute__((format(printf, 1, 2)))
index b51b1567bb5570dfc5b4a19bffd5af865d254e77..655cc2ca10cc82e88d5472789ea3a34b4f21bb20 100644 (file)
@@ -982,10 +982,25 @@ int is_console_locked(void)
        return console_locked;
 }
 
-void wake_up_klogd(void)
+static DEFINE_PER_CPU(int, printk_pending);
+
+void printk_tick(void)
 {
-       if (!oops_in_progress && waitqueue_active(&log_wait))
+       if (__get_cpu_var(printk_pending)) {
+               __get_cpu_var(printk_pending) = 0;
                wake_up_interruptible(&log_wait);
+       }
+}
+
+int printk_needs_cpu(int cpu)
+{
+       return per_cpu(printk_pending, cpu);
+}
+
+void wake_up_klogd(void)
+{
+       if (waitqueue_active(&log_wait))
+               __get_cpu_var(printk_pending) = 1;
 }
 
 /**
index 825b4c00fe4436a1921d4f57a6cb6d9e37510d3d..c13d4f182370f3f19e1a2fdbf3ad92d7553e1f51 100644 (file)
@@ -255,7 +255,7 @@ void tick_nohz_stop_sched_tick(int inidle)
        next_jiffies = get_next_timer_interrupt(last_jiffies);
        delta_jiffies = next_jiffies - last_jiffies;
 
-       if (rcu_needs_cpu(cpu))
+       if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu))
                delta_jiffies = 1;
        /*
         * Do not stop the tick, if we are only one off
index 03bc7f1f159350d2ad29ca45d3b3a28fc275f296..510fe69351ca2ec19700802b59ac3dbe9d142019 100644 (file)
@@ -978,6 +978,7 @@ void update_process_times(int user_tick)
        run_local_timers();
        if (rcu_pending(cpu))
                rcu_check_callbacks(cpu, user_tick);
+       printk_tick();
        scheduler_tick();
        run_posix_cpu_timers(p);
 }