/* Allow everyone to use the CPU hotplug again */ cpu_maps_update_begin(); cpu_hotplug_disabled = 0; if (cpumask_empty(frozen_cpus)) goto out; printk(KERN_INFO "Enabling non-boot CPUs ...\n"); arch_enable_nonboot_cpus_begin(); for_each_cpu(cpu, frozen_cpus) { error = _cpu_up(cpu, 1); if (!error) { printk(KERN_INFO "CPU%d is up\n", cpu); continue; } printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error); } arch_enable_nonboot_cpus_end(); cpumask_clear(frozen_cpus);out: cpu_maps_update_done();} static int __init alloc_frozen_cpus(void){ if (!alloc_cpumask_var(&frozen_cpus, GFP_KERNEL|__GFP_ZERO)) return -ENOMEM; return 0;}core_initcall(alloc_frozen_cpus); /* * Prevent regular CPU hotplug from racing with the freezer, by disabling CPU * hotplug when tasks are about to be frozen. Also, don't allow the freezer * to continue until any currently running CPU hotplug operation gets * completed. * To modify the 'cpu_hotplug_disabled' flag, we need to acquire the * 'cpu_add_remove_lock'. And this same lock is also taken by the regular * CPU hotplug path and released only after it is complete. Thus, we * (and hence the freezer) will block here until any currently running CPU * hotplug operation gets completed. */void cpu_hotplug_disable_before_freeze(void){ cpu_maps_update_begin(); cpu_hotplug_disabled = 1; cpu_maps_update_done();} /* * When tasks have been thawed, re-enable regular CPU hotplug (which had been * disabled while beginning to freeze tasks). */void cpu_hotplug_enable_after_thaw(void){ cpu_maps_update_begin(); cpu_hotplug_disabled = 0; cpu_maps_update_done();} /* * When callbacks for CPU hotplug notifications are being executed, we must * ensure that the state of the system with respect to the tasks being frozen * or not, as reported by the notification, remains unchanged *throughout the * duration* of the execution of the callbacks. * Hence we need to prevent the freezer from racing with regular CPU hotplug. * * This synchronization is implemented by mutually excluding regular CPU * hotplug and Suspend/Hibernate call paths by hooking onto the Suspend/ * Hibernate notifications. */static intcpu_hotplug_pm_callback(struct notifier_block *nb, unsigned long action, void *ptr){ switch (action) { case PM_SUSPEND_PREPARE: case PM_HIBERNATION_PREPARE: cpu_hotplug_disable_before_freeze(); break; case PM_POST_SUSPEND: case PM_POST_HIBERNATION: cpu_hotplug_enable_after_thaw(); break; default: return NOTIFY_DONE; } return NOTIFY_OK;} static int __init cpu_hotplug_pm_sync_init(void){ pm_notifier(cpu_hotplug_pm_callback, 0); return 0;}core_initcall(cpu_hotplug_pm_sync_init); #endif /* CONFIG_PM_SLEEP_SMP */ /** * notify_cpu_starting(cpu) - call the CPU_STARTING notifiers * @cpu: cpu that just started * * This function calls the cpu_chain notifiers with CPU_STARTING. * It must be called by the arch code on the new cpu, before the new cpu * enables interrupts and before the "boot" cpu returns from __cpu_up(). */void __cpuinit notify_cpu_starting(unsigned int cpu){ unsigned long val = CPU_STARTING; #ifdef CONFIG_PM_SLEEP_SMP if (frozen_cpus != NULL && cpumask_test_cpu(cpu, frozen_cpus)) val = CPU_STARTING_FROZEN;#endif /* CONFIG_PM_SLEEP_SMP */ cpu_notify(val, (void *)(long)cpu);} #endif /* CONFIG_SMP */ /* * cpu_bit_bitmap[] is a special, "compressed" data structure that * represents all NR_CPUS bits binary values of 1<<nr. * * It is used by cpumask_of() to get a constant address to a CPU * mask value that has a single bit set only. */ /* cpu_bit_bitmap[0] is empty - so we can back into it */#define MASK_DECLARE_1(x) [x+1][0] = (1UL << (x))#define MASK_DECLARE_2(x) MASK_DECLARE_1(x), MASK_DECLARE_1(x+1)#define MASK_DECLARE_4(x) MASK_DECLARE_2(x), MASK_DECLARE_2(x+2)#define MASK_DECLARE_8(x) MASK_DECLARE_4(x), MASK_DECLARE_4(x+4) const unsigned long cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)] = { MASK_DECLARE_8(0), MASK_DECLARE_8(8), MASK_DECLARE_8(16), MASK_DECLARE_8(24),#if BITS_PER_LONG > 32 MASK_DECLARE_8(32), MASK_DECLARE_8(40), MASK_DECLARE_8(48), MASK_DECLARE_8(56),#endif};EXPORT_SYMBOL_GPL(cpu_bit_bitmap); const DECLARE_BITMAP(cpu_all_bits, NR_CPUS) = CPU_BITS_ALL;EXPORT_SYMBOL(cpu_all_bits); #ifdef CONFIG_INIT_ALL_POSSIBLEstatic DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly = CPU_BITS_ALL;#elsestatic DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly;#endifconst struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits);EXPORT_SYMBOL(cpu_possible_mask); static DECLARE_BITMAP(cpu_online_bits, CONFIG_NR_CPUS) __read_mostly;const struct cpumask *const cpu_online_mask = to_cpumask(cpu_online_bits);EXPORT_SYMBOL(cpu_online_mask); static DECLARE_BITMAP(cpu_present_bits, CONFIG_NR_CPUS) __read_mostly;const struct cpumask *const cpu_present_mask = to_cpumask(cpu_present_bits);EXPORT_SYMBOL(cpu_present_mask); static DECLARE_BITMAP(cpu_active_bits, CONFIG_NR_CPUS) __read_mostly;const struct cpumask *const cpu_active_mask = to_cpumask(cpu_active_bits);EXPORT_SYMBOL(cpu_active_mask); void set_cpu_possible(unsigned int cpu, bool possible){ if (possible) cpumask_set_cpu(cpu, to_cpumask(cpu_possible_bits)); else cpumask_clear_cpu(cpu, to_cpumask(cpu_possible_bits));} void set_cpu_present(unsigned int cpu, bool present){ if (present) cpumask_set_cpu(cpu, to_cpumask(cpu_present_bits)); else cpumask_clear_cpu(cpu, to_cpumask(cpu_present_bits));} void set_cpu_online(unsigned int cpu, bool online){ if (online) cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits)); else cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits));} void set_cpu_active(unsigned int cpu, bool active){ if (active) cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits)); else cpumask_clear_cpu(cpu, to_cpumask(cpu_active_bits));} void init_cpu_present(const struct cpumask *src){ cpumask_copy(to_cpumask(cpu_present_bits), src);} void init_cpu_possible(const struct cpumask *src){ cpumask_copy(to_cpumask(cpu_possible_bits), src);} void init_cpu_online(const struct cpumask *src){ cpumask_copy(to_cpumask(cpu_online_bits), src);}Lines 501–725 of 725. Previous lines
/* Allow everyone to use the CPU hotplug again */ cpu_maps_update_begin(); cpu_hotplug_disabled = 0; if (cpumask_empty(frozen_cpus)) goto out; printk(KERN_INFO "Enabling non-boot CPUs ...\n"); arch_enable_nonboot_cpus_begin(); for_each_cpu(cpu, frozen_cpus) { error = _cpu_up(cpu, 1); if (!error) { printk(KERN_INFO "CPU%d is up\n", cpu); continue; } printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error); } arch_enable_nonboot_cpus_end(); cpumask_clear(frozen_cpus); out: cpu_maps_update_done(); } static int __init alloc_frozen_cpus(void) { if (!alloc_cpumask_var(&frozen_cpus, GFP_KERNEL|__GFP_ZERO)) return -ENOMEM; return 0; } core_initcall(alloc_frozen_cpus); /* * Prevent regular CPU hotplug from racing with the freezer, by disabling CPU * hotplug when tasks are about to be frozen. Also, don't allow the freezer * to continue until any currently running CPU hotplug operation gets * completed. * To modify the 'cpu_hotplug_disabled' flag, we need to acquire the * 'cpu_add_remove_lock'. And this same lock is also taken by the regular * CPU hotplug path and released only after it is complete. Thus, we * (and hence the freezer) will block here until any currently running CPU * hotplug operation gets completed. */ void cpu_hotplug_disable_before_freeze(void) { cpu_maps_update_begin(); cpu_hotplug_disabled = 1; cpu_maps_update_done(); } /* * When tasks have been thawed, re-enable regular CPU hotplug (which had been * disabled while beginning to freeze tasks). */ void cpu_hotplug_enable_after_thaw(void) { cpu_maps_update_begin(); cpu_hotplug_disabled = 0; cpu_maps_update_done(); } /* * When callbacks for CPU hotplug notifications are being executed, we must * ensure that the state of the system with respect to the tasks being frozen * or not, as reported by the notification, remains unchanged *throughout the * duration* of the execution of the callbacks. * Hence we need to prevent the freezer from racing with regular CPU hotplug. * * This synchronization is implemented by mutually excluding regular CPU * hotplug and Suspend/Hibernate call paths by hooking onto the Suspend/ * Hibernate notifications. */ static int cpu_hotplug_pm_callback(struct notifier_block *nb, unsigned long action, void *ptr) { switch (action) { case PM_SUSPEND_PREPARE: case PM_HIBERNATION_PREPARE: cpu_hotplug_disable_before_freeze(); break; case PM_POST_SUSPEND: case PM_POST_HIBERNATION: cpu_hotplug_enable_after_thaw(); break; default: return NOTIFY_DONE; } return NOTIFY_OK; } static int __init cpu_hotplug_pm_sync_init(void) { pm_notifier(cpu_hotplug_pm_callback, 0); return 0; } core_initcall(cpu_hotplug_pm_sync_init); #endif /* CONFIG_PM_SLEEP_SMP */ /** * notify_cpu_starting(cpu) - call the CPU_STARTING notifiers * @cpu: cpu that just started * * This function calls the cpu_chain notifiers with CPU_STARTING. * It must be called by the arch code on the new cpu, before the new cpu * enables interrupts and before the "boot" cpu returns from __cpu_up(). */ void __cpuinit notify_cpu_starting(unsigned int cpu) { unsigned long val = CPU_STARTING; #ifdef CONFIG_PM_SLEEP_SMP if (frozen_cpus != NULL && cpumask_test_cpu(cpu, frozen_cpus)) val = CPU_STARTING_FROZEN; #endif /* CONFIG_PM_SLEEP_SMP */ cpu_notify(val, (void *)(long)cpu); } #endif /* CONFIG_SMP */ /* * cpu_bit_bitmap[] is a special, "compressed" data structure that * represents all NR_CPUS bits binary values of 1<<nr. * * It is used by cpumask_of() to get a constant address to a CPU * mask value that has a single bit set only. */ /* cpu_bit_bitmap[0] is empty - so we can back into it */ #define MASK_DECLARE_1(x) [x+1][0] = (1UL << (x)) #define MASK_DECLARE_2(x) MASK_DECLARE_1(x), MASK_DECLARE_1(x+1) #define MASK_DECLARE_4(x) MASK_DECLARE_2(x), MASK_DECLARE_2(x+2) #define MASK_DECLARE_8(x) MASK_DECLARE_4(x), MASK_DECLARE_4(x+4) const unsigned long cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)] = { MASK_DECLARE_8(0), MASK_DECLARE_8(8), MASK_DECLARE_8(16), MASK_DECLARE_8(24), #if BITS_PER_LONG > 32 MASK_DECLARE_8(32), MASK_DECLARE_8(40), MASK_DECLARE_8(48), MASK_DECLARE_8(56), #endif }; EXPORT_SYMBOL_GPL(cpu_bit_bitmap); const DECLARE_BITMAP(cpu_all_bits, NR_CPUS) = CPU_BITS_ALL; EXPORT_SYMBOL(cpu_all_bits); #ifdef CONFIG_INIT_ALL_POSSIBLE static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly = CPU_BITS_ALL; #else static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly; #endif const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits); EXPORT_SYMBOL(cpu_possible_mask); static DECLARE_BITMAP(cpu_online_bits, CONFIG_NR_CPUS) __read_mostly; const struct cpumask *const cpu_online_mask = to_cpumask(cpu_online_bits); EXPORT_SYMBOL(cpu_online_mask); static DECLARE_BITMAP(cpu_present_bits, CONFIG_NR_CPUS) __read_mostly; const struct cpumask *const cpu_present_mask = to_cpumask(cpu_present_bits); EXPORT_SYMBOL(cpu_present_mask); static DECLARE_BITMAP(cpu_active_bits, CONFIG_NR_CPUS) __read_mostly; const struct cpumask *const cpu_active_mask = to_cpumask(cpu_active_bits); EXPORT_SYMBOL(cpu_active_mask); void set_cpu_possible(unsigned int cpu, bool possible) { if (possible) cpumask_set_cpu(cpu, to_cpumask(cpu_possible_bits)); else cpumask_clear_cpu(cpu, to_cpumask(cpu_possible_bits)); } void set_cpu_present(unsigned int cpu, bool present) { if (present) cpumask_set_cpu(cpu, to_cpumask(cpu_present_bits)); else cpumask_clear_cpu(cpu, to_cpumask(cpu_present_bits)); } void set_cpu_online(unsigned int cpu, bool online) { if (online) cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits)); else cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits)); } void set_cpu_active(unsigned int cpu, bool active) { if (active) cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits)); else cpumask_clear_cpu(cpu, to_cpumask(cpu_active_bits)); } void init_cpu_present(const struct cpumask *src) { cpumask_copy(to_cpumask(cpu_present_bits), src); } void init_cpu_possible(const struct cpumask *src) { cpumask_copy(to_cpumask(cpu_possible_bits), src); } void init_cpu_online(const struct cpumask *src) { cpumask_copy(to_cpumask(cpu_online_bits), src); }