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