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