DPDK
24.11.0-rc3
|
#include <stdbool.h>
#include <stdint.h>
#include <rte_atomic.h>
#include <rte_branch_prediction.h>
#include <rte_seqcount.h>
#include <rte_spinlock.h>
Go to the source code of this file.
Data Structures | |
struct | rte_seqlock_t |
Macros | |
#define | RTE_SEQLOCK_INITIALIZER |
Functions | |
static void | rte_seqlock_init (rte_seqlock_t *seqlock) |
static uint32_t | rte_seqlock_read_begin (const rte_seqlock_t *seqlock) |
static bool | rte_seqlock_read_retry (const rte_seqlock_t *seqlock, uint32_t begin_sn) |
static void | rte_seqlock_write_lock (rte_seqlock_t *seqlock) |
static void | rte_seqlock_write_unlock (rte_seqlock_t *seqlock) |
RTE Seqlock
A sequence lock (seqlock) is a synchronization primitive allowing multiple, parallel, readers to efficiently and safely (i.e., in a data-race free manner) access lock-protected data. The RTE seqlock permits multiple writers as well. A spinlock is used for writer-writer synchronization.
A reader never blocks a writer. Very high frequency writes may prevent readers from making progress.
A seqlock is not preemption-safe on the writer side. If a writer is preempted, it may block readers until the writer thread is allowed to continue. Heavy computations should be kept out of the writer-side critical section, to avoid delaying readers.
Seqlocks are useful for data which are read by many cores, at a high frequency, and relatively infrequently written to.
One way to think about seqlocks is that they provide means to perform atomic operations on objects larger than what the native machine instructions allow for.
To avoid resource reclamation issues, the data protected by a seqlock should typically be kept self-contained (e.g., no pointers to mutable, dynamically allocated data).
Example usage:
In case there is only a single writer, or writer-writer serialization is provided by other means, the use of sequence lock (i.e., rte_seqlock_t) can be replaced with the use of the "raw" rte_seqcount_t type instead.
Definition in file rte_seqlock.h.
#define RTE_SEQLOCK_INITIALIZER |
A static seqlock initializer.
Definition at line 109 of file rte_seqlock.h.
|
inlinestatic |
Initialize the seqlock.
This function initializes the seqlock, and leaves the writer-side spinlock unlocked.
seqlock | A pointer to the seqlock. |
Definition at line 125 of file rte_seqlock.h.
|
inlinestatic |
Begin a read-side critical section.
See rte_seqcount_read_retry() for details.
seqlock | A pointer to the seqlock. |
Definition at line 146 of file rte_seqlock.h.
|
inlinestatic |
End a read-side critical section.
See rte_seqcount_read_retry() for details.
seqlock | A pointer to the seqlock. |
begin_sn | The seqlock sequence number returned by rte_seqlock_read_begin(). |
Definition at line 168 of file rte_seqlock.h.
|
inlinestatic |
Begin a write-side critical section.
A call to this function acquires the write lock associated seqlock
, and marks the beginning of a write-side critical section.
After having called this function, the caller may go on to modify (both read and write) the protected data, in an atomic or non-atomic manner.
After the necessary updates have been performed, the application calls rte_seqlock_write_unlock().
This function is not preemption-safe in the sense that preemption of the calling thread may block reader progress until the writer thread is rescheduled.
Unlike rte_seqlock_read_begin(), each call made to rte_seqlock_write_lock() must be matched with an unlock call.
seqlock | A pointer to the seqlock. |
Definition at line 199 of file rte_seqlock.h.
|
inlinestatic |
End a write-side critical section.
A call to this function marks the end of the write-side critical section, for seqlock
. After this call has been made, the protected data may no longer be modified.
seqlock | A pointer to the seqlock. |
Definition at line 221 of file rte_seqlock.h.