1*4418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
2*4418919fSjohnjiang  * Copyright(c) 2019 Intel Corporation
3*4418919fSjohnjiang  */
4*4418919fSjohnjiang 
5*4418919fSjohnjiang #ifndef _RTE_STACK_LF_H_
6*4418919fSjohnjiang #define _RTE_STACK_LF_H_
7*4418919fSjohnjiang 
8*4418919fSjohnjiang #if !(defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_ARM64))
9*4418919fSjohnjiang #include "rte_stack_lf_stubs.h"
10*4418919fSjohnjiang #else
11*4418919fSjohnjiang #ifdef RTE_USE_C11_MEM_MODEL
12*4418919fSjohnjiang #include "rte_stack_lf_c11.h"
13*4418919fSjohnjiang #else
14*4418919fSjohnjiang #include "rte_stack_lf_generic.h"
15*4418919fSjohnjiang #endif
16*4418919fSjohnjiang #endif
17*4418919fSjohnjiang 
18*4418919fSjohnjiang /**
19*4418919fSjohnjiang  * @internal Push several objects on the lock-free stack (MT-safe).
20*4418919fSjohnjiang  *
21*4418919fSjohnjiang  * @param s
22*4418919fSjohnjiang  *   A pointer to the stack structure.
23*4418919fSjohnjiang  * @param obj_table
24*4418919fSjohnjiang  *   A pointer to a table of void * pointers (objects).
25*4418919fSjohnjiang  * @param n
26*4418919fSjohnjiang  *   The number of objects to push on the stack from the obj_table.
27*4418919fSjohnjiang  * @return
28*4418919fSjohnjiang  *   Actual number of objects enqueued.
29*4418919fSjohnjiang  */
30*4418919fSjohnjiang static __rte_always_inline unsigned int
__rte_stack_lf_push(struct rte_stack * s,void * const * obj_table,unsigned int n)31*4418919fSjohnjiang __rte_stack_lf_push(struct rte_stack *s,
32*4418919fSjohnjiang 		    void * const *obj_table,
33*4418919fSjohnjiang 		    unsigned int n)
34*4418919fSjohnjiang {
35*4418919fSjohnjiang 	struct rte_stack_lf_elem *tmp, *first, *last = NULL;
36*4418919fSjohnjiang 	unsigned int i;
37*4418919fSjohnjiang 
38*4418919fSjohnjiang 	if (unlikely(n == 0))
39*4418919fSjohnjiang 		return 0;
40*4418919fSjohnjiang 
41*4418919fSjohnjiang 	/* Pop n free elements */
42*4418919fSjohnjiang 	first = __rte_stack_lf_pop_elems(&s->stack_lf.free, n, NULL, &last);
43*4418919fSjohnjiang 	if (unlikely(first == NULL))
44*4418919fSjohnjiang 		return 0;
45*4418919fSjohnjiang 
46*4418919fSjohnjiang 	/* Construct the list elements */
47*4418919fSjohnjiang 	for (tmp = first, i = 0; i < n; i++, tmp = tmp->next)
48*4418919fSjohnjiang 		tmp->data = obj_table[n - i - 1];
49*4418919fSjohnjiang 
50*4418919fSjohnjiang 	/* Push them to the used list */
51*4418919fSjohnjiang 	__rte_stack_lf_push_elems(&s->stack_lf.used, first, last, n);
52*4418919fSjohnjiang 
53*4418919fSjohnjiang 	return n;
54*4418919fSjohnjiang }
55*4418919fSjohnjiang 
56*4418919fSjohnjiang /**
57*4418919fSjohnjiang  * @internal Pop several objects from the lock-free stack (MT-safe).
58*4418919fSjohnjiang  *
59*4418919fSjohnjiang  * @param s
60*4418919fSjohnjiang  *   A pointer to the stack structure.
61*4418919fSjohnjiang  * @param obj_table
62*4418919fSjohnjiang  *   A pointer to a table of void * pointers (objects).
63*4418919fSjohnjiang  * @param n
64*4418919fSjohnjiang  *   The number of objects to pull from the stack.
65*4418919fSjohnjiang  * @return
66*4418919fSjohnjiang  *   - Actual number of objects popped.
67*4418919fSjohnjiang  */
68*4418919fSjohnjiang static __rte_always_inline unsigned int
__rte_stack_lf_pop(struct rte_stack * s,void ** obj_table,unsigned int n)69*4418919fSjohnjiang __rte_stack_lf_pop(struct rte_stack *s, void **obj_table, unsigned int n)
70*4418919fSjohnjiang {
71*4418919fSjohnjiang 	struct rte_stack_lf_elem *first, *last = NULL;
72*4418919fSjohnjiang 
73*4418919fSjohnjiang 	if (unlikely(n == 0))
74*4418919fSjohnjiang 		return 0;
75*4418919fSjohnjiang 
76*4418919fSjohnjiang 	/* Pop n used elements */
77*4418919fSjohnjiang 	first = __rte_stack_lf_pop_elems(&s->stack_lf.used,
78*4418919fSjohnjiang 					 n, obj_table, &last);
79*4418919fSjohnjiang 	if (unlikely(first == NULL))
80*4418919fSjohnjiang 		return 0;
81*4418919fSjohnjiang 
82*4418919fSjohnjiang 	/* Push the list elements to the free list */
83*4418919fSjohnjiang 	__rte_stack_lf_push_elems(&s->stack_lf.free, first, last, n);
84*4418919fSjohnjiang 
85*4418919fSjohnjiang 	return n;
86*4418919fSjohnjiang }
87*4418919fSjohnjiang 
88*4418919fSjohnjiang /**
89*4418919fSjohnjiang  * @internal Initialize a lock-free stack.
90*4418919fSjohnjiang  *
91*4418919fSjohnjiang  * @param s
92*4418919fSjohnjiang  *   A pointer to the stack structure.
93*4418919fSjohnjiang  * @param count
94*4418919fSjohnjiang  *   The size of the stack.
95*4418919fSjohnjiang  */
96*4418919fSjohnjiang void
97*4418919fSjohnjiang rte_stack_lf_init(struct rte_stack *s, unsigned int count);
98*4418919fSjohnjiang 
99*4418919fSjohnjiang /**
100*4418919fSjohnjiang  * @internal Return the memory required for a lock-free stack.
101*4418919fSjohnjiang  *
102*4418919fSjohnjiang  * @param count
103*4418919fSjohnjiang  *   The size of the stack.
104*4418919fSjohnjiang  * @return
105*4418919fSjohnjiang  *   The bytes to allocate for a lock-free stack.
106*4418919fSjohnjiang  */
107*4418919fSjohnjiang ssize_t
108*4418919fSjohnjiang rte_stack_lf_get_memsize(unsigned int count);
109*4418919fSjohnjiang 
110*4418919fSjohnjiang #endif /* _RTE_STACK_LF_H_ */
111