Skip to content

rcu_dereference()

Purpose

rcu_dereference() safely acquires a pointer protected by RCU.

It provides the required memory-ordering guarantees so that readers observe a fully initialized object published by rcu_assign_pointer().


Prototype

typeof(*p) *rcu_dereference(p);

#include <linux/rcupdate.h>

Usage Pattern

struct my_object *obj;

rcu_read_lock();

obj = rcu_dereference(g_obj);

if (obj)
    use_object(obj);

rcu_read_unlock();

Why Not Direct Pointer Access?

Incorrect:

obj = g_obj;

Although this appears to work, it does not provide the required memory-ordering guarantees.

The compiler or CPU may reorder memory operations.

Readers could potentially observe:

Published Pointer
Partially Initialized Object

Publication Pair

rcu_dereference() is paired with:

rcu_assign_pointer()

Writer:

new = kmalloc(sizeof(*new), GFP_KERNEL);

new->version = 1;
new->value = 100;

rcu_assign_pointer(g_obj, new);

Reader:

rcu_read_lock();

obj = rcu_dereference(g_obj);

if (obj)
    printk("%d\n", obj->value);

rcu_read_unlock();

Memory Ordering

Conceptually:

Writer:

Initialize Object
Publish Pointer

Reader:

Acquire Pointer
Access Object Fields

This ordering ensures that readers see a fully initialized object.


Typical Use Case

RCU-protected global pointer:

static struct device_entry __rcu *g_device;

Reader:

struct device_entry *dev;

rcu_read_lock();

dev = rcu_dereference(g_device);

if (dev)
    process_device(dev);

rcu_read_unlock();

Common Mistake

Incorrect:

rcu_read_lock();

obj = g_obj;

printk("%d\n", obj->value);

rcu_read_unlock();

The pointer is loaded directly.

Correct:

rcu_read_lock();

obj = rcu_dereference(g_obj);

printk("%d\n", obj->value);

rcu_read_unlock();

Relationship to RCU Read-Side Critical Sections

rcu_dereference() should normally be used inside:

rcu_read_lock();
...
rcu_read_unlock();

This guarantees that the object remains valid while being accessed.