~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/include/linux/stop_machine.h

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php