DPDK 21.11.9
|
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <errno.h>
#include <rte_common.h>
#include <rte_memory.h>
#include <rte_lcore.h>
#include <rte_debug.h>
#include <rte_atomic.h>
#include <rte_ring.h>
Go to the source code of this file.
Data Structures | |
struct | rte_rcu_qsbr_dq_parameters |
Macros | |
#define | RTE_RCU_QSBR_DQ_MT_UNSAFE 1 |
Typedefs | |
typedef void(* | rte_rcu_qsbr_free_resource_t) (void *p, void *e, unsigned int n) |
Functions | |
size_t | rte_rcu_qsbr_get_memsize (uint32_t max_threads) |
int | rte_rcu_qsbr_init (struct rte_rcu_qsbr *v, uint32_t max_threads) |
int | rte_rcu_qsbr_thread_register (struct rte_rcu_qsbr *v, unsigned int thread_id) |
int | rte_rcu_qsbr_thread_unregister (struct rte_rcu_qsbr *v, unsigned int thread_id) |
static __rte_always_inline void | rte_rcu_qsbr_thread_online (struct rte_rcu_qsbr *v, unsigned int thread_id) |
static __rte_always_inline void | rte_rcu_qsbr_thread_offline (struct rte_rcu_qsbr *v, unsigned int thread_id) |
static __rte_always_inline void | rte_rcu_qsbr_lock (__rte_unused struct rte_rcu_qsbr *v, __rte_unused unsigned int thread_id) |
static __rte_always_inline void | rte_rcu_qsbr_unlock (__rte_unused struct rte_rcu_qsbr *v, __rte_unused unsigned int thread_id) |
static __rte_always_inline uint64_t | rte_rcu_qsbr_start (struct rte_rcu_qsbr *v) |
static __rte_always_inline void | rte_rcu_qsbr_quiescent (struct rte_rcu_qsbr *v, unsigned int thread_id) |
static __rte_always_inline int | rte_rcu_qsbr_check (struct rte_rcu_qsbr *v, uint64_t t, bool wait) |
void | rte_rcu_qsbr_synchronize (struct rte_rcu_qsbr *v, unsigned int thread_id) |
int | rte_rcu_qsbr_dump (FILE *f, struct rte_rcu_qsbr *v) |
__rte_experimental struct rte_rcu_qsbr_dq * | rte_rcu_qsbr_dq_create (const struct rte_rcu_qsbr_dq_parameters *params) |
__rte_experimental int | rte_rcu_qsbr_dq_enqueue (struct rte_rcu_qsbr_dq *dq, void *e) |
__rte_experimental int | rte_rcu_qsbr_dq_reclaim (struct rte_rcu_qsbr_dq *dq, unsigned int n, unsigned int *freed, unsigned int *pending, unsigned int *available) |
__rte_experimental int | rte_rcu_qsbr_dq_delete (struct rte_rcu_qsbr_dq *dq) |
RTE Quiescent State Based Reclamation (QSBR).
Quiescent State (QS) is any point in the thread execution where the thread does not hold a reference to a data structure in shared memory. While using lock-less data structures, the writer can safely free memory once all the reader threads have entered quiescent state.
This library provides the ability for the readers to report quiescent state and for the writers to identify when all the readers have entered quiescent state.
Definition in file rte_rcu_qsbr.h.
#define RTE_RCU_QSBR_DQ_MT_UNSAFE 1 |
Various flags supported. < Enqueue and reclaim operations are multi-thread safe by default. The call back functions registered to free the resources are assumed to be multi-thread safe. Set this flag if multi-thread safety is not required.
Definition at line 149 of file rte_rcu_qsbr.h.
typedef void(* rte_rcu_qsbr_free_resource_t) (void *p, void *e, unsigned int n) |
Call back function called to free the resources.
p | Pointer provided while creating the defer queue |
e | Pointer to the resource data stored on the defer queue |
n | Number of resources to free. Currently, this is set to 1. |
Definition at line 137 of file rte_rcu_qsbr.h.
size_t rte_rcu_qsbr_get_memsize | ( | uint32_t | max_threads | ) |
Return the size of the memory occupied by a Quiescent State variable.
max_threads | Maximum number of threads reporting quiescent state on this variable. |
int rte_rcu_qsbr_init | ( | struct rte_rcu_qsbr * | v, |
uint32_t | max_threads | ||
) |
Initialize a Quiescent State (QS) variable.
v | QS variable |
max_threads | Maximum number of threads reporting quiescent state on this variable. This should be the same value as passed to rte_rcu_qsbr_get_memsize. |
int rte_rcu_qsbr_thread_register | ( | struct rte_rcu_qsbr * | v, |
unsigned int | thread_id | ||
) |
Register a reader thread to report its quiescent state on a QS variable.
This is implemented as a lock-free function. It is multi-thread safe. Any reader thread that wants to report its quiescent state must call this API. This can be called during initialization or as part of the packet processing loop.
Note that rte_rcu_qsbr_thread_online must be called before the thread updates its quiescent state using rte_rcu_qsbr_quiescent.
v | QS variable |
thread_id | Reader thread with this thread ID will report its quiescent state on the QS variable. thread_id is a value between 0 and (max_threads - 1). 'max_threads' is the parameter passed in 'rte_rcu_qsbr_init' API. |
int rte_rcu_qsbr_thread_unregister | ( | struct rte_rcu_qsbr * | v, |
unsigned int | thread_id | ||
) |
Remove a reader thread, from the list of threads reporting their quiescent state on a QS variable.
This is implemented as a lock-free function. It is multi-thread safe. This API can be called from the reader threads during shutdown. Ongoing quiescent state queries will stop waiting for the status from this unregistered reader thread.
v | QS variable |
thread_id | Reader thread with this thread ID will stop reporting its quiescent state on the QS variable. |
|
static |
Add a registered reader thread, to the list of threads reporting their quiescent state on a QS variable.
This is implemented as a lock-free function. It is multi-thread safe.
Any registered reader thread that wants to report its quiescent state must call this API before calling rte_rcu_qsbr_quiescent. This can be called during initialization or as part of the packet processing loop.
The reader thread must call rte_rcu_qsbr_thread_offline API, before calling any functions that block, to ensure that rte_rcu_qsbr_check API does not wait indefinitely for the reader thread to update its QS.
The reader thread must call rte_rcu_thread_online API, after the blocking function call returns, to ensure that rte_rcu_qsbr_check API waits for the reader thread to update its quiescent state.
v | QS variable |
thread_id | Reader thread with this thread ID will report its quiescent state on the QS variable. |
Definition at line 303 of file rte_rcu_qsbr.h.
|
static |
Remove a registered reader thread from the list of threads reporting their quiescent state on a QS variable.
This is implemented as a lock-free function. It is multi-thread safe.
This can be called during initialization or as part of the packet processing loop.
The reader thread must call rte_rcu_qsbr_thread_offline API, before calling any functions that block, to ensure that rte_rcu_qsbr_check API does not wait indefinitely for the reader thread to update its QS.
v | QS variable |
thread_id | rte_rcu_qsbr_check API will not wait for the reader thread with this thread ID to report its quiescent state on the QS variable. |
Definition at line 356 of file rte_rcu_qsbr.h.
|
static |
Acquire a lock for accessing a shared data structure.
This is implemented as a lock-free function. It is multi-thread safe.
This API is provided to aid debugging. This should be called before accessing a shared data structure.
When RTE_LIBRTE_RCU_DEBUG is enabled a lock counter is incremented. Similarly rte_rcu_qsbr_unlock will decrement the counter. When the rte_rcu_qsbr_check API will verify that this counter is 0.
When RTE_LIBRTE_RCU_DEBUG is disabled, this API will do nothing.
v | QS variable |
thread_id | Reader thread id |
Definition at line 393 of file rte_rcu_qsbr.h.
|
static |
Release a lock after accessing a shared data structure.
This is implemented as a lock-free function. It is multi-thread safe.
This API is provided to aid debugging. This should be called after accessing a shared data structure.
When RTE_LIBRTE_RCU_DEBUG is enabled, rte_rcu_qsbr_unlock will decrement a lock counter. rte_rcu_qsbr_check API will verify that this counter is 0.
When RTE_LIBRTE_RCU_DEBUG is disabled, this API will do nothing.
v | QS variable |
thread_id | Reader thread id |
Definition at line 426 of file rte_rcu_qsbr.h.
|
static |
Ask the reader threads to report the quiescent state status.
This is implemented as a lock-free function. It is multi-thread safe and can be called from worker threads.
v | QS variable |
Definition at line 456 of file rte_rcu_qsbr.h.
|
static |
Update quiescent state for a reader thread.
This is implemented as a lock-free function. It is multi-thread safe. All the reader threads registered to report their quiescent state on the QS variable must call this API.
v | QS variable |
thread_id | Update the quiescent state for the reader with this thread ID. |
Definition at line 485 of file rte_rcu_qsbr.h.
|
static |
Checks if all the reader threads have entered the quiescent state referenced by token.
This is implemented as a lock-free function. It is multi-thread safe and can be called from the worker threads as well.
If this API is called with 'wait' set to true, the following factors must be considered:
1) If the calling thread is also reporting the status on the same QS variable, it must update the quiescent state status, before calling this API.
2) In addition, while calling from multiple threads, only one of those threads can be reporting the quiescent state status on a given QS variable.
v | QS variable |
t | Token returned by rte_rcu_qsbr_start API |
wait | If true, block till all the reader threads have completed entering the quiescent state referenced by token 't'. |
Definition at line 672 of file rte_rcu_qsbr.h.
void rte_rcu_qsbr_synchronize | ( | struct rte_rcu_qsbr * | v, |
unsigned int | thread_id | ||
) |
Wait till the reader threads have entered quiescent state.
This is implemented as a lock-free function. It is multi-thread safe. This API can be thought of as a wrapper around rte_rcu_qsbr_start and rte_rcu_qsbr_check APIs.
If this API is called from multiple threads, only one of those threads can be reporting the quiescent state status on a given QS variable.
v | QS variable |
thread_id | Thread ID of the caller if it is registered to report quiescent state on this QS variable (i.e. the calling thread is also part of the readside critical section). If not, pass RTE_QSBR_THRID_INVALID. |
int rte_rcu_qsbr_dump | ( | FILE * | f, |
struct rte_rcu_qsbr * | v | ||
) |
Dump the details of a single QS variables to a file.
It is NOT multi-thread safe.
f | A pointer to a file for output |
v | QS variable |
__rte_experimental struct rte_rcu_qsbr_dq * rte_rcu_qsbr_dq_create | ( | const struct rte_rcu_qsbr_dq_parameters * | params | ) |
Create a queue used to store the data structure elements that can be freed later. This queue is referred to as 'defer queue'.
params | Parameters to create a defer queue. |
__rte_experimental int rte_rcu_qsbr_dq_enqueue | ( | struct rte_rcu_qsbr_dq * | dq, |
void * | e | ||
) |
Enqueue one resource to the defer queue and start the grace period. The resource will be freed later after at least one grace period is over.
If the defer queue is full, it will attempt to reclaim resources. It will also reclaim resources at regular intervals to avoid the defer queue from growing too big.
Multi-thread safety is provided as the defer queue configuration. When multi-thread safety is requested, it is possible that the resources are not stored in their order of deletion. This results in resources being held in the defer queue longer than they should.
dq | Defer queue to allocate an entry from. |
e | Pointer to resource data to copy to the defer queue. The size of the data to copy is equal to the element size provided when the defer queue was created. |
__rte_experimental int rte_rcu_qsbr_dq_reclaim | ( | struct rte_rcu_qsbr_dq * | dq, |
unsigned int | n, | ||
unsigned int * | freed, | ||
unsigned int * | pending, | ||
unsigned int * | available | ||
) |
Free resources from the defer queue.
This API is multi-thread safe.
dq | Defer queue to free an entry from. |
n | Maximum number of resources to free. |
freed | Number of resources that were freed. |
pending | Number of resources pending on the defer queue. This number might not be accurate if multi-thread safety is configured. |
available | Number of resources that can be added to the defer queue. This number might not be accurate if multi-thread safety is configured. |
__rte_experimental int rte_rcu_qsbr_dq_delete | ( | struct rte_rcu_qsbr_dq * | dq | ) |
Delete a defer queue.
It tries to reclaim all the resources on the defer queue. If any of the resources have not completed the grace period the reclamation stops and returns immediately. The rest of the resources are not reclaimed and the defer queue is not freed.
dq | Defer queue to delete. |