f1cbb9803ffc98c5ed32969bcd6f49c22a93e4b0
[dpdk.git] / lib / stack / rte_stack.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019 Intel Corporation
3  */
4
5 #include <string.h>
6
7 #include <rte_string_fns.h>
8 #include <rte_atomic.h>
9 #include <rte_eal.h>
10 #include <rte_eal_memconfig.h>
11 #include <rte_errno.h>
12 #include <rte_malloc.h>
13 #include <rte_memzone.h>
14 #include <rte_rwlock.h>
15 #include <rte_tailq.h>
16
17 #include "rte_stack.h"
18 #include "stack_pvt.h"
19
20 TAILQ_HEAD(rte_stack_list, rte_tailq_entry);
21
22 static struct rte_tailq_elem rte_stack_tailq = {
23         .name = RTE_TAILQ_STACK_NAME,
24 };
25 EAL_REGISTER_TAILQ(rte_stack_tailq)
26
27
28 static void
29 rte_stack_init(struct rte_stack *s, unsigned int count, uint32_t flags)
30 {
31         memset(s, 0, sizeof(*s));
32
33         if (flags & RTE_STACK_F_LF)
34                 rte_stack_lf_init(s, count);
35         else
36                 rte_stack_std_init(s);
37 }
38
39 static ssize_t
40 rte_stack_get_memsize(unsigned int count, uint32_t flags)
41 {
42         if (flags & RTE_STACK_F_LF)
43                 return rte_stack_lf_get_memsize(count);
44         else
45                 return rte_stack_std_get_memsize(count);
46 }
47
48 struct rte_stack *
49 rte_stack_create(const char *name, unsigned int count, int socket_id,
50                  uint32_t flags)
51 {
52         char mz_name[RTE_MEMZONE_NAMESIZE];
53         struct rte_stack_list *stack_list;
54         const struct rte_memzone *mz;
55         struct rte_tailq_entry *te;
56         struct rte_stack *s;
57         unsigned int sz;
58         int ret;
59
60         if (flags & ~(RTE_STACK_F_LF)) {
61                 STACK_LOG_ERR("Unsupported stack flags %#x\n", flags);
62                 return NULL;
63         }
64
65 #ifdef RTE_ARCH_64
66         RTE_BUILD_BUG_ON(sizeof(struct rte_stack_lf_head) != 16);
67 #endif
68 #if !defined(RTE_STACK_LF_SUPPORTED)
69         if (flags & RTE_STACK_F_LF) {
70                 STACK_LOG_ERR("Lock-free stack is not supported on your platform\n");
71                 rte_errno = ENOTSUP;
72                 return NULL;
73         }
74 #endif
75
76         sz = rte_stack_get_memsize(count, flags);
77
78         ret = snprintf(mz_name, sizeof(mz_name), "%s%s",
79                        RTE_STACK_MZ_PREFIX, name);
80         if (ret < 0 || ret >= (int)sizeof(mz_name)) {
81                 rte_errno = ENAMETOOLONG;
82                 return NULL;
83         }
84
85         te = rte_zmalloc("STACK_TAILQ_ENTRY", sizeof(*te), 0);
86         if (te == NULL) {
87                 STACK_LOG_ERR("Cannot reserve memory for tailq\n");
88                 rte_errno = ENOMEM;
89                 return NULL;
90         }
91
92         rte_mcfg_tailq_write_lock();
93
94         mz = rte_memzone_reserve_aligned(mz_name, sz, socket_id,
95                                          0, __alignof__(*s));
96         if (mz == NULL) {
97                 STACK_LOG_ERR("Cannot reserve stack memzone!\n");
98                 rte_mcfg_tailq_write_unlock();
99                 rte_free(te);
100                 return NULL;
101         }
102
103         s = mz->addr;
104
105         rte_stack_init(s, count, flags);
106
107         /* Store the name for later lookups */
108         ret = strlcpy(s->name, name, sizeof(s->name));
109         if (ret < 0 || ret >= (int)sizeof(s->name)) {
110                 rte_mcfg_tailq_write_unlock();
111
112                 rte_errno = ENAMETOOLONG;
113                 rte_free(te);
114                 rte_memzone_free(mz);
115                 return NULL;
116         }
117
118         s->memzone = mz;
119         s->capacity = count;
120         s->flags = flags;
121
122         te->data = s;
123
124         stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list);
125
126         TAILQ_INSERT_TAIL(stack_list, te, next);
127
128         rte_mcfg_tailq_write_unlock();
129
130         return s;
131 }
132
133 void
134 rte_stack_free(struct rte_stack *s)
135 {
136         struct rte_stack_list *stack_list;
137         struct rte_tailq_entry *te;
138
139         if (s == NULL)
140                 return;
141
142         stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list);
143         rte_mcfg_tailq_write_lock();
144
145         /* find out tailq entry */
146         TAILQ_FOREACH(te, stack_list, next) {
147                 if (te->data == s)
148                         break;
149         }
150
151         if (te == NULL) {
152                 rte_mcfg_tailq_write_unlock();
153                 return;
154         }
155
156         TAILQ_REMOVE(stack_list, te, next);
157
158         rte_mcfg_tailq_write_unlock();
159
160         rte_free(te);
161
162         rte_memzone_free(s->memzone);
163 }
164
165 struct rte_stack *
166 rte_stack_lookup(const char *name)
167 {
168         struct rte_stack_list *stack_list;
169         struct rte_tailq_entry *te;
170         struct rte_stack *r = NULL;
171
172         if (name == NULL) {
173                 rte_errno = EINVAL;
174                 return NULL;
175         }
176
177         stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list);
178
179         rte_mcfg_tailq_read_lock();
180
181         TAILQ_FOREACH(te, stack_list, next) {
182                 r = (struct rte_stack *) te->data;
183                 if (strncmp(name, r->name, RTE_STACK_NAMESIZE) == 0)
184                         break;
185         }
186
187         rte_mcfg_tailq_read_unlock();
188
189         if (te == NULL) {
190                 rte_errno = ENOENT;
191                 return NULL;
192         }
193
194         return r;
195 }
196
197 RTE_LOG_REGISTER_DEFAULT(stack_logtype, NOTICE);