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