Skip to content

Commit 1c6fd59

Browse files
committed
Merge branch 'rework/kthreads' into for-linus
2 parents a5c7a39 + 701850d commit 1c6fd59

File tree

12 files changed

+1034
-321
lines changed

12 files changed

+1034
-321
lines changed

drivers/tty/sysrq.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ void __handle_sysrq(int key, bool check_mask)
578578

579579
rcu_sysrq_start();
580580
rcu_read_lock();
581+
printk_prefer_direct_enter();
581582
/*
582583
* Raise the apparent loglevel to maximum so that the sysrq header
583584
* is shown to provide the user with positive feedback. We do not
@@ -619,6 +620,7 @@ void __handle_sysrq(int key, bool check_mask)
619620
pr_cont("\n");
620621
console_loglevel = orig_log_level;
621622
}
623+
printk_prefer_direct_exit();
622624
rcu_read_unlock();
623625
rcu_sysrq_end();
624626

include/linux/console.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <linux/atomic.h>
1818
#include <linux/types.h>
19+
#include <linux/mutex.h>
1920

2021
struct vc_data;
2122
struct console_font_op;
@@ -151,6 +152,24 @@ struct console {
151152
int cflag;
152153
uint ispeed;
153154
uint ospeed;
155+
u64 seq;
156+
unsigned long dropped;
157+
struct task_struct *thread;
158+
bool blocked;
159+
160+
/*
161+
* The per-console lock is used by printing kthreads to synchronize
162+
* this console with callers of console_lock(). This is necessary in
163+
* order to allow printing kthreads to run in parallel to each other,
164+
* while each safely accessing the @blocked field and synchronizing
165+
* against direct printing via console_lock/console_unlock.
166+
*
167+
* Note: For synchronizing against direct printing via
168+
* console_trylock/console_unlock, see the static global
169+
* variable @console_kthreads_active.
170+
*/
171+
struct mutex lock;
172+
154173
void *data;
155174
struct console *next;
156175
};

include/linux/printk.h

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ extern void __printk_safe_exit(void);
170170
#define printk_deferred_enter __printk_safe_enter
171171
#define printk_deferred_exit __printk_safe_exit
172172

173+
extern void printk_prefer_direct_enter(void);
174+
extern void printk_prefer_direct_exit(void);
175+
176+
extern bool pr_flush(int timeout_ms, bool reset_on_progress);
177+
173178
/*
174179
* Please don't use printk_ratelimit(), because it shares ratelimiting state
175180
* with all other unrelated printk_ratelimit() callsites. Instead use
@@ -220,6 +225,19 @@ static inline void printk_deferred_exit(void)
220225
{
221226
}
222227

228+
static inline void printk_prefer_direct_enter(void)
229+
{
230+
}
231+
232+
static inline void printk_prefer_direct_exit(void)
233+
{
234+
}
235+
236+
static inline bool pr_flush(int timeout_ms, bool reset_on_progress)
237+
{
238+
return true;
239+
}
240+
223241
static inline int printk_ratelimit(void)
224242
{
225243
return 0;
@@ -277,45 +295,57 @@ static inline void printk_trigger_flush(void)
277295
#endif
278296

279297
#ifdef CONFIG_SMP
280-
extern int __printk_cpu_trylock(void);
281-
extern void __printk_wait_on_cpu_lock(void);
282-
extern void __printk_cpu_unlock(void);
298+
extern int __printk_cpu_sync_try_get(void);
299+
extern void __printk_cpu_sync_wait(void);
300+
extern void __printk_cpu_sync_put(void);
301+
302+
#else
303+
304+
#define __printk_cpu_sync_try_get() true
305+
#define __printk_cpu_sync_wait()
306+
#define __printk_cpu_sync_put()
307+
#endif /* CONFIG_SMP */
283308

284309
/**
285-
* printk_cpu_lock_irqsave() - Acquire the printk cpu-reentrant spinning
286-
* lock and disable interrupts.
310+
* printk_cpu_sync_get_irqsave() - Disable interrupts and acquire the printk
311+
* cpu-reentrant spinning lock.
287312
* @flags: Stack-allocated storage for saving local interrupt state,
288-
* to be passed to printk_cpu_unlock_irqrestore().
313+
* to be passed to printk_cpu_sync_put_irqrestore().
289314
*
290315
* If the lock is owned by another CPU, spin until it becomes available.
291316
* Interrupts are restored while spinning.
317+
*
318+
* CAUTION: This function must be used carefully. It does not behave like a
319+
* typical lock. Here are important things to watch out for...
320+
*
321+
* * This function is reentrant on the same CPU. Therefore the calling
322+
* code must not assume exclusive access to data if code accessing the
323+
* data can run reentrant or within NMI context on the same CPU.
324+
*
325+
* * If there exists usage of this function from NMI context, it becomes
326+
* unsafe to perform any type of locking or spinning to wait for other
327+
* CPUs after calling this function from any context. This includes
328+
* using spinlocks or any other busy-waiting synchronization methods.
292329
*/
293-
#define printk_cpu_lock_irqsave(flags) \
294-
for (;;) { \
295-
local_irq_save(flags); \
296-
if (__printk_cpu_trylock()) \
297-
break; \
298-
local_irq_restore(flags); \
299-
__printk_wait_on_cpu_lock(); \
330+
#define printk_cpu_sync_get_irqsave(flags) \
331+
for (;;) { \
332+
local_irq_save(flags); \
333+
if (__printk_cpu_sync_try_get()) \
334+
break; \
335+
local_irq_restore(flags); \
336+
__printk_cpu_sync_wait(); \
300337
}
301338

302339
/**
303-
* printk_cpu_unlock_irqrestore() - Release the printk cpu-reentrant spinning
304-
* lock and restore interrupts.
305-
* @flags: Caller's saved interrupt state, from printk_cpu_lock_irqsave().
340+
* printk_cpu_sync_put_irqrestore() - Release the printk cpu-reentrant spinning
341+
* lock and restore interrupts.
342+
* @flags: Caller's saved interrupt state, from printk_cpu_sync_get_irqsave().
306343
*/
307-
#define printk_cpu_unlock_irqrestore(flags) \
344+
#define printk_cpu_sync_put_irqrestore(flags) \
308345
do { \
309-
__printk_cpu_unlock(); \
346+
__printk_cpu_sync_put(); \
310347
local_irq_restore(flags); \
311-
} while (0) \
312-
313-
#else
314-
315-
#define printk_cpu_lock_irqsave(flags) ((void)flags)
316-
#define printk_cpu_unlock_irqrestore(flags) ((void)flags)
317-
318-
#endif /* CONFIG_SMP */
348+
} while (0)
319349

320350
extern int kptr_restrict;
321351

kernel/hung_task.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
127127
* complain:
128128
*/
129129
if (sysctl_hung_task_warnings) {
130+
printk_prefer_direct_enter();
131+
130132
if (sysctl_hung_task_warnings > 0)
131133
sysctl_hung_task_warnings--;
132134
pr_err("INFO: task %s:%d blocked for more than %ld seconds.\n",
@@ -142,6 +144,8 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
142144

143145
if (sysctl_hung_task_all_cpu_backtrace)
144146
hung_task_show_all_bt = true;
147+
148+
printk_prefer_direct_exit();
145149
}
146150

147151
touch_nmi_watchdog();
@@ -204,12 +208,17 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
204208
}
205209
unlock:
206210
rcu_read_unlock();
207-
if (hung_task_show_lock)
211+
if (hung_task_show_lock) {
212+
printk_prefer_direct_enter();
208213
debug_show_all_locks();
214+
printk_prefer_direct_exit();
215+
}
209216

210217
if (hung_task_show_all_bt) {
211218
hung_task_show_all_bt = false;
219+
printk_prefer_direct_enter();
212220
trigger_all_cpu_backtrace();
221+
printk_prefer_direct_exit();
213222
}
214223

215224
if (hung_task_call_panic)

kernel/panic.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,8 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
560560
{
561561
disable_trace_on_warning();
562562

563+
printk_prefer_direct_enter();
564+
563565
if (file)
564566
pr_warn("WARNING: CPU: %d PID: %d at %s:%d %pS\n",
565567
raw_smp_processor_id(), current->pid, file, line,
@@ -597,6 +599,8 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
597599

598600
/* Just a warning, don't kill lockdep. */
599601
add_taint(taint, LOCKDEP_STILL_OK);
602+
603+
printk_prefer_direct_exit();
600604
}
601605

602606
#ifndef __WARN_FLAGS

0 commit comments

Comments
 (0)