lib/percpu-refcount.c
Source file repositories/reference/linux-study-clean/lib/percpu-refcount.c
File Facts
- System
- Linux kernel
- Corpus path
lib/percpu-refcount.c- Extension
.c- Size
- 15707 bytes
- Lines
- 480
- Domain
- Kernel Services
- Bucket
- lib
- Inferred role
- Kernel Services: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.
- Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.
- 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.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/kernel.hlinux/sched.hlinux/wait.hlinux/slab.hlinux/mm.hlinux/percpu-refcount.h
Detected Declarations
function percpu_ref_killfunction __percpu_ref_exitfunction percpu_ref_initfunction percpu_ref_call_confirm_rcufunction percpu_ref_switch_to_atomic_rcufunction percpu_ref_noop_confirm_switchfunction __percpu_ref_switch_to_percpufunction __percpu_ref_switch_modefunction percpu_ref_switch_to_percpufunction percpu_ref_switch_to_atomic_syncfunction percpu_ref_switch_to_atomicfunction percpu_ref_killfunction percpu_ref_is_zerofunction percpu_ref_initfunction percpu_ref_resurrectexport percpu_ref_initexport percpu_ref_exitexport percpu_ref_switch_to_atomicexport percpu_ref_switch_to_atomic_syncexport percpu_ref_switch_to_percpuexport percpu_ref_kill_and_confirmexport percpu_ref_is_zeroexport percpu_ref_reinitexport percpu_ref_resurrect
Annotated Snippet
atomic_inc_return(&underflows) < 4) {
pr_err("%s(): percpu_ref underflow", __func__);
mem_dump_obj(data);
}
/* @ref is viewed as dead on all CPUs, send out switch confirmation */
percpu_ref_call_confirm_rcu(rcu);
}
static void percpu_ref_noop_confirm_switch(struct percpu_ref *ref)
{
}
static void __percpu_ref_switch_to_atomic(struct percpu_ref *ref,
percpu_ref_func_t *confirm_switch)
{
if (ref->percpu_count_ptr & __PERCPU_REF_ATOMIC) {
if (confirm_switch)
confirm_switch(ref);
return;
}
/* switching from percpu to atomic */
ref->percpu_count_ptr |= __PERCPU_REF_ATOMIC;
/*
* Non-NULL ->confirm_switch is used to indicate that switching is
* in progress. Use noop one if unspecified.
*/
ref->data->confirm_switch = confirm_switch ?:
percpu_ref_noop_confirm_switch;
percpu_ref_get(ref); /* put after confirmation */
call_rcu_hurry(&ref->data->rcu,
percpu_ref_switch_to_atomic_rcu);
}
static void __percpu_ref_switch_to_percpu(struct percpu_ref *ref)
{
unsigned long __percpu *percpu_count = percpu_count_ptr(ref);
int cpu;
BUG_ON(!percpu_count);
if (!(ref->percpu_count_ptr & __PERCPU_REF_ATOMIC))
return;
if (WARN_ON_ONCE(!ref->data->allow_reinit))
return;
atomic_long_add(PERCPU_COUNT_BIAS, &ref->data->count);
/*
* Restore per-cpu operation. smp_store_release() is paired
* with READ_ONCE() in __ref_is_percpu() and guarantees that the
* zeroing is visible to all percpu accesses which can see the
* following __PERCPU_REF_ATOMIC clearing.
*/
for_each_possible_cpu(cpu)
*per_cpu_ptr(percpu_count, cpu) = 0;
smp_store_release(&ref->percpu_count_ptr,
ref->percpu_count_ptr & ~__PERCPU_REF_ATOMIC);
}
static void __percpu_ref_switch_mode(struct percpu_ref *ref,
percpu_ref_func_t *confirm_switch)
{
struct percpu_ref_data *data = ref->data;
lockdep_assert_held(&percpu_ref_switch_lock);
/*
* If the previous ATOMIC switching hasn't finished yet, wait for
* its completion. If the caller ensures that ATOMIC switching
* isn't in progress, this function can be called from any context.
*/
wait_event_lock_irq(percpu_ref_switch_waitq, !data->confirm_switch,
percpu_ref_switch_lock);
if (data->force_atomic || percpu_ref_is_dying(ref))
__percpu_ref_switch_to_atomic(ref, confirm_switch);
else
__percpu_ref_switch_to_percpu(ref);
}
/**
* percpu_ref_switch_to_atomic - switch a percpu_ref to atomic mode
* @ref: percpu_ref to switch to atomic mode
* @confirm_switch: optional confirmation callback
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/sched.h`, `linux/wait.h`, `linux/slab.h`, `linux/mm.h`, `linux/percpu-refcount.h`.
- Detected declarations: `function percpu_ref_kill`, `function __percpu_ref_exit`, `function percpu_ref_init`, `function percpu_ref_call_confirm_rcu`, `function percpu_ref_switch_to_atomic_rcu`, `function percpu_ref_noop_confirm_switch`, `function __percpu_ref_switch_to_percpu`, `function __percpu_ref_switch_mode`, `function percpu_ref_switch_to_percpu`, `function percpu_ref_switch_to_atomic_sync`.
- Atlas domain: Kernel Services / lib.
- 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.