Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2024 Huawei Technologies Co., Ltd
3 : : */
4 : :
5 : : #include <inttypes.h>
6 : :
7 : : #include <eal_export.h>
8 : : #include <rte_string_fns.h>
9 : :
10 : : #include "soring.h"
11 : :
12 [ - + ]: 252 : RTE_LOG_REGISTER_DEFAULT(soring_logtype, INFO);
13 : :
14 : : static uint32_t
15 : : soring_calc_elem_num(uint32_t count)
16 : : {
17 : : return rte_align32pow2(count + 1);
18 : : }
19 : :
20 : : static int
21 : 15 : soring_check_param(uint32_t esize, uint32_t msize, uint32_t count,
22 : : uint32_t stages)
23 : : {
24 [ + + ]: 15 : if (stages == 0) {
25 : 1 : SORING_LOG(ERR, "invalid number of stages: %u", stages);
26 : 1 : return -EINVAL;
27 : : }
28 : :
29 : : /* Check if element size is a multiple of 4B */
30 [ + + + + ]: 14 : if (esize == 0 || esize % 4 != 0) {
31 : 4 : SORING_LOG(ERR, "invalid element size: %u", esize);
32 : 4 : return -EINVAL;
33 : : }
34 : :
35 : : /* Check if size of metadata is a multiple of 4B */
36 [ + + ]: 10 : if (msize % 4 != 0) {
37 : 1 : SORING_LOG(ERR, "invalid metadata size: %u", msize);
38 : 1 : return -EINVAL;
39 : : }
40 : :
41 : : /* count must be a power of 2 */
42 [ + + ]: 9 : if (rte_is_power_of_2(count) == 0 ||
43 : : (count > RTE_SORING_ELEM_MAX + 1)) {
44 : 1 : SORING_LOG(ERR, "invalid number of elements: %u", count);
45 : 1 : return -EINVAL;
46 : : }
47 : :
48 : : return 0;
49 : : }
50 : :
51 : : /*
52 : : * Calculate size offsets for SORING internal data layout.
53 : : */
54 : : static size_t
55 : : soring_get_szofs(uint32_t esize, uint32_t msize, uint32_t count,
56 : : uint32_t stages, size_t *elst_ofs, size_t *state_ofs,
57 : : size_t *stage_ofs)
58 : : {
59 : : size_t sz;
60 : : const struct rte_soring * const r = NULL;
61 : :
62 : 8 : sz = sizeof(r[0]) + (size_t)count * esize;
63 : 8 : sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE);
64 : :
65 : : if (elst_ofs != NULL)
66 : : *elst_ofs = sz;
67 : :
68 : 8 : sz = sz + (size_t)count * msize;
69 : 8 : sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE);
70 : :
71 : : if (state_ofs != NULL)
72 : : *state_ofs = sz;
73 : :
74 : 8 : sz += sizeof(r->state[0]) * count;
75 : 8 : sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE);
76 : :
77 : : if (stage_ofs != NULL)
78 : : *stage_ofs = sz;
79 : :
80 : 5 : sz += sizeof(r->stage[0]) * stages;
81 : 5 : sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE);
82 : :
83 : : return sz;
84 : : }
85 : :
86 : : static void
87 : 3 : soring_dump_stage_headtail(FILE *f, const char *prefix,
88 : : struct soring_stage *st)
89 : : {
90 : 3 : fprintf(f, "%stail.pos=%"PRIu32"\n", prefix, st->sht.tail.pos);
91 : 3 : fprintf(f, "%stail.sync=%"PRIu32"\n", prefix, st->sht.tail.sync);
92 : 3 : fprintf(f, "%shead=%"PRIu32"\n", prefix, st->sht.head);
93 : 3 : }
94 : :
95 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_dump, 25.03)
96 : : void
97 : 2 : rte_soring_dump(FILE *f, const struct rte_soring *r)
98 : : {
99 : : uint32_t i;
100 : : char buf[32];
101 : :
102 [ - + ]: 2 : if (f == NULL || r == NULL)
103 : 0 : return;
104 : :
105 : 4 : fprintf(f, "soring <%s>@%p\n", r->name, r);
106 : 2 : fprintf(f, " size=%"PRIu32"\n", r->size);
107 : 2 : fprintf(f, " capacity=%"PRIu32"\n", r->capacity);
108 : 2 : fprintf(f, " esize=%"PRIu32"\n", r->esize);
109 : 2 : fprintf(f, " msize=%"PRIu32"\n", r->msize);
110 : 2 : fprintf(f, " used=%u\n", rte_soring_count(r));
111 : 2 : fprintf(f, " avail=%u\n", rte_soring_free_count(r));
112 : :
113 : 2 : rte_ring_headtail_dump(f, " cons.", &(r->cons.ht));
114 : 2 : rte_ring_headtail_dump(f, " prod.", &(r->prod.ht));
115 : :
116 : 2 : fprintf(f, " nb_stage=%"PRIu32"\n", r->nb_stage);
117 [ + + ]: 5 : for (i = 0; i < r->nb_stage; i++) {
118 : : snprintf(buf, sizeof(buf), " stage[%u].", i);
119 : 3 : soring_dump_stage_headtail(f, buf, r->stage + i);
120 : : }
121 : : }
122 : :
123 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_get_memsize, 25.03)
124 : : ssize_t
125 : 7 : rte_soring_get_memsize(const struct rte_soring_param *prm)
126 : : {
127 : : int32_t rc;
128 : : uint32_t count;
129 : :
130 : 7 : count = soring_calc_elem_num(prm->elems);
131 : 7 : rc = soring_check_param(prm->elem_size, prm->meta_size, count,
132 : 7 : prm->stages);
133 [ + + ]: 7 : if (rc != 0)
134 : 2 : return rc;
135 : :
136 : 5 : return soring_get_szofs(prm->elem_size, prm->meta_size, count,
137 : 5 : prm->stages, NULL, NULL, NULL);
138 : : }
139 : :
140 : : /* compilation-time checks */
141 : : static void
142 : : soring_compilation_checks(void)
143 : : {
144 : : RTE_BUILD_BUG_ON((sizeof(struct rte_soring) &
145 : : RTE_CACHE_LINE_MASK) != 0);
146 : : RTE_BUILD_BUG_ON((offsetof(struct rte_soring, cons) &
147 : : RTE_CACHE_LINE_MASK) != 0);
148 : : RTE_BUILD_BUG_ON((offsetof(struct rte_soring, prod) &
149 : : RTE_CACHE_LINE_MASK) != 0);
150 : :
151 : : RTE_BUILD_BUG_ON(offsetof(struct rte_ring_headtail, tail) !=
152 : : offsetof(struct soring_stage_headtail, tail.pos));
153 : : RTE_BUILD_BUG_ON(offsetof(struct rte_ring_headtail, sync_type) !=
154 : : offsetof(struct soring_stage_headtail, unused));
155 : : }
156 : :
157 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_init, 25.03)
158 : : int
159 : 8 : rte_soring_init(struct rte_soring *r, const struct rte_soring_param *prm)
160 : : {
161 : : int32_t rc;
162 : : uint32_t n;
163 : : size_t meta_ofs, stage_ofs, state_ofs;
164 : :
165 : : soring_compilation_checks();
166 : :
167 [ + - ]: 8 : if (r == NULL || prm == NULL)
168 : : return -EINVAL;
169 : :
170 : 8 : n = soring_calc_elem_num(prm->elems);
171 : 8 : rc = soring_check_param(prm->elem_size, prm->meta_size, n, prm->stages);
172 [ + + ]: 8 : if (rc != 0)
173 : : return rc;
174 : :
175 [ + - ]: 3 : soring_get_szofs(prm->elem_size, prm->meta_size, n, prm->stages,
176 : : &meta_ofs, &state_ofs, &stage_ofs);
177 : :
178 : : memset(r, 0, sizeof(*r));
179 [ + - ]: 3 : rc = strlcpy(r->name, prm->name, sizeof(r->name));
180 [ + - ]: 3 : if (rc < 0 || rc >= (int)sizeof(r->name))
181 : : return -ENAMETOOLONG;
182 : :
183 : 3 : r->size = n;
184 : 3 : r->mask = r->size - 1;
185 : 3 : r->capacity = prm->elems;
186 : 3 : r->esize = prm->elem_size;
187 : 3 : r->msize = prm->meta_size;
188 : :
189 : 3 : r->prod.ht.sync_type = prm->prod_synt;
190 : 3 : r->cons.ht.sync_type = prm->cons_synt;
191 : :
192 [ + + ]: 3 : r->state = (union soring_state *)((uintptr_t)r + state_ofs);
193 : : memset(r->state, 0, sizeof(r->state[0]) * r->size);
194 : :
195 : 3 : r->stage = (struct soring_stage *)((uintptr_t)r + stage_ofs);
196 : 3 : r->nb_stage = prm->stages;
197 : 3 : memset(r->stage, 0, r->nb_stage * sizeof(r->stage[0]));
198 : :
199 [ + + ]: 3 : if (r->msize != 0)
200 : 2 : r->meta = (void *)((uintptr_t)r + meta_ofs);
201 : :
202 : : return 0;
203 : : }
|