xref: /dpdk/app/test/test_soring_stress_impl.h (revision 70581c355d6965f7be2dbf1c4fc0d30778c53b98)
1*70581c35SKonstantin Ananyev /* SPDX-License-Identifier: BSD-3-Clause
2*70581c35SKonstantin Ananyev  */
3*70581c35SKonstantin Ananyev 
4*70581c35SKonstantin Ananyev #include <stdalign.h>
5*70581c35SKonstantin Ananyev 
6*70581c35SKonstantin Ananyev #include "test_soring_stress.h"
7*70581c35SKonstantin Ananyev 
8*70581c35SKonstantin Ananyev /**
9*70581c35SKonstantin Ananyev  * Stress test for soring enqueue/dequeue/acquire/release operations.
10*70581c35SKonstantin Ananyev  * Depending on the role, performs at least one of the following patterns
11*70581c35SKonstantin Ananyev  * on each worker:
12*70581c35SKonstantin Ananyev  * - dequeue/read-write data from/to the dequeued objects/enqueue.
13*70581c35SKonstantin Ananyev  * - acquire/read-write data from/to the acquired objects/release.
14*70581c35SKonstantin Ananyev  * Serves as both functional and performance test of soring
15*70581c35SKonstantin Ananyev  * data-path API under high contention
16*70581c35SKonstantin Ananyev  * (for both over committed and non-over committed scenarios).
17*70581c35SKonstantin Ananyev  */
18*70581c35SKonstantin Ananyev 
19*70581c35SKonstantin Ananyev #define RING_NAME	"SORING_STRESS"
20*70581c35SKonstantin Ananyev #define BULK_NUM	32
21*70581c35SKonstantin Ananyev #define RING_SIZE	(2 * BULK_NUM * RTE_MAX_LCORE)
22*70581c35SKonstantin Ananyev 
23*70581c35SKonstantin Ananyev #define MAX_STAGES	16
24*70581c35SKonstantin Ananyev 
25*70581c35SKonstantin Ananyev enum {
26*70581c35SKonstantin Ananyev 	WRK_CMD_STOP,
27*70581c35SKonstantin Ananyev 	WRK_CMD_RUN,
28*70581c35SKonstantin Ananyev };
29*70581c35SKonstantin Ananyev 
30*70581c35SKonstantin Ananyev static alignas(RTE_CACHE_LINE_SIZE) RTE_ATOMIC(uint32_t) wrk_cmd = WRK_CMD_STOP;
31*70581c35SKonstantin Ananyev 
32*70581c35SKonstantin Ananyev /* test run-time in seconds */
33*70581c35SKonstantin Ananyev static const uint32_t run_time = 60;
34*70581c35SKonstantin Ananyev static const uint32_t verbose;
35*70581c35SKonstantin Ananyev 
36*70581c35SKonstantin Ananyev static rte_spinlock_t dump_lock;
37*70581c35SKonstantin Ananyev 
38*70581c35SKonstantin Ananyev struct lcore_op_stat {
39*70581c35SKonstantin Ananyev 	uint64_t nb_lcore;
40*70581c35SKonstantin Ananyev 	uint64_t nb_call;
41*70581c35SKonstantin Ananyev 	uint64_t nb_obj;
42*70581c35SKonstantin Ananyev 	uint64_t nb_cycle;
43*70581c35SKonstantin Ananyev 	uint64_t max_cycle;
44*70581c35SKonstantin Ananyev 	uint64_t min_cycle;
45*70581c35SKonstantin Ananyev };
46*70581c35SKonstantin Ananyev 
47*70581c35SKonstantin Ananyev struct lcore_stat {
48*70581c35SKonstantin Ananyev 	uint64_t nb_cycle;
49*70581c35SKonstantin Ananyev 	struct lcore_op_stat deqenq;
50*70581c35SKonstantin Ananyev 	uint32_t role_mask;
51*70581c35SKonstantin Ananyev 	uint32_t nb_stage;
52*70581c35SKonstantin Ananyev 	struct lcore_op_stat stage[MAX_STAGES];
53*70581c35SKonstantin Ananyev };
54*70581c35SKonstantin Ananyev 
55*70581c35SKonstantin Ananyev #define	ROLE_DEQENQ	RTE_BIT32(0)
56*70581c35SKonstantin Ananyev #define	ROLE_STAGE(n)	RTE_BIT32(n + 1)
57*70581c35SKonstantin Ananyev 
58*70581c35SKonstantin Ananyev struct __rte_cache_aligned lcore_arg {
59*70581c35SKonstantin Ananyev 	struct rte_soring *rng;
60*70581c35SKonstantin Ananyev 	struct lcore_stat stats;
61*70581c35SKonstantin Ananyev };
62*70581c35SKonstantin Ananyev 
63*70581c35SKonstantin Ananyev struct __rte_cache_aligned ring_elem {
64*70581c35SKonstantin Ananyev 	uint32_t cnt[RTE_CACHE_LINE_SIZE / sizeof(uint32_t)];
65*70581c35SKonstantin Ananyev };
66*70581c35SKonstantin Ananyev 
67*70581c35SKonstantin Ananyev /*
68*70581c35SKonstantin Ananyev  * redefinable functions
69*70581c35SKonstantin Ananyev  */
70*70581c35SKonstantin Ananyev 
71*70581c35SKonstantin Ananyev static uint32_t
72*70581c35SKonstantin Ananyev _st_ring_dequeue_burst(struct rte_soring *r, void **obj, uint32_t n,
73*70581c35SKonstantin Ananyev 	uint32_t *avail);
74*70581c35SKonstantin Ananyev 
75*70581c35SKonstantin Ananyev static uint32_t
76*70581c35SKonstantin Ananyev _st_ring_enqueue_bulk(struct rte_soring *r, void * const *obj, uint32_t n,
77*70581c35SKonstantin Ananyev 	uint32_t *free);
78*70581c35SKonstantin Ananyev 
79*70581c35SKonstantin Ananyev static uint32_t
80*70581c35SKonstantin Ananyev _st_ring_acquire_burst(struct rte_soring *r, uint32_t stage, void **obj,
81*70581c35SKonstantin Ananyev 	uint32_t num, uint32_t *token, uint32_t *avail);
82*70581c35SKonstantin Ananyev 
83*70581c35SKonstantin Ananyev static void
84*70581c35SKonstantin Ananyev _st_ring_release(struct rte_soring *r, uint32_t stage, uint32_t token,
85*70581c35SKonstantin Ananyev 	void * const *obj, uint32_t num);
86*70581c35SKonstantin Ananyev 
87*70581c35SKonstantin Ananyev static void
88*70581c35SKonstantin Ananyev lcore_op_stat_update(struct lcore_op_stat *ls, uint64_t call, uint64_t obj,
89*70581c35SKonstantin Ananyev 	uint64_t tm, int32_t prcs)
90*70581c35SKonstantin Ananyev {
91*70581c35SKonstantin Ananyev 	ls->nb_call += call;
92*70581c35SKonstantin Ananyev 	ls->nb_obj += obj;
93*70581c35SKonstantin Ananyev 	ls->nb_cycle += tm;
94*70581c35SKonstantin Ananyev 	if (prcs) {
95*70581c35SKonstantin Ananyev 		ls->max_cycle = RTE_MAX(ls->max_cycle, tm);
96*70581c35SKonstantin Ananyev 		ls->min_cycle = RTE_MIN(ls->min_cycle, tm);
97*70581c35SKonstantin Ananyev 	}
98*70581c35SKonstantin Ananyev }
99*70581c35SKonstantin Ananyev 
100*70581c35SKonstantin Ananyev static void
101*70581c35SKonstantin Ananyev lcore_stat_update(struct lcore_stat *ls, uint64_t call, uint64_t obj,
102*70581c35SKonstantin Ananyev 	uint64_t tm, int32_t prcs)
103*70581c35SKonstantin Ananyev {
104*70581c35SKonstantin Ananyev 	uint32_t i;
105*70581c35SKonstantin Ananyev 
106*70581c35SKonstantin Ananyev 	ls->nb_cycle += tm;
107*70581c35SKonstantin Ananyev 	lcore_op_stat_update(&ls->deqenq, call, obj, tm, prcs);
108*70581c35SKonstantin Ananyev 	for (i = 0; i != ls->nb_stage; i++)
109*70581c35SKonstantin Ananyev 		lcore_op_stat_update(ls->stage + i, call, obj, tm, prcs);
110*70581c35SKonstantin Ananyev }
111*70581c35SKonstantin Ananyev 
112*70581c35SKonstantin Ananyev static void
113*70581c35SKonstantin Ananyev lcore_op_stat_aggr(struct lcore_op_stat *ms, const struct lcore_op_stat *ls)
114*70581c35SKonstantin Ananyev {
115*70581c35SKonstantin Ananyev 	ms->nb_call += ls->nb_call;
116*70581c35SKonstantin Ananyev 	ms->nb_obj += ls->nb_obj;
117*70581c35SKonstantin Ananyev 	ms->nb_cycle += ls->nb_cycle;
118*70581c35SKonstantin Ananyev 	ms->max_cycle = RTE_MAX(ms->max_cycle, ls->max_cycle);
119*70581c35SKonstantin Ananyev 	ms->min_cycle = RTE_MIN(ms->min_cycle, ls->min_cycle);
120*70581c35SKonstantin Ananyev }
121*70581c35SKonstantin Ananyev 
122*70581c35SKonstantin Ananyev static void
123*70581c35SKonstantin Ananyev lcore_stat_aggr(struct lcore_stat *ms, const struct lcore_stat *ls)
124*70581c35SKonstantin Ananyev {
125*70581c35SKonstantin Ananyev 	uint32_t i;
126*70581c35SKonstantin Ananyev 
127*70581c35SKonstantin Ananyev 	ms->nb_cycle = RTE_MAX(ms->nb_cycle, ls->nb_cycle);
128*70581c35SKonstantin Ananyev 	lcore_op_stat_aggr(&ms->deqenq, &ls->deqenq);
129*70581c35SKonstantin Ananyev 	ms->deqenq.nb_lcore += ((ls->role_mask & ROLE_DEQENQ) != 0);
130*70581c35SKonstantin Ananyev 	for (i = 0; i != ms->nb_stage; i++) {
131*70581c35SKonstantin Ananyev 		lcore_op_stat_aggr(ms->stage + i, ls->stage + i);
132*70581c35SKonstantin Ananyev 		ms->stage[i].nb_lcore += ((ls->role_mask & ROLE_STAGE(i)) != 0);
133*70581c35SKonstantin Ananyev 	}
134*70581c35SKonstantin Ananyev }
135*70581c35SKonstantin Ananyev 
136*70581c35SKonstantin Ananyev static void
137*70581c35SKonstantin Ananyev lcore_op_stat_dump(FILE *f, const struct lcore_op_stat *ls, const char *cap,
138*70581c35SKonstantin Ananyev 	long double st)
139*70581c35SKonstantin Ananyev {
140*70581c35SKonstantin Ananyev 	fprintf(f, "\t%s={\n", cap);
141*70581c35SKonstantin Ananyev 
142*70581c35SKonstantin Ananyev 	fprintf(f, "\t\tnb_lcore=%" PRIu64 ",\n", ls->nb_lcore);
143*70581c35SKonstantin Ananyev 	fprintf(f, "\t\tnb_call=%" PRIu64 ",\n", ls->nb_call);
144*70581c35SKonstantin Ananyev 	fprintf(f, "\t\tnb_obj=%" PRIu64 ",\n", ls->nb_obj);
145*70581c35SKonstantin Ananyev 	fprintf(f, "\t\tnb_cycle=%" PRIu64 ",\n", ls->nb_cycle);
146*70581c35SKonstantin Ananyev 	fprintf(f, "\t\tobj/call(avg): %.2Lf\n",
147*70581c35SKonstantin Ananyev 		(long double)ls->nb_obj / ls->nb_call);
148*70581c35SKonstantin Ananyev 	fprintf(f, "\t\tcycles/obj(avg): %.2Lf\n",
149*70581c35SKonstantin Ananyev 		(long double)ls->nb_cycle / ls->nb_obj);
150*70581c35SKonstantin Ananyev 	fprintf(f, "\t\tcycles/call(avg): %.2Lf\n",
151*70581c35SKonstantin Ananyev 		(long double)ls->nb_cycle / ls->nb_call);
152*70581c35SKonstantin Ananyev 
153*70581c35SKonstantin Ananyev 	/* if min/max cycles per call stats was collected */
154*70581c35SKonstantin Ananyev 	if (ls->min_cycle != UINT64_MAX) {
155*70581c35SKonstantin Ananyev 		fprintf(f, "\t\tmax cycles/call=%" PRIu64 "(%.2Lf usec),\n",
156*70581c35SKonstantin Ananyev 			ls->max_cycle,
157*70581c35SKonstantin Ananyev 			(long double)ls->max_cycle / st);
158*70581c35SKonstantin Ananyev 		fprintf(f, "\t\tmin cycles/call=%" PRIu64 "(%.2Lf usec),\n",
159*70581c35SKonstantin Ananyev 			ls->min_cycle,
160*70581c35SKonstantin Ananyev 			(long double)ls->min_cycle / st);
161*70581c35SKonstantin Ananyev 	}
162*70581c35SKonstantin Ananyev 
163*70581c35SKonstantin Ananyev 	fprintf(f, "\t},\n");
164*70581c35SKonstantin Ananyev }
165*70581c35SKonstantin Ananyev 
166*70581c35SKonstantin Ananyev static void
167*70581c35SKonstantin Ananyev lcore_stat_dump(FILE *f, uint32_t lc, const struct lcore_stat *ls)
168*70581c35SKonstantin Ananyev {
169*70581c35SKonstantin Ananyev 	uint32_t i;
170*70581c35SKonstantin Ananyev 	long double st;
171*70581c35SKonstantin Ananyev 	char cap[64];
172*70581c35SKonstantin Ananyev 
173*70581c35SKonstantin Ananyev 	st = (long double)rte_get_timer_hz() / US_PER_S;
174*70581c35SKonstantin Ananyev 
175*70581c35SKonstantin Ananyev 	if (lc == UINT32_MAX)
176*70581c35SKonstantin Ananyev 		fprintf(f, "%s(AGGREGATE)={\n", __func__);
177*70581c35SKonstantin Ananyev 	else
178*70581c35SKonstantin Ananyev 		fprintf(f, "%s(lcore=%u)={\n", __func__, lc);
179*70581c35SKonstantin Ananyev 
180*70581c35SKonstantin Ananyev 	fprintf(f, "\tnb_cycle=%" PRIu64 "(%.2Lf usec),\n",
181*70581c35SKonstantin Ananyev 		ls->nb_cycle, (long double)ls->nb_cycle / st);
182*70581c35SKonstantin Ananyev 
183*70581c35SKonstantin Ananyev 	lcore_op_stat_dump(f, &ls->deqenq, "DEQ+ENQ", st);
184*70581c35SKonstantin Ananyev 	for (i = 0; i != ls->nb_stage; i++) {
185*70581c35SKonstantin Ananyev 		snprintf(cap, sizeof(cap), "%s#%u", "STAGE", i);
186*70581c35SKonstantin Ananyev 		lcore_op_stat_dump(f, ls->stage + i, cap, st);
187*70581c35SKonstantin Ananyev 	}
188*70581c35SKonstantin Ananyev 
189*70581c35SKonstantin Ananyev 	fprintf(f, "};\n");
190*70581c35SKonstantin Ananyev }
191*70581c35SKonstantin Ananyev 
192*70581c35SKonstantin Ananyev static void
193*70581c35SKonstantin Ananyev fill_ring_elm(struct ring_elem *elm, uint32_t fill)
194*70581c35SKonstantin Ananyev {
195*70581c35SKonstantin Ananyev 	uint32_t i;
196*70581c35SKonstantin Ananyev 
197*70581c35SKonstantin Ananyev 	for (i = 0; i != RTE_DIM(elm->cnt); i++)
198*70581c35SKonstantin Ananyev 		elm->cnt[i] = fill;
199*70581c35SKonstantin Ananyev }
200*70581c35SKonstantin Ananyev 
201*70581c35SKonstantin Ananyev static int32_t
202*70581c35SKonstantin Ananyev check_updt_elem(struct ring_elem *elm[], uint32_t num,
203*70581c35SKonstantin Ananyev 	const struct ring_elem *check, const struct ring_elem *fill,
204*70581c35SKonstantin Ananyev 	const char *fname, const char *opname, const struct rte_soring *sor)
205*70581c35SKonstantin Ananyev {
206*70581c35SKonstantin Ananyev 	uint32_t i;
207*70581c35SKonstantin Ananyev 
208*70581c35SKonstantin Ananyev 	for (i = 0; i != num; i++) {
209*70581c35SKonstantin Ananyev 		if (memcmp(check, elm[i], sizeof(*check)) != 0) {
210*70581c35SKonstantin Ananyev 			rte_spinlock_lock(&dump_lock);
211*70581c35SKonstantin Ananyev 			printf("%s:%s: %s(lc=%u, num=%u) failed at %u-th iter, "
212*70581c35SKonstantin Ananyev 				"offending object: %p\n",
213*70581c35SKonstantin Ananyev 				fname, opname, __func__, rte_lcore_id(), num, i,
214*70581c35SKonstantin Ananyev 				elm[i]);
215*70581c35SKonstantin Ananyev 			rte_memdump(stdout, "expected", check, sizeof(*check));
216*70581c35SKonstantin Ananyev 			rte_memdump(stdout, "result", elm[i], sizeof(*elm[i]));
217*70581c35SKonstantin Ananyev 			rte_soring_dump(stdout, sor);
218*70581c35SKonstantin Ananyev 			rte_spinlock_unlock(&dump_lock);
219*70581c35SKonstantin Ananyev 			return -EINVAL;
220*70581c35SKonstantin Ananyev 		}
221*70581c35SKonstantin Ananyev 		memcpy(elm[i], fill, sizeof(*elm[i]));
222*70581c35SKonstantin Ananyev 	}
223*70581c35SKonstantin Ananyev 
224*70581c35SKonstantin Ananyev 	return 0;
225*70581c35SKonstantin Ananyev }
226*70581c35SKonstantin Ananyev 
227*70581c35SKonstantin Ananyev static int
228*70581c35SKonstantin Ananyev check_ring_op(uint32_t exp, uint32_t res, uint32_t lc,
229*70581c35SKonstantin Ananyev 	enum rte_ring_queue_behavior bhv, const char *fname, const char *opname,
230*70581c35SKonstantin Ananyev 	const struct rte_soring *sor)
231*70581c35SKonstantin Ananyev {
232*70581c35SKonstantin Ananyev 	if ((bhv == RTE_RING_QUEUE_FIXED && exp != res) ||
233*70581c35SKonstantin Ananyev 			(bhv == RTE_RING_QUEUE_VARIABLE && exp < res)) {
234*70581c35SKonstantin Ananyev 		rte_spinlock_lock(&dump_lock);
235*70581c35SKonstantin Ananyev 		printf("%s(lc=%u) failure: %s expected: %u, returned %u\n",
236*70581c35SKonstantin Ananyev 			fname, lc, opname, exp, res);
237*70581c35SKonstantin Ananyev 		rte_soring_dump(stdout, sor);
238*70581c35SKonstantin Ananyev 		rte_spinlock_unlock(&dump_lock);
239*70581c35SKonstantin Ananyev 		return -ENOSPC;
240*70581c35SKonstantin Ananyev 	}
241*70581c35SKonstantin Ananyev 	return 0;
242*70581c35SKonstantin Ananyev }
243*70581c35SKonstantin Ananyev 
244*70581c35SKonstantin Ananyev /* num in interval [7/8, 11/8] of BULK_NUM */
245*70581c35SKonstantin Ananyev static inline uint32_t
246*70581c35SKonstantin Ananyev rand_elem_num(void)
247*70581c35SKonstantin Ananyev {
248*70581c35SKonstantin Ananyev 	uint32_t num;
249*70581c35SKonstantin Ananyev 
250*70581c35SKonstantin Ananyev 	num = 7 * BULK_NUM / 8 + rte_rand() % (BULK_NUM / 2);
251*70581c35SKonstantin Ananyev 	return num;
252*70581c35SKonstantin Ananyev }
253*70581c35SKonstantin Ananyev 
254*70581c35SKonstantin Ananyev /*
255*70581c35SKonstantin Ananyev  * for each enabled stage do:
256*70581c35SKonstantin Ananyev  *   acquire burst of objects
257*70581c35SKonstantin Ananyev  *   read and check their contents
258*70581c35SKonstantin Ananyev  *   update and check their contents
259*70581c35SKonstantin Ananyev  *   release burst of objects
260*70581c35SKonstantin Ananyev  * done
261*70581c35SKonstantin Ananyev  */
262*70581c35SKonstantin Ananyev static int32_t
263*70581c35SKonstantin Ananyev test_worker_stages(struct lcore_arg *la, uint32_t lc, const char *fname,
264*70581c35SKonstantin Ananyev 	struct ring_elem *obj[2 * BULK_NUM],
265*70581c35SKonstantin Ananyev 	const struct ring_elem *def_elm, const struct ring_elem *loc_elm,
266*70581c35SKonstantin Ananyev 	const struct ring_elem stg_elm[MAX_STAGES], int32_t prcs)
267*70581c35SKonstantin Ananyev {
268*70581c35SKonstantin Ananyev 	int32_t rc;
269*70581c35SKonstantin Ananyev 	uint32_t i, n, num, tkn;
270*70581c35SKonstantin Ananyev 	uint64_t tm0, tm1;
271*70581c35SKonstantin Ananyev 	const struct ring_elem *celm, *pelm;
272*70581c35SKonstantin Ananyev 
273*70581c35SKonstantin Ananyev 	num = rand_elem_num();
274*70581c35SKonstantin Ananyev 
275*70581c35SKonstantin Ananyev 	rc = 0;
276*70581c35SKonstantin Ananyev 	tkn = 0;
277*70581c35SKonstantin Ananyev 	for (i = 0, pelm = def_elm; i != la->stats.nb_stage; pelm = celm, i++) {
278*70581c35SKonstantin Ananyev 
279*70581c35SKonstantin Ananyev 		celm = stg_elm + i;
280*70581c35SKonstantin Ananyev 
281*70581c35SKonstantin Ananyev 		/* given stage is not enabled on that lcore */
282*70581c35SKonstantin Ananyev 		if ((la->stats.role_mask & ROLE_STAGE(i)) == 0)
283*70581c35SKonstantin Ananyev 			continue;
284*70581c35SKonstantin Ananyev 
285*70581c35SKonstantin Ananyev 		/* reset all pointer values */
286*70581c35SKonstantin Ananyev 		memset(obj, 0, sizeof(*obj) * num);
287*70581c35SKonstantin Ananyev 
288*70581c35SKonstantin Ananyev 		/* acquire num elems */
289*70581c35SKonstantin Ananyev 		tm0 = (prcs != 0) ? rte_rdtsc_precise() : 0;
290*70581c35SKonstantin Ananyev 		n = _st_ring_acquire_burst(la->rng, i, (void **)obj, num,
291*70581c35SKonstantin Ananyev 				&tkn, NULL);
292*70581c35SKonstantin Ananyev 		tm0 = (prcs != 0) ? rte_rdtsc_precise() - tm0 : 0;
293*70581c35SKonstantin Ananyev 
294*70581c35SKonstantin Ananyev 		/* check return value and objects */
295*70581c35SKonstantin Ananyev 		rc = check_ring_op(num, n, lc, RTE_RING_QUEUE_VARIABLE, fname,
296*70581c35SKonstantin Ananyev 			RTE_STR(_st_ring_stage_acquire), la->rng);
297*70581c35SKonstantin Ananyev 		if (rc == 0)
298*70581c35SKonstantin Ananyev 			rc = check_updt_elem(obj, n, pelm, loc_elm, fname,
299*70581c35SKonstantin Ananyev 				RTE_STR(_st_ring_stage_acquire), la->rng);
300*70581c35SKonstantin Ananyev 		if (rc != 0)
301*70581c35SKonstantin Ananyev 			break;
302*70581c35SKonstantin Ananyev 
303*70581c35SKonstantin Ananyev 		/* release num elems */
304*70581c35SKonstantin Ananyev 		rte_compiler_barrier();
305*70581c35SKonstantin Ananyev 		rc = check_updt_elem(obj, n, loc_elm, celm, fname,
306*70581c35SKonstantin Ananyev 			RTE_STR(_st_ring_stage_release), la->rng);
307*70581c35SKonstantin Ananyev 		if (rc != 0)
308*70581c35SKonstantin Ananyev 			break;
309*70581c35SKonstantin Ananyev 
310*70581c35SKonstantin Ananyev 		if (n == 0)
311*70581c35SKonstantin Ananyev 			tm1 = 0;
312*70581c35SKonstantin Ananyev 		else {
313*70581c35SKonstantin Ananyev 			tm1 = (prcs != 0) ? rte_rdtsc_precise() : 0;
314*70581c35SKonstantin Ananyev 			_st_ring_release(la->rng, i, tkn,
315*70581c35SKonstantin Ananyev 					(void **)obj, n);
316*70581c35SKonstantin Ananyev 			tm1 = (prcs != 0) ? rte_rdtsc_precise() - tm1 : 0;
317*70581c35SKonstantin Ananyev 		}
318*70581c35SKonstantin Ananyev 		lcore_op_stat_update(la->stats.stage + i, 1, n, tm0 + tm1,
319*70581c35SKonstantin Ananyev 				prcs);
320*70581c35SKonstantin Ananyev 	}
321*70581c35SKonstantin Ananyev 
322*70581c35SKonstantin Ananyev 	return rc;
323*70581c35SKonstantin Ananyev }
324*70581c35SKonstantin Ananyev 
325*70581c35SKonstantin Ananyev static int32_t
326*70581c35SKonstantin Ananyev test_worker_deqenq(struct lcore_arg *la, uint32_t lc, const char *fname,
327*70581c35SKonstantin Ananyev 	struct ring_elem *obj[2 * BULK_NUM],
328*70581c35SKonstantin Ananyev 	const struct ring_elem *def_elm, const struct ring_elem *loc_elm,
329*70581c35SKonstantin Ananyev 	const struct ring_elem *pelm, int32_t prcs)
330*70581c35SKonstantin Ananyev {
331*70581c35SKonstantin Ananyev 	int32_t rc;
332*70581c35SKonstantin Ananyev 	uint32_t k, n, num;
333*70581c35SKonstantin Ananyev 	uint64_t tm0, tm1;
334*70581c35SKonstantin Ananyev 
335*70581c35SKonstantin Ananyev 	num = rand_elem_num();
336*70581c35SKonstantin Ananyev 
337*70581c35SKonstantin Ananyev 	/* reset all pointer values */
338*70581c35SKonstantin Ananyev 	memset(obj, 0, sizeof(*obj) * num);
339*70581c35SKonstantin Ananyev 
340*70581c35SKonstantin Ananyev 	/* dequeue num elems */
341*70581c35SKonstantin Ananyev 	tm0 = (prcs != 0) ? rte_rdtsc_precise() : 0;
342*70581c35SKonstantin Ananyev 	n = _st_ring_dequeue_burst(la->rng, (void **)obj, num, NULL);
343*70581c35SKonstantin Ananyev 
344*70581c35SKonstantin Ananyev 	tm0 = (prcs != 0) ? rte_rdtsc_precise() - tm0 : 0;
345*70581c35SKonstantin Ananyev 
346*70581c35SKonstantin Ananyev 	/* check return value and objects */
347*70581c35SKonstantin Ananyev 	rc = check_ring_op(num, n, lc, RTE_RING_QUEUE_VARIABLE, fname,
348*70581c35SKonstantin Ananyev 			RTE_STR(_st_ring_dequeue_bulk), la->rng);
349*70581c35SKonstantin Ananyev 	if (rc == 0)
350*70581c35SKonstantin Ananyev 		rc = check_updt_elem(obj, n, pelm, loc_elm, fname,
351*70581c35SKonstantin Ananyev 			RTE_STR(_st_ring_dequeue_bulk), la->rng);
352*70581c35SKonstantin Ananyev 	if (rc != 0)
353*70581c35SKonstantin Ananyev 		return rc;
354*70581c35SKonstantin Ananyev 
355*70581c35SKonstantin Ananyev 	/* enqueue n elems */
356*70581c35SKonstantin Ananyev 	rte_compiler_barrier();
357*70581c35SKonstantin Ananyev 	rc = check_updt_elem(obj, n, loc_elm, def_elm, fname,
358*70581c35SKonstantin Ananyev 		RTE_STR(_st_ring_enqueue_bulk), la->rng);
359*70581c35SKonstantin Ananyev 	if (rc != 0)
360*70581c35SKonstantin Ananyev 		return rc;
361*70581c35SKonstantin Ananyev 
362*70581c35SKonstantin Ananyev 	tm1 = (prcs != 0) ? rte_rdtsc_precise() : 0;
363*70581c35SKonstantin Ananyev 	k = _st_ring_enqueue_bulk(la->rng, (void **)obj, n, NULL);
364*70581c35SKonstantin Ananyev 	tm1 = (prcs != 0) ? rte_rdtsc_precise() - tm1 : 0;
365*70581c35SKonstantin Ananyev 
366*70581c35SKonstantin Ananyev 	/* check return value */
367*70581c35SKonstantin Ananyev 	rc = check_ring_op(n, k, lc, RTE_RING_QUEUE_FIXED, fname,
368*70581c35SKonstantin Ananyev 			RTE_STR(_st_ring_enqueue_bulk), la->rng);
369*70581c35SKonstantin Ananyev 	if (rc != 0)
370*70581c35SKonstantin Ananyev 		return rc;
371*70581c35SKonstantin Ananyev 
372*70581c35SKonstantin Ananyev 	lcore_op_stat_update(&la->stats.deqenq, 1, n, tm0 + tm1, prcs);
373*70581c35SKonstantin Ananyev 	return 0;
374*70581c35SKonstantin Ananyev }
375*70581c35SKonstantin Ananyev 
376*70581c35SKonstantin Ananyev static int
377*70581c35SKonstantin Ananyev test_worker(void *arg, const char *fname, int32_t prcs)
378*70581c35SKonstantin Ananyev {
379*70581c35SKonstantin Ananyev 	int32_t rc;
380*70581c35SKonstantin Ananyev 	uint32_t i, lc;
381*70581c35SKonstantin Ananyev 	uint64_t cl;
382*70581c35SKonstantin Ananyev 	struct lcore_arg *la;
383*70581c35SKonstantin Ananyev 	struct ring_elem *obj[2 * BULK_NUM];
384*70581c35SKonstantin Ananyev 	struct ring_elem *pelm, def_elm, loc_elm, stg_elm[MAX_STAGES];
385*70581c35SKonstantin Ananyev 
386*70581c35SKonstantin Ananyev 	la = arg;
387*70581c35SKonstantin Ananyev 	lc = rte_lcore_id();
388*70581c35SKonstantin Ananyev 
389*70581c35SKonstantin Ananyev 	fill_ring_elm(&def_elm, UINT32_MAX);
390*70581c35SKonstantin Ananyev 	fill_ring_elm(&loc_elm, lc);
391*70581c35SKonstantin Ananyev 
392*70581c35SKonstantin Ananyev 	for (i = 0; i != RTE_DIM(stg_elm); i++)
393*70581c35SKonstantin Ananyev 		fill_ring_elm(stg_elm + i, (i + 1) << 24);
394*70581c35SKonstantin Ananyev 
395*70581c35SKonstantin Ananyev 	pelm = stg_elm + la->stats.nb_stage - 1;
396*70581c35SKonstantin Ananyev 
397*70581c35SKonstantin Ananyev 	/* Acquire ordering is not required as the main is not
398*70581c35SKonstantin Ananyev 	 * really releasing any data through 'wrk_cmd' to
399*70581c35SKonstantin Ananyev 	 * the worker.
400*70581c35SKonstantin Ananyev 	 */
401*70581c35SKonstantin Ananyev 	while (rte_atomic_load_explicit(&wrk_cmd, rte_memory_order_relaxed) !=
402*70581c35SKonstantin Ananyev 			WRK_CMD_RUN)
403*70581c35SKonstantin Ananyev 		rte_pause();
404*70581c35SKonstantin Ananyev 
405*70581c35SKonstantin Ananyev 	cl = rte_rdtsc_precise();
406*70581c35SKonstantin Ananyev 
407*70581c35SKonstantin Ananyev 	do {
408*70581c35SKonstantin Ananyev 		if ((la->stats.role_mask & ~ROLE_DEQENQ) != 0) {
409*70581c35SKonstantin Ananyev 			rc = test_worker_stages(la, lc, fname, obj,
410*70581c35SKonstantin Ananyev 				&def_elm, &loc_elm, stg_elm, prcs);
411*70581c35SKonstantin Ananyev 			if (rc != 0)
412*70581c35SKonstantin Ananyev 				break;
413*70581c35SKonstantin Ananyev 		}
414*70581c35SKonstantin Ananyev 
415*70581c35SKonstantin Ananyev 		if ((la->stats.role_mask & ROLE_DEQENQ) != 0) {
416*70581c35SKonstantin Ananyev 			rc = test_worker_deqenq(la, lc, fname, obj,
417*70581c35SKonstantin Ananyev 				&def_elm, &loc_elm, pelm, prcs);
418*70581c35SKonstantin Ananyev 			if (rc != 0)
419*70581c35SKonstantin Ananyev 				break;
420*70581c35SKonstantin Ananyev 		}
421*70581c35SKonstantin Ananyev 
422*70581c35SKonstantin Ananyev 	} while (rte_atomic_load_explicit(&wrk_cmd,
423*70581c35SKonstantin Ananyev 				rte_memory_order_relaxed) == WRK_CMD_RUN);
424*70581c35SKonstantin Ananyev 
425*70581c35SKonstantin Ananyev 	cl = rte_rdtsc_precise() - cl;
426*70581c35SKonstantin Ananyev 	if (prcs == 0)
427*70581c35SKonstantin Ananyev 		lcore_stat_update(&la->stats, 0, 0, cl, 0);
428*70581c35SKonstantin Ananyev 	la->stats.nb_cycle = cl;
429*70581c35SKonstantin Ananyev 	return rc;
430*70581c35SKonstantin Ananyev }
431*70581c35SKonstantin Ananyev static int
432*70581c35SKonstantin Ananyev test_worker_prcs(void *arg)
433*70581c35SKonstantin Ananyev {
434*70581c35SKonstantin Ananyev 	return test_worker(arg, __func__, 1);
435*70581c35SKonstantin Ananyev }
436*70581c35SKonstantin Ananyev 
437*70581c35SKonstantin Ananyev static int
438*70581c35SKonstantin Ananyev test_worker_avg(void *arg)
439*70581c35SKonstantin Ananyev {
440*70581c35SKonstantin Ananyev 	return test_worker(arg, __func__, 0);
441*70581c35SKonstantin Ananyev }
442*70581c35SKonstantin Ananyev 
443*70581c35SKonstantin Ananyev static void
444*70581c35SKonstantin Ananyev mt1_fini(struct rte_soring *rng, void *data)
445*70581c35SKonstantin Ananyev {
446*70581c35SKonstantin Ananyev 	rte_free(rng);
447*70581c35SKonstantin Ananyev 	rte_free(data);
448*70581c35SKonstantin Ananyev }
449*70581c35SKonstantin Ananyev 
450*70581c35SKonstantin Ananyev static int
451*70581c35SKonstantin Ananyev mt1_init(struct rte_soring **rng, void **data, uint32_t num,
452*70581c35SKonstantin Ananyev 	enum rte_ring_sync_type prod_synt, enum rte_ring_sync_type cons_synt,
453*70581c35SKonstantin Ananyev 	uint32_t nb_stages)
454*70581c35SKonstantin Ananyev {
455*70581c35SKonstantin Ananyev 	int32_t rc;
456*70581c35SKonstantin Ananyev 	size_t sz;
457*70581c35SKonstantin Ananyev 	uint32_t i;
458*70581c35SKonstantin Ananyev 	struct rte_soring *r;
459*70581c35SKonstantin Ananyev 	struct ring_elem *elm;
460*70581c35SKonstantin Ananyev 	void *p;
461*70581c35SKonstantin Ananyev 	struct rte_soring_param prm;
462*70581c35SKonstantin Ananyev 
463*70581c35SKonstantin Ananyev 	*rng = NULL;
464*70581c35SKonstantin Ananyev 	*data = NULL;
465*70581c35SKonstantin Ananyev 
466*70581c35SKonstantin Ananyev 	sz = num * sizeof(*elm);
467*70581c35SKonstantin Ananyev 	elm = rte_zmalloc(NULL, sz, alignof(typeof(*elm)));
468*70581c35SKonstantin Ananyev 	if (elm == NULL) {
469*70581c35SKonstantin Ananyev 		printf("%s: alloc(%zu) for %u elems data failed",
470*70581c35SKonstantin Ananyev 			__func__, sz, num);
471*70581c35SKonstantin Ananyev 		return -ENOMEM;
472*70581c35SKonstantin Ananyev 	}
473*70581c35SKonstantin Ananyev 
474*70581c35SKonstantin Ananyev 	*data = elm;
475*70581c35SKonstantin Ananyev 
476*70581c35SKonstantin Ananyev 	/* alloc soring */
477*70581c35SKonstantin Ananyev 	memset(&prm, 0, sizeof(prm));
478*70581c35SKonstantin Ananyev 
479*70581c35SKonstantin Ananyev 	prm.name = __func__;
480*70581c35SKonstantin Ananyev 	prm.elems = num;
481*70581c35SKonstantin Ananyev 	prm.elem_size = sizeof(uintptr_t);
482*70581c35SKonstantin Ananyev 	prm.stages = nb_stages;
483*70581c35SKonstantin Ananyev 	prm.prod_synt = prod_synt;
484*70581c35SKonstantin Ananyev 	prm.cons_synt = cons_synt;
485*70581c35SKonstantin Ananyev 
486*70581c35SKonstantin Ananyev 	sz = rte_soring_get_memsize(&prm);
487*70581c35SKonstantin Ananyev 	r = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);
488*70581c35SKonstantin Ananyev 	if (r == NULL) {
489*70581c35SKonstantin Ananyev 		printf("%s: alloc(%zu) for FIFO with %u elems failed",
490*70581c35SKonstantin Ananyev 			__func__, sz, prm.elems);
491*70581c35SKonstantin Ananyev 		return -ENOMEM;
492*70581c35SKonstantin Ananyev 	}
493*70581c35SKonstantin Ananyev 
494*70581c35SKonstantin Ananyev 	*rng = r;
495*70581c35SKonstantin Ananyev 
496*70581c35SKonstantin Ananyev 	rc = rte_soring_init(r, &prm);
497*70581c35SKonstantin Ananyev 	if (rc != 0) {
498*70581c35SKonstantin Ananyev 		printf("%s: rte_soring_init(r=%p,elems=%u,stages=%u) failed, "
499*70581c35SKonstantin Ananyev 			"error: %d(%s)\n",
500*70581c35SKonstantin Ananyev 			__func__, r, prm.elems, prm.stages, rc, strerror(-rc));
501*70581c35SKonstantin Ananyev 		return rc;
502*70581c35SKonstantin Ananyev 	}
503*70581c35SKonstantin Ananyev 
504*70581c35SKonstantin Ananyev 	for (i = 0; i != num; i++) {
505*70581c35SKonstantin Ananyev 		fill_ring_elm(elm + i, UINT32_MAX);
506*70581c35SKonstantin Ananyev 		p = elm + i;
507*70581c35SKonstantin Ananyev 		if (_st_ring_enqueue_bulk(r, &p, 1, NULL) != 1)
508*70581c35SKonstantin Ananyev 			break;
509*70581c35SKonstantin Ananyev 	}
510*70581c35SKonstantin Ananyev 
511*70581c35SKonstantin Ananyev 	if (i != num) {
512*70581c35SKonstantin Ananyev 		printf("%s: _st_ring_enqueue(%p, %u) returned %u\n",
513*70581c35SKonstantin Ananyev 			__func__, r, num, i);
514*70581c35SKonstantin Ananyev 		return -ENOSPC;
515*70581c35SKonstantin Ananyev 	}
516*70581c35SKonstantin Ananyev 
517*70581c35SKonstantin Ananyev 	return 0;
518*70581c35SKonstantin Ananyev }
519*70581c35SKonstantin Ananyev 
520*70581c35SKonstantin Ananyev static int
521*70581c35SKonstantin Ananyev test_mt(int (*test)(void *), enum rte_ring_sync_type prod_synt,
522*70581c35SKonstantin Ananyev 	enum rte_ring_sync_type cons_synt, uint32_t nb_stage,
523*70581c35SKonstantin Ananyev 	const uint32_t role_mask[RTE_MAX_LCORE])
524*70581c35SKonstantin Ananyev {
525*70581c35SKonstantin Ananyev 	int32_t rc;
526*70581c35SKonstantin Ananyev 	uint32_t i, lc, mc;
527*70581c35SKonstantin Ananyev 	struct rte_soring *r;
528*70581c35SKonstantin Ananyev 	void *data;
529*70581c35SKonstantin Ananyev 	struct lcore_arg arg[RTE_MAX_LCORE];
530*70581c35SKonstantin Ananyev 
531*70581c35SKonstantin Ananyev 	static const struct lcore_op_stat init_stat = {
532*70581c35SKonstantin Ananyev 		.min_cycle = UINT64_MAX,
533*70581c35SKonstantin Ananyev 	};
534*70581c35SKonstantin Ananyev 
535*70581c35SKonstantin Ananyev 	rc = mt1_init(&r, &data, RING_SIZE, prod_synt, cons_synt, nb_stage);
536*70581c35SKonstantin Ananyev 
537*70581c35SKonstantin Ananyev 	if (rc != 0) {
538*70581c35SKonstantin Ananyev 		mt1_fini(r, data);
539*70581c35SKonstantin Ananyev 		return rc;
540*70581c35SKonstantin Ananyev 	}
541*70581c35SKonstantin Ananyev 
542*70581c35SKonstantin Ananyev 	memset(arg, 0, sizeof(arg));
543*70581c35SKonstantin Ananyev 
544*70581c35SKonstantin Ananyev 	/* launch on all workers */
545*70581c35SKonstantin Ananyev 	RTE_LCORE_FOREACH_WORKER(lc) {
546*70581c35SKonstantin Ananyev 		arg[lc].rng = r;
547*70581c35SKonstantin Ananyev 		arg[lc].stats.deqenq = init_stat;
548*70581c35SKonstantin Ananyev 		arg[lc].stats.nb_stage = nb_stage;
549*70581c35SKonstantin Ananyev 		arg[lc].stats.role_mask = role_mask[lc];
550*70581c35SKonstantin Ananyev 		for (i = 0; i != arg[lc].stats.nb_stage; i++)
551*70581c35SKonstantin Ananyev 			arg[lc].stats.stage[i] = init_stat;
552*70581c35SKonstantin Ananyev 		rte_eal_remote_launch(test, &arg[lc], lc);
553*70581c35SKonstantin Ananyev 	}
554*70581c35SKonstantin Ananyev 
555*70581c35SKonstantin Ananyev 	/* signal workers to start test */
556*70581c35SKonstantin Ananyev 	rte_atomic_store_explicit(&wrk_cmd, WRK_CMD_RUN,
557*70581c35SKonstantin Ananyev 			rte_memory_order_release);
558*70581c35SKonstantin Ananyev 
559*70581c35SKonstantin Ananyev 	rte_delay_us(run_time * US_PER_S);
560*70581c35SKonstantin Ananyev 
561*70581c35SKonstantin Ananyev 	/* signal workers to stop test */
562*70581c35SKonstantin Ananyev 	rte_atomic_store_explicit(&wrk_cmd, WRK_CMD_STOP,
563*70581c35SKonstantin Ananyev 			rte_memory_order_release);
564*70581c35SKonstantin Ananyev 
565*70581c35SKonstantin Ananyev 	/* wait for workers and collect stats. */
566*70581c35SKonstantin Ananyev 	mc = rte_lcore_id();
567*70581c35SKonstantin Ananyev 	arg[mc].stats.deqenq = init_stat;
568*70581c35SKonstantin Ananyev 	arg[mc].stats.nb_stage = nb_stage;
569*70581c35SKonstantin Ananyev 	for (i = 0; i != arg[mc].stats.nb_stage; i++)
570*70581c35SKonstantin Ananyev 		arg[mc].stats.stage[i] = init_stat;
571*70581c35SKonstantin Ananyev 
572*70581c35SKonstantin Ananyev 	rc = 0;
573*70581c35SKonstantin Ananyev 	RTE_LCORE_FOREACH_WORKER(lc) {
574*70581c35SKonstantin Ananyev 		rc |= rte_eal_wait_lcore(lc);
575*70581c35SKonstantin Ananyev 		lcore_stat_aggr(&arg[mc].stats, &arg[lc].stats);
576*70581c35SKonstantin Ananyev 		if (verbose != 0)
577*70581c35SKonstantin Ananyev 			lcore_stat_dump(stdout, lc, &arg[lc].stats);
578*70581c35SKonstantin Ananyev 	}
579*70581c35SKonstantin Ananyev 
580*70581c35SKonstantin Ananyev 	lcore_stat_dump(stdout, UINT32_MAX, &arg[mc].stats);
581*70581c35SKonstantin Ananyev 	rte_soring_dump(stdout, r);
582*70581c35SKonstantin Ananyev 	mt1_fini(r, data);
583*70581c35SKonstantin Ananyev 	return rc;
584*70581c35SKonstantin Ananyev }
585*70581c35SKonstantin Ananyev 
586*70581c35SKonstantin Ananyev /*
587*70581c35SKonstantin Ananyev  * launch all stages and deq+enq on all worker lcores
588*70581c35SKonstantin Ananyev  */
589*70581c35SKonstantin Ananyev static void
590*70581c35SKonstantin Ananyev role_mask_sym(uint32_t nb_stage, uint32_t role_mask[RTE_MAX_LCORE])
591*70581c35SKonstantin Ananyev {
592*70581c35SKonstantin Ananyev 	uint32_t lc;
593*70581c35SKonstantin Ananyev 	const uint32_t msk =  RTE_BIT32(nb_stage + 2) - 1;
594*70581c35SKonstantin Ananyev 
595*70581c35SKonstantin Ananyev 	memset(role_mask, 0, sizeof(role_mask[0]) * RTE_MAX_LCORE);
596*70581c35SKonstantin Ananyev 	RTE_LCORE_FOREACH_WORKER(lc)
597*70581c35SKonstantin Ananyev 		role_mask[lc] = msk;
598*70581c35SKonstantin Ananyev }
599*70581c35SKonstantin Ananyev 
600*70581c35SKonstantin Ananyev /*
601*70581c35SKonstantin Ananyev  * Divide all workers in two (nearly) equal groups:
602*70581c35SKonstantin Ananyev  * - workers from 'even' group do deque+enque
603*70581c35SKonstantin Ananyev  * - workers from 'odd' group do acquire/release (for all stages)
604*70581c35SKonstantin Ananyev  */
605*70581c35SKonstantin Ananyev static void
606*70581c35SKonstantin Ananyev role_mask_even_odd(uint32_t nb_stage, uint32_t role_mask[RTE_MAX_LCORE])
607*70581c35SKonstantin Ananyev {
608*70581c35SKonstantin Ananyev 	uint32_t i, lc;
609*70581c35SKonstantin Ananyev 	const uint32_t msk[2] = {
610*70581c35SKonstantin Ananyev 		[0] = ROLE_DEQENQ,
611*70581c35SKonstantin Ananyev 		[1] =  RTE_GENMASK32(nb_stage + 1, 1),
612*70581c35SKonstantin Ananyev 	};
613*70581c35SKonstantin Ananyev 
614*70581c35SKonstantin Ananyev 	memset(role_mask, 0, sizeof(role_mask[0]) * RTE_MAX_LCORE);
615*70581c35SKonstantin Ananyev 
616*70581c35SKonstantin Ananyev 	i = 0;
617*70581c35SKonstantin Ananyev 	RTE_LCORE_FOREACH_WORKER(lc) {
618*70581c35SKonstantin Ananyev 		role_mask[lc] = msk[i & 1];
619*70581c35SKonstantin Ananyev 		i++;
620*70581c35SKonstantin Ananyev 	}
621*70581c35SKonstantin Ananyev 	if (i == 1) {
622*70581c35SKonstantin Ananyev 		lc = rte_get_next_lcore(-1, 1, 0);
623*70581c35SKonstantin Ananyev 		role_mask[lc] |= msk[i & 1];
624*70581c35SKonstantin Ananyev 	}
625*70581c35SKonstantin Ananyev }
626*70581c35SKonstantin Ananyev 
627*70581c35SKonstantin Ananyev /*
628*70581c35SKonstantin Ananyev  * Divide all workers (nearly) evenly among all possible stages
629*70581c35SKonstantin Ananyev  */
630*70581c35SKonstantin Ananyev static void
631*70581c35SKonstantin Ananyev role_mask_div(uint32_t nb_stage, uint32_t role_mask[RTE_MAX_LCORE])
632*70581c35SKonstantin Ananyev {
633*70581c35SKonstantin Ananyev 	uint32_t i, lc;
634*70581c35SKonstantin Ananyev 	uint32_t msk[nb_stage + 1];
635*70581c35SKonstantin Ananyev 
636*70581c35SKonstantin Ananyev 	memset(role_mask, 0, sizeof(role_mask[0]) * RTE_MAX_LCORE);
637*70581c35SKonstantin Ananyev 
638*70581c35SKonstantin Ananyev 	for (i = 0; i != RTE_DIM(msk); i++) {
639*70581c35SKonstantin Ananyev 		msk[i] = RTE_BIT32(i);
640*70581c35SKonstantin Ananyev 	};
641*70581c35SKonstantin Ananyev 
642*70581c35SKonstantin Ananyev 	i = 0;
643*70581c35SKonstantin Ananyev 	RTE_LCORE_FOREACH_WORKER(lc) {
644*70581c35SKonstantin Ananyev 		role_mask[lc] = msk[i % RTE_DIM(msk)];
645*70581c35SKonstantin Ananyev 		i++;
646*70581c35SKonstantin Ananyev 	}
647*70581c35SKonstantin Ananyev 	if (i < RTE_DIM(msk)) {
648*70581c35SKonstantin Ananyev 		lc = rte_get_next_lcore(-1, 1, 0);
649*70581c35SKonstantin Ananyev 		for (; i != RTE_DIM(msk); i++)
650*70581c35SKonstantin Ananyev 			role_mask[lc] |= msk[i % RTE_DIM(msk)];
651*70581c35SKonstantin Ananyev 	}
652*70581c35SKonstantin Ananyev }
653*70581c35SKonstantin Ananyev 
654*70581c35SKonstantin Ananyev /*
655*70581c35SKonstantin Ananyev  * one worker does ST enqueue+dequeue, while all others - stages processing.
656*70581c35SKonstantin Ananyev  */
657*70581c35SKonstantin Ananyev static void
658*70581c35SKonstantin Ananyev role_mask_denq_st(uint32_t nb_stage, uint32_t role_mask[RTE_MAX_LCORE])
659*70581c35SKonstantin Ananyev {
660*70581c35SKonstantin Ananyev 	uint32_t i, lc;
661*70581c35SKonstantin Ananyev 	const uint32_t msk[2] = {
662*70581c35SKonstantin Ananyev 		[0] = ROLE_DEQENQ,
663*70581c35SKonstantin Ananyev 		[1] =  RTE_GENMASK32(nb_stage + 1, 1),
664*70581c35SKonstantin Ananyev 	};
665*70581c35SKonstantin Ananyev 
666*70581c35SKonstantin Ananyev 	memset(role_mask, 0, sizeof(role_mask[0]) * RTE_MAX_LCORE);
667*70581c35SKonstantin Ananyev 
668*70581c35SKonstantin Ananyev 	i = 0;
669*70581c35SKonstantin Ananyev 	RTE_LCORE_FOREACH_WORKER(lc) {
670*70581c35SKonstantin Ananyev 		if (i == 0)
671*70581c35SKonstantin Ananyev 			role_mask[lc] = msk[0];
672*70581c35SKonstantin Ananyev 		else
673*70581c35SKonstantin Ananyev 			role_mask[lc] = msk[1];
674*70581c35SKonstantin Ananyev 		i++;
675*70581c35SKonstantin Ananyev 	}
676*70581c35SKonstantin Ananyev 	if (i == 1) {
677*70581c35SKonstantin Ananyev 		lc = rte_get_next_lcore(-1, 1, 0);
678*70581c35SKonstantin Ananyev 		role_mask[lc] |= msk[1];
679*70581c35SKonstantin Ananyev 	}
680*70581c35SKonstantin Ananyev }
681*70581c35SKonstantin Ananyev 
682*70581c35SKonstantin Ananyev 
683*70581c35SKonstantin Ananyev static int
684*70581c35SKonstantin Ananyev test_sym_mt1(int (*test)(void *))
685*70581c35SKonstantin Ananyev {
686*70581c35SKonstantin Ananyev 	uint32_t role_mask[RTE_MAX_LCORE];
687*70581c35SKonstantin Ananyev 	const uint32_t nb_stage = 1;
688*70581c35SKonstantin Ananyev 
689*70581c35SKonstantin Ananyev 	role_mask_sym(nb_stage, role_mask);
690*70581c35SKonstantin Ananyev 	return test_mt(test, RTE_RING_SYNC_MT, RTE_RING_SYNC_MT,
691*70581c35SKonstantin Ananyev 			nb_stage, role_mask);
692*70581c35SKonstantin Ananyev }
693*70581c35SKonstantin Ananyev 
694*70581c35SKonstantin Ananyev static int
695*70581c35SKonstantin Ananyev test_sym_mt4(int (*test)(void *))
696*70581c35SKonstantin Ananyev {
697*70581c35SKonstantin Ananyev 	uint32_t role_mask[RTE_MAX_LCORE];
698*70581c35SKonstantin Ananyev 
699*70581c35SKonstantin Ananyev 	const uint32_t nb_stage = 4;
700*70581c35SKonstantin Ananyev 
701*70581c35SKonstantin Ananyev 	role_mask_sym(nb_stage, role_mask);
702*70581c35SKonstantin Ananyev 	return test_mt(test, RTE_RING_SYNC_MT, RTE_RING_SYNC_MT,
703*70581c35SKonstantin Ananyev 			nb_stage, role_mask);
704*70581c35SKonstantin Ananyev }
705*70581c35SKonstantin Ananyev 
706*70581c35SKonstantin Ananyev static int
707*70581c35SKonstantin Ananyev test_sym_mt_rts4(int (*test)(void *))
708*70581c35SKonstantin Ananyev {
709*70581c35SKonstantin Ananyev 	uint32_t role_mask[RTE_MAX_LCORE];
710*70581c35SKonstantin Ananyev 
711*70581c35SKonstantin Ananyev 	const uint32_t nb_stage = 4;
712*70581c35SKonstantin Ananyev 
713*70581c35SKonstantin Ananyev 	role_mask_sym(nb_stage, role_mask);
714*70581c35SKonstantin Ananyev 	return test_mt(test, RTE_RING_SYNC_MT_RTS, RTE_RING_SYNC_MT_RTS,
715*70581c35SKonstantin Ananyev 			nb_stage, role_mask);
716*70581c35SKonstantin Ananyev }
717*70581c35SKonstantin Ananyev 
718*70581c35SKonstantin Ananyev static int
719*70581c35SKonstantin Ananyev test_sym_mt_hts4(int (*test)(void *))
720*70581c35SKonstantin Ananyev {
721*70581c35SKonstantin Ananyev 	uint32_t role_mask[RTE_MAX_LCORE];
722*70581c35SKonstantin Ananyev 
723*70581c35SKonstantin Ananyev 	const uint32_t nb_stage = 4;
724*70581c35SKonstantin Ananyev 
725*70581c35SKonstantin Ananyev 	role_mask_sym(nb_stage, role_mask);
726*70581c35SKonstantin Ananyev 	return test_mt(test, RTE_RING_SYNC_MT_HTS, RTE_RING_SYNC_MT_HTS,
727*70581c35SKonstantin Ananyev 			nb_stage, role_mask);
728*70581c35SKonstantin Ananyev }
729*70581c35SKonstantin Ananyev 
730*70581c35SKonstantin Ananyev static int
731*70581c35SKonstantin Ananyev test_stdenq_stage4(int (*test)(void *))
732*70581c35SKonstantin Ananyev {
733*70581c35SKonstantin Ananyev 	uint32_t role_mask[RTE_MAX_LCORE];
734*70581c35SKonstantin Ananyev 
735*70581c35SKonstantin Ananyev 	const uint32_t nb_stage = 4;
736*70581c35SKonstantin Ananyev 
737*70581c35SKonstantin Ananyev 	role_mask_denq_st(nb_stage, role_mask);
738*70581c35SKonstantin Ananyev 	return test_mt(test, RTE_RING_SYNC_ST, RTE_RING_SYNC_ST,
739*70581c35SKonstantin Ananyev 			nb_stage, role_mask);
740*70581c35SKonstantin Ananyev }
741*70581c35SKonstantin Ananyev 
742*70581c35SKonstantin Ananyev 
743*70581c35SKonstantin Ananyev static int
744*70581c35SKonstantin Ananyev test_even_odd_mt5(int (*test)(void *))
745*70581c35SKonstantin Ananyev {
746*70581c35SKonstantin Ananyev 	uint32_t role_mask[RTE_MAX_LCORE];
747*70581c35SKonstantin Ananyev 
748*70581c35SKonstantin Ananyev 	const uint32_t nb_stage = 5;
749*70581c35SKonstantin Ananyev 
750*70581c35SKonstantin Ananyev 	role_mask_even_odd(nb_stage, role_mask);
751*70581c35SKonstantin Ananyev 	return test_mt(test, RTE_RING_SYNC_MT, RTE_RING_SYNC_MT,
752*70581c35SKonstantin Ananyev 			nb_stage, role_mask);
753*70581c35SKonstantin Ananyev }
754*70581c35SKonstantin Ananyev 
755*70581c35SKonstantin Ananyev static int
756*70581c35SKonstantin Ananyev test_div_mt3(int (*test)(void *))
757*70581c35SKonstantin Ananyev {
758*70581c35SKonstantin Ananyev 	uint32_t role_mask[RTE_MAX_LCORE];
759*70581c35SKonstantin Ananyev 
760*70581c35SKonstantin Ananyev 	const uint32_t nb_stage = 3;
761*70581c35SKonstantin Ananyev 
762*70581c35SKonstantin Ananyev 	role_mask_div(nb_stage, role_mask);
763*70581c35SKonstantin Ananyev 	return test_mt(test, RTE_RING_SYNC_MT, RTE_RING_SYNC_MT,
764*70581c35SKonstantin Ananyev 			nb_stage, role_mask);
765*70581c35SKonstantin Ananyev }
766*70581c35SKonstantin Ananyev 
767*70581c35SKonstantin Ananyev static const struct test_case tests[] = {
768*70581c35SKonstantin Ananyev 	{
769*70581c35SKonstantin Ananyev 		.name = "MT_DEQENQ-MT_STG1-PRCS",
770*70581c35SKonstantin Ananyev 		.func = test_sym_mt1,
771*70581c35SKonstantin Ananyev 		.wfunc = test_worker_prcs,
772*70581c35SKonstantin Ananyev 	},
773*70581c35SKonstantin Ananyev 	{
774*70581c35SKonstantin Ananyev 		.name = "MT_DEQENQ-MT_STG1-AVG",
775*70581c35SKonstantin Ananyev 		.func = test_sym_mt1,
776*70581c35SKonstantin Ananyev 		.wfunc = test_worker_avg,
777*70581c35SKonstantin Ananyev 	},
778*70581c35SKonstantin Ananyev 	{
779*70581c35SKonstantin Ananyev 		.name = "MT_DEQENQ-MT_STG4-PRCS",
780*70581c35SKonstantin Ananyev 		.func = test_sym_mt4,
781*70581c35SKonstantin Ananyev 		.wfunc = test_worker_prcs,
782*70581c35SKonstantin Ananyev 	},
783*70581c35SKonstantin Ananyev 	{
784*70581c35SKonstantin Ananyev 		.name = "MT_DEQENQ-MT_STG4-AVG",
785*70581c35SKonstantin Ananyev 		.func = test_sym_mt4,
786*70581c35SKonstantin Ananyev 		.wfunc = test_worker_avg,
787*70581c35SKonstantin Ananyev 	},
788*70581c35SKonstantin Ananyev 	{
789*70581c35SKonstantin Ananyev 		.name = "MTRTS_DEQENQ-MT_STG4-PRCS",
790*70581c35SKonstantin Ananyev 		.func = test_sym_mt_rts4,
791*70581c35SKonstantin Ananyev 		.wfunc = test_worker_prcs,
792*70581c35SKonstantin Ananyev 	},
793*70581c35SKonstantin Ananyev 	{
794*70581c35SKonstantin Ananyev 		.name = "MTRTS_DEQENQ-MT_STG4-AVG",
795*70581c35SKonstantin Ananyev 		.func = test_sym_mt_rts4,
796*70581c35SKonstantin Ananyev 		.wfunc = test_worker_avg,
797*70581c35SKonstantin Ananyev 	},
798*70581c35SKonstantin Ananyev 	{
799*70581c35SKonstantin Ananyev 		.name = "MTHTS_DEQENQ-MT_STG4-PRCS",
800*70581c35SKonstantin Ananyev 		.func = test_sym_mt_hts4,
801*70581c35SKonstantin Ananyev 		.wfunc = test_worker_prcs,
802*70581c35SKonstantin Ananyev 	},
803*70581c35SKonstantin Ananyev 	{
804*70581c35SKonstantin Ananyev 		.name = "MTHTS_DEQENQ-MT_STG4-AVG",
805*70581c35SKonstantin Ananyev 		.func = test_sym_mt_hts4,
806*70581c35SKonstantin Ananyev 		.wfunc = test_worker_avg,
807*70581c35SKonstantin Ananyev 	},
808*70581c35SKonstantin Ananyev 	{
809*70581c35SKonstantin Ananyev 		.name = "MT_DEQENQ-MT_STG5-1:1-PRCS",
810*70581c35SKonstantin Ananyev 		.func = test_even_odd_mt5,
811*70581c35SKonstantin Ananyev 		.wfunc = test_worker_prcs,
812*70581c35SKonstantin Ananyev 	},
813*70581c35SKonstantin Ananyev 	{
814*70581c35SKonstantin Ananyev 		.name = "MT_DEQENQ-MT_STG5-1:1-AVG",
815*70581c35SKonstantin Ananyev 		.func = test_even_odd_mt5,
816*70581c35SKonstantin Ananyev 		.wfunc = test_worker_avg,
817*70581c35SKonstantin Ananyev 	},
818*70581c35SKonstantin Ananyev 	{
819*70581c35SKonstantin Ananyev 		.name = "MT_DEQENQ-MT_STG3-1:3-PRCS",
820*70581c35SKonstantin Ananyev 		.func = test_div_mt3,
821*70581c35SKonstantin Ananyev 		.wfunc = test_worker_prcs,
822*70581c35SKonstantin Ananyev 	},
823*70581c35SKonstantin Ananyev 	{
824*70581c35SKonstantin Ananyev 		.name = "MT_DEQENQ_MT_STG3-1:3-AVG",
825*70581c35SKonstantin Ananyev 		.func = test_div_mt3,
826*70581c35SKonstantin Ananyev 		.wfunc = test_worker_avg,
827*70581c35SKonstantin Ananyev 	},
828*70581c35SKonstantin Ananyev 	{
829*70581c35SKonstantin Ananyev 		.name = "ST_DEQENQ-MT_STG4-PRCS",
830*70581c35SKonstantin Ananyev 		.func = test_stdenq_stage4,
831*70581c35SKonstantin Ananyev 		.wfunc = test_worker_prcs,
832*70581c35SKonstantin Ananyev 	},
833*70581c35SKonstantin Ananyev 	{
834*70581c35SKonstantin Ananyev 		.name = "ST_DEQENQ-MT_STG4-AVG",
835*70581c35SKonstantin Ananyev 		.func = test_stdenq_stage4,
836*70581c35SKonstantin Ananyev 		.wfunc = test_worker_avg,
837*70581c35SKonstantin Ananyev 	},
838*70581c35SKonstantin Ananyev };
839