1*99a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 2*99a2dd95SBruce Richardson * Copyright(c) 2019 Intel Corporation 3*99a2dd95SBruce Richardson */ 4*99a2dd95SBruce Richardson 5*99a2dd95SBruce Richardson /** 6*99a2dd95SBruce Richardson * @file rte_stack.h 7*99a2dd95SBruce Richardson * 8*99a2dd95SBruce Richardson * RTE Stack. 9*99a2dd95SBruce Richardson * 10*99a2dd95SBruce Richardson * librte_stack provides an API for configuration and use of a bounded stack of 11*99a2dd95SBruce Richardson * pointers. Push and pop operations are MT-safe, allowing concurrent access, 12*99a2dd95SBruce Richardson * and the interface supports pushing and popping multiple pointers at a time. 13*99a2dd95SBruce Richardson */ 14*99a2dd95SBruce Richardson 15*99a2dd95SBruce Richardson #ifndef _RTE_STACK_H_ 16*99a2dd95SBruce Richardson #define _RTE_STACK_H_ 17*99a2dd95SBruce Richardson 18*99a2dd95SBruce Richardson #ifdef __cplusplus 19*99a2dd95SBruce Richardson extern "C" { 20*99a2dd95SBruce Richardson #endif 21*99a2dd95SBruce Richardson 22*99a2dd95SBruce Richardson #include <rte_atomic.h> 23*99a2dd95SBruce Richardson #include <rte_compat.h> 24*99a2dd95SBruce Richardson #include <rte_debug.h> 25*99a2dd95SBruce Richardson #include <rte_errno.h> 26*99a2dd95SBruce Richardson #include <rte_memzone.h> 27*99a2dd95SBruce Richardson #include <rte_spinlock.h> 28*99a2dd95SBruce Richardson 29*99a2dd95SBruce Richardson #define RTE_TAILQ_STACK_NAME "RTE_STACK" 30*99a2dd95SBruce Richardson #define RTE_STACK_MZ_PREFIX "STK_" 31*99a2dd95SBruce Richardson /** The maximum length of a stack name. */ 32*99a2dd95SBruce Richardson #define RTE_STACK_NAMESIZE (RTE_MEMZONE_NAMESIZE - \ 33*99a2dd95SBruce Richardson sizeof(RTE_STACK_MZ_PREFIX) + 1) 34*99a2dd95SBruce Richardson 35*99a2dd95SBruce Richardson struct rte_stack_lf_elem { 36*99a2dd95SBruce Richardson void *data; /**< Data pointer */ 37*99a2dd95SBruce Richardson struct rte_stack_lf_elem *next; /**< Next pointer */ 38*99a2dd95SBruce Richardson }; 39*99a2dd95SBruce Richardson 40*99a2dd95SBruce Richardson struct rte_stack_lf_head { 41*99a2dd95SBruce Richardson struct rte_stack_lf_elem *top; /**< Stack top */ 42*99a2dd95SBruce Richardson uint64_t cnt; /**< Modification counter for avoiding ABA problem */ 43*99a2dd95SBruce Richardson }; 44*99a2dd95SBruce Richardson 45*99a2dd95SBruce Richardson struct rte_stack_lf_list { 46*99a2dd95SBruce Richardson /** List head */ 47*99a2dd95SBruce Richardson struct rte_stack_lf_head head __rte_aligned(16); 48*99a2dd95SBruce Richardson /** List len */ 49*99a2dd95SBruce Richardson uint64_t len; 50*99a2dd95SBruce Richardson }; 51*99a2dd95SBruce Richardson 52*99a2dd95SBruce Richardson /* Structure containing two lock-free LIFO lists: the stack itself and a list 53*99a2dd95SBruce Richardson * of free linked-list elements. 54*99a2dd95SBruce Richardson */ 55*99a2dd95SBruce Richardson struct rte_stack_lf { 56*99a2dd95SBruce Richardson /** LIFO list of elements */ 57*99a2dd95SBruce Richardson struct rte_stack_lf_list used __rte_cache_aligned; 58*99a2dd95SBruce Richardson /** LIFO list of free elements */ 59*99a2dd95SBruce Richardson struct rte_stack_lf_list free __rte_cache_aligned; 60*99a2dd95SBruce Richardson /** LIFO elements */ 61*99a2dd95SBruce Richardson struct rte_stack_lf_elem elems[] __rte_cache_aligned; 62*99a2dd95SBruce Richardson }; 63*99a2dd95SBruce Richardson 64*99a2dd95SBruce Richardson /* Structure containing the LIFO, its current length, and a lock for mutual 65*99a2dd95SBruce Richardson * exclusion. 66*99a2dd95SBruce Richardson */ 67*99a2dd95SBruce Richardson struct rte_stack_std { 68*99a2dd95SBruce Richardson rte_spinlock_t lock; /**< LIFO lock */ 69*99a2dd95SBruce Richardson uint32_t len; /**< LIFO len */ 70*99a2dd95SBruce Richardson void *objs[]; /**< LIFO pointer table */ 71*99a2dd95SBruce Richardson }; 72*99a2dd95SBruce Richardson 73*99a2dd95SBruce Richardson /* The RTE stack structure contains the LIFO structure itself, plus metadata 74*99a2dd95SBruce Richardson * such as its name and memzone pointer. 75*99a2dd95SBruce Richardson */ 76*99a2dd95SBruce Richardson struct rte_stack { 77*99a2dd95SBruce Richardson /** Name of the stack. */ 78*99a2dd95SBruce Richardson char name[RTE_STACK_NAMESIZE] __rte_cache_aligned; 79*99a2dd95SBruce Richardson /** Memzone containing the rte_stack structure. */ 80*99a2dd95SBruce Richardson const struct rte_memzone *memzone; 81*99a2dd95SBruce Richardson uint32_t capacity; /**< Usable size of the stack. */ 82*99a2dd95SBruce Richardson uint32_t flags; /**< Flags supplied at creation. */ 83*99a2dd95SBruce Richardson RTE_STD_C11 84*99a2dd95SBruce Richardson union { 85*99a2dd95SBruce Richardson struct rte_stack_lf stack_lf; /**< Lock-free LIFO structure. */ 86*99a2dd95SBruce Richardson struct rte_stack_std stack_std; /**< LIFO structure. */ 87*99a2dd95SBruce Richardson }; 88*99a2dd95SBruce Richardson } __rte_cache_aligned; 89*99a2dd95SBruce Richardson 90*99a2dd95SBruce Richardson /** 91*99a2dd95SBruce Richardson * The stack uses lock-free push and pop functions. This flag is only 92*99a2dd95SBruce Richardson * supported on x86_64 platforms, currently. 93*99a2dd95SBruce Richardson */ 94*99a2dd95SBruce Richardson #define RTE_STACK_F_LF 0x0001 95*99a2dd95SBruce Richardson 96*99a2dd95SBruce Richardson #include "rte_stack_std.h" 97*99a2dd95SBruce Richardson #include "rte_stack_lf.h" 98*99a2dd95SBruce Richardson 99*99a2dd95SBruce Richardson /** 100*99a2dd95SBruce Richardson * Push several objects on the stack (MT-safe). 101*99a2dd95SBruce Richardson * 102*99a2dd95SBruce Richardson * @param s 103*99a2dd95SBruce Richardson * A pointer to the stack structure. 104*99a2dd95SBruce Richardson * @param obj_table 105*99a2dd95SBruce Richardson * A pointer to a table of void * pointers (objects). 106*99a2dd95SBruce Richardson * @param n 107*99a2dd95SBruce Richardson * The number of objects to push on the stack from the obj_table. 108*99a2dd95SBruce Richardson * @return 109*99a2dd95SBruce Richardson * Actual number of objects pushed (either 0 or *n*). 110*99a2dd95SBruce Richardson */ 111*99a2dd95SBruce Richardson static __rte_always_inline unsigned int 112*99a2dd95SBruce Richardson rte_stack_push(struct rte_stack *s, void * const *obj_table, unsigned int n) 113*99a2dd95SBruce Richardson { 114*99a2dd95SBruce Richardson RTE_ASSERT(s != NULL); 115*99a2dd95SBruce Richardson RTE_ASSERT(obj_table != NULL); 116*99a2dd95SBruce Richardson 117*99a2dd95SBruce Richardson if (s->flags & RTE_STACK_F_LF) 118*99a2dd95SBruce Richardson return __rte_stack_lf_push(s, obj_table, n); 119*99a2dd95SBruce Richardson else 120*99a2dd95SBruce Richardson return __rte_stack_std_push(s, obj_table, n); 121*99a2dd95SBruce Richardson } 122*99a2dd95SBruce Richardson 123*99a2dd95SBruce Richardson /** 124*99a2dd95SBruce Richardson * Pop several objects from the stack (MT-safe). 125*99a2dd95SBruce Richardson * 126*99a2dd95SBruce Richardson * @param s 127*99a2dd95SBruce Richardson * A pointer to the stack structure. 128*99a2dd95SBruce Richardson * @param obj_table 129*99a2dd95SBruce Richardson * A pointer to a table of void * pointers (objects). 130*99a2dd95SBruce Richardson * @param n 131*99a2dd95SBruce Richardson * The number of objects to pull from the stack. 132*99a2dd95SBruce Richardson * @return 133*99a2dd95SBruce Richardson * Actual number of objects popped (either 0 or *n*). 134*99a2dd95SBruce Richardson */ 135*99a2dd95SBruce Richardson static __rte_always_inline unsigned int 136*99a2dd95SBruce Richardson rte_stack_pop(struct rte_stack *s, void **obj_table, unsigned int n) 137*99a2dd95SBruce Richardson { 138*99a2dd95SBruce Richardson RTE_ASSERT(s != NULL); 139*99a2dd95SBruce Richardson RTE_ASSERT(obj_table != NULL); 140*99a2dd95SBruce Richardson 141*99a2dd95SBruce Richardson if (s->flags & RTE_STACK_F_LF) 142*99a2dd95SBruce Richardson return __rte_stack_lf_pop(s, obj_table, n); 143*99a2dd95SBruce Richardson else 144*99a2dd95SBruce Richardson return __rte_stack_std_pop(s, obj_table, n); 145*99a2dd95SBruce Richardson } 146*99a2dd95SBruce Richardson 147*99a2dd95SBruce Richardson /** 148*99a2dd95SBruce Richardson * Return the number of used entries in a stack. 149*99a2dd95SBruce Richardson * 150*99a2dd95SBruce Richardson * @param s 151*99a2dd95SBruce Richardson * A pointer to the stack structure. 152*99a2dd95SBruce Richardson * @return 153*99a2dd95SBruce Richardson * The number of used entries in the stack. 154*99a2dd95SBruce Richardson */ 155*99a2dd95SBruce Richardson static __rte_always_inline unsigned int 156*99a2dd95SBruce Richardson rte_stack_count(struct rte_stack *s) 157*99a2dd95SBruce Richardson { 158*99a2dd95SBruce Richardson RTE_ASSERT(s != NULL); 159*99a2dd95SBruce Richardson 160*99a2dd95SBruce Richardson if (s->flags & RTE_STACK_F_LF) 161*99a2dd95SBruce Richardson return __rte_stack_lf_count(s); 162*99a2dd95SBruce Richardson else 163*99a2dd95SBruce Richardson return __rte_stack_std_count(s); 164*99a2dd95SBruce Richardson } 165*99a2dd95SBruce Richardson 166*99a2dd95SBruce Richardson /** 167*99a2dd95SBruce Richardson * Return the number of free entries in a stack. 168*99a2dd95SBruce Richardson * 169*99a2dd95SBruce Richardson * @param s 170*99a2dd95SBruce Richardson * A pointer to the stack structure. 171*99a2dd95SBruce Richardson * @return 172*99a2dd95SBruce Richardson * The number of free entries in the stack. 173*99a2dd95SBruce Richardson */ 174*99a2dd95SBruce Richardson static __rte_always_inline unsigned int 175*99a2dd95SBruce Richardson rte_stack_free_count(struct rte_stack *s) 176*99a2dd95SBruce Richardson { 177*99a2dd95SBruce Richardson RTE_ASSERT(s != NULL); 178*99a2dd95SBruce Richardson 179*99a2dd95SBruce Richardson return s->capacity - rte_stack_count(s); 180*99a2dd95SBruce Richardson } 181*99a2dd95SBruce Richardson 182*99a2dd95SBruce Richardson /** 183*99a2dd95SBruce Richardson * Create a new stack named *name* in memory. 184*99a2dd95SBruce Richardson * 185*99a2dd95SBruce Richardson * This function uses ``memzone_reserve()`` to allocate memory for a stack of 186*99a2dd95SBruce Richardson * size *count*. The behavior of the stack is controlled by the *flags*. 187*99a2dd95SBruce Richardson * 188*99a2dd95SBruce Richardson * @param name 189*99a2dd95SBruce Richardson * The name of the stack. 190*99a2dd95SBruce Richardson * @param count 191*99a2dd95SBruce Richardson * The size of the stack. 192*99a2dd95SBruce Richardson * @param socket_id 193*99a2dd95SBruce Richardson * The *socket_id* argument is the socket identifier in case of 194*99a2dd95SBruce Richardson * NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA 195*99a2dd95SBruce Richardson * constraint for the reserved zone. 196*99a2dd95SBruce Richardson * @param flags 197*99a2dd95SBruce Richardson * An OR of the following: 198*99a2dd95SBruce Richardson * - RTE_STACK_F_LF: If this flag is set, the stack uses lock-free 199*99a2dd95SBruce Richardson * variants of the push and pop functions. Otherwise, it achieves 200*99a2dd95SBruce Richardson * thread-safety using a lock. 201*99a2dd95SBruce Richardson * @return 202*99a2dd95SBruce Richardson * On success, the pointer to the new allocated stack. NULL on error with 203*99a2dd95SBruce Richardson * rte_errno set appropriately. Possible errno values include: 204*99a2dd95SBruce Richardson * - ENOSPC - the maximum number of memzones has already been allocated 205*99a2dd95SBruce Richardson * - EEXIST - a stack with the same name already exists 206*99a2dd95SBruce Richardson * - ENOMEM - insufficient memory to create the stack 207*99a2dd95SBruce Richardson * - ENAMETOOLONG - name size exceeds RTE_STACK_NAMESIZE 208*99a2dd95SBruce Richardson */ 209*99a2dd95SBruce Richardson struct rte_stack * 210*99a2dd95SBruce Richardson rte_stack_create(const char *name, unsigned int count, int socket_id, 211*99a2dd95SBruce Richardson uint32_t flags); 212*99a2dd95SBruce Richardson 213*99a2dd95SBruce Richardson /** 214*99a2dd95SBruce Richardson * Free all memory used by the stack. 215*99a2dd95SBruce Richardson * 216*99a2dd95SBruce Richardson * @param s 217*99a2dd95SBruce Richardson * Stack to free 218*99a2dd95SBruce Richardson */ 219*99a2dd95SBruce Richardson void 220*99a2dd95SBruce Richardson rte_stack_free(struct rte_stack *s); 221*99a2dd95SBruce Richardson 222*99a2dd95SBruce Richardson /** 223*99a2dd95SBruce Richardson * Lookup a stack by its name. 224*99a2dd95SBruce Richardson * 225*99a2dd95SBruce Richardson * @param name 226*99a2dd95SBruce Richardson * The name of the stack. 227*99a2dd95SBruce Richardson * @return 228*99a2dd95SBruce Richardson * The pointer to the stack matching the name, or NULL if not found, 229*99a2dd95SBruce Richardson * with rte_errno set appropriately. Possible rte_errno values include: 230*99a2dd95SBruce Richardson * - ENOENT - Stack with name *name* not found. 231*99a2dd95SBruce Richardson * - EINVAL - *name* pointer is NULL. 232*99a2dd95SBruce Richardson */ 233*99a2dd95SBruce Richardson struct rte_stack * 234*99a2dd95SBruce Richardson rte_stack_lookup(const char *name); 235*99a2dd95SBruce Richardson 236*99a2dd95SBruce Richardson #ifdef __cplusplus 237*99a2dd95SBruce Richardson } 238*99a2dd95SBruce Richardson #endif 239*99a2dd95SBruce Richardson 240*99a2dd95SBruce Richardson #endif /* _RTE_STACK_H_ */ 241