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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
From: John Ogness <john.ogness@linutronix.de>
Date: Tue, 5 Dec 2023 14:09:31 +0000
Subject: [PATCH 35/46] printk: nbcon: Start printing threads
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.9/older/patches-6.9-rt5.tar.xz
If there are no boot consoles, the printing threads are started
in early_initcall.
If there are boot consoles, the printing threads are started
after the last boot console has unregistered. The printing
threads do not need to be concerned about boot consoles because
boot consoles cannot register once a non-boot console has
registered.
Until a printing thread of a console has started, that console
will print using atomic_write() in the printk() caller context.
Signed-off-by: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
kernel/printk/internal.h | 2 ++
kernel/printk/nbcon.c | 18 +++++++++++++++++-
kernel/printk/printk.c | 14 ++++++++++++++
3 files changed, 33 insertions(+), 1 deletion(-)
--- a/kernel/printk/internal.h
+++ b/kernel/printk/internal.h
@@ -48,6 +48,7 @@ struct printk_ringbuffer;
struct dev_printk_info;
extern struct printk_ringbuffer *prb;
+extern bool printk_threads_enabled;
__printf(4, 0)
int vprintk_store(int facility, int level,
@@ -159,6 +160,7 @@ static inline void nbcon_kthread_wake(st
static inline void nbcon_kthread_wake(struct console *con) { }
static inline void nbcon_kthread_create(struct console *con) { }
+#define printk_threads_enabled (false)
/*
* In !PRINTK builds we still export console_sem
--- a/kernel/printk/nbcon.c
+++ b/kernel/printk/nbcon.c
@@ -213,6 +213,8 @@ static void nbcon_seq_try_update(struct
}
}
+bool printk_threads_enabled __ro_after_init;
+
/**
* nbcon_context_try_acquire_direct - Try to acquire directly
* @ctxt: The context of the caller
@@ -1522,7 +1524,7 @@ void nbcon_kthread_create(struct console
if (!(con->flags & CON_NBCON) || !con->write_thread)
return;
- if (con->kthread)
+ if (!printk_threads_enabled || con->kthread)
return;
/*
@@ -1548,6 +1550,19 @@ void nbcon_kthread_create(struct console
sched_set_normal(con->kthread, -20);
}
+static int __init printk_setup_threads(void)
+{
+ struct console *con;
+
+ console_list_lock();
+ printk_threads_enabled = true;
+ for_each_console(con)
+ nbcon_kthread_create(con);
+ console_list_unlock();
+ return 0;
+}
+early_initcall(printk_setup_threads);
+
/**
* nbcon_alloc - Allocate buffers needed by the nbcon console
* @con: Console to allocate buffers for
@@ -1597,6 +1612,7 @@ void nbcon_init(struct console *con, u64
init_irq_work(&con->irq_work, nbcon_irq_work);
nbcon_seq_force(con, init_seq);
nbcon_state_set(con, &state);
+ nbcon_kthread_create(con);
}
/**
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2389,6 +2389,9 @@ asmlinkage int vprintk_emit(int facility
*
* - When this CPU is in panic.
*
+ * - When booting, before the printing threads have been
+ * started.
+ *
* - During shutdown, since the printing threads may not get
* a chance to print the final messages.
*
@@ -2397,6 +2400,7 @@ asmlinkage int vprintk_emit(int facility
* consoles cannot print simultaneously with boot consoles.
*/
if (is_panic_context ||
+ !printk_threads_enabled ||
(system_state > SYSTEM_RUNNING)) {
nbcon_atomic_flush_pending();
}
@@ -3725,6 +3729,7 @@ EXPORT_SYMBOL(register_console);
/* Must be called under console_list_lock(). */
static int unregister_console_locked(struct console *console)
{
+ bool is_boot_con = (console->flags & CON_BOOT);
bool found_legacy_con = false;
bool found_nbcon_con = false;
bool found_boot_con = false;
@@ -3807,6 +3812,15 @@ static int unregister_console_locked(str
if (!found_nbcon_con)
have_nbcon_console = found_nbcon_con;
+ /*
+ * When the last boot console unregisters, start up the
+ * printing threads.
+ */
+ if (is_boot_con && !have_boot_console) {
+ for_each_console(c)
+ nbcon_kthread_create(c);
+ }
+
return res;
}
|