File: 0022-printk-avoid-preempt_disable-for-PREEMPT_RT.patch

package info (click to toggle)
linux 6.1.153-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 1,496,348 kB
  • sloc: ansic: 23,476,872; asm: 266,650; sh: 110,570; makefile: 49,899; python: 36,950; perl: 36,836; cpp: 6,055; yacc: 4,908; lex: 2,725; awk: 1,440; ruby: 25; sed: 5
file content (96 lines) | stat: -rw-r--r-- 3,426 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
From 39a7b7e2eac42d144c47998c3bb51c8eea3504dc Mon Sep 17 00:00:00 2001
From: John Ogness <john.ogness@linutronix.de>
Date: Fri, 4 Feb 2022 16:01:17 +0106
Subject: [PATCH 22/68] printk: avoid preempt_disable() for PREEMPT_RT
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.141-rt52.tar.xz

During non-normal operation, printk() calls will attempt to
write the messages directly to the consoles. This involves
using console_trylock() to acquire @console_sem.

Preemption is disabled while directly printing to the consoles
in order to ensure that the printing task is not scheduled away
while holding @console_sem, thus blocking all other printers
and causing delays in printing.

Commit fd5f7cde1b85 ("printk: Never set console_may_schedule in
console_trylock()") specifically reverted a previous attempt at
allowing preemption while printing.

However, on PREEMPT_RT systems, disabling preemption while
printing is not allowed because console drivers typically
acquire a spin lock (which under PREEMPT_RT is an rtmutex).
Since direct printing is only used during early boot and
non-panic dumps, the risks of delayed print output for these
scenarios will be accepted under PREEMPT_RT.

Signed-off-by: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 kernel/printk/printk.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 6dc27e34a4b6..73e11c1533ea 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2010,6 +2010,7 @@ static int console_lock_spinning_disable_and_check(void)
 	return 1;
 }
 
+#if !IS_ENABLED(CONFIG_PREEMPT_RT)
 /**
  * console_trylock_spinning - try to get console_lock by busy waiting
  *
@@ -2089,6 +2090,7 @@ static int console_trylock_spinning(void)
 
 	return 1;
 }
+#endif /* CONFIG_PREEMPT_RT */
 
 /*
  * Call the specified console driver, asking it to write out the specified
@@ -2428,6 +2430,18 @@ asmlinkage int vprintk_emit(int facility, int level,
 
 	/* If called from the scheduler, we can not call up(). */
 	if (!in_sched && allow_direct_printing()) {
+#if IS_ENABLED(CONFIG_PREEMPT_RT)
+		/*
+		 * Use the non-spinning trylock since PREEMPT_RT does not
+		 * support console lock handovers.
+		 *
+		 * Direct printing will most likely involve taking spinlocks.
+		 * For PREEMPT_RT, this is only allowed if in a preemptible
+		 * context.
+		 */
+		if (preemptible() && console_trylock())
+			console_unlock();
+#else
 		/*
 		 * The caller may be holding system-critical or
 		 * timing-sensitive locks. Disable preemption during direct
@@ -2445,6 +2459,7 @@ asmlinkage int vprintk_emit(int facility, int level,
 		if (console_trylock_spinning())
 			console_unlock();
 		preempt_enable();
+#endif
 	}
 
 	if (in_sched)
@@ -3154,8 +3169,12 @@ static bool console_emit_next_record_transferable(struct console *con, char *tex
 	/*
 	 * Handovers are only supported if threaded printers are atomically
 	 * blocked. The context taking over the console_lock may be atomic.
+	 *
+	 * PREEMPT_RT also does not support handovers because the spinning
+	 * waiter can cause large latencies.
 	 */
-	if (!console_kthreads_atomically_blocked()) {
+	if (!console_kthreads_atomically_blocked() ||
+	    IS_ENABLED(CONFIG_PREEMPT_RT)) {
 		*handover = false;
 		handover = NULL;
 	}
-- 
2.49.0