kernel/smp.c
Source file repositories/reference/linux-study-clean/kernel/smp.c
File Facts
- System
- Linux kernel
- Corpus path
kernel/smp.c- Extension
.c- Size
- 33613 bytes
- Lines
- 1195
- Domain
- Core OS
- Bucket
- Scheduler, Processes, Timers, Sync, And Syscalls
- Inferred role
- Core OS: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/irq_work.hlinux/rcupdate.hlinux/rculist.hlinux/kernel.hlinux/export.hlinux/percpu.hlinux/init.hlinux/interrupt.hlinux/gfp.hlinux/smp.hlinux/cpu.hlinux/sched.hlinux/sched/idle.hlinux/hypervisor.hlinux/sched/clock.hlinux/nmi.hlinux/sched/debug.hlinux/jump_label.hlinux/string_choices.htrace/events/ipi.htrace/events/csd.hsmpboot.hsched/smp.h
Detected Declarations
struct call_function_datastruct smp_call_on_cpu_structfunction smpcfd_prepare_cpufunction cpu_to_nodefunction smpcfd_dead_cpufunction smpcfd_dying_cpufunction call_function_initfunction send_call_function_single_ipifunction send_call_function_ipi_maskfunction csd_do_funcfunction de7b09ef658dfunction __csd_lock_recordfunction csd_lock_recordfunction csd_lock_wait_getcpufunction csd_lock_is_stuckfunction csd_lock_wait_toolongfunction __csd_lock_waitfunction csd_lock_waitfunction csd_lock_recordfunction csd_lockfunction csd_unlockfunction __smp_call_single_queuefunction generic_exec_singlefunction generic_smp_call_function_single_interruptfunction __flush_smp_call_function_queuefunction llist_for_each_entryfunction contextfunction smp_call_function_singlefunction smp_call_function_single_asyncfunction smp_call_function_anyfunction smp_call_function_many_condfunction for_each_cpufunction smp_call_function_manyfunction smp_call_functionfunction entirelyfunction nrcpusfunction maxcpusfunction setup_nr_cpu_idsfunction smp_initfunction on_each_cpu_cond_maskfunction do_nothingfunction wake_up_all_idle_cpusfunction for_each_possible_cpufunction cpus_peek_for_pending_ipifunction for_each_cpufunction smp_call_on_cpu_callbackfunction smp_call_on_cpuexport smp_call_function_single
Annotated Snippet
struct call_function_data {
call_single_data_t __percpu *csd;
cpumask_var_t cpumask;
cpumask_var_t cpumask_ipi;
};
static DEFINE_PER_CPU_ALIGNED(struct call_function_data, cfd_data);
static DEFINE_PER_CPU_SHARED_ALIGNED(struct llist_head, call_single_queue);
static DEFINE_PER_CPU(atomic_t, trigger_backtrace) = ATOMIC_INIT(1);
static void __flush_smp_call_function_queue(bool warn_cpu_offline);
int smpcfd_prepare_cpu(unsigned int cpu)
{
struct call_function_data *cfd = &per_cpu(cfd_data, cpu);
if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL,
cpu_to_node(cpu)))
return -ENOMEM;
if (!zalloc_cpumask_var_node(&cfd->cpumask_ipi, GFP_KERNEL,
cpu_to_node(cpu))) {
free_cpumask_var(cfd->cpumask);
return -ENOMEM;
}
cfd->csd = alloc_percpu(call_single_data_t);
if (!cfd->csd) {
free_cpumask_var(cfd->cpumask);
free_cpumask_var(cfd->cpumask_ipi);
return -ENOMEM;
}
return 0;
}
int smpcfd_dead_cpu(unsigned int cpu)
{
struct call_function_data *cfd = &per_cpu(cfd_data, cpu);
free_cpumask_var(cfd->cpumask);
free_cpumask_var(cfd->cpumask_ipi);
free_percpu(cfd->csd);
return 0;
}
int smpcfd_dying_cpu(unsigned int cpu)
{
/*
* The IPIs for the smp-call-function callbacks queued by other CPUs
* might arrive late, either due to hardware latencies or because this
* CPU disabled interrupts (inside stop-machine) before the IPIs were
* sent. So flush out any pending callbacks explicitly (without waiting
* for the IPIs to arrive), to ensure that the outgoing CPU doesn't go
* offline with work still pending.
*
* This runs with interrupts disabled inside the stopper task invoked by
* stop_machine(), ensuring mutually exclusive CPU offlining and IPI flush.
*/
__flush_smp_call_function_queue(false);
irq_work_run();
return 0;
}
void __init call_function_init(void)
{
int i;
for_each_possible_cpu(i)
init_llist_head(&per_cpu(call_single_queue, i));
smpcfd_prepare_cpu(smp_processor_id());
}
static __always_inline void
send_call_function_single_ipi(int cpu)
{
if (call_function_single_prep_ipi(cpu)) {
trace_ipi_send_cpu(cpu, _RET_IP_,
generic_smp_call_function_single_interrupt);
arch_send_call_function_single_ipi(cpu);
}
}
static __always_inline void
send_call_function_ipi_mask(struct cpumask *mask)
{
trace_ipi_send_cpumask(mask, _RET_IP_,
generic_smp_call_function_single_interrupt);
arch_send_call_function_ipi_mask(mask);
Annotation
- Immediate include surface: `linux/irq_work.h`, `linux/rcupdate.h`, `linux/rculist.h`, `linux/kernel.h`, `linux/export.h`, `linux/percpu.h`, `linux/init.h`, `linux/interrupt.h`.
- Detected declarations: `struct call_function_data`, `struct smp_call_on_cpu_struct`, `function smpcfd_prepare_cpu`, `function cpu_to_node`, `function smpcfd_dead_cpu`, `function smpcfd_dying_cpu`, `function call_function_init`, `function send_call_function_single_ipi`, `function send_call_function_ipi_mask`, `function csd_do_func`.
- Atlas domain: Core OS / Scheduler, Processes, Timers, Sync, And Syscalls.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.