> +     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 <[email protected]>
SUSE Labs, CR

Reply via email to