Day65 - Linux Kernel RCU APIs and Usage¶
Overview¶
This lab explores how Linux Kernel RCU APIs are used to safely publish new objects and reclaim old objects without blocking readers.
Two experiments are implemented:
- RCU API Usage Simulation
- call_rcu() Deferred Reclamation Simulation
The implementation is a simplified userspace model built with C11 atomics and pthreads.
Lab1 - RCU API Usage Simulation¶
Objective¶
Understand the semantics of:
and verify the RCU publication and reclamation workflow.
Data Structure¶
Global pointer:
Reader tracking:
Simulated RCU APIs¶
rcu_read_lock()¶
static void rcu_read_lock(void)
{
atomic_fetch_add_explicit(
&g_reader_count,
1,
memory_order_acquire);
}
rcu_read_unlock()¶
static void rcu_read_unlock(void)
{
atomic_fetch_sub_explicit(
&g_reader_count,
1,
memory_order_release);
}
rcu_dereference()¶
static struct rcu_object *rcu_dereference(void)
{
return atomic_load_explicit(
&g_rcu_ptr,
memory_order_acquire);
}
rcu_assign_pointer()¶
static void rcu_assign_pointer(struct rcu_object *obj)
{
atomic_store_explicit(
&g_rcu_ptr,
obj,
memory_order_release);
}
synchronize_rcu()¶
static void synchronize_rcu(void)
{
while (atomic_load_explicit(
&g_reader_count,
memory_order_acquire) != 0) {
sched_yield();
}
}
Reader Flow¶
Readers keep using the object even after a writer publishes a newer version.
Writer Flow¶
allocate new object
↓
initialize object
↓
rcu_assign_pointer()
↓
synchronize_rcu()
↓
free old object
Expected Behavior¶
publish new object
↓
old readers continue using old object
↓
grace period completes
↓
old object reclaimed
Lab2 - call_rcu() Deferred Reclamation¶
Objective¶
Understand asynchronous object reclamation using:
instead of:
Data Structure¶
rcu_head¶
Reclaimable Object¶
Callback Queue¶
The lab implements a simple callback queue:
Each queued node represents a pending callback request.
call_rcu()¶
The writer does not wait for a grace period.
Instead:
Reclaimer Thread¶
The reclaimer thread performs:
Pseudo flow:
Callback Function¶
static void rcu_object_free_cb(
struct rcu_head *head)
{
struct rcu_object *obj;
obj = container_of(
head,
struct rcu_object,
rcu);
free(obj);
}
Expected Behavior¶
Writer:
Reclaimer:
Results¶
Lab1¶
Verified:
workflow.
Readers safely continued using old objects until the grace period completed.
Lab2¶
Verified:
workflow.
Writers no longer blocked while waiting for readers.
Object reclamation was performed asynchronously by the reclaimer thread.
Key Takeaways¶
RCU Reader Side¶
allows lockless access to published objects.
RCU Writer Side¶
safely publishes a new object.
Grace Period¶
blocks until all current readers leave their read-side critical sections.
Deferred Reclamation¶
moves reclamation into a callback queue and allows writers to continue immediately.
Publication vs Reclamation¶
The most important RCU design principle is:
A new object can be published immediately, while the old object must remain alive until the grace period completes.