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