stack: introduce stack library
[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_atomic.h>
8 #include <rte_eal.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_rwlock.h>
14 #include <rte_tailq.h>
15
16 #include "rte_stack.h"
17 #include "rte_stack_pvt.h"
18
19 int stack_logtype;
20
21 TAILQ_HEAD(rte_stack_list, rte_tailq_entry);
22
23 static struct rte_tailq_elem rte_stack_tailq = {
24         .name = RTE_TAILQ_STACK_NAME,
25 };
26 EAL_REGISTER_TAILQ(rte_stack_tailq)
27
28 static void
29 rte_stack_init(struct rte_stack *s)
30 {
31         memset(s, 0, sizeof(*s));
32
33         rte_stack_std_init(s);
34 }
35
36 static ssize_t
37 rte_stack_get_memsize(unsigned int count)
38 {
39         return rte_stack_std_get_memsize(count);
40 }
41
42 struct rte_stack *
43 rte_stack_create(const char *name, unsigned int count, int socket_id,
44                  uint32_t flags)
45 {
46         char mz_name[RTE_MEMZONE_NAMESIZE];
47         struct rte_stack_list *stack_list;
48         const struct rte_memzone *mz;
49         struct rte_tailq_entry *te;
50         struct rte_stack *s;
51         unsigned int sz;
52         int ret;
53
54         RTE_SET_USED(flags);
55
56         sz = rte_stack_get_memsize(count);
57
58         ret = snprintf(mz_name, sizeof(mz_name), "%s%s",
59                        RTE_STACK_MZ_PREFIX, name);
60         if (ret < 0 || ret >= (int)sizeof(mz_name)) {
61                 rte_errno = ENAMETOOLONG;
62                 return NULL;
63         }
64
65         te = rte_zmalloc("STACK_TAILQ_ENTRY", sizeof(*te), 0);
66         if (te == NULL) {
67                 STACK_LOG_ERR("Cannot reserve memory for tailq\n");
68                 rte_errno = ENOMEM;
69                 return NULL;
70         }
71
72         rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
73
74         mz = rte_memzone_reserve_aligned(mz_name, sz, socket_id,
75                                          0, __alignof__(*s));
76         if (mz == NULL) {
77                 STACK_LOG_ERR("Cannot reserve stack memzone!\n");
78                 rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
79                 rte_free(te);
80                 return NULL;
81         }
82
83         s = mz->addr;
84
85         rte_stack_init(s);
86
87         /* Store the name for later lookups */
88         ret = snprintf(s->name, sizeof(s->name), "%s", name);
89         if (ret < 0 || ret >= (int)sizeof(s->name)) {
90                 rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
91
92                 rte_errno = ENAMETOOLONG;
93                 rte_free(te);
94                 rte_memzone_free(mz);
95                 return NULL;
96         }
97
98         s->memzone = mz;
99         s->capacity = count;
100         s->flags = flags;
101
102         te->data = s;
103
104         stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list);
105
106         TAILQ_INSERT_TAIL(stack_list, te, next);
107
108         rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
109
110         return s;
111 }
112
113 void
114 rte_stack_free(struct rte_stack *s)
115 {
116         struct rte_stack_list *stack_list;
117         struct rte_tailq_entry *te;
118
119         if (s == NULL)
120                 return;
121
122         stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list);
123         rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
124
125         /* find out tailq entry */
126         TAILQ_FOREACH(te, stack_list, next) {
127                 if (te->data == s)
128                         break;
129         }
130
131         if (te == NULL) {
132                 rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
133                 return;
134         }
135
136         TAILQ_REMOVE(stack_list, te, next);
137
138         rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
139
140         rte_free(te);
141
142         rte_memzone_free(s->memzone);
143 }
144
145 struct rte_stack *
146 rte_stack_lookup(const char *name)
147 {
148         struct rte_stack_list *stack_list;
149         struct rte_tailq_entry *te;
150         struct rte_stack *r = NULL;
151
152         if (name == NULL) {
153                 rte_errno = EINVAL;
154                 return NULL;
155         }
156
157         stack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list);
158
159         rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
160
161         TAILQ_FOREACH(te, stack_list, next) {
162                 r = (struct rte_stack *) te->data;
163                 if (strncmp(name, r->name, RTE_STACK_NAMESIZE) == 0)
164                         break;
165         }
166
167         rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
168
169         if (te == NULL) {
170                 rte_errno = ENOENT;
171                 return NULL;
172         }
173
174         return r;
175 }
176
177 RTE_INIT(librte_stack_init_log)
178 {
179         stack_logtype = rte_log_register("lib.stack");
180         if (stack_logtype >= 0)
181                 rte_log_set_level(stack_logtype, RTE_LOG_NOTICE);
182 }