Read-Copy Update (RCU) is a synchronization mechanism optimized for read-mostly data. The key insight is that readers need not acquire any lock, perform atomic instructions, or execute memory barriers (on most architectures). Updates proceed by:Documentation Index
Fetch the complete documentation index at: https://mintlify.com/torvalds/linux/llms.txt
Use this file to discover all available pages before exploring further.
- Copying the data to be changed.
- Modifying the copy.
- Publishing the new version atomically.
- Waiting for a grace period — until all pre-existing readers have finished.
- Freeing the old version.
Zero-cost readers
rcu_read_lock / rcu_read_unlock are typically no-ops on non-preemptible kernels.Safe pointer publication
rcu_assign_pointer inserts the necessary memory barriers to safely publish a new pointer.Safe pointer dereference
rcu_dereference enforces dependency ordering so the compiler cannot speculate loads.Deferred free
call_rcu and kfree_rcu free memory after a grace period — no explicit waiting.Read-side critical sections
rcu_read_lock / rcu_read_unlock
CONFIG_PREEMPT_RCU kernels they manipulate a per-task nesting counter.
Rules for read-side critical sections:
- Must not block or sleep (
GFP_ATOMICallocations are acceptable). - Must not call
schedule(). - Must not exit to user space.
- May be nested.
Pointer access
rcu_dereference
An
__rcu-annotated pointer. Sparse will warn if you dereference an __rcu pointer without this macro.rcu_assign_pointer
The
__rcu-annotated pointer to update.The new value to publish. All fields of the new structure must be initialized before calling
rcu_assign_pointer.Grace period management
A grace period is a time interval after a pointer update during which every CPU must have passed through at least one quiescent state (context switch, user-mode execution, or idle loop). After a grace period, no reader can hold a reference to the old version.synchronize_rcu
call_rcu — asynchronous grace period
An
rcu_head embedded in the object to be freed. Must not be modified until the callback fires.Callback invoked after the grace period. Signature:
void cb(struct rcu_head *head). Retrieve the enclosing object with container_of.kfree_rcu — RCU-deferred kfree
call_rcu with a kfree callback. Eliminates the need to write a custom callback just to free an object.
RCU-protected lists
Therculist.h API wraps list_head operations with the correct barriers for RCU traversal.
RCU pointer replacement — full example
SRCU — Sleepable RCU
Standard RCU read-side critical sections may not sleep. SRCU (Sleepable RCU) lifts this restriction at the cost of a small per-subsystem overhead and slower grace periods.The SRCU domain. Each subsystem that needs SRCU must have its own
srcu_struct.SRCU grace periods are slower than regular RCU grace periods because the kernel must wait for all SRCU read-side critical sections to complete rather than simply waiting for all CPUs to pass through a quiescent state. Use SRCU only when blocking inside the read-side critical section is genuinely required.
When to use RCU versus locks
- Use RCU when
- Use a lock when
- RCU vs rwlock
- Reads vastly outnumber writes (read-mostly data).
- Read-side latency is critical (e.g., network packet processing, process scheduling).
- Readers must not be delayed by writers under any circumstance.
- You need to traverse a list from interrupt context without locking.
task_struct lookups, module list, VFS dentry cache.| Criterion | RCU | mutex | spinlock |
|---|---|---|---|
| Read-side cost | Near zero | Expensive (sleep) | Moderate (spin) |
| Write-side cost | Grace period wait | Sleep until available | Spin until available |
| Readers can sleep | No (SRCU: yes) | Yes | No |
| Usable from IRQ | Yes | No | Yes |
| Scales with readers | Perfectly | No | No |
RCU usage checklist
Always use rcu_dereference inside rcu_read_lock
Always use rcu_dereference inside rcu_read_lock
Dereferencing an
__rcu pointer outside a read-side critical section is undefined behavior. Sparse (make C=1) will flag violations.Always initialize before rcu_assign_pointer
Always initialize before rcu_assign_pointer
All fields of the new object must be fully initialized and visible to other CPUs before calling
rcu_assign_pointer. The macro provides the necessary store-release barrier.Wait for a grace period before freeing
Wait for a grace period before freeing
Never free an RCU-protected object immediately after removing it from a data structure. Always use
synchronize_rcu(), call_rcu(), or kfree_rcu() first.Protect writers with a separate lock
Protect writers with a separate lock
RCU does not serialize concurrent writers. If multiple threads may update the same RCU-protected data structure, they must hold a conventional lock (e.g., a spinlock or mutex) with respect to each other.
