How Linux Kernel’s Seqlock Eliminates Lock Contention for High‑Performance Concurrency
The article explains the Linux kernel Seqlock mechanism—a lightweight lock‑free synchronization primitive that uses a sequence number and a spinlock to allow concurrent reads and writes, compares it with spinlocks and rwlocks, and shows real kernel and user‑space examples.
What Is Seqlock?
Seqlock is a lightweight lock‑free synchronization primitive used in the Linux kernel to avoid the blocking behavior of mutexes and rwlocks. It combines a sequence number with a spinlock, allowing readers to proceed concurrently with writers while still detecting stale reads.
Seqlock Structure
The core data structure is:
typedef struct {
unsigned sequence;
spinlock_t lock;
} seqlock_t;The sequence field records write epochs; even values mean no writer is active, odd values indicate an ongoing write. The spinlock protects the critical section during writes.
Initialization
Two ways:
Static initialization with seqlock_t my_seqlock = SEQLOCK_UNLOCKED; sets sequence to 0 (even) and the spinlock to unlocked.
Dynamic initialization via seqlock_init(my_seqlock_ptr); which sets sequence = 0 and calls spin_lock_init(&lock).
Write Path
Writer calls write_seqlock(&seq), acquires the spinlock, increments sequence (making it odd), issues smp_wmb(), updates protected data, issues another smp_wmb(), increments sequence again (making it even), and releases the spinlock with write_sequnlock(&seq). This guarantees that all writes are ordered and visible before the second increment.
Read Path
Reader obtains a snapshot with read_seqbegin(&seq), reads the data without acquiring any lock, then calls read_seqretry(&seq, start). If the sequence value is unchanged and even, the read is valid; otherwise the reader repeats the loop.
Advantages Over Traditional Locks
Seqlock eliminates read‑side blocking, so readers never wait for writers, which greatly improves throughput in read‑heavy workloads such as time‑keeping, network stacks, and performance counters. It also gives writers priority because a writer can start as soon as it acquires the spinlock, even if readers are active.
Comparison with Spinlock and RWLock
Spinlocks are suitable for very short critical sections but suffer from busy‑waiting under high contention. RWlocks block readers during writes and give equal priority to readers and writers. Seqlock provides lock‑free reads and higher writer priority at the cost of possible read retries when writes are frequent.
Kernel Use Cases
Typical read‑many/write‑few data such as xtime (system time), jiffies_64, and various performance counters are protected by Seqlock. The article shows the actual kernel code for updating and reading jiffies_64 using write_seqlock / read_seqbegin and the retry loop.
User‑Space Example
A minimal C++ implementation demonstrates a Seqlock class with atomic sequence and lock, a writer that increments the sequence before and after updating shared data, and readers that loop on read_begin and read_retry. The program spawns multiple reader threads and a writer thread, showing that the lock‑free reads remain correct while the writer proceeds.
Deepin Linux
Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
