History

Fix PREEMPT_RCU without HOTPLUG_CPU

PREEMPT_RCU without HOTPLUG_CPU is broken. The rcu_online_cpu is called to initially populate rcu_cpu_online_map with all online CPUs when the hotplug event handler is installed, and also to populate the map with CPUs as they come online. The former case is meant to happen with and without HOTPLUG_CPU, but without HOTPLUG_CPU, the rcu_offline_cpu function is no-oped -- while it still gets called, it does not set the rcu CPU map. With a blank RCU CPU map, grace periods get to tick by completely oblivious to active RCU read side critical sections. This results in free-before-grace bugs. Fix is obvious once the problem is known. (Also, change __devinit to __cpuinit so the function gets thrown away on !HOTPLUG_CPU kernels).

Nick Piggin committed 18 years ago

Commit 70ff0551 parent eb6d42e1 file · +8 −12Browse files

Showing the changes to kernel (1 of 1 file). Show all

Unified · Split

kernel/rcupreempt.c+8−12
@@ -925,26 +925,22 @@ void rcu_offline_cpu(int cpu) · 924 unmodified lines
925925 spin_unlock_irqrestore(&rdp->lock, flags);
926926 }
927927
928−void __devinit rcu_online_cpu(int cpu)
929−{
930− unsigned long flags;
931−
932− spin_lock_irqsave(&rcu_ctrlblk.fliplock, flags);
933− cpu_set(cpu, rcu_cpu_online_map);
934− spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, flags);
935−}
936−
937928 #else /* #ifdef CONFIG_HOTPLUG_CPU */
938929
939930 void rcu_offline_cpu(int cpu)
940931 {
941932 }
942933
943−void __devinit rcu_online_cpu(int cpu)
934+#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
935+
936+void __cpuinit rcu_online_cpu(int cpu)
944937 {
945−}
938+ unsigned long flags;
946939
947−#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
940+ spin_lock_irqsave(&rcu_ctrlblk.fliplock, flags);
941+ cpu_set(cpu, rcu_cpu_online_map);
942+ spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, flags);
943+}
948944
949945 static void rcu_process_callbacks(struct softirq_action *unused)
950946 {