drivers/tty/vt/vt.c | 1 - drivers/video/fbdev/core/fbcon.c | 6 ------ include/linux/console.h | 1 - kernel/printk/printk.c | 16 ---------------- 4 files changed, 24 deletions(-)
do_con_write(), fbcon_redraw.*() invoke console_conditional_schedule()
which is a conditional scheduling point based on printk's internal
variables console_may_schedule. It may only be used if the console lock
is acquired for instance via console_lock() or console_trylock().
Prinkt sets the internal variable to 1 (and allows to schedule)
if the console lock has been acquired via console_lock(). The trylock
does not allow it.
The console_conditional_schedule() invocation in do_con_write() is
invoked shortly before console_unlock().
The console_conditional_schedule() invocation in fbcon_redraw.*()
original from fbcon_scroll() / vt's con_scroll() which originate from a
line feed.
In console_unlock() the variable is set to 0 (forbids to schedule) and
it tries to schedule while making progress printing. This is brand new
compared to when console_conditional_schedule() was added in v2.4.9.11.
In v2.6.38-rc3, console_unlock() (started its existence) iterated over
all consoles and flushed them with disabled interrupts. A scheduling
attempt here was not possible, it relied that a long print scheduled
before console_unlock().
Since commit 8d91f8b15361d ("printk: do cond_resched() between lines
while outputting to consoles"), which appeared in v4.5-rc1,
console_unlock() attempts to schedule if it was allowed to schedule
while during console_lock(). Each record is idealy one line so after
every line feed.
This console_conditional_schedule() is also only relevant on
PREEMPT_NONE and PREEMPT_VOLUNTARY builds. In other configurations
cond_resched() becomes a nop and has no impact.
I'm bringing this all up just proof that it is not required anymore. It
becomes a problem on a PREEMPT_RT build with debug code enabled because
that might_sleep() in cond_resched() remains and triggers a warnings.
This is due to
legacy_kthread_func-> console_flush_one_record -> vt_console_print-> lf
-> con_scroll -> fbcon_scroll
and vt_console_print() acquires a spinlock_t which does not allow a
voluntary schedule. There is no need to fb_scroll() to schedule since
console_flush_one_record() attempts to schedule after each line.
!PREEMPT_RT is not affected because the legacy printing thread is only
enabled on PREEMPT_RT builds.
Therefore I suggest to remove console_conditional_schedule().
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Helge Deller <deller@gmx.de>
Cc: linux-fbdev@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Fixes: 5f53ca3ff83b4 ("printk: Implement legacy printer kthread for PREEMPT_RT")
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
A follow-up to
https://lore.kernel.org/all/20260114145955.d924Z-zu@linutronix.de/
drivers/tty/vt/vt.c | 1 -
drivers/video/fbdev/core/fbcon.c | 6 ------
include/linux/console.h | 1 -
kernel/printk/printk.c | 16 ----------------
4 files changed, 24 deletions(-)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 59b4b5e126ba1..53daf7614b1af 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -3236,7 +3236,6 @@ static int do_con_write(struct tty_struct *tty, const u8 *buf, int count)
goto rescan_last_byte;
}
con_flush(vc, &draw);
- console_conditional_schedule();
notify_update(vc);
return n;
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 7be9e865325d9..36dd9d4a46ae0 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -1607,12 +1607,10 @@ static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
start = s;
}
}
- console_conditional_schedule();
s++;
} while (s < le);
if (s > start)
fbcon_putcs(vc, start, s - start, dy, x);
- console_conditional_schedule();
dy++;
}
}
@@ -1648,14 +1646,12 @@ static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info,
}
scr_writew(c, d);
- console_conditional_schedule();
s++;
d++;
} while (s < le);
if (s > start)
par->bitops->bmove(vc, info, line + ycount, x, line, x, 1,
s - start);
- console_conditional_schedule();
if (ycount > 0)
line++;
else {
@@ -1703,13 +1699,11 @@ static void fbcon_redraw(struct vc_data *vc, int line, int count, int offset)
}
}
scr_writew(c, d);
- console_conditional_schedule();
s++;
d++;
} while (s < le);
if (s > start)
fbcon_putcs(vc, start, s - start, line, x);
- console_conditional_schedule();
if (offset > 0)
line++;
else {
diff --git a/include/linux/console.h b/include/linux/console.h
index fc9f5c5c1b04c..ec506d3501965 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -697,7 +697,6 @@ extern int unregister_console(struct console *);
extern void console_lock(void);
extern int console_trylock(void);
extern void console_unlock(void);
-extern void console_conditional_schedule(void);
extern void console_unblank(void);
extern void console_flush_on_panic(enum con_flush_mode mode);
extern struct tty_driver *console_device(int *);
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 1d765ad242b82..9296bf41aa49d 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -3362,22 +3362,6 @@ void console_unlock(void)
}
EXPORT_SYMBOL(console_unlock);
-/**
- * console_conditional_schedule - yield the CPU if required
- *
- * If the console code is currently allowed to sleep, and
- * if this CPU should yield the CPU to another task, do
- * so here.
- *
- * Must be called within console_lock();.
- */
-void __sched console_conditional_schedule(void)
-{
- if (console_may_schedule)
- cond_resched();
-}
-EXPORT_SYMBOL(console_conditional_schedule);
-
void console_unblank(void)
{
bool found_unblank = false;
--
2.51.0
On Mon 2026-01-26 19:08:36, Sebastian Andrzej Siewior wrote:
> do_con_write(), fbcon_redraw.*() invoke console_conditional_schedule()
> which is a conditional scheduling point based on printk's internal
> variables console_may_schedule. It may only be used if the console lock
> is acquired for instance via console_lock() or console_trylock().
>
> Prinkt sets the internal variable to 1 (and allows to schedule)
> if the console lock has been acquired via console_lock(). The trylock
> does not allow it.
>
> The console_conditional_schedule() invocation in do_con_write() is
> invoked shortly before console_unlock().
> The console_conditional_schedule() invocation in fbcon_redraw.*()
> original from fbcon_scroll() / vt's con_scroll() which originate from a
> line feed.
>
> In console_unlock() the variable is set to 0 (forbids to schedule) and
> it tries to schedule while making progress printing. This is brand new
> compared to when console_conditional_schedule() was added in v2.4.9.11.
>
> In v2.6.38-rc3, console_unlock() (started its existence) iterated over
> all consoles and flushed them with disabled interrupts. A scheduling
> attempt here was not possible, it relied that a long print scheduled
> before console_unlock().
>
> Since commit 8d91f8b15361d ("printk: do cond_resched() between lines
> while outputting to consoles"), which appeared in v4.5-rc1,
> console_unlock() attempts to schedule if it was allowed to schedule
> while during console_lock(). Each record is idealy one line so after
> every line feed.
>
> This console_conditional_schedule() is also only relevant on
> PREEMPT_NONE and PREEMPT_VOLUNTARY builds. In other configurations
> cond_resched() becomes a nop and has no impact.
>
> I'm bringing this all up just proof that it is not required anymore. It
> becomes a problem on a PREEMPT_RT build with debug code enabled because
> that might_sleep() in cond_resched() remains and triggers a warnings.
> This is due to
>
> legacy_kthread_func-> console_flush_one_record -> vt_console_print-> lf
> -> con_scroll -> fbcon_scroll
>
> and vt_console_print() acquires a spinlock_t which does not allow a
> voluntary schedule. There is no need to fb_scroll() to schedule since
> console_flush_one_record() attempts to schedule after each line.
> !PREEMPT_RT is not affected because the legacy printing thread is only
> enabled on PREEMPT_RT builds.
>
> Therefore I suggest to remove console_conditional_schedule().
>
> Cc: Simona Vetter <simona@ffwll.ch>
> Cc: Helge Deller <deller@gmx.de>
> Cc: linux-fbdev@vger.kernel.org
> Cc: dri-devel@lists.freedesktop.org
> Fixes: 5f53ca3ff83b4 ("printk: Implement legacy printer kthread for PREEMPT_RT")
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Just for record. This change looks OK from printk() POV.
printk() does console_trylock() and calls console_unlock()
with preemption disabled anyway, see vprintk_emit().
VT code still synchronizes some operations using console_lock().
It is possible that some non-printk related operations rely
on this. But it is hard to say. It might actually be a good
idea to find it out.
Also I have seen many printk-related softlockups. But they
were always caused by slow serial consoles. I can't remember
any in VT code.
Feel free to use:
Acked-by: Petr Mladek <pmladek@suse.com> # from printk() POV
Best Regards,
Petr
On Mon, Jan 26, 2026 at 07:08:36PM +0100, Sebastian Andrzej Siewior wrote:
> do_con_write(), fbcon_redraw.*() invoke console_conditional_schedule()
> which is a conditional scheduling point based on printk's internal
> variables console_may_schedule. It may only be used if the console lock
> is acquired for instance via console_lock() or console_trylock().
>
> Prinkt sets the internal variable to 1 (and allows to schedule)
> if the console lock has been acquired via console_lock(). The trylock
> does not allow it.
>
> The console_conditional_schedule() invocation in do_con_write() is
> invoked shortly before console_unlock().
> The console_conditional_schedule() invocation in fbcon_redraw.*()
> original from fbcon_scroll() / vt's con_scroll() which originate from a
> line feed.
>
> In console_unlock() the variable is set to 0 (forbids to schedule) and
> it tries to schedule while making progress printing. This is brand new
> compared to when console_conditional_schedule() was added in v2.4.9.11.
>
> In v2.6.38-rc3, console_unlock() (started its existence) iterated over
> all consoles and flushed them with disabled interrupts. A scheduling
> attempt here was not possible, it relied that a long print scheduled
> before console_unlock().
>
> Since commit 8d91f8b15361d ("printk: do cond_resched() between lines
> while outputting to consoles"), which appeared in v4.5-rc1,
> console_unlock() attempts to schedule if it was allowed to schedule
> while during console_lock(). Each record is idealy one line so after
> every line feed.
>
> This console_conditional_schedule() is also only relevant on
> PREEMPT_NONE and PREEMPT_VOLUNTARY builds. In other configurations
> cond_resched() becomes a nop and has no impact.
>
> I'm bringing this all up just proof that it is not required anymore. It
> becomes a problem on a PREEMPT_RT build with debug code enabled because
> that might_sleep() in cond_resched() remains and triggers a warnings.
> This is due to
>
> legacy_kthread_func-> console_flush_one_record -> vt_console_print-> lf
> -> con_scroll -> fbcon_scroll
>
> and vt_console_print() acquires a spinlock_t which does not allow a
> voluntary schedule. There is no need to fb_scroll() to schedule since
> console_flush_one_record() attempts to schedule after each line.
> !PREEMPT_RT is not affected because the legacy printing thread is only
> enabled on PREEMPT_RT builds.
>
> Therefore I suggest to remove console_conditional_schedule().
>
> Cc: Simona Vetter <simona@ffwll.ch>
> Cc: Helge Deller <deller@gmx.de>
> Cc: linux-fbdev@vger.kernel.org
> Cc: dri-devel@lists.freedesktop.org
> Fixes: 5f53ca3ff83b4 ("printk: Implement legacy printer kthread for PREEMPT_RT")
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>
> A follow-up to
> https://lore.kernel.org/all/20260114145955.d924Z-zu@linutronix.de/
>
> drivers/tty/vt/vt.c | 1 -
> drivers/video/fbdev/core/fbcon.c | 6 ------
> include/linux/console.h | 1 -
> kernel/printk/printk.c | 16 ----------------
> 4 files changed, 24 deletions(-)
>
> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> index 59b4b5e126ba1..53daf7614b1af 100644
> --- a/drivers/tty/vt/vt.c
> +++ b/drivers/tty/vt/vt.c
> @@ -3236,7 +3236,6 @@ static int do_con_write(struct tty_struct *tty, const u8 *buf, int count)
> goto rescan_last_byte;
> }
> con_flush(vc, &draw);
> - console_conditional_schedule();
> notify_update(vc);
>
> return n;
No objection from me about removing this if it's not needed anymore!
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
On 1/27/26 15:24, Greg Kroah-Hartman wrote:
> On Mon, Jan 26, 2026 at 07:08:36PM +0100, Sebastian Andrzej Siewior wrote:
>> do_con_write(), fbcon_redraw.*() invoke console_conditional_schedule()
>> which is a conditional scheduling point based on printk's internal
>> variables console_may_schedule. It may only be used if the console lock
>> is acquired for instance via console_lock() or console_trylock().
>>
>> Prinkt sets the internal variable to 1 (and allows to schedule)
>> if the console lock has been acquired via console_lock(). The trylock
>> does not allow it.
>>
>> The console_conditional_schedule() invocation in do_con_write() is
>> invoked shortly before console_unlock().
>> The console_conditional_schedule() invocation in fbcon_redraw.*()
>> original from fbcon_scroll() / vt's con_scroll() which originate from a
>> line feed.
>>
>> In console_unlock() the variable is set to 0 (forbids to schedule) and
>> it tries to schedule while making progress printing. This is brand new
>> compared to when console_conditional_schedule() was added in v2.4.9.11.
>>
>> In v2.6.38-rc3, console_unlock() (started its existence) iterated over
>> all consoles and flushed them with disabled interrupts. A scheduling
>> attempt here was not possible, it relied that a long print scheduled
>> before console_unlock().
>>
>> Since commit 8d91f8b15361d ("printk: do cond_resched() between lines
>> while outputting to consoles"), which appeared in v4.5-rc1,
>> console_unlock() attempts to schedule if it was allowed to schedule
>> while during console_lock(). Each record is idealy one line so after
>> every line feed.
>>
>> This console_conditional_schedule() is also only relevant on
>> PREEMPT_NONE and PREEMPT_VOLUNTARY builds. In other configurations
>> cond_resched() becomes a nop and has no impact.
>>
>> I'm bringing this all up just proof that it is not required anymore. It
>> becomes a problem on a PREEMPT_RT build with debug code enabled because
>> that might_sleep() in cond_resched() remains and triggers a warnings.
>> This is due to
>>
>> legacy_kthread_func-> console_flush_one_record -> vt_console_print-> lf
>> -> con_scroll -> fbcon_scroll
>>
>> and vt_console_print() acquires a spinlock_t which does not allow a
>> voluntary schedule. There is no need to fb_scroll() to schedule since
>> console_flush_one_record() attempts to schedule after each line.
>> !PREEMPT_RT is not affected because the legacy printing thread is only
>> enabled on PREEMPT_RT builds.
>>
>> Therefore I suggest to remove console_conditional_schedule().
>>
>> Cc: Simona Vetter <simona@ffwll.ch>
>> Cc: Helge Deller <deller@gmx.de>
>> Cc: linux-fbdev@vger.kernel.org
>> Cc: dri-devel@lists.freedesktop.org
>> Fixes: 5f53ca3ff83b4 ("printk: Implement legacy printer kthread for PREEMPT_RT")
>> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>> ---
>>
>> A follow-up to
>> https://lore.kernel.org/all/20260114145955.d924Z-zu@linutronix.de/
>>
>> drivers/tty/vt/vt.c | 1 -
>> drivers/video/fbdev/core/fbcon.c | 6 ------
>> include/linux/console.h | 1 -
>> kernel/printk/printk.c | 16 ----------------
>> 4 files changed, 24 deletions(-)
>>
>> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
>> [....]
>
> No objection from me about removing this if it's not needed anymore!
>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
I've added it to the fbdev git tree to get some testing....
Thanks!
Helge
© 2016 - 2026 Red Hat, Inc.