|
@@ -1208,13 +1208,47 @@ int is_console_locked(void)
|
|
|
return console_locked;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Delayed printk facility, for scheduler-internal messages:
|
|
|
+ */
|
|
|
+#define PRINTK_BUF_SIZE 512
|
|
|
+
|
|
|
+#define PRINTK_PENDING_WAKEUP 0x01
|
|
|
+#define PRINTK_PENDING_SCHED 0x02
|
|
|
+
|
|
|
static DEFINE_PER_CPU(int, printk_pending);
|
|
|
+static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf);
|
|
|
+
|
|
|
+int printk_sched(const char *fmt, ...)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+ va_list args;
|
|
|
+ char *buf;
|
|
|
+ int r;
|
|
|
+
|
|
|
+ local_irq_save(flags);
|
|
|
+ buf = __get_cpu_var(printk_sched_buf);
|
|
|
+
|
|
|
+ va_start(args, fmt);
|
|
|
+ r = vsnprintf(buf, PRINTK_BUF_SIZE, fmt, args);
|
|
|
+ va_end(args);
|
|
|
+
|
|
|
+ __this_cpu_or(printk_pending, PRINTK_PENDING_SCHED);
|
|
|
+ local_irq_restore(flags);
|
|
|
+
|
|
|
+ return r;
|
|
|
+}
|
|
|
|
|
|
void printk_tick(void)
|
|
|
{
|
|
|
if (__this_cpu_read(printk_pending)) {
|
|
|
- __this_cpu_write(printk_pending, 0);
|
|
|
- wake_up_interruptible(&log_wait);
|
|
|
+ int pending = __this_cpu_xchg(printk_pending, 0);
|
|
|
+ if (pending & PRINTK_PENDING_SCHED) {
|
|
|
+ char *buf = __get_cpu_var(printk_sched_buf);
|
|
|
+ printk(KERN_WARNING "[sched_delayed] %s", buf);
|
|
|
+ }
|
|
|
+ if (pending & PRINTK_PENDING_WAKEUP)
|
|
|
+ wake_up_interruptible(&log_wait);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1228,7 +1262,7 @@ int printk_needs_cpu(int cpu)
|
|
|
void wake_up_klogd(void)
|
|
|
{
|
|
|
if (waitqueue_active(&log_wait))
|
|
|
- this_cpu_write(printk_pending, 1);
|
|
|
+ this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
|
|
|
}
|
|
|
|
|
|
/**
|