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