Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b845b517 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar
Browse files

printk: robustify printk



Avoid deadlocks against rq->lock and xtime_lock by deferring the klogd
wakeup by polling from the timer tick.

Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 796aadeb
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -200,6 +200,8 @@ extern struct ratelimit_state printk_ratelimit_state;
extern int printk_ratelimit(void);
extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
				   unsigned int interval_msec);
extern void printk_tick(void);
extern int printk_needs_cpu(int);
#else
static inline int vprintk(const char *s, va_list args)
	__attribute__ ((format (printf, 1, 0)));
@@ -211,6 +213,8 @@ static inline int printk_ratelimit(void) { return 0; }
static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \
					  unsigned int interval_msec)	\
		{ return false; }
static inline void printk_tick(void) { }
static inline int printk_needs_cpu(int) { return 0; }
#endif

extern void asmlinkage __attribute__((format(printf, 1, 2)))
+17 −2
Original line number Diff line number Diff line
@@ -982,11 +982,26 @@ int is_console_locked(void)
	return console_locked;
}

void wake_up_klogd(void)
static DEFINE_PER_CPU(int, printk_pending);

void printk_tick(void)
{
	if (!oops_in_progress && waitqueue_active(&log_wait))
	if (__get_cpu_var(printk_pending)) {
		__get_cpu_var(printk_pending) = 0;
		wake_up_interruptible(&log_wait);
	}
}

int printk_needs_cpu(int cpu)
{
	return per_cpu(printk_pending, cpu);
}

void wake_up_klogd(void)
{
	if (waitqueue_active(&log_wait))
		__get_cpu_var(printk_pending) = 1;
}

/**
 * release_console_sem - unlock the console system
+1 −1
Original line number Diff line number Diff line
@@ -255,7 +255,7 @@ void tick_nohz_stop_sched_tick(int inidle)
	next_jiffies = get_next_timer_interrupt(last_jiffies);
	delta_jiffies = next_jiffies - last_jiffies;

	if (rcu_needs_cpu(cpu))
	if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu))
		delta_jiffies = 1;
	/*
	 * Do not stop the tick, if we are only one off
+1 −0
Original line number Diff line number Diff line
@@ -978,6 +978,7 @@ void update_process_times(int user_tick)
	run_local_timers();
	if (rcu_pending(cpu))
		rcu_check_callbacks(cpu, user_tick);
	printk_tick();
	scheduler_tick();
	run_posix_cpu_timers(p);
}