e4c0ce131dd22433a5446db60caf4ff092944ab3
[dpdk.git] / lib / librte_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 int stack_logtype;
21
22 TAILQ_HEAD(rte_stack_list, rte_tailq_entry);
23
24 static struct rte_tailq_elem rte_stack_tailq = {
25         .name = RTE_TAILQ_STACK_NAME,
26 };
27 EAL_REGISTER_TAILQ(rte_stack_tailq)
28
29
30 static void
31 rte_stack_init(struct rte_stack *s, unsigned int count, uint32_t flags)
32 {
33         memset(s, 0, sizeof(*s));
34
35         if (flags & RTE_STACK_F_LF)
36                 rte_stack_lf_init(s, count);
37         else
38                 rte_stack_std_init(s);
39 }
40
41 static ssize_t
42 rte_stack_get_memsize(unsigned int count, uint32_t flags)
43 {
44         if (flags & RTE_STACK_F_LF)
45                 return rte_stack_lf_get_memsize(count);
46         else
47                 return rte_stack_std_get_memsize(count);
48 }
49
50 struct rte_stack *
51 rte_stack_create(const char *name, unsigned int count, int socket_id,
52                  uint32_t flags)
53 {
54         char mz_name[RTE_MEMZONE_NAMESIZE];
55         struct rte_stack_list *stack_list;
56         const struct rte_memzone *mz;
57         struct rte_tailq_entry *te;
58         struct rte_stack *s;
59         unsigned int sz;
60         int ret;
61
62         if (flags & ~(RTE_STACK_F_LF)) {
63                 STACK_LOG_ERR("Unsupported stack flags %#x\n", flags);
64                 return NULL;
65         }
66
67 #ifdef RTE_ARCH_64
68         RTE_BUILD_BUG_ON(sizeof(struct rte_stack_lf_head) != 16);
69 #else
70         if (flags & RTE_STACK_F_LF) {
71                 STACK_LOG_ERR("Lock-free stack is not supported on your platform\n");
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(stack_logtype, lib.stack, NOTICE);