console_unlock
---
for (;;) {
raw_spin_lock_irqsave(&logbuf_lock, flags);
//get the log from printk log buffer
raw_spin_unlock(&logbuf_lock);
//irq is disabled
stop_critical_timings(); /* don't trace print latency */
call_console_drivers(level, text, len);
start_critical_timings();
local_irq_restore(flags);
if (do_cond_resched)
cond_resched();
}
---
static void call_console_drivers(int level, const char *text, size_t len)
{
struct console *con;
trace_console(text, len);
if (level >= console_loglevel && !ignore_loglevel)
return;
console_loglevel is the first one of the /proc/sys/kernel/printk
if (!console_drivers)
return;
for_each_console(con) {
if (exclusive_console && con != exclusive_console)
continue;
if (!(con->flags & CON_ENABLED))
continue;
if (!con->write)
continue;
if (!cpu_online(smp_processor_id()) &&
!(con->flags & CON_ANYTIME))
continue;
con->write(con, text, len);
output to console device, maybe a serial port or other.
}
}
As we know, printk could be used anywhere, even irq context or critical section.
This means console->write callback cannot invoke any function that will lead to schedule.
How to achieve this ? Let look at one example:
sclp_console -> sclp_console_write() ->sclp_sync_wait()
>>>>
/* Loop until driver state indicates finished request */
while (sclp_running_state != sclp_running_state_idle) {
/* Check for expired request timer */
if (timer_pending(&sclp_request_timer) &&
get_clock() > timeout &&
del_timer(&sclp_request_timer))
sclp_request_timer.function(sclp_request_timer.data);
cpu_relax();
}
>>>>>
The irq has been disabled in console_unlock, so it is a polling under irq disabled.
If the console is very slow and dmesgs are flooded, softlockup, rcu stall even harlockup maybe triggered.
Here is an example:
workqueue: avoid hard lockups in show_workqueue_state()
show_workqueue_state() can print out a lot of messages while being in
atomic context, e.g. sysrq-t -> show_workqueue_state(). If the console
device is slow it may end up triggering NMI hard lockup watchdog.
Signed-off-by: Sergey Senozhatsky