Fact-checked by Grok 2 weeks ago

Seqlock

A seqlock (sequence lock) is a synchronization primitive in the that enables lockless reads of shared data structures, allowing multiple readers to access data concurrently without blocking, while ensuring writers can proceed without starvation by using a sequence counter to detect and retry reads affected by concurrent writes. It is particularly suited for read-mostly scenarios where data updates are infrequent, such as or statistical counters, as readers may need to retry their operations if a write occurs during the read. Seqlocks build on sequence counters (seqcount_t), a core component where writers increment a counter to an odd value before modifying data and to an even value afterward, signaling stability to readers who compare the counter before and after their access. The full seqlock structure (seqlock_t) integrates this sequence counter with a to serialize multiple writers and disable preemption during updates, preventing indefinite reader spinning. Reader , such as read_seqbegin() and read_seqretry(), facilitate non-blocking access, while writers use write_seqlock() and write_sequnlock() for exclusive modifications. Notable limitations include unsuitability for protecting data containing pointers, as concurrent writes could invalidate reader accesses mid-operation, and the requirement for writers to remain non-preemptible to avoid performance issues. Variants like seqcount_latch_t extend functionality for non-maskable interrupt (NMI) contexts or multiversion concurrency control. Seqlocks are widely used in the kernel for efficient synchronization in subsystems like timekeeping and networking, balancing speed and consistency without the overhead of traditional reader-writer locks.

Introduction

Definition and Purpose

A seqlock, short for sequential lock, is a reader-writer designed to facilitate concurrent access to shared data structures in multiprocessor environments. It employs a sequence counter to track updates, enabling multiple readers to perform lock-free operations while ensuring data consistency through retry mechanisms if a write occurs during a read. This mechanism combines elements of sequence counters with optional locking for writers, distinguishing it from traditional locks by allowing readers to proceed without acquiring any lock, provided they verify the sequence counter before and after accessing the data. The primary purpose of a seqlock is to optimize in scenarios where reads vastly outnumber writes, such as in operating system components for timekeeping, collection, or configuration data that changes infrequently. By avoiding the overhead of exclusive locking for readers, seqlocks reduce contention and latency in high-throughput read paths, making them particularly suitable for kernel-level synchronization where scalability is critical. This approach addresses the classic readers-writers problem by prioritizing writer progress—writers do not wait for ongoing readers—while preventing reader through bounded retry loops, thus ensuring without indefinite blocking. Seqlocks originated in the development of the , where they were introduced to handle needs in performance-sensitive areas like the time code. Their design emphasizes no writer starvation, as writers can always proceed after briefly disabling preemption or acquiring a lightweight lock, providing a balance between efficiency and correctness in shared-memory systems.

Historical Development

The seqlock mechanism originated in the development efforts as a novel primitive designed to enable efficient reader-writer access to shared data structures, particularly for scenarios with infrequent writes. Initially conceived by Stephen Hemminger and termed "frlocks," it drew inspiration from earlier sequence-number-based ideas proposed by Andrea Arcangeli for optimizing read-write locks. The concept was first proposed in a for fast reader/writer locking in gettimeofday operations during the 2.5 development series in 2002. This primitive was formally introduced and stabilized in version 2.5.60 in early 2003, with Hemminger contributing the core implementation for protecting time-related variables like xtime and get_jiffies_64(). It was subsequently integrated into the stable 2.6.x series, marking its transition from experimental to production use. Early adoption focused on the architecture, where seqlocks addressed the need to synchronize time updates with user-space queries without incurring the overhead of traditional locks, which were infeasible due to user-space constraints. Over subsequent releases, seqlocks evolved through refinements to enhance robustness and performance. Key improvements included better handling of overflows—using (64-bit on 64-bit architectures) that wrap around but maintain consistency via reader retries—and optimizations to reduce the frequency of read retries in contended scenarios. In version 3.17 (2014), the was updated to use atomic_long_t for 64-bit support on 64-bit systems, further reducing overflow concerns. These changes were documented in sources starting with version 2.6, evolving from basic seqcount_t structures to advanced variants like seqcount_latch_t for multiversion support and seqlock_t with embedded spinlocks for writer serialization. A significant milestone in seqlock-like techniques predates its Linux implementation, with the first practical application appearing in FreeBSD's timecounter framework around 2002, which employed generation counters for precise, low-overhead timekeeping in environments. This BSD approach influenced broader adoption of similar optimistic concurrency mechanisms across systems, underscoring seqlocks' role in enabling scalable synchronization for read-mostly data.

Core Mechanism

Sequence Counter Operation

A seqlock relies on a shared sequence counter, implemented as an within the seqcount_t , to track the of the protected . This serves as the core for detecting concurrent modifications without requiring readers to locks. Additionally, seqlocks incorporate an optional —embedded in the seqlock_t type—for serializing writer access and preventing writer , while readers operate lock-free. Writers follow strict increment rules to manipulate the : they increment it by immediately before beginning an update, shifting the value to an odd number to indicate that a write is in progress and the data may be inconsistent. Upon completing the update, writers increment the counter by another , restoring it to an even value to signal that the data is stable again. These atomic increments ensure that the counter accurately reflects the update lifecycle, allowing concurrent readers to detect . In the implementation, the sequence counter is a 32-bit unsigned designed to handle wraparound safely through its properties. Readers compare the 's value before and after their read operation, detecting changes even if the overflows, as long as updates are short-lived and do not span the full 32-bit multiple times. This approach avoids explicit checks, relying instead on the retry logic to maintain consistency. The sequence provides a guarantee by enabling readers to validate stability: if the is even at the start of a read and remains unchanged (still even) at the end, the read obtained a consistent of the . Any change in the value during the read indicates potential modification, prompting a retry to ensure correctness. This mechanism underpins the seqlock's efficiency in read-heavy scenarios.

Reader Access Protocol

In seqlocks, readers access shared through a lock-free that relies on counters to detect concurrent modifications without blocking writers or other readers. The process begins with the reader atomically loading the current counter value, denoted as seq1, using a like read_seqbegin. This value indicates the of the data: an even number suggests stability, while an odd number signals that a write operation is in progress. If seq1 is even, the reader proceeds to copy the shared fields into local variables without acquiring any lock, ensuring the read-side remains lightweight and non-blocking. Upon completing the read, the reader loads the sequence counter again, obtaining seq2 via a like read_seqretry, which also enforces memory barriers for consistency. The read is validated by checking if seq2 equals seq1 and is even; a mismatch or odd value implies that a modified the during the read, rendering it inconsistent. In such cases, the reader discards the copied data and retries the entire process from the acquisition step, forming an optimistic retry loop. This loop continues until a consistent is obtained, with no predefined bound on retries; however, under typical low-write contention scenarios, the probability of prolonged retries remains low, as writers complete quickly and increments are infrequent. The protocol can be outlined in the following , which encapsulates the acquisition, read, validation, and retry mechanism:
do {
    seq1 = read_seqbegin(&shared_seqlock);  // Load initial sequence counter
    // Copy shared data to local variables (read-side [critical section](/page/Critical_section))
    local_data = shared_data;
} while (read_seqretry(&shared_seqlock, seq1));  // Validate and retry if needed
// Use local_data as consistent [snapshot](/page/Snapshot)
This ensures readers observe either a pre- or post-update view of the data, prioritizing progress for writers while maintaining read efficiency.

Writer Update Protocol

In the seqlock mechanism, writers follow a structured to update shared data while ensuring among multiple writers and providing signals to readers. This involves acquiring a for , managing the sequence to indicate the update state, and releasing resources upon completion. The acquisition phase begins with the writer invoking write_seqlock(), which first acquires an internal (embedded in the seqlock_t or provided externally) to and prevent concurrent writes. This step increments the sequence from an even value to an odd one, signaling to readers that an update is in progress and prompting them to retry if they detect the mismatch. Preemption is disabled during this phase to avoid indefinite reader spinning. During the update phase, the writer performs the data modification while the sequence counter remains odd, ensuring that the critical section is protected from other writers but allowing non-blocking reader attempts (which will typically retry). This phase assumes atomic updates for simple data types, though complex structures may require additional safeguards to maintain consistency. Upon completion, the writer calls write_sequnlock(), which increments the sequence counter again to an even value, indicating that the data is now stable and readers can proceed without retrying. The spinlock is then released, allowing the next writer to proceed. This protocol prevents writer starvation, as writers are not blocked by ongoing reads, enabling progress even in high-read-contention scenarios. The following pseudocode outlines the writer protocol:
write_seqlock(&lock);
do_something_to_data();  /* [Critical section](/page/Critical_section) */
write_sequnlock(&lock);
```[](https://docs.kernel.org/locking/seqlock.html)

## Key Properties

### Advantages Over Traditional Locks

Seqlocks provide lock-free reads, where readers perform no [synchronization](/page/Synchronization) beyond checking a sequence counter, incurring minimal overhead in the form of potential retries. This approach is particularly advantageous for read-mostly data structures, such as counters or timestamps, as it eliminates the need for readers to acquire or release locks, allowing them to proceed without blocking or being blocked by writers.[](https://docs.kernel.org/locking/seqlock.html)

Writers benefit from reduced contention, as readers do not hold any locks that could impede write operations, leading to lower [latency](/page/Latency) in scenarios with infrequent writes. Unlike traditional reader-writer locks, seqlocks ensure that writers are not stalled by ongoing reads, promoting efficient progress for updates even in the presence of concurrent reader activity.[](https://docs.kernel.org/locking/seqlock.html)

In multi-core systems, seqlocks exhibit strong scalability with a high number of concurrent readers, avoiding the queuing and [serialization](/page/Serialization) that can occur with reader-writer locks under heavy read loads. This makes them suitable for environments where read amplification—due to occasional retries—is acceptable in exchange for overall system throughput. Additionally, seqlocks avoid reader-writer fairness issues, such as [priority inversion](/page/Priority_inversion), where writers might otherwise be indefinitely delayed by a queue of readers.[](https://docs.kernel.org/locking/seqlock.html)

In the [Linux kernel](/page/Linux_kernel), seqlocks are employed for protecting data like jiffies (a [tick](/page/Tick) counter for system uptime) and [cycle](/page/Cycle) counters, where the rare writes justify the retry mechanism to achieve consistent, high-performance access.[](https://docs.kernel.org/locking/seqlock.html)

### Limitations and Potential Issues

Seqlocks, while efficient for certain workloads, carry several limitations that can lead to failure modes in inappropriate use cases. One primary risk is livelock, where readers may enter an indefinite retry loop if a writer is preempted or interrupted during its [critical section](/page/Critical_section), leaving the sequence counter in an odd state that signals ongoing modification. The `seqlock_t` variant mitigates this by automatically disabling preemption via its embedded [spinlock](/page/Spinlock). This issue is particularly severe in [real-time](/page/Real-time) scheduling classes, potentially causing readers to spin indefinitely without bounded progress guarantees.[](https://docs.kernel.org/locking/seqlock.html) Although rare under normal conditions, excessive write activity or excessively slow readers can exacerbate this, leading to repeated retries without completion.[](https://docs.kernel.org/locking/seqlock.html)

Seqlocks are inherently restricted to protecting small, flat data structures without pointers, as the optimistic read protocol assumes atomic access to the entire protected data. If the data includes pointers, a writer can invalidate a pointer mid-read, causing the reader to follow invalid references and potentially crash or produce incorrect results; in such cases, Read-Copy-Update (RCU) mechanisms are recommended instead for managing dynamic structures.[](https://docs.kernel.org/locking/seqlock.html) This limitation stems from the lack of locking on the read side, which prioritizes performance but sacrifices safety for complex data types.[](https://docs.kernel.org/locking/seqlock.html)

The `seqlock_t` variant, which incorporates an internal [spinlock](/page/Spinlock) for writer serialization, can still lead to writer blocking under high contention, as multiple writers will queue on the spinlock, effectively serializing access and diminishing the [scalability](/page/Scalability) benefits over traditional locks.[](https://docs.kernel.org/locking/seqlock.html) Additionally, interpreting sequence counter values during [debugging](/page/Debugging) is challenging due to the asynchronous nature of retries and the opaque odd/even parity signaling, complicating trace analysis without full contextual awareness of concurrent operations. The mechanism handles sequence counter [overflow](/page/Overflow) through its 32-bit wrapping, but extremely long-running readers spanning multiple wrap-arounds risk misinterpreting changes, though this scenario is exceedingly rare given typical write frequencies.[](https://docs.kernel.org/locking/seqlock.html)

## Implementations and Usage

### API in Linux Kernel

The seqlock API in the Linux kernel provides a mechanism for reader-writer synchronization using sequence counters, where readers perform lockless operations while writers use a combined sequence counter and spinlock for serialization.[](https://docs.kernel.org/locking/seqlock.html) The core data structure is `seqlock_t`, which encapsulates a sequence counter and an embedded spinlock to ensure mutual exclusion among writers and prevent preemption during updates.[](https://docs.kernel.org/locking/seqlock.html) Instances of `seqlock_t` can be initialized statically using the macro `DEFINE_SEQLOCK(name)`, which declares and initializes the structure with an unlocked state, or dynamically via the function `void seqlock_init(seqlock_t *sl)` for runtime allocation.[](https://docs.kernel.org/locking/seqlock.html)

For readers, the API offers lock-free access through the function `unsigned read_seqbegin(const seqlock_t *sl)`, which acquires the current [sequence](/page/Sequence) value without locking, allowing the reader to proceed with data access.[](https://docs.kernel.org/locking/seqlock.html) To verify consistency after reading, readers invoke `int read_seqretry(const seqlock_t *sl, unsigned start)`, which compares the initial sequence against the current one and returns a non-zero value if a writer has intervened, prompting a retry of the read operation.[](https://docs.kernel.org/locking/seqlock.html) These functions enable efficient, non-blocking reads suitable for high-frequency access scenarios.

Writers acquire exclusive access using `void write_seqlock(seqlock_t *sl)`, which first acquires the embedded [spinlock](/page/Spinlock) and increments the sequence counter to an odd value, signaling the start of an update.[](https://docs.kernel.org/locking/seqlock.html) Upon completion, `void write_sequnlock(seqlock_t *sl)` releases the [spinlock](/page/Spinlock) and increments the sequence to an even value, notifying readers that the update is finished and consistent.[](https://docs.kernel.org/locking/seqlock.html) This pairing ensures that writers are serialized via the [spinlock](/page/Spinlock) while the sequence counter tracks modification epochs for reader validation.

The [API](/page/API) includes variants for specialized use cases, such as `seqcount_t`, a lightweight sequence counter without an embedded lock that requires external [synchronization](/page/Synchronization) mechanisms for writers, offering finer control in environments where additional locking is managed separately.[](https://docs.kernel.org/locking/seqlock.html) For scenarios demanding lockless writer operations—though riskier due to potential races—functions like `raw_read_seqcount_begin(const seqcount_t *s)` provide raw access without lockdep annotations or preemption checks.[](https://docs.kernel.org/locking/seqlock.html) All seqlock-related definitions and functions are provided in the header file `include/linux/seqlock.h`, with the [API](/page/API) stabilized and available since Linux kernel version 2.6.[](https://lwn.net/Articles/22818/)

### Practical Examples in Systems

One prominent application of seqlocks in the [Linux kernel](/page/Linux_kernel) is in timekeeping, specifically for protecting the `jiffies_64` variable, which maintains a 64-bit counter of system uptime ticks across multiple CPUs. This mechanism enables lock-free reads by multiple consumers, such as scheduling and timer subsystems, while allowing writers to increment the counter without blocking, essential for maintaining precise timing in multiprocessor environments.[](https://lwn.net/Articles/22818/)

In the networking subsystem, seqlocks underpin the `u64_stats_sync` structure used in `tcp_statistics` to track per-CPU packet metrics like retransmits and errors. This approach supports high-frequency reads from tools like `netstat` or `ss` under heavy traffic loads, where updates from packet processing are infrequent, minimizing contention and ensuring consistent 64-bit atomicity on 32-bit architectures.

Beyond the kernel, seqlocks have been adapted in user-space libraries like DPDK for high-performance packet processing. In DPDK's ring buffers and shared data structures, the `rte_seqlock` primitive facilitates concurrent reader access to sequence numbers and metadata during fast-path operations, such as enqueuing/dequeuing packets in multi-core environments, reducing latency for network I/O-intensive applications.[](https://doc.dpdk.org/api/rte__seqlock_8h.html)

## Comparisons with Alternatives

### Versus Read-Write Locks

Seqlocks and read-write locks (rwlocks) represent distinct approaches to reader-writer [synchronization](/page/Synchronization) in concurrent systems, particularly within the [Linux kernel](/page/Linux_kernel). Rwlocks permit multiple concurrent readers but require writers to block all readers and additional writers until the update completes, often involving queuing mechanisms and atomic [reference counting](/page/Reference_counting) to track active readers. In contrast, seqlocks provide non-blocking, optimistic reads that proceed without acquiring locks; readers simply check a sequence counter before and after accessing the data, retrying the operation if the counter indicates a concurrent write. This design eliminates direct blocking for readers, avoiding the latency spikes from context switches or spin-waiting that rwlocks impose during writes.[](https://docs.kernel.org/locking/seqlock.html)[](https://docs.kernel.org/locking/locktypes.html)

The overhead profiles of these mechanisms highlight further trade-offs. Rwlocks rely on atomic operations for incrementing and decrementing reader counts, which can introduce contention and cache-line bouncing in high-concurrency environments with many readers. Seqlocks minimize this by using simple, non-atomic counter reads for most reader paths, coupled with a lightweight [spinlock](/page/Spinlock) only for writers to serialize updates and advance the sequence. However, this shifts potential costs to readers in the form of occasional retries during write activity, whereas rwlocks guarantee consistent reads without such loops.[](https://docs.kernel.org/locking/seqlock.html)

Fairness considerations also diverge significantly. In read-intensive workloads, rwlocks risk writer starvation, as a steady stream of readers can indefinitely delay writers waiting to acquire exclusive access. Seqlocks mitigate this by ensuring writers do not wait for readers to finish—reads are invalidated via the sequence counter instead—thus guaranteeing writer progress without fully excluding concurrent readers.[](https://docs.kernel.org/locking/seqlock.html)

Seqlocks suit scenarios with extreme read-write skew, such as protecting rarely updated data like system timestamps where readers vastly outnumber writers and can tolerate infrequent retries. Rwlocks, conversely, perform better in balanced read-write patterns, offering stronger consistency guarantees without retry logic. In the [Linux kernel](/page/Linux_kernel), rwlocks are implemented via the `rwlock_t` structure, which employs [spinlocks](/page/Spinlock) for both reader and writer acquisition in non-real-time (non-PREEMPT_RT) kernels. Seqlocks use the `seqlock_t` structure, integrating a sequence counter with an embedded [spinlock](/page/Spinlock) for a hybrid approach that favors read [scalability](/page/Scalability) over rwlocks' more uniform locking.[](https://docs.kernel.org/locking/seqlock.html)[](https://docs.kernel.org/locking/locktypes.html)

### Versus Read-Copy-Update (RCU)

Seqlocks and [Read-Copy-Update](/page/Read-copy-update) (RCU) are both lock-free synchronization mechanisms optimized for read-mostly workloads in the [Linux kernel](/page/Linux_kernel), but they differ fundamentally in their update approaches and applicability. Seqlocks perform in-place updates to the protected [data structure](/page/Data_structure), where writers increment a sequence counter before modifying the data and again after, ensuring readers can detect concurrent changes through mismatched sequence numbers and retry their read operation. In contrast, RCU employs a copy-and-swap strategy for updates: writers create a new copy of the data structure, modify it, atomically swap pointers to the new version, and defer reclamation of the old version until a [grace period](/page/Grace_period) elapses, during which all pre-existing readers complete without requiring retries. This allows RCU to handle more intricate update patterns without interrupting ongoing reads.[](https://www.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.2011.08.28a.pdf)[](https://docs.kernel.org/locking/seqlock.html)

Seqlocks are best suited for simple, fixed-size data structures without pointers, such as counters or timestamps, where readers can safely retry the entire read if an update is detected, as the data remains self-contained and does not risk dereferencing invalid memory. RCU, however, excels with complex, dynamic structures like linked lists or [trees](/page/Linden), where updates may involve pointer changes; it relies on grace periods to guarantee that readers see consistent views without pointer hazards, enabling safe traversal of large data sets. Seqlocks cannot support pointer-containing data due to the potential for readers to follow stale pointers during an in-place update, whereas RCU's deferred reclamation avoids such issues through quiescent-state tracking across CPUs.[](https://www.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.2011.08.28a.pdf)

In terms of overhead, seqlocks impose minimal cost on writers—primarily incrementing the sequence counter and occasionally acquiring a brief [spinlock](/page/Spinlock) for [serialization](/page/Serialization)—but readers may incur retry loops under contention, leading to variable performance that degrades with write frequency. RCU shifts this burden to writers, who must copy the structure and wait for a [grace period](/page/Grace_period) (typically microseconds to milliseconds, depending on system load), resulting in higher update latency; however, readers experience guaranteed progress with low, consistent overhead, often just lightweight barriers in non-preemptible kernels. This trade-off makes seqlocks efficient for scenarios with rare writes but potentially costly retries, while RCU ensures predictable reader throughput at the expense of update complexity.[](https://www.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.2011.08.28a.pdf)[](https://docs.kernel.org/locking/seqlock.html)

Seqlocks handle contention by allowing writers to proceed without blocking readers, but in write-heavy environments, frequent sequence changes can cause excessive reader retries, risking livelock—particularly problematic for [real-time](/page/Real-time) tasks that may spin indefinitely on an odd [sequence](/page/Sequence) [counter](/page/Counter). RCU mitigates this through quiescent-state guarantees, where updates wait for all CPUs to reach safe points (e.g., voluntary [context](/page/Context) switches or [idle](/page/IDLE) periods), providing multi-CPU safety without retries or [starvation](/page/Starvation), though it requires careful grace-period management to avoid prolonged update delays. Thus, seqlocks are prone to fairness issues under high contention, while RCU offers robust protection for concurrent access across many cores.[](https://www.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.2011.08.28a.pdf)

In the [Linux kernel](/page/Linux_kernel), seqlocks are typically applied to short critical sections involving simple primitives, such as updating system counters or timekeeping variables, where quick reads outweigh occasional retries. RCU is preferred for longer read operations, like traversing file-system [metadata](/page/Metadata) or [network](/page/Network) [routing](/page/Routing) tables, where guaranteed consistency without retries supports scalable, high-throughput access. For instance, seqlocks protect packet headers in networking stacks for fast parsing, while RCU safeguards linked structures in the [virtual file system](/page/Virtual_file_system) for efficient directory traversals. These choices reflect seqlocks' niche for lightweight, atomic-like operations versus RCU's broader utility in complex, read-intensive subsystems.[](https://www.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.2011.08.28a.pdf)[](https://docs.kernel.org/locking/seqlock.html)

References

  1. [1]
    Sequence counters and sequential locks
    Sequence counters are a reader-writer consistency mechanism with lockless readers (read-only retry loops), and no writer starvation.
  2. [2]
    fast reader/writer lock for gettimeofday 2.5.30 - LWN.net
    Aug 12, 2002 · Kernel Mailing List <linux-kernel@vger.kernel.org>. Subject ... A new composite primitive 'frlock' is defined in include/linux/frlock ...
  3. [3]
    Linux-kernel mailing list archive 2003-02,: Re: lots of calls to __write ...
    ISTR a patch from Stephen Hemminger at OSDL that used Andrea's sequence number trick based rwlock (frlock) to implement do_gettimeofday. It might be ...
  4. [4]
    None
    Summary of each segment:
  5. [5]
    Sequence counters and sequential locks - The Linux Kernel Archives
    Sequence counters are a reader-writer consistency mechanism with lockless readers (read-only retry loops), and no writer starvation.
  6. [6]
    [PDF] Timecounters: Efficient and precise timekeeping in SMP kernels.
    This article is about the code in the FreeBSD kernel which keeps track of time. Time and timescale basics. Despite the fact that time is the physical quantity ( ...
  7. [7]
    [PDF] A Survey of Parallel Processing in Linux - San Jose State University
    The benefit of a seq lock is that a writer can proceed while one or more readers are still holding the lock; in other words, a writer is never starved by ...
  8. [8]
    Driver porting: mutual exclusion with seqlocks - LWN.net
    Feb 14, 2003 · The 2.5.60 kernel added a new type of lock called a "seqlock." Seqlocks are a specialized primitive intended for the following sort of ...Missing: origin | Show results with:origin
  9. [9]
    lib/eal/include/rte_seqlock.h File Reference - Documentation - DPDK
    A seqlock is not preemption-safe on the writer side. If a writer is ... To avoid resource reclamation issues, the data protected by a seqlock should ...
  10. [10]
  11. [11]
    [PDF] Is Parallel Programming Hard, And, If So, What Can You Do About It?
    Dec 16, 2011 · Is Parallel Programming Hard, And, If So, What Can You Do. About It? Edited by: Paul E. McKenney. Linux ... kernel, while other code is GPLv2 ...<|control11|><|separator|>