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