Re: [RFC][PATCH v4 1/2] printk: Make printk() completely async

From: Jan Kara
Date: Tue Mar 15 2016 - 06:04:29 EST


> + if (!sync_print) {
> + if (printk_thread && !in_panic) {
> + /*
> + * This will wakeup the printing kthread and offload
> + * printing to a schedulable context.
> + */
> + __this_cpu_or(printk_pending,
> + PRINTK_PENDING_KTHREAD_OUTPUT);
> + irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
> + } else if (in_sched) {
> + /*
> + * @in_sched messages may come too early, when we don't
> + * yet have @printk_thread. We can't print deferred
> + * messages directly, because this may deadlock, route
> + * them via IRQ context.
> + */
> + __this_cpu_or(printk_pending,
> + PRINTK_PENDING_IRQ_OUTPUT);
> + irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
> + } else {
> + sync_print = true;
> + }
> + }

I'm a bit undecided whether we want to go through irq work even for the
common case of !in_sched messages or whether we want to directly call
wake_up() in that case. Maybe I'd do it like:

if (!sync_print) {
if (in_sched) {
__this_cpu_or(printk_pending,
PRINTK_PENDING_IRQ_OUTPUT);
irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
} else if (printk_thread && !in_panic) {
wake_up(&printing_wait);
} else {
sync_print = true;
}
}

and the wake_up_klogd_work_func() would look like:

static void wake_up_klogd_work_func(struct irq_work *irq_work)
{
int pending = __this_cpu_xchg(printk_pending, 0);

if (pending & PRINTK_PENDING_OUTPUT) {
if (printk_thread) {
wake_up(&printing_wait);
} else {
/*
* If trylock fails, someone else is doing the printing
*/
if (console_trylock())
console_unlock();
}
}
...

Honza

--
Jan Kara <jack@xxxxxxxx>
SUSE Labs, CR