1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019 Arm Limited
3 */
4
5 #include <rte_malloc.h>
6 #include <rte_ring.h>
7 #include <rte_ring_elem.h>
8
9 /* API type to call
10 * rte_ring_<sp/mp or sc/mc>_enqueue_<bulk/burst>
11 * TEST_RING_THREAD_DEF - Uses configured SPSC/MPMC calls
12 * TEST_RING_THREAD_SPSC - Calls SP or SC API
13 * TEST_RING_THREAD_MPMC - Calls MP or MC API
14 */
15 #define TEST_RING_THREAD_DEF 1
16 #define TEST_RING_THREAD_SPSC 2
17 #define TEST_RING_THREAD_MPMC 4
18
19 /* API type to call
20 * TEST_RING_ELEM_SINGLE - Calls single element APIs
21 * TEST_RING_ELEM_BULK - Calls bulk APIs
22 * TEST_RING_ELEM_BURST - Calls burst APIs
23 */
24 #define TEST_RING_ELEM_SINGLE 8
25 #define TEST_RING_ELEM_BULK 16
26 #define TEST_RING_ELEM_BURST 32
27
28 #define TEST_RING_IGNORE_API_TYPE ~0U
29
30 /* This function is placed here as it is required for both
31 * performance and functional tests.
32 */
33 static inline struct rte_ring*
test_ring_create(const char * name,int esize,unsigned int count,int socket_id,unsigned int flags)34 test_ring_create(const char *name, int esize, unsigned int count,
35 int socket_id, unsigned int flags)
36 {
37 /* Legacy queue APIs? */
38 if (esize == -1)
39 return rte_ring_create(name, count, socket_id, flags);
40 else
41 return rte_ring_create_elem(name, esize, count,
42 socket_id, flags);
43 }
44
45 static inline void*
test_ring_inc_ptr(void * obj,int esize,unsigned int n)46 test_ring_inc_ptr(void *obj, int esize, unsigned int n)
47 {
48 size_t sz;
49
50 sz = sizeof(void *);
51 /* Legacy queue APIs? */
52 if (esize != -1)
53 sz = esize;
54
55 return (void *)((uint32_t *)obj + (n * sz / sizeof(uint32_t)));
56 }
57
58 static inline void
test_ring_mem_copy(void * dst,void * const * src,int esize,unsigned int num)59 test_ring_mem_copy(void *dst, void * const *src, int esize, unsigned int num)
60 {
61 size_t sz;
62
63 sz = num * sizeof(void *);
64 if (esize != -1)
65 sz = esize * num;
66
67 memcpy(dst, src, sz);
68 }
69
70 /* Copy to the ring memory */
71 static inline void
test_ring_copy_to(struct rte_ring_zc_data * zcd,void * const * src,int esize,unsigned int num)72 test_ring_copy_to(struct rte_ring_zc_data *zcd, void * const *src, int esize,
73 unsigned int num)
74 {
75 test_ring_mem_copy(zcd->ptr1, src, esize, zcd->n1);
76 if (zcd->n1 != num) {
77 if (esize == -1)
78 src = src + zcd->n1;
79 else
80 src = (void * const *)((const uint32_t *)src +
81 (zcd->n1 * esize / sizeof(uint32_t)));
82 test_ring_mem_copy(zcd->ptr2, src,
83 esize, num - zcd->n1);
84 }
85 }
86
87 /* Copy from the ring memory */
88 static inline void
test_ring_copy_from(struct rte_ring_zc_data * zcd,void * dst,int esize,unsigned int num)89 test_ring_copy_from(struct rte_ring_zc_data *zcd, void *dst, int esize,
90 unsigned int num)
91 {
92 test_ring_mem_copy(dst, zcd->ptr1, esize, zcd->n1);
93
94 if (zcd->n1 != num) {
95 dst = test_ring_inc_ptr(dst, esize, zcd->n1);
96 test_ring_mem_copy(dst, zcd->ptr2, esize, num - zcd->n1);
97 }
98 }
99
100 static __rte_always_inline unsigned int
test_ring_enqueue(struct rte_ring * r,void ** obj,int esize,unsigned int n,unsigned int api_type)101 test_ring_enqueue(struct rte_ring *r, void **obj, int esize, unsigned int n,
102 unsigned int api_type)
103 {
104 /* Legacy queue APIs? */
105 if (esize == -1)
106 switch (api_type) {
107 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE):
108 return rte_ring_enqueue(r, *obj);
109 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE):
110 return rte_ring_sp_enqueue(r, *obj);
111 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE):
112 return rte_ring_mp_enqueue(r, *obj);
113 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK):
114 return rte_ring_enqueue_bulk(r, obj, n, NULL);
115 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK):
116 return rte_ring_sp_enqueue_bulk(r, obj, n, NULL);
117 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK):
118 return rte_ring_mp_enqueue_bulk(r, obj, n, NULL);
119 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST):
120 return rte_ring_enqueue_burst(r, obj, n, NULL);
121 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST):
122 return rte_ring_sp_enqueue_burst(r, obj, n, NULL);
123 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST):
124 return rte_ring_mp_enqueue_burst(r, obj, n, NULL);
125 default:
126 printf("Invalid API type\n");
127 return 0;
128 }
129 else
130 switch (api_type) {
131 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE):
132 return rte_ring_enqueue_elem(r, obj, esize);
133 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE):
134 return rte_ring_sp_enqueue_elem(r, obj, esize);
135 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE):
136 return rte_ring_mp_enqueue_elem(r, obj, esize);
137 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK):
138 return rte_ring_enqueue_bulk_elem(r, obj, esize, n,
139 NULL);
140 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK):
141 return rte_ring_sp_enqueue_bulk_elem(r, obj, esize, n,
142 NULL);
143 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK):
144 return rte_ring_mp_enqueue_bulk_elem(r, obj, esize, n,
145 NULL);
146 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST):
147 return rte_ring_enqueue_burst_elem(r, obj, esize, n,
148 NULL);
149 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST):
150 return rte_ring_sp_enqueue_burst_elem(r, obj, esize, n,
151 NULL);
152 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST):
153 return rte_ring_mp_enqueue_burst_elem(r, obj, esize, n,
154 NULL);
155 default:
156 printf("Invalid API type\n");
157 return 0;
158 }
159 }
160
161 static __rte_always_inline unsigned int
test_ring_dequeue(struct rte_ring * r,void ** obj,int esize,unsigned int n,unsigned int api_type)162 test_ring_dequeue(struct rte_ring *r, void **obj, int esize, unsigned int n,
163 unsigned int api_type)
164 {
165 /* Legacy queue APIs? */
166 if (esize == -1)
167 switch (api_type) {
168 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE):
169 return rte_ring_dequeue(r, obj);
170 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE):
171 return rte_ring_sc_dequeue(r, obj);
172 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE):
173 return rte_ring_mc_dequeue(r, obj);
174 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK):
175 return rte_ring_dequeue_bulk(r, obj, n, NULL);
176 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK):
177 return rte_ring_sc_dequeue_bulk(r, obj, n, NULL);
178 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK):
179 return rte_ring_mc_dequeue_bulk(r, obj, n, NULL);
180 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST):
181 return rte_ring_dequeue_burst(r, obj, n, NULL);
182 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST):
183 return rte_ring_sc_dequeue_burst(r, obj, n, NULL);
184 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST):
185 return rte_ring_mc_dequeue_burst(r, obj, n, NULL);
186 default:
187 printf("Invalid API type\n");
188 return 0;
189 }
190 else
191 switch (api_type) {
192 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE):
193 return rte_ring_dequeue_elem(r, obj, esize);
194 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE):
195 return rte_ring_sc_dequeue_elem(r, obj, esize);
196 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE):
197 return rte_ring_mc_dequeue_elem(r, obj, esize);
198 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK):
199 return rte_ring_dequeue_bulk_elem(r, obj, esize,
200 n, NULL);
201 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK):
202 return rte_ring_sc_dequeue_bulk_elem(r, obj, esize,
203 n, NULL);
204 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK):
205 return rte_ring_mc_dequeue_bulk_elem(r, obj, esize,
206 n, NULL);
207 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST):
208 return rte_ring_dequeue_burst_elem(r, obj, esize,
209 n, NULL);
210 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST):
211 return rte_ring_sc_dequeue_burst_elem(r, obj, esize,
212 n, NULL);
213 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST):
214 return rte_ring_mc_dequeue_burst_elem(r, obj, esize,
215 n, NULL);
216 default:
217 printf("Invalid API type\n");
218 return 0;
219 }
220 }
221
222 /* This function is placed here as it is required for both
223 * performance and functional tests.
224 */
225 static __rte_always_inline void *
test_ring_calloc(unsigned int rsize,int esize)226 test_ring_calloc(unsigned int rsize, int esize)
227 {
228 unsigned int sz;
229 void *p;
230
231 /* Legacy queue APIs? */
232 if (esize == -1)
233 sz = sizeof(void *);
234 else
235 sz = esize;
236
237 p = rte_zmalloc(NULL, rsize * sz, RTE_CACHE_LINE_SIZE);
238 if (p == NULL)
239 printf("Failed to allocate memory\n");
240
241 return p;
242 }
243