Skip to content

Commit 29fda1a

Browse files
committed
printk: Reduce pr_flush() pooling time
pr_flush() does not guarantee that all messages would really get flushed to the console. The best it could do is to wait with a given timeout.[*] The current interval 100ms for checking the progress might seem too long in some situations. For example, such delays are not appreciated during suspend and resume especially when the consoles have been flushed "long" time before the check. On the other hand, the sleeping wait might be useful in other situations. Especially, it would allow flushing the messages using printk kthreads on the same CPU[*]. Use msleep(1) as a compromise. Also measure the time using jiffies. msleep() does not guarantee precise wakeup after the given delay. It might be much longer, especially for times < 20s. See Documentation/timers/timers-howto.rst for more details. Note that msecs_to_jiffies() already translates a negative value into an infinite timeout. [*] console_unlock() does not guarantee flushing the consoles since the commit dbdda84 ("printk: Add console owner and waiter logic to load balance console writes"). It would be possible to guarantee it another way. For example, the spinning might be enabled only when the console_lock has been taken via console_trylock(). But the load balancing is helpful. And more importantly, the flush with a timeout has been added as a preparation step for introducing printk kthreads. Signed-off-by: Petr Mladek <pmladek@suse.com> Reviewed-by: John Ogness <john.ogness@linutronix.de> Link: https://lore.kernel.org/r/20231006082151.6969-3-pmladek@suse.com
1 parent 054c22b commit 29fda1a

File tree

1 file changed

+13
-13
lines changed

1 file changed

+13
-13
lines changed

kernel/printk/printk.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3726,7 +3726,8 @@ late_initcall(printk_late_init);
37263726
/* If @con is specified, only wait for that console. Otherwise wait for all. */
37273727
static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress)
37283728
{
3729-
int remaining = timeout_ms;
3729+
unsigned long timeout_jiffies = msecs_to_jiffies(timeout_ms);
3730+
unsigned long remaining_jiffies = timeout_jiffies;
37303731
struct console *c;
37313732
u64 last_diff = 0;
37323733
u64 printk_seq;
@@ -3743,6 +3744,9 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
37433744
console_unlock();
37443745

37453746
for (;;) {
3747+
unsigned long begin_jiffies;
3748+
unsigned long slept_jiffies;
3749+
37463750
diff = 0;
37473751

37483752
/*
@@ -3771,24 +3775,20 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
37713775
console_srcu_read_unlock(cookie);
37723776

37733777
if (diff != last_diff && reset_on_progress)
3774-
remaining = timeout_ms;
3778+
remaining_jiffies = timeout_jiffies;
37753779

37763780
console_unlock();
37773781

37783782
/* Note: @diff is 0 if there are no usable consoles. */
3779-
if (diff == 0 || remaining == 0)
3783+
if (diff == 0 || remaining_jiffies == 0)
37803784
break;
37813785

3782-
if (remaining < 0) {
3783-
/* no timeout limit */
3784-
msleep(100);
3785-
} else if (remaining < 100) {
3786-
msleep(remaining);
3787-
remaining = 0;
3788-
} else {
3789-
msleep(100);
3790-
remaining -= 100;
3791-
}
3786+
/* msleep(1) might sleep much longer. Check time by jiffies. */
3787+
begin_jiffies = jiffies;
3788+
msleep(1);
3789+
slept_jiffies = jiffies - begin_jiffies;
3790+
3791+
remaining_jiffies -= min(slept_jiffies, remaining_jiffies);
37923792

37933793
last_diff = diff;
37943794
}

0 commit comments

Comments
 (0)