summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--init/main.c10
-rw-r--r--kernel/sched/core.c4
-rw-r--r--lib/smp_processor_id.c2
3 files changed, 14 insertions, 2 deletions
diff --git a/init/main.c b/init/main.c
index badae3bf08f1..df58a416dd1d 100644
--- a/init/main.c
+++ b/init/main.c
@@ -414,6 +414,16 @@ static noinline void __ref rest_init(void)
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);
/*
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 877241e9f2b0..c3e50cada84d 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6238,8 +6238,10 @@ void ___might_sleep(const char *file, int line, int preempt_offset)
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;
diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c
index 690d75b132fa..2fb007be0212 100644
--- a/lib/smp_processor_id.c
+++ b/lib/smp_processor_id.c
@@ -28,7 +28,7 @@ notrace static unsigned int check_preemption_disabled(const char *what1,
/*
* It is valid to assume CPU-locality during early bootup:
*/
- if (system_state != SYSTEM_RUNNING)
+ if (system_state < SYSTEM_SCHEDULING)
goto out;
/*