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