Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2019 Arm Limited
3 : : */
4 : :
5 : : #include <rte_malloc.h>
6 : : #include <rte_memcpy.h>
7 : : #include <rte_ptr_compress.h>
8 : : #include <rte_ring.h>
9 : : #include <rte_ring_elem.h>
10 : :
11 : : /* API type to call
12 : : * rte_ring_<sp/mp or sc/mc>_enqueue_<bulk/burst>
13 : : * TEST_RING_THREAD_DEF - Uses configured SPSC/MPMC calls
14 : : * TEST_RING_THREAD_SPSC - Calls SP or SC API
15 : : * TEST_RING_THREAD_MPMC - Calls MP or MC API
16 : : */
17 : : #define TEST_RING_THREAD_DEF 1
18 : : #define TEST_RING_THREAD_SPSC 2
19 : : #define TEST_RING_THREAD_MPMC 4
20 : :
21 : : /* API type to call
22 : : * TEST_RING_ELEM_SINGLE - Calls single element APIs
23 : : * TEST_RING_ELEM_BULK - Calls bulk APIs
24 : : * TEST_RING_ELEM_BURST - Calls burst APIs
25 : : */
26 : : #define TEST_RING_ELEM_SINGLE 8
27 : : #define TEST_RING_ELEM_BULK 16
28 : : #define TEST_RING_ELEM_BURST 32
29 : :
30 : : #define TEST_RING_ELEM_BURST_ZC 64
31 : : #define TEST_RING_ELEM_BURST_ZC_COMPRESS_PTR_16 128
32 : : #define TEST_RING_ELEM_BURST_ZC_COMPRESS_PTR_32 256
33 : :
34 : : #define TEST_RING_IGNORE_API_TYPE ~0U
35 : :
36 : : /* This function is placed here as it is required for both
37 : : * performance and functional tests.
38 : : */
39 : : static inline struct rte_ring*
40 : 320 : test_ring_create(const char *name, int esize, unsigned int count,
41 : : int socket_id, unsigned int flags)
42 : : {
43 : : /* Legacy queue APIs? */
44 [ + + ]: 320 : if (esize == -1)
45 : 64 : return rte_ring_create(name, count, socket_id, flags);
46 : : else
47 : 257 : return rte_ring_create_elem(name, esize, count,
48 : : socket_id, flags);
49 : : }
50 : :
51 : : static inline void*
52 : : test_ring_inc_ptr(void *obj, int esize, unsigned int n)
53 : : {
54 : : size_t sz;
55 : :
56 : : sz = sizeof(void *);
57 : : /* Legacy queue APIs? */
58 [ + + + + : 59253 : if (esize != -1)
+ + + + +
+ + + + +
+ + + + +
- ]
59 : : sz = esize;
60 : :
61 [ - + ]: 77375 : return (void *)((uint32_t *)obj + (n * sz / sizeof(uint32_t)));
62 : : }
63 : :
64 : : static inline void
65 : : test_ring_mem_copy(void *dst, void * const *src, int esize, unsigned int num)
66 : : {
67 : : size_t sz;
68 : :
69 : 11496 : sz = num * sizeof(void *);
70 : 11496 : if (esize != -1)
71 : 11496 : sz = esize * num;
72 : :
73 : : memcpy(dst, src, sz);
74 : 456 : }
75 : :
76 : : /* Copy to the ring memory */
77 : : static inline void
78 : 5520 : test_ring_copy_to(struct rte_ring_zc_data *zcd, void * const *src, int esize,
79 : : unsigned int num)
80 : : {
81 [ + - ]: 5520 : test_ring_mem_copy(zcd->ptr1, src, esize, zcd->n1);
82 [ + + ]: 5520 : if (zcd->n1 != num) {
83 [ - + ]: 228 : if (esize == -1)
84 : 0 : src = src + zcd->n1;
85 : : else
86 : 228 : src = (void * const *)((const uint32_t *)src +
87 : 228 : (zcd->n1 * esize / sizeof(uint32_t)));
88 [ + - ]: 228 : test_ring_mem_copy(zcd->ptr2, src,
89 : : esize, num - zcd->n1);
90 : : }
91 : 5520 : }
92 : :
93 : : /* Copy from the ring memory */
94 : : static inline void
95 : 5520 : test_ring_copy_from(struct rte_ring_zc_data *zcd, void *dst, int esize,
96 : : unsigned int num)
97 : : {
98 [ + - ]: 5520 : test_ring_mem_copy(dst, zcd->ptr1, esize, zcd->n1);
99 : :
100 [ + + ]: 5520 : if (zcd->n1 != num) {
101 : : dst = test_ring_inc_ptr(dst, esize, zcd->n1);
102 [ + - ]: 228 : test_ring_mem_copy(dst, zcd->ptr2, esize, num - zcd->n1);
103 : : }
104 : 5520 : }
105 : :
106 : : static inline unsigned int
107 : 20645 : test_ring_enqueue(struct rte_ring *r, void **obj, int esize, unsigned int n,
108 : : unsigned int api_type)
109 : : {
110 : : unsigned int ret;
111 : : struct rte_ring_zc_data zcd = {0};
112 : :
113 : : /* Legacy queue APIs? */
114 [ + + ]: 20645 : if (esize == -1)
115 [ + - - + : 4129 : switch (api_type) {
- - + - -
- ]
116 : 4127 : case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE):
117 [ - + - - : 8254 : return rte_ring_enqueue(r, *obj);
- ]
118 : 0 : case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE):
119 : 0 : return rte_ring_sp_enqueue(r, *obj);
120 : 0 : case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE):
121 : 0 : return rte_ring_mp_enqueue(r, *obj);
122 : : case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK):
123 : 1 : return rte_ring_enqueue_bulk(r, obj, n, NULL);
124 : : case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK):
125 : 0 : return rte_ring_sp_enqueue_bulk(r, obj, n, NULL);
126 : : case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK):
127 : 0 : return rte_ring_mp_enqueue_bulk(r, obj, n, NULL);
128 : : case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST):
129 : 1 : return rte_ring_enqueue_burst(r, obj, n, NULL);
130 : : case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST):
131 : 0 : return rte_ring_sp_enqueue_burst(r, obj, n, NULL);
132 : : case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST):
133 : 0 : return rte_ring_mp_enqueue_burst(r, obj, n, NULL);
134 : : default:
135 : : printf("Invalid API type\n");
136 : 0 : return 0;
137 : : }
138 : : else
139 [ + - - + : 16516 : switch (api_type) {
- - + - -
- - - - ]
140 : 16508 : case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE):
141 [ - + - - : 33016 : return rte_ring_enqueue_elem(r, obj, esize);
- ]
142 : 0 : case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE):
143 : 0 : return rte_ring_sp_enqueue_elem(r, obj, esize);
144 : 0 : case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE):
145 : 0 : return rte_ring_mp_enqueue_elem(r, obj, esize);
146 : 4 : case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK):
147 [ - + - - : 4 : return rte_ring_enqueue_bulk_elem(r, obj, esize, n,
- ]
148 : : NULL);
149 : 0 : case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK):
150 : 0 : return rte_ring_sp_enqueue_bulk_elem(r, obj, esize, n,
151 : : NULL);
152 : 0 : case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK):
153 : 0 : return rte_ring_mp_enqueue_bulk_elem(r, obj, esize, n,
154 : : NULL);
155 : 4 : case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST):
156 [ - + - - : 4 : return rte_ring_enqueue_burst_elem(r, obj, esize, n,
- ]
157 : : NULL);
158 : 0 : case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST):
159 : 0 : return rte_ring_sp_enqueue_burst_elem(r, obj, esize, n,
160 : : NULL);
161 : 0 : case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST):
162 : 0 : return rte_ring_mp_enqueue_burst_elem(r, obj, esize, n,
163 : : NULL);
164 : 0 : case (TEST_RING_ELEM_BURST_ZC):
165 [ # # # ]: 0 : ret = rte_ring_enqueue_zc_burst_elem_start(
166 : : r, esize, n, &zcd, NULL);
167 [ # # ]: 0 : if (unlikely(ret == 0))
168 : : return 0;
169 [ # # ]: 0 : rte_memcpy(zcd.ptr1, (char *)obj, zcd.n1 * esize);
170 [ # # ]: 0 : if (unlikely(zcd.ptr2 != NULL))
171 : 0 : rte_memcpy(zcd.ptr2,
172 : : (char *)obj + zcd.n1 * esize,
173 [ # # ]: 0 : (ret - zcd.n1) * esize);
174 : : rte_ring_enqueue_zc_finish(r, ret);
175 : 0 : return ret;
176 : 0 : case (TEST_RING_ELEM_BURST_ZC_COMPRESS_PTR_16):
177 : : /* rings cannot store uint16_t so we use a uint32_t
178 : : * and half the requested number of elements
179 : : * and compensate by doubling the returned numbers
180 : : */
181 [ # # # ]: 0 : ret = rte_ring_enqueue_zc_burst_elem_start(
182 : : r, sizeof(uint32_t), n / 2, &zcd, NULL);
183 [ # # ]: 0 : if (unlikely(ret == 0))
184 : : return 0;
185 : 0 : rte_ptr_compress_16_shift(
186 : 0 : 0, obj, zcd.ptr1, zcd.n1 * 2, 3);
187 [ # # ]: 0 : if (unlikely(zcd.ptr2 != NULL))
188 : 0 : rte_ptr_compress_16_shift(0,
189 : : obj + (zcd.n1 * 2),
190 : : zcd.ptr2,
191 : 0 : (ret - zcd.n1) * 2, 3);
192 : : rte_ring_enqueue_zc_finish(r, ret);
193 : 0 : return ret * 2;
194 : : case (TEST_RING_ELEM_BURST_ZC_COMPRESS_PTR_32):
195 : : ret = rte_ring_enqueue_zc_burst_elem_start(
196 : : r, sizeof(uint32_t), n, &zcd, NULL);
197 [ # # ]: 0 : if (unlikely(ret == 0))
198 : : return 0;
199 : 0 : rte_ptr_compress_32_shift(0, obj, zcd.ptr1, zcd.n1, 3);
200 [ # # ]: 0 : if (unlikely(zcd.ptr2 != NULL))
201 : 0 : rte_ptr_compress_32_shift(0, obj + zcd.n1,
202 : 0 : zcd.ptr2, ret - zcd.n1, 3);
203 : : rte_ring_enqueue_zc_finish(r, ret);
204 : 0 : return ret;
205 : : default:
206 : : printf("Invalid API type\n");
207 : 0 : return 0;
208 : : }
209 : : }
210 : :
211 : : static inline unsigned int
212 : 20490 : test_ring_dequeue(struct rte_ring *r, void **obj, int esize, unsigned int n,
213 : : unsigned int api_type)
214 : : {
215 : : unsigned int ret;
216 : : struct rte_ring_zc_data zcd = {0};
217 : :
218 : : /* Legacy queue APIs? */
219 [ + + ]: 20490 : if (esize == -1)
220 [ + - - + : 4098 : switch (api_type) {
- - + - -
- ]
221 : : case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE):
222 : 4095 : return rte_ring_dequeue(r, obj);
223 : : case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE):
224 : 0 : return rte_ring_sc_dequeue(r, obj);
225 : : case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE):
226 : 0 : return rte_ring_mc_dequeue(r, obj);
227 : : case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK):
228 : 1 : return rte_ring_dequeue_bulk(r, obj, n, NULL);
229 : : case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK):
230 : 0 : return rte_ring_sc_dequeue_bulk(r, obj, n, NULL);
231 : : case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK):
232 : 0 : return rte_ring_mc_dequeue_bulk(r, obj, n, NULL);
233 : : case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST):
234 : 2 : return rte_ring_dequeue_burst(r, obj, n, NULL);
235 : : case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST):
236 : 0 : return rte_ring_sc_dequeue_burst(r, obj, n, NULL);
237 : : case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST):
238 : 0 : return rte_ring_mc_dequeue_burst(r, obj, n, NULL);
239 : : default:
240 : : printf("Invalid API type\n");
241 : 0 : return 0;
242 : : }
243 : : else
244 [ + - - + : 16392 : switch (api_type) {
- - + - -
- - - - ]
245 : 16380 : case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE):
246 [ - + - - : 32760 : return rte_ring_dequeue_elem(r, obj, esize);
- ]
247 : 0 : case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE):
248 : 0 : return rte_ring_sc_dequeue_elem(r, obj, esize);
249 : 0 : case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE):
250 : 0 : return rte_ring_mc_dequeue_elem(r, obj, esize);
251 : 4 : case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK):
252 [ - + - - : 4 : return rte_ring_dequeue_bulk_elem(r, obj, esize,
- ]
253 : : n, NULL);
254 : 0 : case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK):
255 : 0 : return rte_ring_sc_dequeue_bulk_elem(r, obj, esize,
256 : : n, NULL);
257 : 0 : case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK):
258 : 0 : return rte_ring_mc_dequeue_bulk_elem(r, obj, esize,
259 : : n, NULL);
260 : 8 : case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST):
261 [ - + - - : 8 : return rte_ring_dequeue_burst_elem(r, obj, esize,
- ]
262 : : n, NULL);
263 : 0 : case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST):
264 : 0 : return rte_ring_sc_dequeue_burst_elem(r, obj, esize,
265 : : n, NULL);
266 : 0 : case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST):
267 : 0 : return rte_ring_mc_dequeue_burst_elem(r, obj, esize,
268 : : n, NULL);
269 : 0 : case (TEST_RING_ELEM_BURST_ZC):
270 [ # # # ]: 0 : ret = rte_ring_dequeue_zc_burst_elem_start(
271 : : r, esize, n, &zcd, NULL);
272 [ # # ]: 0 : if (unlikely(ret == 0))
273 : : return 0;
274 [ # # ]: 0 : rte_memcpy((char *)obj, zcd.ptr1, zcd.n1 * esize);
275 [ # # ]: 0 : if (unlikely(zcd.ptr2 != NULL))
276 : 0 : rte_memcpy((char *)obj + zcd.n1 * esize,
277 : : zcd.ptr2,
278 [ # # ]: 0 : (ret - zcd.n1) * esize);
279 : : rte_ring_dequeue_zc_finish(r, ret);
280 : 0 : return ret;
281 : 0 : case (TEST_RING_ELEM_BURST_ZC_COMPRESS_PTR_16):
282 : : /* rings cannot store uint16_t so we use a uint32_t
283 : : * and half the requested number of elements
284 : : * and compensate by doubling the returned numbers
285 : : */
286 [ # # # ]: 0 : ret = rte_ring_dequeue_zc_burst_elem_start(
287 : : r, sizeof(uint32_t), n / 2, &zcd, NULL);
288 [ # # ]: 0 : if (unlikely(ret == 0))
289 : : return 0;
290 : 0 : rte_ptr_decompress_16_shift(
291 : 0 : 0, zcd.ptr1, obj, zcd.n1 * 2, 3);
292 [ # # ]: 0 : if (unlikely(zcd.ptr2 != NULL))
293 : 0 : rte_ptr_decompress_16_shift(0, zcd.ptr2,
294 : 0 : obj + zcd.n1,
295 : 0 : (ret - zcd.n1) * 2,
296 : : 3);
297 : : rte_ring_dequeue_zc_finish(r, ret);
298 : 0 : return ret * 2;
299 : : case (TEST_RING_ELEM_BURST_ZC_COMPRESS_PTR_32):
300 : : ret = rte_ring_dequeue_zc_burst_elem_start(
301 : : r, sizeof(uint32_t), n, &zcd, NULL);
302 [ # # ]: 0 : if (unlikely(ret == 0))
303 : : return 0;
304 : 0 : rte_ptr_decompress_32_shift(0, zcd.ptr1, obj, zcd.n1, 3);
305 [ # # ]: 0 : if (unlikely(zcd.ptr2 != NULL))
306 : 0 : rte_ptr_decompress_32_shift(0, zcd.ptr2,
307 : 0 : obj + zcd.n1, ret - zcd.n1, 3);
308 : : rte_ring_dequeue_zc_finish(r, ret);
309 : 0 : return ret;
310 : : default:
311 : : printf("Invalid API type\n");
312 : 0 : return 0;
313 : : }
314 : : }
315 : :
316 : : /* This function is placed here as it is required for both
317 : : * performance and functional tests.
318 : : */
319 : : static inline void *
320 : 580 : test_ring_calloc(unsigned int rsize, int esize)
321 : : {
322 : : unsigned int sz;
323 : : void *p;
324 : :
325 : : /* Legacy queue APIs? */
326 [ + + ]: 580 : if (esize == -1)
327 : : sz = sizeof(void *);
328 : : else
329 : : sz = esize;
330 : :
331 : 580 : p = rte_zmalloc(NULL, rsize * sz, RTE_CACHE_LINE_SIZE);
332 [ - + ]: 580 : if (p == NULL)
333 : : printf("Failed to allocate memory\n");
334 : :
335 : 580 : return p;
336 : : }
|