DPDK 26.11.0-rc2
rte_stack.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019 Intel Corporation
3 * Copyright(c) 2026 SmartShare Systems
4 */
5
16#ifndef _RTE_STACK_H_
17#define _RTE_STACK_H_
18
19#include <stdalign.h>
20
21#include <rte_debug.h>
22#include <rte_errno.h>
23#include <rte_memzone.h>
24#include <rte_spinlock.h>
25
26#define RTE_TAILQ_STACK_NAME "RTE_STACK"
27#define RTE_STACK_MZ_PREFIX "STK_"
29#define RTE_STACK_NAMESIZE (RTE_MEMZONE_NAMESIZE - \
30 sizeof(RTE_STACK_MZ_PREFIX) + 1)
31
32static_assert(((sizeof(void *) * RTE_STACK_PILE_BULK_SIZE) & RTE_CACHE_LINE_MASK) == 0,
33 "Pile bulk size must be divisible by CPU cache line size");
34static_assert(RTE_IS_POWER_OF_2(RTE_STACK_PILE_BULK_SIZE),
35 "Pile bulk size must be power of 2");
36
37/* Note: Also used as solo (single-object) pile element. */
38struct rte_stack_lf_elem {
39 void *data;
40 struct rte_stack_lf_elem *next;
41};
42
43/*
44 * Bulk (multi-object) pile element.
45 * Inherited from the rte_stack_lf_elem (single-object) class,
46 * and extended with an array for holding a bulk of object pointers.
47 */
48struct rte_stack_pile_bulk_elem {
49 /* The first part must be ABI compatible with the rte_stack_lf_elem parent class. */
50 struct rte_stack_lf_elem elem;
51 /* The second part differs. */
52 alignas(RTE_CACHE_LINE_SIZE)
53 void *objs[RTE_STACK_PILE_BULK_SIZE];
54};
55
56static_assert(offsetof(struct rte_stack_pile_bulk_elem, elem) == 0,
57 "Inherited type mismatch");
58
59struct __rte_aligned(16) rte_stack_lf_head {
60 struct rte_stack_lf_elem *top;
61 uint64_t cnt;
62};
63
64struct rte_stack_lf_list {
66 struct rte_stack_lf_head head;
68 RTE_ATOMIC(uint64_t) len;
69};
70
71/* Structure containing two lock-free LIFO lists: the stack itself and a list
72 * of free linked-list elements.
73 */
74struct rte_stack_lf {
76 alignas(RTE_CACHE_LINE_SIZE) struct rte_stack_lf_list used;
79 alignas(RTE_CACHE_LINE_SIZE) struct rte_stack_lf_list free;
82 alignas(RTE_CACHE_LINE_SIZE) struct rte_stack_lf_elem elems[];
83};
84
85/* Pile structure containing three lock-free LIFO-like lists:
86 * - A list of elements, each element holding a bulk of pointers to objects.
87 * - A list of elements, each element holding one pointer to an object.
88 * - A list of free linked-list elements.
89 */
90struct rte_stack_pile {
92 alignas(RTE_CACHE_LINE_SIZE) struct rte_stack_lf_list bulk;
95 alignas(RTE_CACHE_LINE_SIZE) struct rte_stack_lf_list solo;
98 alignas(RTE_CACHE_LINE_SIZE) struct rte_stack_lf_list free_bulk;
101 alignas(RTE_CACHE_LINE_SIZE) struct rte_stack_lf_list free_solo;
104 alignas(RTE_CACHE_LINE_SIZE) void *elems[];
105};
106
107/* Structure containing the LIFO, its current length, and a lock for mutual
108 * exclusion.
109 */
110struct rte_stack_std {
111 rte_spinlock_t lock;
112 uint32_t len;
113 void *objs[];
114};
115
116/* The RTE stack structure contains the LIFO structure itself, plus metadata
117 * such as its name and memzone pointer.
118 */
119struct __rte_cache_aligned rte_stack {
121 alignas(RTE_CACHE_LINE_SIZE) char name[RTE_STACK_NAMESIZE];
123 const struct rte_memzone *memzone;
124 uint32_t capacity;
125 uint32_t flags;
126 union {
127 struct rte_stack_lf stack_lf;
128 struct rte_stack_pile stack_pile;
129 struct rte_stack_std stack_std;
130 };
131};
132
137#define RTE_STACK_F_LF 0x0001
138
148#define RTE_STACK_F_PILE 0x0002
149
150#include "rte_stack_std.h"
151#include "rte_stack_lf.h"
152#include "rte_stack_pile.h"
153
154#ifdef __cplusplus
155extern "C" {
156#endif
157
170static __rte_always_inline unsigned int
171rte_stack_push(struct rte_stack *s, void * const *obj_table, unsigned int n)
172{
173 RTE_ASSERT(s != NULL);
174 RTE_ASSERT(obj_table != NULL);
175
176 if (s->flags & RTE_STACK_F_LF)
177 return __rte_stack_lf_push(s, obj_table, n);
178 else if (s->flags & RTE_STACK_F_PILE)
179 return __rte_stack_pile_push(s, obj_table, n);
180 else
181 return __rte_stack_std_push(s, obj_table, n);
182}
183
196static __rte_always_inline unsigned int
197rte_stack_pop(struct rte_stack *s, void **obj_table, unsigned int n)
198{
199 RTE_ASSERT(s != NULL);
200 RTE_ASSERT(obj_table != NULL);
201
202 if (s->flags & RTE_STACK_F_LF)
203 return __rte_stack_lf_pop(s, obj_table, n);
204 else if (s->flags & RTE_STACK_F_PILE)
205 return __rte_stack_pile_pop(s, obj_table, n);
206 else
207 return __rte_stack_std_pop(s, obj_table, n);
208}
209
218static __rte_always_inline unsigned int
219rte_stack_count(struct rte_stack *s)
220{
221 RTE_ASSERT(s != NULL);
222
223 if (s->flags & RTE_STACK_F_LF)
224 return __rte_stack_lf_count(s);
225 else if (s->flags & RTE_STACK_F_PILE)
226 return __rte_stack_pile_count(s);
227 else
228 return __rte_stack_std_count(s);
229}
230
239static __rte_always_inline unsigned int
240rte_stack_free_count(struct rte_stack *s)
241{
242 RTE_ASSERT(s != NULL);
243
244 return s->capacity - rte_stack_count(s);
245}
246
275struct rte_stack *
276rte_stack_create(const char *name, unsigned int count, int socket_id,
277 uint32_t flags);
278
286void
287rte_stack_free(struct rte_stack *s);
288
300struct rte_stack *
301rte_stack_lookup(const char *name);
302
303#ifdef __cplusplus
304}
305#endif
306
307#endif /* _RTE_STACK_H_ */
#define RTE_IS_POWER_OF_2(n)
Definition: rte_bitops.h:1246
#define offsetof(TYPE, MEMBER)
Definition: rte_common.h:1066
#define RTE_CACHE_LINE_MASK
Definition: rte_common.h:921
#define RTE_CACHE_GUARD
Definition: rte_common.h:959
#define __rte_cache_aligned
Definition: rte_common.h:939
#define __rte_always_inline
Definition: rte_common.h:534
#define RTE_STACK_F_LF
Definition: rte_stack.h:137
struct rte_stack * rte_stack_create(const char *name, unsigned int count, int socket_id, uint32_t flags)
#define RTE_STACK_NAMESIZE
Definition: rte_stack.h:29
void rte_stack_free(struct rte_stack *s)
static __rte_always_inline unsigned int rte_stack_count(struct rte_stack *s)
Definition: rte_stack.h:219
#define RTE_STACK_F_PILE
Definition: rte_stack.h:148
static __rte_always_inline unsigned int rte_stack_push(struct rte_stack *s, void *const *obj_table, unsigned int n)
Definition: rte_stack.h:171
static __rte_always_inline unsigned int rte_stack_free_count(struct rte_stack *s)
Definition: rte_stack.h:240
static __rte_always_inline unsigned int rte_stack_pop(struct rte_stack *s, void **obj_table, unsigned int n)
Definition: rte_stack.h:197
struct __rte_aligned(16) rte_stack_lf_head
Definition: rte_stack.h:59
struct rte_stack * rte_stack_lookup(const char *name)
uint32_t flags
Definition: rte_memzone.h:64