1 #ifndef _LINUX_STOP_MACHINE 2 #define _LINUX_STOP_MACHINE 3 /* "Bogolock": stop the entire machine, disable interrupts. This is a 4 very heavy lock, which is equivalent to grabbing every spinlock 5 (and more). So the "read" side to such a lock is anything which 6 diables preeempt. */ 7 #include <linux/cpu.h> 8 #include <linux/cpumask.h> 9 #include <asm/system.h> 10 11 #if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP) 12 13 /* Deprecated, but useful for transition. */ 14 #define ALL_CPUS ~0U 15 16 /** 17 * stop_machine: freeze the machine on all CPUs and run this function 18 * @fn: the function to run 19 * @data: the data ptr for the @fn() 20 * @cpus: the cpus to run the @fn() on (NULL = any online cpu) 21 * 22 * Description: This causes a thread to be scheduled on every cpu, 23 * each of which disables interrupts. The result is that noone is 24 * holding a spinlock or inside any other preempt-disabled region when 25 * @fn() runs. 26 * 27 * This can be thought of as a very heavy write lock, equivalent to 28 * grabbing every spinlock in the kernel. */ 29 int stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus); 30 31 /** 32 * __stop_machine: freeze the machine on all CPUs and run this function 33 * @fn: the function to run 34 * @data: the data ptr for the @fn 35 * @cpus: the cpus to run the @fn() on (NULL = any online cpu) 36 * 37 * Description: This is a special version of the above, which assumes cpus 38 * won't come or go while it's being called. Used by hotplug cpu. 39 */ 40 int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus); 41 #else 42 43 static inline int stop_machine(int (*fn)(void *), void *data, 44 const cpumask_t *cpus) 45 { 46 int ret; 47 local_irq_disable(); 48 ret = fn(data); 49 local_irq_enable(); 50 return ret; 51 } 52 #endif /* CONFIG_SMP */ 53 54 static inline int __deprecated stop_machine_run(int (*fn)(void *), void *data, 55 unsigned int cpu) 56 { 57 /* If they don't care which cpu fn runs on, just pick one. */ 58 if (cpu == NR_CPUS) 59 return stop_machine(fn, data, NULL); 60 else if (cpu == ~0U) 61 return stop_machine(fn, data, &cpu_possible_map); 62 else { 63 cpumask_t cpus = cpumask_of_cpu(cpu); 64 return stop_machine(fn, data, &cpus); 65 } 66 } 67 #endif /* _LINUX_STOP_MACHINE */ 68