Fact-checked by Grok 2 weeks ago

Read-copy-update

Read-copy-update (RCU) is a mechanism optimized for multi-threaded environments where read operations vastly outnumber updates, allowing concurrent readers to access shared s without acquiring locks or blocking writers. In RCU, readers demarcate their critical sections using lightweight primitives like rcu_read_lock() and rcu_read_unlock(), which impose minimal overhead, often none beyond barriers. Writers, in contrast, copy the affected , apply modifications to the copy, and use operations such as rcu_assign_pointer() to references to the new version, while deferring reclamation of the old version until a "" elapses—ensuring all pre-existing readers have completed. This approach splits updates into removal and reclamation phases, enabling high scalability and performance in read-mostly workloads. RCU was co-invented by Paul E. McKenney and John D. Slingwine in the mid-1990s as a solution to concurrency problems in shared-memory systems, with its foundational concepts detailed in early publications exploring execution history for . It was integrated into the during the 2.5 development series around 2002, initially to enhance efficiency in components like the directory-entry cache (dcache). Since then, RCU has evolved into a core kernel facility, maintained primarily by McKenney, and is now used across diverse subsystems including the (VFS), networking stack, and scheduler. Implementations extend beyond the kernel to user-space libraries, such as Userspace RCU (URCU), which provide similar semantics for application-level . Key advantages of RCU over traditional methods like reader-writer locks or include drastically reduced contention for readers, as they avoid primitives entirely in many cases, and better throughput in scenarios with thousands of concurrent readers. It enforces strict guarantees, such as grace-period completion before memory reclamation and via barriers, to prevent issues like use-after-free or races across CPUs. However, RCU requires careful usage, as readers must not sleep (in non-sleepable variants) and updates can introduce memory overhead from deferred reclamation. The Linux kernel offers multiple RCU flavors to suit different needs: preemptible RCU for low-latency real-time systems, RCU-bh for bottom-half softirq contexts, Sleepable RCU (SRCU) for code that may block or sleep, and Tasks RCU variants for process-level synchronization without explicit reader locking. These adaptations have made RCU indispensable for high-performance computing, embedded systems, and cloud infrastructure, where it protects critical data structures like routing tables and notifier chains. Ongoing research and development continue to refine RCU for emerging architectures, including heterogeneous and real-time environments, with recent API enhancements such as polling for grace periods as of 2024.

Introduction

Overview

Read-copy-update (RCU) is a lock-free mechanism designed to allow multiple concurrent readers to access shared data structures without acquiring locks or incurring significant overhead, while updaters create copies of the data for safe modifications. This technique enables efficient concurrent execution in environments where reads greatly outnumber updates, such as multiprocessor systems. The basic RCU process involves an updater copying the target , applying modifications to the copy, and then atomically replacing the pointer to the original structure with one pointing to the updated version. Following this replacement, the updater waits for a —a mechanism ensuring that all pre-existing readers have completed their access to the old version—before reclaiming and freeing the obsolete structure. RCU's core goal is to minimize overhead for read-mostly workloads, thereby improving and in high-concurrency settings. It was initially motivated by the challenges of handling read-heavy scenarios in operating system kernels, where traditional locking mechanisms introduce excessive contention and complexity.

Key Terminology

In Read-Copy Update (RCU), a quiescent state refers to any point in time during which a given CPU or thread is not executing within an RCU read-side , such as during a , idle loop execution, or user-mode operation. This state allows the RCU mechanism to progress grace periods by confirming that no ongoing reads from that CPU are accessing old versions of protected data. In non-preemptive kernels, quiescent states are typically detected at scheduler boundaries, including voluntary es and transitions to or from handlers. A is the time interval starting from an update invocation during which every pre-existing RCU read-side on all CPUs must complete, ensuring that updaters can safely reclaim memory previously protected by RCU. This period ends only after each CPU has passed through at least one quiescent state since the grace period began, guaranteeing that no lingering reads hold references to outdated data structures. Grace periods provide the core guarantee of RCU, allowing concurrent readers to proceed without blocking updaters once the period concludes. The read-side encompasses the code region delimited by calls to RCU read-acquisition primitives, such as rcu_read_lock() and rcu_read_unlock(), within which shared data structures are accessed for reading. These sections must avoid blocking operations like sleeping or yielding in classic RCU to prevent indefinite grace-period delays, though they may contain nested locks or preemptions in modern variants. Readers within such sections observe a consistent view of the data, typically via pointer indirection, without acquiring locks. An updater is the code or thread responsible for modifying RCU-protected data structures, typically by creating a copy of the structure, applying changes to the copy, and then atomically replacing the pointer to the old structure with one to the new version using primitives like rcu_assign_pointer(). Updaters invoke grace-period-waiting functions, such as synchronize_rcu(), to ensure that all pre-existing read-side critical sections have completed before freeing the old data copy. This approach enables non-blocking reads while allowing updates to proceed after a bounded delay. Terminology in RCU distinguishes classic RCU, which assumes non-preemptive kernels where read-side critical sections incur zero runtime overhead and quiescent states rely on voluntary context switches or interrupts, from modern variants like , which support within read-side sections and require additional mechanisms to track potentially preempted readers. In classic RCU, terms like "quiescent state" emphasize non-preemptive boundaries, whereas modern implementations extend these concepts to handle scheduling events that could prolong read-side execution.

RCU Fundamentals

Read-Side Primitives

In Read-Copy Update (RCU), read-side primitives enable efficient, lock-free access to shared data structures by readers, allowing them to traverse data without blocking updaters. The primary primitives are rcu_read_lock() and rcu_read_unlock(), which delimit RCU read-side critical sections. These markers ensure that readers complete their sections before updaters can free old data versions, typically detected via a mechanism. Within a read-side critical section, rcu_read_lock() prevents voluntary preemption in non-preemptive kernel environments, such as older kernels, by disabling context switches until the matching rcu_read_unlock() is invoked. In preemptible kernels, these primitives instead track the reader's progress to allow safe preemption while ensuring the 's integrity. These primitives can nest arbitrarily, with each rcu_read_lock() requiring a corresponding rcu_read_unlock() to properly exit. RCU guarantees that during a read-side critical section, readers observe a consistent view of the —either the pre-update version or the fully updated version—without intermediate states that could lead to inconsistencies. To safely dereference RCU-protected pointers within such sections, readers must use the rcu_dereference() primitive, which provides volatile-qualified access to prevent optimizations from reordering loads that might violate RCU's model. This ensures that the pointer retrieved remains valid for the duration of the critical section. In certain configurations, such as non-preemptive kernels without debugging overhead, RCU read-side primitives impose zero runtime overhead, as they compile to no-ops and invoke no locking mechanisms, enabling readers to access data as efficiently as with plain pointer dereferences outside critical sections. However, in preemptible environments, additional lightweight tracking (e.g., per-CPU counters) may introduce minimal overhead to handle potential preemptions.

Update-Side Primitives

In read-copy-update (RCU), update-side operations enable safe modifications to shared structures by allowing concurrent readers uninterrupted access to consistent views of the , without requiring locks on the read path. A common approach in RCU updates is to copy the relevant part of the structure when modifications to its contents are needed, such as a in a , to isolate changes from ongoing reads. However, structural updates like insertions and deletions often use direct pointer updates without copying. Once copied (if applicable), the updater modifies this new version—for instance, changing a field value or adjusting pointers—while the original remains accessible to active readers. To publish the modified copy or new pointer, the updater employs the rcu_assign_pointer() primitive, which performs an pointer with appropriate barriers to guarantee that readers see a fully initialized structure. This primitive is essential for RCU-protected pointers, ensuring store-release ordering that synchronizes the update with subsequent read-side accesses. After installing the new version, the updater must wait for a to elapse before reclaiming the old data, as this period guarantees the completion of all prior RCU read-side critical sections. The synchronize_rcu() implements this blocking wait, allowing the updater to safely free or repurpose the obsolete structure once it returns. For non-blocking updates, particularly in scenarios where the updater cannot afford to wait, the call_rcu() primitive registers a callback to be invoked asynchronously after the , deferring reclamation without halting the update thread. This asynchronous mechanism is widely used in the for scalable updates in high-throughput environments. RCU updates handle insertions, deletions, and modifications through these primitives, often tailored to data structures like singly linked lists. For an insertion, the updater copies the target node if needed, creates a new node with the desired data, adjusts pointers in the copy or new node, and uses rcu_assign_pointer() to link it into the list atomically, followed by synchronize_rcu() or call_rcu() to reclaim any displaced elements. In deletions, the updater identifies the node to remove, updates surrounding pointers via rcu_assign_pointer() to bypass it (potentially copying nodes for complex traversals), and then waits for the grace period before freeing the deleted node. Modifications follow a similar pattern: copy the node, apply changes to the copy (e.g., updating a value), assign the new pointer with rcu_assign_pointer(), and defer old node reclamation, ensuring readers traversing the list see consistent entries. These operations maintain list integrity under concurrent reads, with the Linux kernel providing specialized helpers like list_add_rcu() and list_del_rcu() to encapsulate the pointer assignments for list-specific updates.

Grace Periods

In read-copy-update (RCU), a is the interval during which all pre-existing RCU read-side critical sections must complete before an updater can safely reclaim associated with replaced structures. This mechanism is necessary for memory reclamation because RCU readers may hold references to old versions of data without acquiring locks, requiring updaters to wait until no such references remain active to avoid use-after-free errors. The grace period ensures that destructive operations, such as freeing , occur only after all potentially referencing readers have passed through a point where their access is guaranteed to have ended. Grace periods are detected through quiescent states, which are points in time when a CPU is not executing within an RCU read-side . Examples of quiescent states include CPU periods, voluntary switches, and transitions to user mode, as these indicate that no RCU-protected data is being accessed on that CPU. In non-preemptive kernels, quiescent states are directly detected at scheduler entry points, such as during switches, allowing RCU to track when each CPU has ceased RCU read-side activity without the need for additional instrumentation. Algorithms for grace period expiration rely on monitoring these quiescent states across all CPUs to confirm that pre-existing readers have finished. Once every CPU has reported at least one quiescent state following the start of the —typically invoked via primitives like synchronize_rcu()—the period expires, permitting memory reclamation. In multiprocessor systems, expiration algorithms must aggregate state reports efficiently to handle contention, ensuring that the grace period completes only after all CPUs, including those handling interrupts or offline transitions, have quiesced. Expedited grace periods provide a to shorten these wait times by actively forcing quiescent states, at the expense of higher overhead. For instance, they may use interprocessor interrupts (IPIs) to prompt context switches or check for active critical sections directly, reducing from milliseconds to tens of microseconds on small systems, though this increases CPU disturbance and power consumption. Such expediting is useful for -sensitive updates but trades off the low-overhead nature of normal grace periods. Challenges in multiprocessor systems arise from coordinating quiescent state detection across numerous CPUs, where delays in any single CPU—due to heavy loads, long-running critical sections, or offline states—can prolong the grace period. Ensuring all CPUs reach quiescence requires robust tracking mechanisms, such as priority boosting for blocked tasks after timeouts like 500 milliseconds, to prevent indefinite stalls while maintaining scalability up to thousands of CPUs.

Implementations and Variants

Basic Implementation

The basic implementation of Read-Copy-Update (RCU) can be illustrated through a simplified suitable for a non-preemptive environment, featuring a single updater and multiple concurrent readers. This model uses a global to track the number of active readers, enabling the updater to detect when a has elapsed without requiring locks on the read side.

Reader Pseudocode

Readers access shared data without acquiring locks, relying on the absence of preemption to ensure they complete promptly.
rcu_read_lock() {
    atomic_inc(&rcu_counter);  // Increment global counter atomically
}

rcu_read_unlock() {
    atomic_dec(&rcu_counter);  // Decrement global counter atomically
}

// Example read-side critical section
void reader_example(struct data **gp) {
    struct data *p;
    rcu_read_lock();
    p = *gp;  // Direct pointer access (assumes atomic load)
    if (p != [NULL](/page/Null)) {
        do_something_with(p->field);  // Read data fields
    }
    rcu_read_unlock();
}

Updater Pseudocode

The updater creates a copy of the , modifies it, publishes the new version atomically, waits for a (when no readers are active), and then frees the old version.
synchronize_rcu() {
    while (atomic_read(&rcu_counter) != 0) {
        ;  // Spin until no active readers ([grace period](/page/Grace_period))
    }
    smp_mb();  // [Memory barrier](/page/Memory_barrier) to ensure ordering
}

void updater_example(struct data **gp) {
    struct data *new_data, *old_data;
    new_data = malloc(sizeof(struct data));  // Allocate and copy old data
    memcpy(new_data, *gp, sizeof(struct data));
    new_data->field = updated_value;  // Modify the copy
    old_data = *gp;
    *gp = new_data;  // Atomic pointer replacement (e.g., via atomic exchange)
    synchronize_rcu();  // Wait for [grace period](/page/Grace_period)
    free(old_data);  // Safe to free old data now
}
This demonstrates the core read-side and update-side primitives of RCU in a minimal form. Readers simply adjust the global to mark their critical sections, allowing lock-free traversal of shared data. The updater, after publishing the updated structure, invokes a wait via the to guarantee that all pre-existing readers have completed before reclaiming memory. The model assumes a non-preemptive where threads run to completion or block only outside RCU critical sections, and quiescent states (points where readers are not active) are directly tracked via the without needing per-CPU mechanisms. However, this simple model has limitations, such as no support for reader preemption, which could leave the counter incremented indefinitely if a reader is preempted within its ; it also lacks handling for multiple updaters or CPU hotplug events.

Sample Kernel Interface

The Read-Copy Update (RCU) in the provides a standardized for implementing RCU , enabling efficient read-mostly access patterns while ensuring safe updates. This consists of lightweight primitives for readers and more involved mechanisms for updaters, with built-in support for nesting and preemption in certain configurations. On the read side, the core functions are rcu_read_lock() and rcu_read_unlock(), which delimit RCU read-side s. The function signatures are void rcu_read_lock(void) to enter a critical section and void rcu_read_unlock(void) to exit it. These calls are extremely lightweight, typically involving no locking, and are designed to protect traversals of RCU-protected data structures, such as linked lists. For example, to safely traverse a list, would invoke rcu_read_lock(), use a like list_for_each_entry_rcu() to iterate entries while dereferencing pointers with rcu_dereference(), and then call rcu_read_unlock(). The dereference function, rcu_dereference(p), with signature typeof(p) rcu_dereference(p), safely acquires an RCU-protected pointer within a read-side , ensuring the reader sees a consistent view without immediate invalidation by concurrent updates. For updates, the API includes rcu_assign_pointer() to safely publish new values and synchronization primitives to wait for grace periods. The assignment function has the signature rcu_assign_pointer(p, v), where p is the pointer and v is the new value, ensuring that readers will only see fully initialized data. To wait for a grace period—during which all pre-existing read-side critical sections complete—updaters use synchronize_rcu(), with signature void synchronize_rcu(void), which blocks until the grace period ends. For non-blocking updates, call_rcu() registers a callback for deferred execution after a grace period, with signature void call_rcu(struct rcu_head *head, rcu_callback_t func), commonly used for freeing removed elements, such as in list deletions via list_del_rcu() followed by callback registration on the freed structure. A typical pattern for deferred work is to remove an item from an RCU-protected list with rcu_assign_pointer()-based updates, then invoke call_rcu() on its rcu_head member to schedule reclamation. RCU read-side critical sections support nesting, allowing multiple rcu_read_lock() calls without as long as they are properly balanced with corresponding rcu_read_unlock() invocations; this enables safe in traversal code. To avoid deadlocks and ensure correctness, readers must not block or sleep within critical sections unless using a preemptible RCU variant, as blocking could indefinitely delay grace periods. Error handling emphasizes validating pointer assignments and dereferences to prevent use-after-free issues, often by assigning dereferenced values to local variables for repeated access within a section. The kernel configuration option CONFIG_PREEMPT_RCU enables a preemptible flavor of RCU, allowing voluntary preemption in read-side sections while tracking them via task structures, which is useful for low-latency systems but adds slight overhead compared to the non-preemptible variant.

Advanced Variants

Hierarchical RCU addresses challenges in NUMA systems with large numbers of CPUs by organizing them into a of rcu_node hierarchies, where leaf nodes pair CPUs and root nodes cover the entire system. This partitioning reduces lock contention significantly—for instance, on a 4,096-CPU system, it limits contention to 64 CPUs per leaf lock compared to all CPUs contending for a single global lock in classic RCU. By avoiding unnecessary wakeups of idle CPUs, hierarchical RCU also improves while maintaining correct grace-period detection. Tree RCU extends this hierarchy for preemptible kernels, employing per-CPU rcu_data structures with counters like gp_seq to track local grace-period states and quiescent states without global synchronization overhead. The rcu_state structure interconnects the tree of rcu_node and rcu_data elements, supporting up to millions of CPUs across multiple levels and managing blocked tasks during preemption. This design enhances in environments where tasks can be preempted, differing from non-preemptible variants by distributing callback queuing and state propagation across CPUs. Expedited RCU provides faster grace periods through functions like synchronize_rcu_expedited(), which sends inter-processor interrupts (IPIs) to non-idle, online CPUs to force immediate quiescent states. In RCU-preempt mode, it sets flags checked at rcu_read_unlock() to report quiescence, while in RCU-sched, it triggers context switches via rescheduling flags. Batching multiple requests using sequence counters reduces IPI overhead, though this variant trades higher disturbance for latencies as low as tens of microseconds on small systems. Preemptible RCU (PREEMPT_RCU) allows read-side critical sections to be preempted or blocked, using per-CPU rcu_flipctr arrays to track reader counts across multi-stage grace periods without memory barriers in lock/unlock primitives. Primitives like rcu_read_lock() increment counters under IRQ disablement, while rcu_read_unlock() decrements them and supports priority boosting to prevent indefinite blocking in scenarios. This variant integrates with priority inheritance mechanisms, extending grace periods until all pre-existing readers complete despite preemption. In kernels like , preemptible RCU is employed to ensure low-latency operation, with RCU processing confined to dedicated threads and removed from intermediate kernel paths to minimize . This configuration requires enabling full preemption and uses preemptible mechanisms to handle without compromising guarantees. Userspace adaptations like liburcu port kernel RCU concepts to application-level code, providing lock-free data structures such as hash tables and queues with read-side scaling linear to the number of cores. It offers flavors including QSBR for zero-overhead reads requiring explicit quiescent-state calls, and memory-barrier (MB) for faster grace periods at the cost of read performance. Other variants like signal-based or bullet-proof handle thread registration automatically, adapting kernel-style rcu_read_lock()/synchronize_rcu() for concurrent userspace environments without kernel privileges.

Applications

In the Linux Kernel

Read-copy-update (RCU) was integrated into the Linux kernel during the 2.5 development series, with initial commits appearing in October 2002, marking a key milestone in enhancing synchronization for read-heavy workloads. This addition allowed the kernel to handle concurrent reads and updates more efficiently without traditional locking overhead, paving the way for its widespread adoption across core subsystems. As of Linux kernel v6.10 (July 2024), there are over 21,000 invocations of the RCU , reflecting its deep entrenchment in the codebase and evolution from earlier implementations. By v6.17 (September 2025), this has grown to over 23,000. In networking, RCU protects structures like tables, where frequent reads tolerate brief staleness while updates propagate without blocking readers, using primitives such as rcu_read_lock_bh(). For file systems, it manages the entry (dentry) through deferred reclamation, separating removal from freeing to support high-concurrency lookups. In the scheduler, RCU safeguards runqueue structures and task lists, enabling safe access during operations like NMI handlers via rcu_read_lock_sched() and synchronize_sched(). RCU's design contributes significantly to the kernel's scalability on multi-core servers and in environments, where it minimizes contention in read-dominated paths across hundreds of CPUs. For instance, kernel developers leverage RCU's —such as rcu_read_lock() for read-side critical sections—to maintain performance in large-scale deployments without the bottlenecks of reader-writer locks.

In Other Operating Systems

incorporates RCU support, including in subsystems like the () for graphics, with implementations added starting in 2018. This approach supports efficient read-mostly access in kernel subsystems, differing from by integrating with its token-based synchronization model to reduce overhead. Ongoing enhancements are evident in areas like the and broader lockless algorithm discussions. Research kernels such as K42 have integrated RCU principles through mechanisms like deferred object deletion, enabling scalable synchronization for cache-coherent (ccNUMA) architectures without traditional locking overhead. In K42, this RCU-like technique facilitates high-performance access to shared data structures in a research focused on extensibility and API compatibility. Experimental adaptations of RCU extend to and systems, where modifications address concerns by allowing preemption of RCU read-side critical sections and reducing grace period overheads in resource-constrained environments. These enhancements enable RCU to meet deterministic timing requirements in multiprocessor setups, such as those in automotive or applications, by minimizing callback queuing delays and supporting voluntary quiescent states during idle periods.

User-Space Implementations

Userspace RCU implementations enable read-mostly synchronization in application-level code, outside of kernel environments, by providing libraries that adapt RCU primitives to user-space constraints. The primary such library is liburcu, an LGPLv2.1-licensed userspace RCU implementation developed by Mathieu Desnoyers, which offers read-side critical sections that scale linearly with the number of CPU cores while minimizing overhead. Liburcu's API closely mirrors the Linux kernel's RCU interface, including functions like rcu_read_lock() and rcu_read_unlock() for read-side protection, synchronize_rcu() for waiting on grace periods, and thread registration calls such as rcu_register_thread() to handle user-space threading models. This design allows developers to port kernel-style RCU usage to applications with minimal changes, supporting multiple flavors like quiescient-state-based (QSBR), memory-barrier-free, and signal-based variants to suit different performance needs. Key challenges in user-space RCU arise from the lack of kernel-level control over scheduling and interrupts. Signal handling requires careful management, as signal-based flavors use a dedicated signal like SIGUSR1 to detect quiescent states, potentially conflicting with application signals unless masked appropriately. Thread preemption is addressed through explicit thread registration, which informs the of active to ensure accurate grace-period detection, but this adds setup overhead compared to kernel RCU. Integration with (pthreads) is seamless, as liburcu supports multi-threaded environments by tracking thread states during reads and updates, enabling lock-free access in concurrent programs without blocking writers on readers. Liburcu finds applications in high-performance databases and distributed storage systems, such as Sheepdog, where it facilitates scalable updates to shared data structures under heavy read loads. In web servers and DNS resolvers like Knot DNS and gdnsd, it optimizes read-mostly operations such as lookups, reducing in query-heavy scenarios. Parallel libraries benefit from liburcu's concurrent data structures () module, which includes RCU-protected hash tables, queues, and lists suitable for cloud workloads involving dynamic key-value stores and . These structures enable resizable, lock-free hash tables that maintain constant-time performance during resizing, as demonstrated in relativistic programming approaches for user-space concurrency. In modern containerized environments, such as those orchestrated by , liburcu powers tracing tools like LTTng-UST and networking applications, ensuring efficient synchronization across isolated processes in cloud-native deployments.

Performance and Trade-offs

Advantages

Read-copy-update (RCU) provides extremely low overhead on the read side, often approaching zero in non-preemptive kernels where read-side primitives such as rcu_read_lock() and rcu_read_unlock() compile to empty statements on most architectures. This absence of locks, instructions, or barriers during reads enables exceptionally high throughput in read-heavy workloads, where readers vastly outnumber updaters, such as in tables or descriptors. Grace periods in RCU further contribute to this low overhead by deferring update completion until all pre-existing reads have finished, without requiring readers to synchronize directly with updaters. RCU scales effectively to thousands of CPUs, supporting configurations up to 8192 in the through hierarchical tree-based that minimize global operations and contention. Unlike traditional locks, RCU avoids cacheline bouncing and contention on shared variables, allowing concurrent reads and batched updates to proceed without blocking, which maintains as CPU counts increase in large-scale shared-memory systems. RCU exhibits strong , interoperating seamlessly with other primitives like spinlocks, sequence locks, atomic operations, and reference counters within read-side critical sections. This modularity allows developers to integrate RCU into existing codebases for read-mostly data structures while leveraging complementary mechanisms for other needs, fostering scalable and maintainable designs. In and environments, RCU reduces through features like preemptible variants with sub-100-microsecond budgets and polled grace periods introduced in , enabling predictable response times without excessive synchronization costs. Recent kernel optimizations, including dynamic callback offloading to dedicated kthreads, further enhance scalability and control for and hyperscale workloads by adapting to varying CPU loads. RCU promotes , particularly in and devices, by avoiding unnecessary awakenings of idle CPUs and implementing lazy grace periods that delay non-urgent callbacks, yielding over 10% power savings on battery-powered platforms like . These mechanisms track idle states and batch operations to minimize interrupts, aligning with the demands of power-constrained systems.

Disadvantages and Limitations

One significant limitation of Read-Copy Update (RCU) is the high associated with updates, as they must wait for a to complete before old data versions can be safely reclaimed. This ensures that all pre-existing RCU read-side critical sections have finished, but in large systems or under heavy load, it can extend to seconds, with the Linux kernel's default stall warning threshold set at . In virtualized environments, invoking synchronize_rcu() can cause spikes of several seconds on overcommitted hosts due to preempted RCU readers. Such delays make RCU unsuitable for scenarios requiring low- updates, as the updater blocks until the ends. RCU also imposes memory overhead by retaining old versions of data structures throughout the , preventing immediate reclamation and increasing the overall . This retention is necessary to allow concurrent readers uninterrupted access, but it results in larger footprints and potential out-of-memory conditions during prolonged . In systems with frequent updates, this overhead accumulates, exacerbating pressure compared to traditional locking mechanisms that permit quicker cleanup. RCU is optimized for read-mostly workloads and performs poorly in write-heavy environments, leading to issues and higher overhead than alternatives like reader-writer locks. For short-lived structures, frequent updates cause rapid accumulation of obsolete versions, amplifying consumption without proportional benefits, as the delays do not align with the transient . RCU implementations presents challenges due to the non-deterministic of , which depend on CPU scheduling and quiescent states, making reproduction of issues like stalls difficult. RCU stall warnings help detect excessively long , but diagnosing root causes—such as CPU or preemption problems—requires specialized tools and can be complex in production systems. To mitigate these limitations, expedited variants reduce by actively forcing quiescent states, though at the cost of increased CPU overhead. In kernels as of 2024, approaches like workqueue-driven expedited s and hybrid combinations with locks (e.g., in percpu reader-writer semaphores) address in critical paths while preserving RCU's read-side .

Comparisons

With Reader-Writer Locks

Read-copy-update (RCU) enables an unbounded number of concurrent readers to access shared data structures without any , in contrast to reader-writer locks, which require readers to either or when a writer holds the lock. This difference arises because RCU readers use lightweight primitives like rcu_read_lock() and rcu_read_unlock(), which impose negligible overhead and allow parallel execution even during updates, whereas reader-writer locks enforce through acquire and release operations that can serialize access. In terms of update handling, RCU updaters must wait for a —a quiescent state where all pre-existing readers have completed—before freeing old data versions, but this does not block new readers from starting. Reader-writer locks, however, block all new readers (and writers) during the write phase to ensure consistency, potentially leading to contention under high read loads. For example, in a doubly-linked list traversal, RCU replaces read-side locking with RCU read-side critical sections, allowing readers to proceed uninterrupted while updaters use callbacks like call_rcu() for deferred reclamation. RCU's read-side overhead is near-zero, typically involving only compiler barriers, but updates incur costs from copying data structures and waiting for grace periods. Reader-writer locks, by comparison, impose acquire and release costs on every read and write operation, which can accumulate in systems with frequent reads. Performance evaluations, such as those on System V implementations, show RCU outperforming reader-writer locks by factors of up to 10 in read-heavy workloads due to reduced overhead. RCU is particularly suited for read-mostly workloads where reads vastly outnumber writes, such as in routing tables or file-system directories, while reader-writer locks are more appropriate for scenarios with balanced read-write ratios requiring strict . This divergence stems from RCU's tolerance for temporary inconsistencies during updates, which reader-writer locks avoid through immediate exclusion.

With Other Synchronization Mechanisms

Read-copy-update (RCU) differs from s in its approach to ensuring reader consistency without requiring retries. Seqlocks employ sequence counters to detect concurrent writes, allowing lockless readers to proceed but potentially forcing them to spin or retry if a writer intervenes during the read, which can introduce variable latency under contention. In contrast, RCU guarantees a consistent for readers via grace periods, enabling non-blocking, wait-free reads without retries, though at the cost of deferred updates. Seqlocks are lighter-weight for simple, read-mostly data where occasional reader retries are tolerable, but RCU is preferred when consistent, low-latency reads are critical without ning. Compared to hazard pointers and epoch-based reclamation, RCU is particularly optimized for kernel environments through its use of quiescent-state-based grace periods, which efficiently detect when all readers have completed access to old data versions. Hazard pointers, a pointer-based safe memory reclamation (SMR) technique, allow threads to announce specific objects they are accessing, enabling immediate reclamation once unprotected, but incur higher overhead from per-access announcements and scans across all threads' pointers. Epoch-based reclamation (EBR), by contrast, uses global epochs to batch reclamations, assuming no long-held pointers across operations, which simplifies implementation but limits flexibility for data structures retaining references. RCU's quiescent-state approach provides bounded protection durations tailored to kernel workloads, making it more scalable for system-wide use, whereas hazard pointers and EBR offer greater generality for user-space lock-free data structures. RCU also contrasts with software transactional memory (STM) by eschewing speculative execution in favor of explicit versioning and copying. STM encapsulates updates in atomic transactions that may abort and retry on conflicts, incurring speculation overhead from buffering changes and conflict detection. RCU, however, requires manual copying of data structures for updates, allowing concurrent readers to access unchanged versions without aborts, thus avoiding STM's rollback costs but demanding more programmer effort for versioning. While STM simplifies complex concurrent modifications through atomicity, RCU suits scenarios with infrequent, non-conflicting updates where speculation is unnecessary. RCU is typically chosen over these alternatives in kernel contexts for its low read-side overhead and integration with system scheduling for grace periods, enabling efficient protection of read-mostly data like configuration structures. In user space, seqlocks, hazard pointers, or EBR may be favored for lightweight lock-free implementations, while STM is selected for applications needing automatic conflict resolution despite higher costs.

History and Intellectual Property

Historical Development

The origins of read-copy-update (RCU) trace back to early ideas in concurrent data structure management from the 1980s. In 1980, H. T. Kung and Philip L. Lehman introduced concepts resembling RCU in their work on concurrent manipulation of binary search trees, where they described techniques for deferring updates and using garbage collection to allow safe concurrent reads without immediate synchronization. These ideas laid foundational principles of procrastination in synchronization, influencing later developments in scalable concurrency mechanisms. During the 1990s, Paul E. McKenney advanced these concepts while working at Sequent Computer Systems (later acquired by ), initially developing RCU prototypes for the DYNIX/ptx operating system around 1993–1994 to address scalability issues in multiprocessor environments. McKenney, collaborating with John D. Slingwine, formalized RCU in their 1998 paper "Read-Copy Update: Using Execution History to Solve Concurrency Problems," which described leveraging execution history to permit concurrent reads during updates without locks, targeting linked data structures in systems like 's research-oriented K42 kernel. RCU's integration into the occurred in version 2.5.43 in October 2002, driven by McKenney and implemented by Rusty Russell, who contributed the efficient rcu-sched variant using per-CPU counters to minimize update overhead. This marked RCU's transition to a widely adopted open-source , despite originating from proprietary research, amid broader industry shifts toward following high-profile disputes like the lawsuits against and contributors, which ultimately bolstered community-driven adoption by affirming contributions' legitimacy. Key evolutionary milestones followed in the mid-2000s to enhance RCU's suitability for diverse workloads. Hierarchical RCU was introduced in 2008 to improve scalability on large systems by organizing grace periods across CPU hierarchies, reducing contention in multi-level cache environments. Preemptible RCU arrived in 2007 with 2.6.24, allowing read-side critical sections to be safely preempted, which was crucial for and low-latency applications by mitigating issues. Tree RCU emerged in 2009 as an extension of the hierarchical variant, employing a tree-based structure for more efficient grace-period detection on systems with thousands of CPUs, further solidifying RCU's role in . Paul E. McKenney has served as the primary maintainer of RCU in the Linux kernel since its inception, overseeing its refinements and ensuring compatibility with evolving hardware and workloads through 2025.

Patents

The primary patents covering read-copy-update (RCU) mechanisms originated from work at Sequent Computer Systems, later acquired by IBM, and focused on methods for achieving low-overhead mutual exclusion and data coherency in multiprocessor systems through thread activity summaries and quiescent state detection. The foundational U.S. Patent 5,442,758, issued on August 15, 1995, to Sequent (assigned to IBM), describes an apparatus for concurrent reading and updating of shared data using execution history to track quiescent states, enabling zero-overhead mutual exclusion. This was followed by U.S. Patent 5,608,893, issued on March 4, 1997, to IBM, which extends coherency maintenance using thread activity summaries to detect when updates can safely proceed without blocking readers. Subsequent patents include U.S. Patent 6,219,690, issued on April 17, 2001, to IBM, detailing efficient implementations of read-copy-update for reduced overhead in multiprocessor environments. U.S. Patent 6,886,162, issued on April 26, 2005, to Sequent and IBM, addresses high-speed thread activity summarization across multiple nodes using hierarchical bit masks to minimize remote memory operations during grace period detection. These patents broadly cover copy-update synchronization techniques that allow readers to access data structures without locks while updaters create new versions and defer reclamation until safe. The RCU patents became a point of contention in the v. , filed in March 2003, where alleged that improperly contributed RCU code—derived from Sequent's proprietary Unix implementations—to , infringing on 's Unix licensing rights. The case, which spanned from 2003 to 2007 before administrative closure due to 's bankruptcy and later dismissal of remaining claims in 2016, scrutinized RCU among other technologies but resulted in no findings of infringement or restrictions on RCU's use in . All major RCU-related patents had expired by , with the core ones lapsing between and due to their 17- or 20-year terms from filing or issuance. As of 2025, no active patents on fundamental RCU mechanisms remain, allowing unrestricted adoption and implementation in open-source kernels like without barriers. This expiration has facilitated widespread integration of RCU variants across operating systems, enhancing in concurrent environments without licensing concerns.

References

  1. [1]
    What is RCU? -- “Read, Copy, Update” - The Linux Kernel Archives
    RCU is a synchronization mechanism that was added to the Linux kernel during the 2.5 development effort that is optimized for read-mostly situations.
  2. [2]
    A Tour Through RCU's Requirements — The Linux Kernel 5.10.0 ...
    Read-copy update (RCU) is a synchronization mechanism that is often used as a replacement for reader-writer locking. RCU is unusual in that updaters do not ...
  3. [3]
    [PDF] READ-COPY UPDATE: USING EXECUTION HISTORY TO SOLVE ...
    READ-COPY UPDATE: USING EXECUTION HISTORY TO SOLVE. CONCURRENCY PROBLEMS. PAUL E. MCKENNEY. 15450 SW Koll Parkway. Beaverton, OR 97006 USA mckenney@sequent.com.Missing: RCU inventor
  4. [4]
    [PDF] Stateless model checking of the Linux kernel's read–copy update ...
    Read–copy update (RCU) is a synchronization mechanism used heavily in key components of the Linux kernel, such as the virtual filesystem (VFS), to achieve ...
  5. [5]
    [PDF] User-Level Implementations of Read-Copy Update - EfficiOS
    Dec 16, 2010 · RCU's light-weight read paths support the increasing need to track read-mostly connectivity, hardware- configuration, and security-policy data.
  6. [6]
    Using RCU (Read-Copy-Update) for synchronization - QEMU
    Read-copy update (RCU) is a synchronization mechanism that is used to protect read-mostly data structures. RCU is very efficient and scalable on the read side.
  7. [7]
    [PDF] Read-Copy Update - The Linux Kernel Archives
    This paper lists how read-copy update has been used in DYNIX/ptx, Tornado, and K42. The paper also shows some “toy” examples and describes patches that ...Missing: seminal | Show results with:seminal
  8. [8]
  9. [9]
    What is RCU?
    This is the great strength of classic RCU in a non-preemptive kernel: read-side overhead is precisely zero, at least on non-Alpha CPUs. And there is ...
  10. [10]
    The design of preemptible read-copy-update - LWN.net
    Oct 8, 2007 · This article was contributed by Paul McKenney. This document walks through the design of preemptible RCU. Introduction. Read-copy update (RCU) ...Overview Of Preemptible Rcu... · Read-Side Primitives · Answers To Quick Quizzes
  11. [11]
    A Tour Through RCU's Requirements - The Linux Kernel Archives
    Read-copy update (RCU) is a synchronization mechanism that is often used as a replacement for reader-writer locking. RCU is unusual in that updaters do not ...
  12. [12]
    [PDF] What is RCU, Fundamentally? - PDXScholar
    Dec 17, 2007 · What is RCU, Fundamentally? Paul E. McKenney. IBM Linux Technology Center. Jonathan Walpole. Portland State University.Missing: preemptible | Show results with:preemptible
  13. [13]
    RCU part 3: the RCU API - LWN.net
    Jan 7, 2008 · The design of preemptible read-copy-update (McKenney, October 2007). Describes a high-performance RCU implementation for realtime use ...Rcu Has A Family Of... · Rcu Has Publish-Subscribe... · Answers To Quick Quizzes<|control11|><|separator|>
  14. [14]
    [PDF] Read-Copy Update: Using Execution History to Solve Concurrency ...
    Read-Copy Update: Using Execution History to Solve Concurrency Problems. P.E. McKenney, Senior Member, IEEE, and J.D. Slingwine.
  15. [15]
    What is RCU? -- “Read, Copy, Update” — The Linux Kernel documentation
    ### Summary of Update-Side Primitives in RCU (Source: https://www.kernel.org/doc/html/latest/RCU/whatisRCU.html)
  16. [16]
  17. [17]
  18. [18]
    What is RCU, Fundamentally? - LWN.net
    Dec 17, 2007 · Read-copy update (RCU) is a synchronization mechanism that was added to the Linux kernel in October of 2002. RCU achieves scalability ...Publish-Subscribe Mechanism · Wait For Pre-Existing Rcu... · Example 2: Maintaining...
  19. [19]
    A Tour Through TREE_RCU's Expedited Grace Periods
    This document describes RCU's expedited grace periods. Unlike RCU's normal grace periods, which accept long latencies to attain high efficiency and minimal ...
  20. [20]
    None
    Below is a merged summary of the "Toy RCU Implementations" from *perfbook.2024.12.27a.pdf*, consolidating all the information from the provided segments into a dense, structured format. Given the volume of data, I’ll use a combination of narrative text for an overview and tables in CSV format to capture detailed pseudocode, steps, assumptions, limitations, and URLs efficiently. The response retains all information while ensuring clarity and completeness.
  21. [21]
  22. [22]
    The RCU API, 2019 edition - LWN.net
    Jan 23, 2019 · Read-copy update (RCU) is a synchronization mechanism that was added to the Linux kernel in October 2002. RCU is most frequently described as a replacement for ...
  23. [23]
    Hierarchical RCU - LWN.net
    Nov 4, 2008 · Such states are called “quiescent states”, and after each CPU has passed through at least one quiescent state, the RCU grace period ends.
  24. [24]
    A Tour Through TREE_RCU's Data Structures [LWN.net]
    A grace period can be completed at the root once every CPU (or, in the case of CONFIG_PREEMPT_RCU, task) has passed through a quiescent state. Once a grace ...The rcu_state Structure · The rcu_node Structure · The rcu_data Structure
  25. [25]
    Technical details of the real-time preemption - Wiki
    Oct 3, 2023 · The PREEMPT_RT preemption models both use preemptible RCU mechanisms. Additionally the PREEMPT_RT patch eliminates RCU handling from all ...
  26. [26]
    Userspace RCU
    liburcu is a LGPLv2.1 userspace RCU (read-copy-update) library. This data synchronization library provides read-side access which scales linearly with the ...
  27. [27]
    User-space RCU - LWN.net
    Nov 13, 2013 · This article was contributed by Paul E. McKenney, Mathieu Desnoyers, and Lai Jiangshan. The user-space read-copy update (URCU) library was ...
  28. [28]
    [PDF] A Critical RCU Safety Property is... Ease of Use!
    These attractive performance and scal- ability properties have led to significant RCU use within the. Linux kernel, with more than 15,000 calls to its API as of.
  29. [29]
    What is RCU? Part 2: Usage
    ### Summary of RCU Applications in Linux Kernel
  30. [30]
    Lockless algorithms [was Re: splxxx replacements?]
    ... RCU is starting to be pushed by various people ... DragonFly has five locking primitives: * Critical ... implementation. RCU suffers from a level of ...
  31. [31]
  32. [32]
    Using RCU in the Linux 2.5 Kernel - Linux Journal
    Oct 1, 2003 · RCU-like mechanisms also may be used in preemptive kernels without suppressing preemption, as demonstrated by the K42 research OS. Most ...
  33. [33]
    [PDF] Providing a Linux API on the Scalable K42 Kernel - Computer Science
    K42 is an open-source research kernel targeted for 64- bit cache-coherent ... K42 has developed deferred object deletion [12] similar to RCU [22] allowing objects ...
  34. [34]
    [PDF] Read-Copy Update (RCU) - Open Standards
    Mar 8, 2023 · On the other hand, Paul was asked to begin this effort in 2014, it is now 2022, and C++ implementations have been used in production for some ...Missing: inventor | Show results with:inventor
  35. [35]
    [PDF] Extending RCU for Realtime and Embedded Workloads
    Jul 19, 2006 · This past year has seen significant increases in RCU's realtime capabilities, particularly the ability to preempt RCU read-side critical sec ...Missing: research | Show results with:research
  36. [36]
    [PDF] Resizable, Scalable, Concurrent Hash Tables via Relativistic ...
    These resize algorithms allow Read-. Copy Update (RCU) hash tables to maintain constant- time performance as the number of entries grows, and re- claim memory ...
  37. [37]
    [PDF] Read Copy Update - The Linux Kernel Archives
    Read-copy update allows lock-free read-only access to data structures that are being con- currently modified. The accessing code needs neither locks nor atomic ...
  38. [38]
    The RCU API, 2024 edition - LWN.net
    Read-copy-update (RCU) is a synchronization mechanism that was added to the Linux kernel in October 2002. RCU is most frequently used as a ...
  39. [39]
    Reader-Writer-Locking/RCU Analogy - USENIX
    ... reader-writer locks and then with RCU, comparing the results. This structure ... Read-Copy Update. rwlock_t, spinlock_t. read_lock(), rcu_read_lock ...
  40. [40]
    [PDF] Using Read-Copy-Update Techniques for System V IPC in the Linux ...
    The grace period will delay freeing of memory, which means that both the memory and the cache footprint of the code will be somewhat larger when using RCU than ...
  41. [41]
    Sequence counters and sequential locks
    Sequence counters are a reader-writer consistency mechanism with lockless readers (read-only retry loops), and no writer starvation.Missing: differences | Show results with:differences<|control11|><|separator|>
  42. [42]
    Unreliable Guide To Locking - The Linux Kernel documentation
    Avoiding Locks: Read Copy Update¶. There is a special method of read/write ... Paul McKenney, John Ashby for proofreading, correcting, flaming, commenting.
  43. [43]
    None
    ### Summary: Hazard Pointers vs. RCU in Linux Kernel
  44. [44]
    [PDF] Reclaiming Memory for Lock-Free Data Structures - cs.Toronto
    hazard pointers, epoch based reclamation and transactional memory assisted reclamation. ... Concurrent updates with RCU: Search tree as an example. In ...
  45. [45]
    RCU and Transactions
    Because read-copy update (RCU) finds its main use in the Linux kernel, one might be forgiven for assuming that there had been no academic work on combining RCU ...
  46. [46]
    The open-source patent conundrum (News.com) [LWN.net]
    "According to the American Intellectual Property Law Association, software patent lawsuits come with a defense cost of about $3 million. Even before the case ...
  47. [47]
    Verification of the Tree-Based Hierarchical Read-Copy Update in ...
    Oct 10, 2016 · Read-Copy Update (RCU) is a scalable, high-performance Linux-kernel synchronization mechanism that runs low-overhead readers concurrently with ...Missing: seminal | Show results with:seminal
  48. [48]
    Speakers | Kernel Recipes
    Paul is a software engineer at Meta Platforms, where he maintains the RCU implementation within the Linux kernel, where the variety of workloads present highly ...
  49. [49]
    US5442758A - Google Patents - Google Patents
    This invention is a substantially zero-overhead mutual-exclusion apparatus and method that allow concurrent reading and updating data while maintaining data ...
  50. [50]
  51. [51]
  52. [52]
  53. [53]
    SCO Group v. IBM, No. 16-4040 (10th Cir. 2017) - Justia Law
    SCO accused IBM of stealing and improperly using source code developed as part of the Project to strengthen its own operating system.
  54. [54]
    The SCO lawsuit, 20 years later - LWN.net
    On March 7, 2003, a struggling company called The SCO Group filed a lawsuit against IBM, claiming that the success of Linux was the result of a theft of SCO's ...缺少字词: resolution RCU