| From: Thomas Gleixner <tglx@linutronix.de> |
| Date: Tue, 16 May 2017 20:42:48 +0200 |
| Subject: [PATCH 17/17] sched/core: Enable might_sleep() and smp_processor_id() |
| checks early |
| |
| might_sleep() and smp_processor_id() checks are enabled after the boot |
| process is done. That hides bugs in the SMP bringup and driver |
| initialization code. |
| |
| Enable it right when the scheduler starts working, i.e. when init task and |
| kthreadd have been created and right before the idle task enables |
| preemption. |
| |
| Tested-by: Mark Rutland <mark.rutland@arm.com> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> |
| Acked-by: Mark Rutland <mark.rutland@arm.com> |
| Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Steven Rostedt <rostedt@goodmis.org> |
| Link: http://lkml.kernel.org/r/20170516184736.272225698@linutronix.de |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| --- |
| init/main.c | 10 ++++++++++ |
| kernel/sched/core.c | 4 +++- |
| lib/smp_processor_id.c | 2 +- |
| 3 files changed, 14 insertions(+), 2 deletions(-) |
| |
| --- a/init/main.c |
| +++ b/init/main.c |
| @@ -414,6 +414,16 @@ static noinline void __ref rest_init(voi |
| rcu_read_lock(); |
| kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns); |
| rcu_read_unlock(); |
| + |
| + /* |
| + * Enable might_sleep() and smp_processor_id() checks. |
| + * They cannot be enabled earlier because with CONFIG_PRREMPT=y |
| + * kernel_thread() would trigger might_sleep() splats. With |
| + * CONFIG_PREEMPT_VOLUNTARY=y the init task might have scheduled |
| + * already, but it's stuck on the kthreadd_done completion. |
| + */ |
| + system_state = SYSTEM_SCHEDULING; |
| + |
| complete(&kthreadd_done); |
| |
| /* |
| --- a/kernel/sched/core.c |
| +++ b/kernel/sched/core.c |
| @@ -6223,8 +6223,10 @@ void ___might_sleep(const char *file, in |
| |
| if ((preempt_count_equals(preempt_offset) && !irqs_disabled() && |
| !is_idle_task(current)) || |
| - system_state != SYSTEM_RUNNING || oops_in_progress) |
| + system_state == SYSTEM_BOOTING || system_state > SYSTEM_RUNNING || |
| + oops_in_progress) |
| return; |
| + |
| if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) |
| return; |
| prev_jiffy = jiffies; |
| --- a/lib/smp_processor_id.c |
| +++ b/lib/smp_processor_id.c |
| @@ -28,7 +28,7 @@ notrace static unsigned int check_preemp |
| /* |
| * It is valid to assume CPU-locality during early bootup: |
| */ |
| - if (system_state != SYSTEM_RUNNING) |
| + if (system_state < SYSTEM_SCHEDULING) |
| goto out; |
| |
| /* |