File: /Users/paulross/dev/linux/linux-3.13/include/linux/stop_machine.h

Green shading in the line number column means the source is part of the translation unit, red means it is conditionally excluded. Highlighted line numbers link to the translation unit page. Highlighted macros link to the macro page.

       1: #ifndef _LINUX_STOP_MACHINE
       2: #define _LINUX_STOP_MACHINE
       3: 
       4: #include <linux/cpu.h>
       5: #include <linux/cpumask.h>
       6: #include <linux/smp.h>
       7: #include <linux/list.h>
       8: 
       9: /*
      10:  * stop_cpu[s]() is simplistic per-cpu maximum priority cpu
      11:  * monopolization mechanism.  The caller can specify a non-sleeping
      12:  * function to be executed on a single or multiple cpus preempting all
      13:  * other processes and monopolizing those cpus until it finishes.
      14:  *
      15:  * Resources for this mechanism are preallocated when a cpu is brought
      16:  * up and requests are guaranteed to be served as long as the target
      17:  * cpus are online.
      18:  */
      19: typedef int (*cpu_stop_fn_t)(void *arg);
      20: 
      21: #ifdef CONFIG_SMP
      22: 
      23: struct cpu_stop_work {
      24:     struct list_head    list;        /* cpu_stopper->works */
      25:     cpu_stop_fn_t        fn;
      26:     void            *arg;
      27:     struct cpu_stop_done    *done;
      28: };
      29: 
      30: int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg);
      31: int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *arg);
      32: void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
      33:              struct cpu_stop_work *work_buf);
      34: int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg);
      35: int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg);
      36: 
      37: #else    /* CONFIG_SMP */
      38: 
      39: #include <linux/workqueue.h>
      40: 
      41: struct cpu_stop_work {
      42:     struct work_struct    work;
      43:     cpu_stop_fn_t        fn;
      44:     void            *arg;
      45: };
      46: 
      47: static inline int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg)
      48: {
      49:     int ret = -ENOENT;
      50:     preempt_disable();
      51:     if (cpu == smp_processor_id())
      52:         ret = fn(arg);
      53:     preempt_enable();
      54:     return ret;
      55: }
      56: 
      57: static void stop_one_cpu_nowait_workfn(struct work_struct *work)
      58: {
      59:     struct cpu_stop_work *stwork =
      60:         container_of(work, struct cpu_stop_work, work);
      61:     preempt_disable();
      62:     stwork->fn(stwork->arg);
      63:     preempt_enable();
      64: }
      65: 
      66: static inline void stop_one_cpu_nowait(unsigned int cpu,
      67:                        cpu_stop_fn_t fn, void *arg,
      68:                        struct cpu_stop_work *work_buf)
      69: {
      70:     if (cpu == smp_processor_id()) {
      71:         INIT_WORK(&work_buf->work, stop_one_cpu_nowait_workfn);
      72:         work_buf->fn = fn;
      73:         work_buf->arg = arg;
      74:         schedule_work(&work_buf->work);
      75:     }
      76: }
      77: 
      78: static inline int stop_cpus(const struct cpumask *cpumask,
      79:                 cpu_stop_fn_t fn, void *arg)
      80: {
      81:     if (cpumask_test_cpu(raw_smp_processor_id(), cpumask))
      82:         return stop_one_cpu(raw_smp_processor_id(), fn, arg);
      83:     return -ENOENT;
      84: }
      85: 
      86: static inline int try_stop_cpus(const struct cpumask *cpumask,
      87:                 cpu_stop_fn_t fn, void *arg)
      88: {
      89:     return stop_cpus(cpumask, fn, arg);
      90: }
      91: 
      92: #endif    /* CONFIG_SMP */
      93: 
      94: /*
      95:  * stop_machine "Bogolock": stop the entire machine, disable
      96:  * interrupts.  This is a very heavy lock, which is equivalent to
      97:  * grabbing every spinlock (and more).  So the "read" side to such a
      98:  * lock is anything which disables preemption.
      99:  */
     100: #if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP)
     101: 
     102: /**
     103:  * stop_machine: freeze the machine on all CPUs and run this function
     104:  * @fn: the function to run
     105:  * @data: the data ptr for the @fn()
     106:  * @cpus: the cpus to run the @fn() on (NULL = any online cpu)
     107:  *
     108:  * Description: This causes a thread to be scheduled on every cpu,
     109:  * each of which disables interrupts.  The result is that no one is
     110:  * holding a spinlock or inside any other preempt-disabled region when
     111:  * @fn() runs.
     112:  *
     113:  * This can be thought of as a very heavy write lock, equivalent to
     114:  * grabbing every spinlock in the kernel. */
     115: int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
     116: 
     117: /**
     118:  * __stop_machine: freeze the machine on all CPUs and run this function
     119:  * @fn: the function to run
     120:  * @data: the data ptr for the @fn
     121:  * @cpus: the cpus to run the @fn() on (NULL = any online cpu)
     122:  *
     123:  * Description: This is a special version of the above, which assumes cpus
     124:  * won't come or go while it's being called.  Used by hotplug cpu.
     125:  */
     126: int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
     127: 
     128: int stop_machine_from_inactive_cpu(int (*fn)(void *), void *data,
     129:                    const struct cpumask *cpus);
     130: 
     131: #else     /* CONFIG_STOP_MACHINE && CONFIG_SMP */
     132: 
     133: static inline int __stop_machine(int (*fn)(void *), void *data,
     134:                  const struct cpumask *cpus)
     135: {
     136:     unsigned long flags;
     137:     int ret;
     138:     local_irq_save(flags);
     139:     ret = fn(data);
     140:     local_irq_restore(flags);
     141:     return ret;
     142: }
     143: 
     144: static inline int stop_machine(int (*fn)(void *), void *data,
     145:                    const struct cpumask *cpus)
     146: {
     147:     return __stop_machine(fn, data, cpus);
     148: }
     149: 
     150: static inline int stop_machine_from_inactive_cpu(int (*fn)(void *), void *data,
     151:                          const struct cpumask *cpus)
     152: {
     153:     return __stop_machine(fn, data, cpus);
     154: }
     155: 
     156: #endif    /* CONFIG_STOP_MACHINE && CONFIG_SMP */
     157: #endif    /* _LINUX_STOP_MACHINE */
     158: