1a152c68eSDaniel Mrzyglod/*
27e18fa1bSKonstantin Ananyev * Copyright (c) 2016-2017  Intel Corporation.
3a152c68eSDaniel Mrzyglod * Licensed under the Apache License, Version 2.0 (the "License");
4a152c68eSDaniel Mrzyglod * you may not use this file except in compliance with the License.
5a152c68eSDaniel Mrzyglod * You may obtain a copy of the License at:
6a152c68eSDaniel Mrzyglod *
7a152c68eSDaniel Mrzyglod *     http://www.apache.org/licenses/LICENSE-2.0
8a152c68eSDaniel Mrzyglod *
9a152c68eSDaniel Mrzyglod * Unless required by applicable law or agreed to in writing, software
10a152c68eSDaniel Mrzyglod * distributed under the License is distributed on an "AS IS" BASIS,
11a152c68eSDaniel Mrzyglod * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a152c68eSDaniel Mrzyglod * See the License for the specific language governing permissions and
13a152c68eSDaniel Mrzyglod * limitations under the License.
14a152c68eSDaniel Mrzyglod */
15a152c68eSDaniel Mrzyglod
16a152c68eSDaniel Mrzyglod#ifndef TEST_TLE_DRING_H_
17a152c68eSDaniel Mrzyglod#define TEST_TLE_DRING_H_
18a152c68eSDaniel Mrzyglod
19a152c68eSDaniel Mrzyglod#include <string.h>
20a152c68eSDaniel Mrzyglod#include <stdarg.h>
21a152c68eSDaniel Mrzyglod#include <stdio.h>
22a152c68eSDaniel Mrzyglod#include <stdlib.h>
23a152c68eSDaniel Mrzyglod#include <stdint.h>
24a152c68eSDaniel Mrzyglod#include <inttypes.h>
25a152c68eSDaniel Mrzyglod#include <errno.h>
26a152c68eSDaniel Mrzyglod
27a152c68eSDaniel Mrzyglod#include <gtest/gtest.h>
28a152c68eSDaniel Mrzyglod#include <gmock/gmock.h>
29a152c68eSDaniel Mrzyglod
30a152c68eSDaniel Mrzyglod#include <rte_common.h>
31a152c68eSDaniel Mrzyglod#include <rte_log.h>
32a152c68eSDaniel Mrzyglod#include <rte_errno.h>
33a152c68eSDaniel Mrzyglod#include <rte_launch.h>
34a152c68eSDaniel Mrzyglod#include <rte_cycles.h>
35a152c68eSDaniel Mrzyglod#include <rte_eal.h>
36a152c68eSDaniel Mrzyglod#include <rte_per_lcore.h>
37a152c68eSDaniel Mrzyglod#include <rte_lcore.h>
38a152c68eSDaniel Mrzyglod#include <rte_ring.h>
39a152c68eSDaniel Mrzyglod#include <rte_random.h>
40a152c68eSDaniel Mrzyglod
41a152c68eSDaniel Mrzyglod#include <tle_dring.h>
42a152c68eSDaniel Mrzyglod
43a152c68eSDaniel Mrzyglodstruct dring_arg {
44a152c68eSDaniel Mrzyglod	struct tle_dring *dr;
45a152c68eSDaniel Mrzyglod	struct rte_ring *r;
46a152c68eSDaniel Mrzyglod	uint32_t iter;
47a152c68eSDaniel Mrzyglod	int32_t enq_type;
48a152c68eSDaniel Mrzyglod	int32_t deq_type;
49a152c68eSDaniel Mrzyglod	uint32_t enq;
50a152c68eSDaniel Mrzyglod	uint32_t deq;
51a152c68eSDaniel Mrzyglod};
52a152c68eSDaniel Mrzyglod
53a152c68eSDaniel Mrzyglodclass dring: public ::testing::Test {
54a152c68eSDaniel Mrzyglodprotected:
55a152c68eSDaniel Mrzyglod
56a152c68eSDaniel Mrzyglod	virtual void SetUp(void) {};
57a152c68eSDaniel Mrzyglod	virtual void TearDown(void) {};
58a152c68eSDaniel Mrzyglod
59a152c68eSDaniel Mrzyglod	int32_t rc;
60a152c68eSDaniel Mrzyglod	struct rte_ring *r;
61a152c68eSDaniel Mrzyglod	struct tle_dring dr;
62a152c68eSDaniel Mrzyglod	struct dring_arg arg[RTE_MAX_LCORE];
63a152c68eSDaniel Mrzyglod
64a152c68eSDaniel Mrzyglod};
65a152c68eSDaniel Mrzyglod
66a152c68eSDaniel Mrzyglod#define OBJ_NUM		UINT16_MAX
67a152c68eSDaniel Mrzyglod#define ITER_NUM	(4 * OBJ_NUM)
68a152c68eSDaniel Mrzyglod
69a152c68eSDaniel Mrzyglodenum {
70a152c68eSDaniel Mrzyglod	NONE,
71a152c68eSDaniel Mrzyglod	SINGLE,
72a152c68eSDaniel Mrzyglod	MULTI,
73a152c68eSDaniel Mrzyglod};
74a152c68eSDaniel Mrzyglod
75a152c68eSDaniel Mrzyglod/*
76a152c68eSDaniel Mrzyglod * Each enqueued object will contain:
77a152c68eSDaniel Mrzyglod * [2-3]B: it's own sequence number.
78a152c68eSDaniel Mrzyglod * [0-1]B: next object sequence number, or UINT16_MAX.
79a152c68eSDaniel Mrzyglod */
80a152c68eSDaniel Mrzyglodstatic void
81a152c68eSDaniel Mrzyglodtest_fill_obj(uintptr_t obj[], uint32_t num)
82a152c68eSDaniel Mrzyglod{
83a152c68eSDaniel Mrzyglod	uint32_t i;
84a152c68eSDaniel Mrzyglod
85a152c68eSDaniel Mrzyglod	for (i = 0; i != num - 1; i++)
86a152c68eSDaniel Mrzyglod		obj[i] = i << 16 | (i + 1);
87a152c68eSDaniel Mrzyglod
88a152c68eSDaniel Mrzyglod	obj[i] = i << 16 | UINT16_MAX;
89a152c68eSDaniel Mrzyglod}
90a152c68eSDaniel Mrzyglod
91a152c68eSDaniel Mrzyglodstatic uint32_t
92a152c68eSDaniel Mrzyglodtest_check_obj(uintptr_t obj[], uint32_t num)
93a152c68eSDaniel Mrzyglod{
94a152c68eSDaniel Mrzyglod	uint32_t i, h, l, oh, ol;
95a152c68eSDaniel Mrzyglod
96a152c68eSDaniel Mrzyglod	h = obj[0] >> 16;
97a152c68eSDaniel Mrzyglod	l = obj[0] & UINT16_MAX;
98a152c68eSDaniel Mrzyglod
99a152c68eSDaniel Mrzyglod	if (h + 1 != l && l != UINT16_MAX)
100a152c68eSDaniel Mrzyglod		return 0;
101a152c68eSDaniel Mrzyglod
102a152c68eSDaniel Mrzyglod	if (l == UINT16_MAX)
103a152c68eSDaniel Mrzyglod		l = 0;
104a152c68eSDaniel Mrzyglod
105a152c68eSDaniel Mrzyglod	for (i = 1; i != num; i++) {
106a152c68eSDaniel Mrzyglod
107a152c68eSDaniel Mrzyglod		oh = obj[i] >> 16;
108a152c68eSDaniel Mrzyglod		ol = obj[i] & UINT16_MAX;
109a152c68eSDaniel Mrzyglod
110a152c68eSDaniel Mrzyglod		if (l != oh || (oh + 1 != ol && ol != UINT16_MAX))
111a152c68eSDaniel Mrzyglod			return i;
112a152c68eSDaniel Mrzyglod
113a152c68eSDaniel Mrzyglod		l = ol;
114a152c68eSDaniel Mrzyglod		if (l == UINT16_MAX)
115a152c68eSDaniel Mrzyglod			l = 0;
116a152c68eSDaniel Mrzyglod	}
117a152c68eSDaniel Mrzyglod
118a152c68eSDaniel Mrzyglod	return num;
119a152c68eSDaniel Mrzyglod}
120a152c68eSDaniel Mrzyglod
121a152c68eSDaniel Mrzyglod/*
122a152c68eSDaniel Mrzyglod * free memory allocated for drbs and for the ring itself.
123a152c68eSDaniel Mrzyglod */
124a152c68eSDaniel Mrzyglodstatic void
125a152c68eSDaniel Mrzyglodfini_drb_ring(struct rte_ring *r)
126a152c68eSDaniel Mrzyglod{
127a152c68eSDaniel Mrzyglod	struct tle_drb *drb;
128a152c68eSDaniel Mrzyglod
129a152c68eSDaniel Mrzyglod	/* free drbs. */
130a152c68eSDaniel Mrzyglod	while (rte_ring_dequeue(r, (void **)&drb) == 0)
131a152c68eSDaniel Mrzyglod		free(drb);
132a152c68eSDaniel Mrzyglod
133a152c68eSDaniel Mrzyglod	/* free ring. */
134a152c68eSDaniel Mrzyglod	free(r);
135a152c68eSDaniel Mrzyglod}
136a152c68eSDaniel Mrzyglod
137a152c68eSDaniel Mrzyglodstatic struct rte_ring *
138a152c68eSDaniel Mrzyglodinit_drb_ring(uint32_t num)
139a152c68eSDaniel Mrzyglod{
140a152c68eSDaniel Mrzyglod	uint32_t i, k, n;
141a152c68eSDaniel Mrzyglod	size_t sz, tsz;
142a152c68eSDaniel Mrzyglod	struct rte_ring *r;
143a152c68eSDaniel Mrzyglod	struct tle_drb *drb;
144a152c68eSDaniel Mrzyglod
145a152c68eSDaniel Mrzyglod	/* allocate and initialise rte_ring. */
146a152c68eSDaniel Mrzyglod
147a152c68eSDaniel Mrzyglod	n = rte_align32pow2(num);
148fbba0a3bSMohammad Abdul Awal	sz =  rte_ring_get_memsize(n);
149a152c68eSDaniel Mrzyglod
150a152c68eSDaniel Mrzyglod	r = (struct rte_ring *)calloc(1, sz);
151a152c68eSDaniel Mrzyglod	if (r == NULL) {
152a152c68eSDaniel Mrzyglod		printf("%s:%d(%u) failed to allocate %zu bytes;\n",
153a152c68eSDaniel Mrzyglod			__func__, __LINE__, num, sz);
154a152c68eSDaniel Mrzyglod		return NULL;
155a152c68eSDaniel Mrzyglod	}
156a152c68eSDaniel Mrzyglod
157a152c68eSDaniel Mrzyglod	rte_ring_init(r, __func__, n, 0);
158a152c68eSDaniel Mrzyglod
159a152c68eSDaniel Mrzyglod	/* allocate drbs and put them into the ring. */
160a152c68eSDaniel Mrzyglod
161a152c68eSDaniel Mrzyglod	tsz = sz;
162a152c68eSDaniel Mrzyglod	for (i = 0; i != num; i += k) {
163a152c68eSDaniel Mrzyglod		k =  rte_rand() % (UINT8_MAX + 1) + 1;
164a152c68eSDaniel Mrzyglod		k = RTE_MIN(k, num - i);
165a152c68eSDaniel Mrzyglod		sz = tle_drb_calc_size(k);
166a152c68eSDaniel Mrzyglod		drb = (struct tle_drb *)calloc(1, sz);
167a152c68eSDaniel Mrzyglod		if (drb == NULL) {
168a152c68eSDaniel Mrzyglod			printf("%s:%d(%u) %u-th iteration: "
169a152c68eSDaniel Mrzyglod				"failed to allocate %zu bytes;\n",
170a152c68eSDaniel Mrzyglod				__func__, __LINE__, num, i, sz);
171a152c68eSDaniel Mrzyglod			fini_drb_ring(r);
172a152c68eSDaniel Mrzyglod			return NULL;
173a152c68eSDaniel Mrzyglod		}
174a152c68eSDaniel Mrzyglod		drb->size = k;
175a152c68eSDaniel Mrzyglod		rte_ring_enqueue(r, drb);
176a152c68eSDaniel Mrzyglod		tsz += sz;
177a152c68eSDaniel Mrzyglod	}
178a152c68eSDaniel Mrzyglod
179a152c68eSDaniel Mrzyglod	printf("%s(%u) total %zu bytes allocated, number of drbs: %u;\n",
180a152c68eSDaniel Mrzyglod		__func__, num, tsz, rte_ring_count(r));
181a152c68eSDaniel Mrzyglod	return r;
182a152c68eSDaniel Mrzyglod}
183a152c68eSDaniel Mrzyglod
184a152c68eSDaniel Mrzyglodstatic int
185a152c68eSDaniel Mrzyglodtest_dring_enqueue(struct tle_dring *dr, struct rte_ring *r, uint32_t num,
186a152c68eSDaniel Mrzyglod	int32_t type)
187a152c68eSDaniel Mrzyglod{
188a152c68eSDaniel Mrzyglod	uint32_t i, j, k, lc, nb;
189a152c68eSDaniel Mrzyglod	struct tle_drb *drb[num];
190a152c68eSDaniel Mrzyglod	uintptr_t obj[num];
191a152c68eSDaniel Mrzyglod
192a152c68eSDaniel Mrzyglod	lc = rte_lcore_id();
193a152c68eSDaniel Mrzyglod
194a152c68eSDaniel Mrzyglod	/* prepare drbs to enqueue up to *num* objects. */
195a152c68eSDaniel Mrzyglod	for (i = 0, j = 0; i != num; i += k, j++) {
196a152c68eSDaniel Mrzyglod
197a152c68eSDaniel Mrzyglod		if (rte_ring_dequeue(r, (void **)&drb[j]) != 0)
198a152c68eSDaniel Mrzyglod			break;
199a152c68eSDaniel Mrzyglod
200a152c68eSDaniel Mrzyglod		/* udata value for unused drb should be zero. */
201a152c68eSDaniel Mrzyglod		if (drb[j]->udata != NULL) {
202a152c68eSDaniel Mrzyglod			printf("error @ %s:%d(%p, %u) at lcore %u: "
203a152c68eSDaniel Mrzyglod				"erroneous drb@%p={udata=%p, size=%u,};\n",
204a152c68eSDaniel Mrzyglod				__func__, __LINE__, dr, num, lc, drb[j],
205a152c68eSDaniel Mrzyglod				drb[j]->udata, drb[j]->size);
206a152c68eSDaniel Mrzyglod			return -EFAULT;
207a152c68eSDaniel Mrzyglod		}
208a152c68eSDaniel Mrzyglod
209a152c68eSDaniel Mrzyglod		/* update udata value with current lcore id. */
210a152c68eSDaniel Mrzyglod		drb[j]->udata = (void *)(uintptr_t)(lc + 1);
211a152c68eSDaniel Mrzyglod		k = drb[j]->size;
212a152c68eSDaniel Mrzyglod		k = RTE_MIN(k, num - i);
213a152c68eSDaniel Mrzyglod	}
214a152c68eSDaniel Mrzyglod
215a152c68eSDaniel Mrzyglod	/* no free drbs left. */
216a152c68eSDaniel Mrzyglod	if (i == 0)
217a152c68eSDaniel Mrzyglod		return 0;
218a152c68eSDaniel Mrzyglod
219a152c68eSDaniel Mrzyglod	/* fill objects to enqueue. */
220a152c68eSDaniel Mrzyglod	test_fill_obj(obj, i);
221a152c68eSDaniel Mrzyglod
222a152c68eSDaniel Mrzyglod	/* enqueue into the dring. */
223a152c68eSDaniel Mrzyglod	nb = j;
224a152c68eSDaniel Mrzyglod	if (type == SINGLE)
225a152c68eSDaniel Mrzyglod		k = tle_dring_sp_enqueue(dr, (const void **)obj, i, drb, &nb);
226a152c68eSDaniel Mrzyglod	else if (type == MULTI)
227a152c68eSDaniel Mrzyglod		k = tle_dring_mp_enqueue(dr, (const void **)obj, i, drb, &nb);
228a152c68eSDaniel Mrzyglod	else
229a152c68eSDaniel Mrzyglod		return -EINVAL;
230a152c68eSDaniel Mrzyglod
231a152c68eSDaniel Mrzyglod	if (k != i) {
232a152c68eSDaniel Mrzyglod		printf("%s:%d(%p, %p, %u): failed to enqueue %u objects;\n",
233a152c68eSDaniel Mrzyglod			__func__, __LINE__, dr, r, num, i);
234a152c68eSDaniel Mrzyglod	}
235a152c68eSDaniel Mrzyglod
236a152c68eSDaniel Mrzyglod	/* free unused drbs */
237a152c68eSDaniel Mrzyglod	for (i = j - nb; i != j; i++) {
238a152c68eSDaniel Mrzyglod		if ((uintptr_t)drb[i]->udata != lc + 1) {
239a152c68eSDaniel Mrzyglod			printf("error @ %s:%d(%p, %u) at lcore %u: "
240a152c68eSDaniel Mrzyglod				"erroneous drb@%p={udata=%p, size=%u,};\n",
241a152c68eSDaniel Mrzyglod				__func__, __LINE__, dr, num, lc, drb[i],
242a152c68eSDaniel Mrzyglod				drb[i]->udata, drb[i]->size);
243a152c68eSDaniel Mrzyglod			return -EFAULT;
244a152c68eSDaniel Mrzyglod		}
245a152c68eSDaniel Mrzyglod		drb[i]->udata = NULL;
246a152c68eSDaniel Mrzyglod		rte_ring_enqueue(r, drb[i]);
247a152c68eSDaniel Mrzyglod	}
248a152c68eSDaniel Mrzyglod
249a152c68eSDaniel Mrzyglod	return k;
250a152c68eSDaniel Mrzyglod}
251a152c68eSDaniel Mrzyglod
252a152c68eSDaniel Mrzyglodstatic int
253a152c68eSDaniel Mrzyglodtest_dring_dequeue(struct tle_dring *dr, struct rte_ring *r, uint32_t num,
254a152c68eSDaniel Mrzyglod	int32_t type)
255a152c68eSDaniel Mrzyglod{
256a152c68eSDaniel Mrzyglod	uint32_t i, k, lc, n, t;
257a152c68eSDaniel Mrzyglod	struct tle_drb *drb[num];
258a152c68eSDaniel Mrzyglod	uintptr_t obj[num];
259a152c68eSDaniel Mrzyglod
260a152c68eSDaniel Mrzyglod	lc = rte_lcore_id();
261a152c68eSDaniel Mrzyglod	k = num;
262a152c68eSDaniel Mrzyglod
263a152c68eSDaniel Mrzyglod	/* dequeue objects. */
264a152c68eSDaniel Mrzyglod	if (type == SINGLE)
265a152c68eSDaniel Mrzyglod		n = tle_dring_sc_dequeue(dr, (const void **)obj, num, drb, &k);
266a152c68eSDaniel Mrzyglod	else if (type == MULTI)
267a152c68eSDaniel Mrzyglod		n = tle_dring_mc_dequeue(dr, (const void **)obj, num, drb, &k);
268a152c68eSDaniel Mrzyglod	else
269a152c68eSDaniel Mrzyglod		return -EINVAL;
270a152c68eSDaniel Mrzyglod
271a152c68eSDaniel Mrzyglod	if (n == 0)
272a152c68eSDaniel Mrzyglod		return 0;
273a152c68eSDaniel Mrzyglod
274a152c68eSDaniel Mrzyglod	/* check the data returned. */
275a152c68eSDaniel Mrzyglod	t = test_check_obj(obj, n);
276a152c68eSDaniel Mrzyglod	if (t != n) {
277a152c68eSDaniel Mrzyglod		printf("%s:%d(%p, %u) at lcore %u: invalid dequeued object, "
278a152c68eSDaniel Mrzyglod			"n=%u, idx=%u, obj=%#x, prev obj=%#x;\n",
279a152c68eSDaniel Mrzyglod			__func__, __LINE__, dr, num, lc, n, t,
280a152c68eSDaniel Mrzyglod			(uint32_t)obj[t], (t == 0) ? 0 : (uint32_t)obj[t - 1]);
281a152c68eSDaniel Mrzyglod		return -EFAULT;
282a152c68eSDaniel Mrzyglod	}
283a152c68eSDaniel Mrzyglod
284a152c68eSDaniel Mrzyglod	/* check and free drbs. */
285a152c68eSDaniel Mrzyglod	for (i = 0; i != k; i++) {
286a152c68eSDaniel Mrzyglod		/* udata value for drb in use shouldn't be zero. */
287a152c68eSDaniel Mrzyglod		if (drb[i]->udata == NULL) {
288a152c68eSDaniel Mrzyglod			printf("error @ %s:%d(%p, %u) at lcore %u: "
289a152c68eSDaniel Mrzyglod				"erroneous drb@%p={udata=%p, size=%u,};\n",
290a152c68eSDaniel Mrzyglod				__func__, __LINE__, dr, num, lc, drb[i],
291a152c68eSDaniel Mrzyglod				drb[i]->udata, drb[i]->size);
292a152c68eSDaniel Mrzyglod			return -EFAULT;
293a152c68eSDaniel Mrzyglod		}
294a152c68eSDaniel Mrzyglod		drb[i]->udata = NULL;
295a152c68eSDaniel Mrzyglod		rte_ring_enqueue(r, drb[i]);
296a152c68eSDaniel Mrzyglod	}
297a152c68eSDaniel Mrzyglod
298a152c68eSDaniel Mrzyglod	return n;
299a152c68eSDaniel Mrzyglod}
300a152c68eSDaniel Mrzyglod
301a152c68eSDaniel Mrzyglodstatic int
302a152c68eSDaniel Mrzyglodtest_dring_enq_deq(struct dring_arg *arg)
303a152c68eSDaniel Mrzyglod{
304a152c68eSDaniel Mrzyglod	int32_t rc;
305a152c68eSDaniel Mrzyglod	uint32_t i, lc, n;
306a152c68eSDaniel Mrzyglod
307a152c68eSDaniel Mrzyglod	rc = 0;
308a152c68eSDaniel Mrzyglod	arg->enq = 0;
309a152c68eSDaniel Mrzyglod	arg->deq = 0;
310a152c68eSDaniel Mrzyglod	lc = rte_lcore_id();
311a152c68eSDaniel Mrzyglod
312a152c68eSDaniel Mrzyglod	for (i = 0; i != arg->iter; i++) {
313a152c68eSDaniel Mrzyglod
314a152c68eSDaniel Mrzyglod		/* try to enqueue random number of objects. */
315a152c68eSDaniel Mrzyglod		if (arg->enq_type != NONE) {
316a152c68eSDaniel Mrzyglod			n = rte_rand() % (UINT8_MAX + 1);
317a152c68eSDaniel Mrzyglod			rc = test_dring_enqueue(arg->dr, arg->r, n,
318a152c68eSDaniel Mrzyglod				arg->enq_type);
319a152c68eSDaniel Mrzyglod			if (rc < 0)
320a152c68eSDaniel Mrzyglod				break;
321a152c68eSDaniel Mrzyglod			arg->enq += rc;
322a152c68eSDaniel Mrzyglod		}
323a152c68eSDaniel Mrzyglod
324a152c68eSDaniel Mrzyglod		/* try to dequeue random number of objects. */
325a152c68eSDaniel Mrzyglod		if (arg->deq_type != NONE) {
326a152c68eSDaniel Mrzyglod			n = rte_rand() % (UINT8_MAX + 1);
327a152c68eSDaniel Mrzyglod			rc = test_dring_dequeue(arg->dr, arg->r, n,
328a152c68eSDaniel Mrzyglod				arg->deq_type);
329a152c68eSDaniel Mrzyglod			if (rc < 0)
330a152c68eSDaniel Mrzyglod				break;
331a152c68eSDaniel Mrzyglod			arg->deq += rc;
332a152c68eSDaniel Mrzyglod		}
333a152c68eSDaniel Mrzyglod	}
334a152c68eSDaniel Mrzyglod
335a152c68eSDaniel Mrzyglod	if (rc < 0)
336a152c68eSDaniel Mrzyglod		return rc;
337a152c68eSDaniel Mrzyglod
338a152c68eSDaniel Mrzyglod	/* dequeue remaining objects. */
339a152c68eSDaniel Mrzyglod	while (arg->deq_type != NONE && arg->enq != arg->deq) {
340a152c68eSDaniel Mrzyglod
341a152c68eSDaniel Mrzyglod		/* try to dequeue random number of objects. */
342a152c68eSDaniel Mrzyglod		n = rte_rand() % (UINT8_MAX + 1) + 1;
343a152c68eSDaniel Mrzyglod		rc = test_dring_dequeue(arg->dr, arg->r, n, arg->deq_type);
344a152c68eSDaniel Mrzyglod		if (rc <= 0)
345a152c68eSDaniel Mrzyglod			break;
346a152c68eSDaniel Mrzyglod		arg->deq += rc;
347a152c68eSDaniel Mrzyglod	}
348a152c68eSDaniel Mrzyglod
349a152c68eSDaniel Mrzyglod	printf("%s:%d(lcore=%u, enq_type=%d, deq_type=%d): "
350a152c68eSDaniel Mrzyglod		"%u objects enqueued, %u objects dequeued\n",
351a152c68eSDaniel Mrzyglod		__func__, __LINE__, lc, arg->enq_type, arg->deq_type,
352a152c68eSDaniel Mrzyglod		arg->enq, arg->deq);
353a152c68eSDaniel Mrzyglod	return 0;
354a152c68eSDaniel Mrzyglod}
355a152c68eSDaniel Mrzyglod
356a152c68eSDaniel Mrzyglodstatic int
357a152c68eSDaniel Mrzyglodtest_dring_worker(void *arg)
358a152c68eSDaniel Mrzyglod{
359a152c68eSDaniel Mrzyglod	struct dring_arg *p;
360a152c68eSDaniel Mrzyglod
361a152c68eSDaniel Mrzyglod	p = (struct dring_arg *)arg;
362a152c68eSDaniel Mrzyglod	return test_dring_enq_deq(p);
363a152c68eSDaniel Mrzyglod}
364a152c68eSDaniel Mrzyglod
365a152c68eSDaniel Mrzyglod/*
366a152c68eSDaniel Mrzyglod * enqueue/dequeue by multiple threads.
367a152c68eSDaniel Mrzyglod */
368a152c68eSDaniel Mrzyglodstatic int
369a152c68eSDaniel Mrzyglodtest_dring_mt(int32_t master_enq_type, int32_t master_deq_type,
370a152c68eSDaniel Mrzyglod	int32_t slave_enq_type, int32_t slave_deq_type)
371a152c68eSDaniel Mrzyglod{
372a152c68eSDaniel Mrzyglod	int32_t rc;
373a152c68eSDaniel Mrzyglod	uint32_t lc;
374a152c68eSDaniel Mrzyglod	uint64_t deq, enq;
375a152c68eSDaniel Mrzyglod	struct rte_ring *r;
376a152c68eSDaniel Mrzyglod	struct tle_dring dr;
377a152c68eSDaniel Mrzyglod	struct dring_arg arg[RTE_MAX_LCORE];
378a152c68eSDaniel Mrzyglod
3797e18fa1bSKonstantin Ananyev	tle_dring_reset(&dr, 0);
380a152c68eSDaniel Mrzyglod	r = init_drb_ring(OBJ_NUM);
381a152c68eSDaniel Mrzyglod	if (r == NULL)
382a152c68eSDaniel Mrzyglod		return -ENOMEM;
383a152c68eSDaniel Mrzyglod
384a152c68eSDaniel Mrzyglod	memset(arg, 0, sizeof(arg));
385a152c68eSDaniel Mrzyglod
386a152c68eSDaniel Mrzyglod	/* launch on all slaves */
387a152c68eSDaniel Mrzyglod	RTE_LCORE_FOREACH_SLAVE(lc) {
388a152c68eSDaniel Mrzyglod		arg[lc].dr = &dr;
389a152c68eSDaniel Mrzyglod		arg[lc].r = r;
390a152c68eSDaniel Mrzyglod		arg[lc].iter = ITER_NUM;
391a152c68eSDaniel Mrzyglod		arg[lc].enq_type = slave_enq_type;
392a152c68eSDaniel Mrzyglod		arg[lc].deq_type = slave_deq_type;
393a152c68eSDaniel Mrzyglod		rte_eal_remote_launch(test_dring_worker, &arg[lc], lc);
394a152c68eSDaniel Mrzyglod	}
395a152c68eSDaniel Mrzyglod
396a152c68eSDaniel Mrzyglod	/* launch on master */
397a152c68eSDaniel Mrzyglod	lc = rte_lcore_id();
398a152c68eSDaniel Mrzyglod	arg[lc].dr = &dr;
399a152c68eSDaniel Mrzyglod	arg[lc].r = r;
400a152c68eSDaniel Mrzyglod	arg[lc].iter = ITER_NUM;
401a152c68eSDaniel Mrzyglod	arg[lc].enq_type = master_enq_type;
402a152c68eSDaniel Mrzyglod	arg[lc].deq_type = master_deq_type;
403a152c68eSDaniel Mrzyglod	rc = test_dring_worker(&arg[lc]);
404a152c68eSDaniel Mrzyglod	enq = arg[lc].enq;
405a152c68eSDaniel Mrzyglod	deq = arg[lc].deq;
406a152c68eSDaniel Mrzyglod
407a152c68eSDaniel Mrzyglod	/* wait for slaves. */
408a152c68eSDaniel Mrzyglod	RTE_LCORE_FOREACH_SLAVE(lc) {
409a152c68eSDaniel Mrzyglod		rc |= rte_eal_wait_lcore(lc);
410a152c68eSDaniel Mrzyglod		enq += arg[lc].enq;
411a152c68eSDaniel Mrzyglod		deq += arg[lc].deq;
412a152c68eSDaniel Mrzyglod	}
413a152c68eSDaniel Mrzyglod
414a152c68eSDaniel Mrzyglod	printf("%s:%d: total %" PRIu64 " objects enqueued, %"
415a152c68eSDaniel Mrzyglod		PRIu64 " objects dequeued\n",
416a152c68eSDaniel Mrzyglod		__func__, __LINE__, enq, deq);
417a152c68eSDaniel Mrzyglod
418a152c68eSDaniel Mrzyglod	rc = (rc != 0) ? rc : (enq != deq);
419a152c68eSDaniel Mrzyglod	if (rc != 0)
420a152c68eSDaniel Mrzyglod		tle_dring_dump(stdout, 1, &dr);
421a152c68eSDaniel Mrzyglod
422a152c68eSDaniel Mrzyglod	fini_drb_ring(r);
423a152c68eSDaniel Mrzyglod	return rc;
424a152c68eSDaniel Mrzyglod}
425a152c68eSDaniel Mrzyglod
426a152c68eSDaniel Mrzyglod#endif /* TEST_TLE_DRING_H_ */
427