aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/cpu.h
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-02-25 13:34:39 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-03-11 16:20:25 -0400
commit8038dad7e888581266c76df15d70ca457a3c5910 (patch)
treea921a15c300418540c71a410a1caf558d6ba8a80 /include/linux/cpu.h
parentc517d838eb7d07bbe9507871fab3931deccff539 (diff)
smpboot: Add common code for notification from dying CPU
RCU ignores offlined CPUs, so they cannot safely run RCU read-side code. (They -can- use SRCU, but not RCU.) This means that any use of RCU during or after the call to arch_cpu_idle_dead(). Unfortunately, commit 2ed53c0d6cc99 added a complete() call, which will contain RCU read-side critical sections if there is a task waiting to be awakened. Which, as it turns out, there almost never is. In my qemu/KVM testing, the to-be-awakened task is not yet asleep more than 99.5% of the time. In current mainline, failure is even harder to reproduce, requiring a virtualized environment that delays the outgoing CPU by at least three jiffies between the time it exits its stop_machine() task at CPU_DYING time and the time it calls arch_cpu_idle_dead() from the idle loop. However, this problem really can occur, especially in virtualized environments, and therefore really does need to be fixed This suggests moving back to the polling loop, but using a much shorter wait, with gentle exponential backoff instead of the old 100-millisecond wait. Most of the time, the loop will exit without waiting at all, and almost all of the remaining uses will wait only five microseconds. If the outgoing CPU is preempted, a loop will wait one jiffy, then increase the wait by a factor of 11/10ths, rounding up. As before, there is a five-second timeout. This commit therefore provides common-code infrastructure to do the dying-to-surviving CPU handoff in a safe manner. This code also provides an indication at CPU-online of whether the CPU to be onlined previously timed out on offline. The new cpu_check_up_prepare() function returns -EBUSY if this CPU previously took more than five seconds to go offline, or -EAGAIN if it has not yet managed to go offline. The rationale for -EAGAIN is that it might still be preempted, so an additional wait might well find it correctly offlined. Architecture-specific code can decide how to handle these conditions. Systems in which CPUs take themselves completely offline might respond to an -EBUSY return as if it was a zero (success) return. Systems in which the surviving CPU must take some action might take it at this time, or might simply mark the other CPU as unusable. Note that architectures that take the easy way out and simply pass the -EBUSY and -EAGAIN upwards will change the sysfs API. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: <linux-api@vger.kernel.org> Cc: <linux-arch@vger.kernel.org> [ paulmck: Fixed state machine for architectures that don't check earlier CPU-hotplug results as suggested by James Hogan. ]
Diffstat (limited to 'include/linux/cpu.h')
-rw-r--r--include/linux/cpu.h12
1 files changed, 12 insertions, 0 deletions
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 4260e8594bd7..4744ef915acd 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -95,6 +95,8 @@ enum {
95 * Called on the new cpu, just before 95 * Called on the new cpu, just before
96 * enabling interrupts. Must not sleep, 96 * enabling interrupts. Must not sleep,
97 * must not fail */ 97 * must not fail */
98#define CPU_BROKEN 0x000C /* CPU (unsigned)v did not die properly,
99 * perhaps due to preemption. */
98 100
99/* Used for CPU hotplug events occurring while tasks are frozen due to a suspend 101/* Used for CPU hotplug events occurring while tasks are frozen due to a suspend
100 * operation in progress 102 * operation in progress
@@ -271,4 +273,14 @@ void arch_cpu_idle_enter(void);
271void arch_cpu_idle_exit(void); 273void arch_cpu_idle_exit(void);
272void arch_cpu_idle_dead(void); 274void arch_cpu_idle_dead(void);
273 275
276DECLARE_PER_CPU(bool, cpu_dead_idle);
277
278int cpu_report_state(int cpu);
279int cpu_check_up_prepare(int cpu);
280void cpu_set_state_online(int cpu);
281#ifdef CONFIG_HOTPLUG_CPU
282bool cpu_wait_death(unsigned int cpu, int seconds);
283bool cpu_report_death(void);
284#endif /* #ifdef CONFIG_HOTPLUG_CPU */
285
274#endif /* _LINUX_CPU_H_ */ 286#endif /* _LINUX_CPU_H_ */