sched/core: Initialize the idle task with preemption disabled
As pointed out by commit de9b8f5d ("sched: Fix crash trying to dequeue/enqueue the idle thread") init_idle() can and will be invoked more than once on the same idle task. At boot time, it is invoked for the boot CPU thread by sched_init(). Then smp_init() creates the threads for all the secondary CPUs and invokes init_idle() on them. As the hotplug machinery brings the secondaries to life, it will issue calls to idle_thread_get(), which itself invokes init_idle() yet again. In this case it's invoked twice more per secondary: at _cpu_up(), and at bringup_cpu(). Given smp_init() already initializes the idle tasks for all *possible* CPUs, no further initialization should be required. Now, removing init_idle() from idle_thread_get() exposes some interesting expectations with regards to the idle task's preempt_count: the secondary startup always issues a preempt_disable(), requiring some reset of the preempt count to 0 between hot-unplug and hotplug, which is currently served by idle_thread_get() -> idle_init(). Given the idle task is supposed to have preemption disabled once and never see it re-enabled, it seems that what we actually want is to initialize its preempt_count to PREEMPT_DISABLED and leave it there. Do that, and remove init_idle() from idle_thread_get(). Secondary startups were patched via coccinelle: @begone@ @@ -preempt_disable(); ... cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); Signed-off-by:Valentin Schneider <valentin.schneider@arm.com> Signed-off-by:
Ingo Molnar <mingo@kernel.org> Acked-by:
Peter Zijlstra <peterz@infradead.org> Link: https://lore.kernel.org/r/20210512094636.2958515-1-valentin.schneider@arm.com
Showing
- arch/alpha/kernel/smp.c 0 additions, 1 deletionarch/alpha/kernel/smp.c
- arch/arc/kernel/smp.c 0 additions, 1 deletionarch/arc/kernel/smp.c
- arch/arm/kernel/smp.c 0 additions, 1 deletionarch/arm/kernel/smp.c
- arch/arm64/include/asm/preempt.h 1 addition, 1 deletionarch/arm64/include/asm/preempt.h
- arch/arm64/kernel/smp.c 0 additions, 1 deletionarch/arm64/kernel/smp.c
- arch/csky/kernel/smp.c 0 additions, 1 deletionarch/csky/kernel/smp.c
- arch/ia64/kernel/smpboot.c 0 additions, 1 deletionarch/ia64/kernel/smpboot.c
- arch/mips/kernel/smp.c 0 additions, 1 deletionarch/mips/kernel/smp.c
- arch/openrisc/kernel/smp.c 0 additions, 2 deletionsarch/openrisc/kernel/smp.c
- arch/parisc/kernel/smp.c 0 additions, 1 deletionarch/parisc/kernel/smp.c
- arch/powerpc/kernel/smp.c 0 additions, 1 deletionarch/powerpc/kernel/smp.c
- arch/riscv/kernel/smpboot.c 0 additions, 1 deletionarch/riscv/kernel/smpboot.c
- arch/s390/include/asm/preempt.h 2 additions, 2 deletionsarch/s390/include/asm/preempt.h
- arch/s390/kernel/smp.c 0 additions, 1 deletionarch/s390/kernel/smp.c
- arch/sh/kernel/smp.c 0 additions, 2 deletionsarch/sh/kernel/smp.c
- arch/sparc/kernel/smp_32.c 0 additions, 1 deletionarch/sparc/kernel/smp_32.c
- arch/sparc/kernel/smp_64.c 0 additions, 3 deletionsarch/sparc/kernel/smp_64.c
- arch/x86/include/asm/preempt.h 1 addition, 1 deletionarch/x86/include/asm/preempt.h
- arch/x86/kernel/smpboot.c 0 additions, 1 deletionarch/x86/kernel/smpboot.c
- arch/xtensa/kernel/smp.c 0 additions, 1 deletionarch/xtensa/kernel/smp.c
Loading
Please register or sign in to comment