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