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