The RCU API tables, 2019 edition
These tables are part of Paul McKenney's 2019 RCU API update article
RCU Per-Flavor API Table
Attribute | RCU | RCU BH | RCU Sched | SRCU | RCU Tasks | Generic |
---|---|---|---|---|---|---|
Purpose | Wait for RCU read-side critical sections | Wait for RCU-bh read-side critical sections & irqs | Wait for RCU-sched read-side critical sections, preempt-disable regions, hardirqs, & NMIs | Wait for SRCU read-side critical sections, allow sleeping readers | Wait for all non-idle tasks to be seen in userspace or to execute a voluntary context switch | Primitives common to all flavors of RCU |
Initialization | DEFINE_SRCU() DEFINE_STATIC_SRCU() init_srcu_struct() |
RCU_INIT_POINTER() RCU_POINTER_INITIALIZER() |
||||
Read-side critical-section markers |
rcu_read_lock() rcu_read_unlock() rcu_read_lock_bh() rcu_read_unlock_bh() local_bh_disable() /local_bh_enable() rcu_read_lock_sched() rcu_read_unlock_sched() rcu_read_lock_sched_notrace() rcu_read_unlock_sched_notrace() preempt_disable() /preempt_enable() local_irq_save() /local_irq_restore() |
rcu_read_lock_bh() rcu_read_unlock_bh() local_bh_disable() /local_bh_enable() |
rcu_read_lock_sched() rcu_read_unlock_sched() rcu_read_lock_sched_notrace() rcu_read_unlock_sched_notrace() preempt_disable() /preempt_enable() local_irq_save() /local_irq_restore() |
srcu_read_lock() srcu_read_lock_notrace() srcu_read_unlock() srcu_read_unlock_notrace() |
||
Data access |
rcu_dereference() rcu_dereference_check() rcu_dereference_bh() rcu_dereference_bh_check() rcu_dereference_sched() rcu_dereference_sched_check() |
rcu_dereference_bh() rcu_dereference_bh_check() |
rcu_dereference_sched() rcu_dereference_sched_check() |
srcu_dereference() srcu_dereference_check()
srcu_dereference_notrace() |
rcu_access_index() rcu_access_pointer() rcu_dereference_index_check() rcu_dereference_protected() rcu_dereference_raw() rcu_dereference_raw_notrace() rcu_assign_pointer() rcu_swap_protected() rcu_pointer_handoff() |
|
Update-side primitives (synchronous) |
synchronize_rcu() synchronize_net() |
synchronize_rcu_bh() |
synchronize_sched() |
synchronize_srcu() |
synchronize_rcu_tasks() |
synchronize_rcu_mult() |
Update-side primitives (expedited) |
synchronize_rcu_expedited() |
synchronize_rcu_bh_expedited() |
synchronize_sched_expedited() |
synchronize_srcu_expedited() |
||
Update-side primitives (asynchronous/callback) |
call_rcu() |
call_rcu_bh() |
call_rcu_sched() |
call_srcu() |
call_rcu_tasks() |
|
Update-side primitives (wait for callbacks) |
rcu_barrier() |
rcu_barrier_bh() |
rcu_barrier_sched() |
srcu_barrier() |
||
Update-side primitives (initiate / wait) |
get_state_synchronize_rcu() cond_synchronize_rcu() |
get_state_synchronize_sched() cond_synchronize_sched() |
||||
Update-side primitives (free memory) |
kfree_rcu() |
|||||
Validation | rcu_read_lock_held() rcu_read_lock_bh_held() rcu_read_lock_sched_held() |
rcu_read_lock_bh_held() |
rcu_read_lock_sched_held() |
srcu_read_lock_held() |
__rcu init_rcu_head() destroy_rcu_head() init_rcu_head_on_stack() destroy_rcu_head_on_stack() rcu_cpu_stall_reset() rcu_head_init() rcu_head_after_call_rcu() rcu_is_watching() rcu_lockdep_assert() RCU_LOCKDEP_WARN() RCU_NONIDLE() rcu_sleep_check() |
|
Memory ordering | smp_mb__after_srcu_read_unlock() |
|||||
Cleanup | cleanup_srcu_struct() cleanup_srcu_struct_quiesced() |
|||||
Read side constraints | No blocking except preemption and "spinlock" acquisition. | No BH enabling | No blocking | No wait for synchronize_srcu() |
No voluntary context switch | |
Read side overhead | Simple instructions (free on !PREEMPT) | BH disable/enable | Preempt disable/enable (free on !PREEMPT) | Simple instructions, preempt disable/enable | Free | |
Asynchronous update-side overhead
(for example, call_rcu() ) |
sub-microsecond | sub-microsecond | sub-microsecond | sub-microsecond | Global irq-disabled spinlock acquisition | |
Grace-period latency | 10s of milliseconds | 10s of milliseconds | 10s of milliseconds | 10s of milliseconds | From hundreds of milliseconds to minutes (if you have to ask, you cannot afford it) | |
Expedited grace-period latency | 10s of microseconds, but increases with number of CPUs (rough rule of thumb: one microsecond per CPU) | 10s of microseconds, but increases with number of CPUs (rough rule of thumb: one microsecond per CPU) | 10s of microseconds, but increases with number of CPUs (rough rule of thumb: one microsecond per CPU) | 10s of microseconds, but increases with number of CPUs (rough rule of thumb: 200 nanoseconds per CPU) | ||
!PREEMPT default implementation | RCU Sched | RCU Sched | RCU Sched | SRCU | RCU Sched | |
PREEMPT default implementation | Preemptible RCU | Preemptible RCU | Preemptible RCU | SRCU | Tasks RCU |
RCU List APIs
Operation | list | hlist | hlist_nulls | hlist_bl |
---|---|---|---|---|
Circular doubly linked list | Linear doubly linked list | Linear doubly linked list with marked NULL pointer, with up to 31 bits of marking |
Linear doubly linked list with bit locking | |
Initialization | INIT_LIST_HEAD_RCU() |
|||
Full traversal | list_for_each_entry_rcu() list_for_each_entry_lockless() |
hlist_for_each_entry_rcu() hlist_for_each_entry_rcu_bh() hlist_for_each_entry_rcu_notrace() |
hlist_nulls_for_each_entry_rcu() hlist_nulls_for_each_entry_safe() |
hlist_bl_for_each_entry_rcu() |
Resume traversal | list_for_each_entry_continue_rcu() list_for_each_entry_from_rcu() |
hlist_for_each_entry_continue_rcu() hlist_for_each_entry_continue_rcu_bh() hlist_for_each_entry_from_rcu() |
||
Stepwise traversal | list_entry_rcu() list_entry_lockless() list_first_or_null_rcu() list_next_rcu() list_next_or_null_rcu() |
hlist_first_rcu() hlist_next_rcu() hlist_pprev_rcu() |
hlist_nulls_first_rcu() hlist_nulls_next_rcu() |
hlist_bl_first_rcu() |
Add | list_add_rcu() list_add_tail_rcu() |
hlist_add_after_rcu() hlist_add_before_rcu() hlist_add_behind_rcu() hlist_add_head_rcu() hlist_add_tail_rcu() |
hlist_nulls_add_head_rcu() |
hlist_bl_add_head_rcu() hlist_bl_set_first_rcu() |
Delete | list_del_rcu() |
hlist_del_rcu() hlist_del_init_rcu() |
hlist_nulls_del_rcu() hlist_nulls_del_init_rcu() |
hlist_bl_del_rcu() hlist_bl_del_init_rcu() |
Replacement | list_replace_rcu() |
hlist_replace_rcu() |
||
Splice | list_splice_init_rcu() list_splice_tail_init_rcu() |
Key
- API members present in initial October 2002 Linux-kernel RCU implementation.
- New API members.
- Deprecated (or removed) API members.