stop_machine.h 2.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2
#ifndef _LINUX_STOP_MACHINE
#define _LINUX_STOP_MACHINE
T
Tejun Heo 已提交
3

L
Linus Torvalds 已提交
4
#include <linux/cpu.h>
5
#include <linux/cpumask.h>
T
Tejun Heo 已提交
6
#include <linux/list.h>
L
Linus Torvalds 已提交
7 8 9
#include <asm/system.h>

#if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP)
J
Jason Baron 已提交
10

T
Tejun Heo 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
/*
 * stop_cpu[s]() is simplistic per-cpu maximum priority cpu
 * monopolization mechanism.  The caller can specify a non-sleeping
 * function to be executed on a single or multiple cpus preempting all
 * other processes and monopolizing those cpus until it finishes.
 *
 * Resources for this mechanism are preallocated when a cpu is brought
 * up and requests are guaranteed to be served as long as the target
 * cpus are online.
 */

typedef int (*cpu_stop_fn_t)(void *arg);

struct cpu_stop_work {
	struct list_head	list;		/* cpu_stopper->works */
	cpu_stop_fn_t		fn;
	void			*arg;
	struct cpu_stop_done	*done;
};

int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg);
void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
			 struct cpu_stop_work *work_buf);
int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg);
int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg);

/*
 * stop_machine "Bogolock": stop the entire machine, disable
 * interrupts.  This is a very heavy lock, which is equivalent to
 * grabbing every spinlock (and more).  So the "read" side to such a
 * lock is anything which disables preeempt.
 */

L
Linus Torvalds 已提交
44
/**
45
 * stop_machine: freeze the machine on all CPUs and run this function
L
Linus Torvalds 已提交
46 47
 * @fn: the function to run
 * @data: the data ptr for the @fn()
48
 * @cpus: the cpus to run the @fn() on (NULL = any online cpu)
L
Linus Torvalds 已提交
49
 *
R
Rusty Russell 已提交
50 51 52 53
 * Description: This causes a thread to be scheduled on every cpu,
 * each of which disables interrupts.  The result is that noone is
 * holding a spinlock or inside any other preempt-disabled region when
 * @fn() runs.
L
Linus Torvalds 已提交
54 55 56
 *
 * This can be thought of as a very heavy write lock, equivalent to
 * grabbing every spinlock in the kernel. */
57
int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
L
Linus Torvalds 已提交
58 59

/**
60
 * __stop_machine: freeze the machine on all CPUs and run this function
L
Linus Torvalds 已提交
61 62
 * @fn: the function to run
 * @data: the data ptr for the @fn
63
 * @cpus: the cpus to run the @fn() on (NULL = any online cpu)
L
Linus Torvalds 已提交
64
 *
R
Rusty Russell 已提交
65 66
 * Description: This is a special version of the above, which assumes cpus
 * won't come or go while it's being called.  Used by hotplug cpu.
L
Linus Torvalds 已提交
67
 */
68
int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
69

L
Linus Torvalds 已提交
70 71
#else

72
static inline int stop_machine(int (*fn)(void *), void *data,
73
			       const struct cpumask *cpus)
L
Linus Torvalds 已提交
74 75 76 77 78 79 80
{
	int ret;
	local_irq_disable();
	ret = fn(data);
	local_irq_enable();
	return ret;
}
81

L
Linus Torvalds 已提交
82 83
#endif /* CONFIG_SMP */
#endif /* _LINUX_STOP_MACHINE */