xref: /dpdk/lib/stack/rte_stack.c (revision 1bb4a528c41f4af4847bd3d58cc2b2b9f1ec9a27)
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.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);
198