dpdk/lib/librte_stack/rte_stack.c
<<
>>
Prefs
   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
  20TAILQ_HEAD(rte_stack_list, rte_tailq_entry);
  21
  22static struct rte_tailq_elem rte_stack_tailq = {
  23        .name = RTE_TAILQ_STACK_NAME,
  24};
  25EAL_REGISTER_TAILQ(rte_stack_tailq)
  26
  27
  28static void
  29rte_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
  39static ssize_t
  40rte_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
  48struct rte_stack *
  49rte_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#else
  68        if (flags & RTE_STACK_F_LF) {
  69                STACK_LOG_ERR("Lock-free stack is not supported on your platform\n");
  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
 131void
 132rte_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
 163struct rte_stack *
 164rte_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
 195RTE_LOG_REGISTER(stack_logtype, lib.stack, NOTICE);
 196