Skip to content

rcu_assign_pointer()

Purpose

rcu_assign_pointer() safely publishes a new RCU-protected pointer.

It provides the required memory-ordering guarantees so that readers using rcu_dereference() observe a fully initialized object.


Prototype

rcu_assign_pointer(p, v);

#include <linux/rcupdate.h>

Usage Pattern

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)
    use_object(obj);

rcu_read_unlock();

Why Not Direct Pointer Assignment?

Incorrect:

g_obj = new;

This does not provide the memory-ordering guarantees required by RCU.

A reader may observe:

Pointer Published
Object Not Fully Visible

because the compiler or CPU may reorder memory operations.


Publication Pair

rcu_assign_pointer() is paired with:

rcu_dereference()

Writer:

Initialize Object
        
rcu_assign_pointer()

Reader:

rcu_dereference()
        
Access Object Fields

Together they establish the required publish-subscribe relationship.


Copy-and-Update Pattern

A common RCU update pattern is:

old = rcu_dereference_protected(g_obj, 1);

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

*new = *old;

new->value = 123;

rcu_assign_pointer(g_obj, new);

Existing readers continue using:

Old Object

New readers begin using:

New Object

Publication Is Not Reclamation

A common misunderstanding is:

Publish New Object
Free Old Object

This is unsafe.

Readers may still hold references to the old object.

Correct sequence:

Publish New Object
Grace Period
Reclaim Old Object

Example Using synchronize_rcu()

old = rcu_dereference_protected(g_obj, 1);

rcu_assign_pointer(g_obj, new);

synchronize_rcu();

kfree(old);

Example Using call_rcu()

old = rcu_dereference_protected(g_obj, 1);

rcu_assign_pointer(g_obj, new);

call_rcu(&old->rcu, free_callback);

Common Mistake

Incorrect:

rcu_assign_pointer(g_obj, new);

kfree(old);

The old object may still be referenced by active readers.

Correct:

rcu_assign_pointer(g_obj, new);

synchronize_rcu();

kfree(old);

or:

rcu_assign_pointer(g_obj, new);

call_rcu(&old->rcu, free_callback);

Relationship to Grace Period

rcu_assign_pointer() only publishes the new object.

It does not wait for readers.

It does not reclaim memory.

Grace period handling must be performed separately using:

synchronize_rcu()

or:

call_rcu()