Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
C
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325/* SPDX-License-Identifier: GPL-2.0 */#ifndef __LINUX_SMP_H#define __LINUX_SMP_H
/* * Generic SMP support * Alan Cox. <alan@redhat.com> */
#include <linux/errno.h>#include <linux/types.h>#include <linux/list.h>#include <linux/cpumask.h>#include <linux/init.h>#include <linux/smp_types.h>
typedef void (*smp_call_func_t)(void *info);typedef bool (*smp_cond_func_t)(int cpu, void *info);
/* * structure shares (partial) layout with struct irq_work */struct __call_single_data { struct __call_single_node node; smp_call_func_t func; void *info;};
#define CSD_INIT(_func, _info) \ (struct __call_single_data){ .func = (_func), .info = (_info), }
/* Use __aligned() to avoid to use 2 cache lines for 1 csd */typedef struct __call_single_data call_single_data_t __aligned(sizeof(struct __call_single_data));
#define INIT_CSD(_csd, _func, _info) \do { \ *(_csd) = CSD_INIT((_func), (_info)); \} while (0)
/* * Enqueue a llist_node on the call_single_queue; be very careful, read * flush_smp_call_function_queue() in detail. */extern void __smp_call_single_queue(int cpu, struct llist_node *node);
/* total number of cpus in this system (may exceed NR_CPUS) */extern unsigned int total_cpus;
int smp_call_function_single(int cpuid, smp_call_func_t func, void *info, bool wait);
void on_each_cpu_cond_mask(smp_cond_func_t cond_func, smp_call_func_t func, void *info, bool wait, const struct cpumask *mask);
int smp_call_function_single_async(int cpu, call_single_data_t *csd);
/* * Cpus stopping functions in panic. All have default weak definitions. * Architecture-dependent code may override them. */void __noreturn panic_smp_self_stop(void);void __noreturn nmi_panic_self_stop(struct pt_regs *regs);void crash_smp_send_stop(void);int panic_smp_redirect_cpu(int target_cpu, void *msg);
/* * Call a function on all processors */static inline void on_each_cpu(smp_call_func_t func, void *info, int wait){ on_each_cpu_cond_mask(NULL, func, info, wait, cpu_online_mask);}
/** * on_each_cpu_mask() - Run a function on processors specified by * cpumask, which may include the local processor. * @mask: The set of cpus to run on (only runs on online subset). * @func: The function to run. This must be fast and non-blocking. * @info: An arbitrary pointer to pass to the function. * @wait: If true, wait (atomically) until function has completed * on other CPUs. * * If @wait is true, then returns once @func has returned. * * You must not call this function with disabled interrupts or from a * hardware interrupt handler or from a bottom half handler. The * exception is that it may be used during early boot while * early_boot_irqs_disabled is set. */static inline void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func, void *info, bool wait){ on_each_cpu_cond_mask(NULL, func, info, wait, mask);}
/* * Call a function on each processor for which the supplied function * cond_func returns a positive value. This may include the local * processor. May be used during early boot while early_boot_irqs_disabled is * set. Use local_irq_save/restore() instead of local_irq_disable/enable(). */static inline void on_each_cpu_cond(smp_cond_func_t cond_func, smp_call_func_t func, void *info, bool wait){ on_each_cpu_cond_mask(cond_func, func, info, wait, cpu_online_mask);}
/* * Architecture specific boot CPU setup. Defined as empty weak function in * init/main.c. Architectures can override it. */void __init smp_prepare_boot_cpu(void);
#ifdef CONFIG_SMP
#include <linux/preempt.h>#include <linux/compiler.h>#include <linux/thread_info.h>#include <asm/smp.h>
/* * main cross-CPU interfaces, handles INIT, TLB flush, STOP, etc. * (defined in asm header): */
/* * stops all CPUs but the current one: */extern void smp_send_stop(void);
/* * sends a 'reschedule' event to another CPU: */extern void arch_smp_send_reschedule(int cpu);/* * scheduler_ipi() is inline so can't be passed as callback reason, but the * callsite IP should be sufficient for root-causing IPIs sent from here. */#define smp_send_reschedule(cpu) ({ \ trace_ipi_send_cpu(cpu, _RET_IP_, NULL); \ arch_smp_send_reschedule(cpu); \})
/* * Prepare machine for booting other CPUs. */extern void smp_prepare_cpus(unsigned int max_cpus);
/* * Bring a CPU up */extern int __cpu_up(unsigned int cpunum, struct task_struct *tidle);
/* * Final polishing of CPUs */extern void smp_cpus_done(unsigned int max_cpus);
/* * Call a function on all other processors */void smp_call_function(smp_call_func_t func, void *info, int wait);void smp_call_function_many(const struct cpumask *mask, smp_call_func_t func, void *info, bool wait);
int smp_call_function_any(const struct cpumask *mask, smp_call_func_t func, void *info, int wait);
void kick_all_cpus_sync(void);void wake_up_all_idle_cpus(void);bool cpus_peek_for_pending_ipi(const struct cpumask *mask);
/* * Generic and arch helpers */void __init call_function_init(void);void generic_smp_call_function_single_interrupt(void);#define generic_smp_call_function_interrupt \ generic_smp_call_function_single_interrupt
extern unsigned int setup_max_cpus;extern void __init setup_nr_cpu_ids(void);extern void __init smp_init(void);
extern int __boot_cpu_id;
static inline int get_boot_cpu_id(void){ return __boot_cpu_id;}
#else /* !SMP */
static inline void smp_send_stop(void) { }
/* * These macros fold the SMP functionality into a single CPU system */#define raw_smp_processor_id() 0static inline void up_smp_call_function(smp_call_func_t func, void *info){}#define smp_call_function(func, info, wait) \ (up_smp_call_function(func, info))
static inline void smp_send_reschedule(int cpu) { }#define smp_call_function_many(mask, func, info, wait) \ (up_smp_call_function(func, info))static inline void call_function_init(void) { }
static inline intsmp_call_function_any(const struct cpumask *mask, smp_call_func_t func, void *info, int wait){ return smp_call_function_single(0, func, info, wait);}
static inline void kick_all_cpus_sync(void) { }static inline void wake_up_all_idle_cpus(void) { }static inline bool cpus_peek_for_pending_ipi(const struct cpumask *mask){ return false;}
#define setup_max_cpus 0
#ifdef CONFIG_UP_LATE_INITextern void __init up_late_init(void);static __always_inline void smp_init(void) { up_late_init(); }#elsestatic inline void smp_init(void) { }#endif
static inline int get_boot_cpu_id(void){ return 0;}
#endif /* !SMP */
#if defined(CONFIG_PREEMPTION) && defined(CONFIG_SMP)int smp_task_ipi_mask_alloc(struct task_struct *task);void smp_task_ipi_mask_free(struct task_struct *task);#elsestatic inline int smp_task_ipi_mask_alloc(struct task_struct *task){ return 0;}
static inline void smp_task_ipi_mask_free(struct task_struct *task) { }#endif
/* * raw_smp_processor_id() - get the current (unstable) CPU id * * raw_smp_processor_id() is arch-specific/arch-defined and * may be a macro or a static inline function. * * For when you know what you are doing and need an unstable * CPU id. */
/* * Allow the architecture to differentiate between a stable and unstable read. * For example, x86 uses an IRQ-safe asm-volatile read for the unstable but a * regular asm read for the stable. */#ifndef __smp_processor_id#define __smp_processor_id() raw_smp_processor_id()#endif
#ifdef CONFIG_DEBUG_PREEMPT extern unsigned int debug_smp_processor_id(void);# define smp_processor_id() debug_smp_processor_id()
#else/** * smp_processor_id() - get the current (stable) CPU id * * This is the normal accessor to the CPU id and should be used * whenever possible. * * The CPU id is stable when: * * - IRQs are disabled; * - preemption is disabled; * - the task is CPU affine. * * When CONFIG_DEBUG_PREEMPT=y, we verify these assumptions and WARN * when smp_processor_id() is used when the CPU id is not stable. */
# define smp_processor_id() __smp_processor_id()#endif
#define get_cpu() ({ preempt_disable(); __smp_processor_id(); })#define put_cpu() preempt_enable()
/* * Callback to arch code if there's nosmp or maxcpus=0 on the * boot command line: */extern void arch_disable_smp_support(void);
extern void arch_thaw_secondary_cpus_begin(void);extern void arch_thaw_secondary_cpus_end(void);
void smp_setup_processor_id(void);
int smp_call_on_cpu(unsigned int cpu, int (*func)(void *), void *par, bool phys);
/* SMP core functions */int smpcfd_prepare_cpu(unsigned int cpu);int smpcfd_dead_cpu(unsigned int cpu);int smpcfd_dying_cpu(unsigned int cpu);
#ifdef CONFIG_CSD_LOCK_WAIT_DEBUGbool csd_lock_is_stuck(void);#elsestatic inline bool csd_lock_is_stuck(void) { return false; }#endif
#endif /* __LINUX_SMP_H */