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