at v2.6.27-rc4 67 lines 2.2 kB view raw
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. */ 29int 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 */ 40int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus); 41#else 42 43static 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 54static 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 */