test/ring: code rework to reduce compilation time
diff mbox series

Message ID 20200429175714.31141-1-konstantin.ananyev@intel.com
State Accepted, archived
Delegated to: David Marchand
Headers show
Series
  • test/ring: code rework to reduce compilation time
Related show

Checks

Context Check Description
ci/iol-testing success Testing PASS
ci/Intel-compilation success Compilation OK
ci/iol-mellanox-Performance success Performance Testing PASS
ci/travis-robot warning Travis build: failed
ci/iol-nxp-Performance success Performance Testing PASS
ci/iol-intel-Performance fail Performance Testing issues
ci/checkpatch warning coding style issues

Commit Message

Ananyev, Konstantin April 29, 2020, 5:57 p.m. UTC
Rework test code to reduce code complexity for the compiler
and bring down compilation time and memory consumption.

Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
 app/test/test_ring.c | 373 +++++++++++++++++++++++++++++--------------
 1 file changed, 249 insertions(+), 124 deletions(-)

Comments

Honnappa Nagarahalli April 29, 2020, 6:19 p.m. UTC | #1
Hi Konstantin,
	Thanks for the patch. I think we need to co-ordinate better on the rte_ring related work to avoid duplicating the efforts. I also have been working on a patch myself and it is undergoing internal review.

I will review this patch soon.

Thanks,
Honnappa

> -----Original Message-----
> From: Konstantin Ananyev <konstantin.ananyev@intel.com>
> Sent: Wednesday, April 29, 2020 12:57 PM
> To: dev@dpdk.org
> Cc: aconole@redhat.com; Honnappa Nagarahalli
> <Honnappa.Nagarahalli@arm.com>; Konstantin Ananyev
> <konstantin.ananyev@intel.com>
> Subject: [PATCH] test/ring: code rework to reduce compilation time
> 
> Rework test code to reduce code complexity for the compiler and bring down
> compilation time and memory consumption.
> 
> Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> ---
>  app/test/test_ring.c | 373 +++++++++++++++++++++++++++++--------------
>  1 file changed, 249 insertions(+), 124 deletions(-)
> 
> diff --git a/app/test/test_ring.c b/app/test/test_ring.c index
> e21557cd9..0ae97d341 100644
> --- a/app/test/test_ring.c
> +++ b/app/test/test_ring.c
> @@ -58,6 +58,181 @@
> 
>  static const int esize[] = {-1, 4, 8, 16, 20};
> 
> +static const struct {
> +	const char *desc;
> +	uint32_t api_type;
> +	uint32_t create_flags;
> +	struct {
> +		unsigned int (*flegacy)(struct rte_ring *r,
> +			void * const *obj_table, unsigned int n,
> +			unsigned int *free_space);
> +		unsigned int (*felem)(struct rte_ring *r, const void *obj_table,
> +			unsigned int esize, unsigned int n,
> +			unsigned int *free_space);
> +	} enq;
> +	struct {
> +		unsigned int (*flegacy)(struct rte_ring *r,
> +			void **obj_table, unsigned int n,
> +			unsigned int *available);
> +		unsigned int (*felem)(struct rte_ring *r, void *obj_table,
> +			unsigned int esize, unsigned int n,
> +			unsigned int *available);
> +	} deq;
> +} test_enqdeq_impl[] = {
> +	{
> +		.desc = "MP/MC sync mode",
> +		.api_type = TEST_RING_ELEM_BULK |
> TEST_RING_THREAD_DEF,
> +		.create_flags = 0,
> +		.enq = {
> +			.flegacy = rte_ring_enqueue_bulk,
> +			.felem = rte_ring_enqueue_bulk_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_dequeue_bulk,
> +			.felem = rte_ring_dequeue_bulk_elem,
> +		},
> +	},
> +	{
> +		.desc = "SP/SC sync mode",
> +		.api_type = TEST_RING_ELEM_BULK |
> TEST_RING_THREAD_SPSC,
> +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> +		.enq = {
> +			.flegacy = rte_ring_sp_enqueue_bulk,
> +			.felem = rte_ring_sp_enqueue_bulk_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_sc_dequeue_bulk,
> +			.felem = rte_ring_sc_dequeue_bulk_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP/MC sync mode",
> +		.api_type = TEST_RING_ELEM_BULK |
> TEST_RING_THREAD_MPMC,
> +		.create_flags = 0,
> +		.enq = {
> +			.flegacy = rte_ring_mp_enqueue_bulk,
> +			.felem = rte_ring_mp_enqueue_bulk_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_mc_dequeue_bulk,
> +			.felem = rte_ring_mc_dequeue_bulk_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP_RTS/MC_RTS sync mode",
> +		.api_type = TEST_RING_ELEM_BULK |
> TEST_RING_THREAD_DEF,
> +		.create_flags = RING_F_MP_RTS_ENQ |
> RING_F_MC_RTS_DEQ,
> +		.enq = {
> +			.flegacy = rte_ring_enqueue_bulk,
> +			.felem = rte_ring_enqueue_bulk_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_dequeue_bulk,
> +			.felem = rte_ring_dequeue_bulk_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP_HTS/MC_HTS sync mode",
> +		.api_type = TEST_RING_ELEM_BULK |
> TEST_RING_THREAD_DEF,
> +		.create_flags = RING_F_MP_HTS_ENQ |
> RING_F_MC_HTS_DEQ,
> +		.enq = {
> +			.flegacy = rte_ring_enqueue_bulk,
> +			.felem = rte_ring_enqueue_bulk_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_dequeue_bulk,
> +			.felem = rte_ring_dequeue_bulk_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP/MC sync mode",
> +		.api_type = TEST_RING_ELEM_BURST |
> TEST_RING_THREAD_DEF,
> +		.create_flags = 0,
> +		.enq = {
> +			.flegacy = rte_ring_enqueue_burst,
> +			.felem = rte_ring_enqueue_burst_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_dequeue_burst,
> +			.felem = rte_ring_dequeue_burst_elem,
> +		},
> +	},
> +	{
> +		.desc = "SP/SC sync mode",
> +		.api_type = TEST_RING_ELEM_BURST |
> TEST_RING_THREAD_SPSC,
> +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> +		.enq = {
> +			.flegacy = rte_ring_sp_enqueue_burst,
> +			.felem = rte_ring_sp_enqueue_burst_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_sc_dequeue_burst,
> +			.felem = rte_ring_sc_dequeue_burst_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP/MC sync mode",
> +		.api_type = TEST_RING_ELEM_BURST |
> TEST_RING_THREAD_MPMC,
> +		.create_flags = 0,
> +		.enq = {
> +			.flegacy = rte_ring_mp_enqueue_burst,
> +			.felem = rte_ring_mp_enqueue_burst_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_mc_dequeue_burst,
> +			.felem = rte_ring_mc_dequeue_burst_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP_RTS/MC_RTS sync mode",
> +		.api_type = TEST_RING_ELEM_BURST |
> TEST_RING_THREAD_DEF,
> +		.create_flags = RING_F_MP_RTS_ENQ |
> RING_F_MC_RTS_DEQ,
> +		.enq = {
> +			.flegacy = rte_ring_enqueue_burst,
> +			.felem = rte_ring_enqueue_burst_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_dequeue_burst,
> +			.felem = rte_ring_dequeue_burst_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP_HTS/MC_HTS sync mode",
> +		.api_type = TEST_RING_ELEM_BURST |
> TEST_RING_THREAD_DEF,
> +		.create_flags = RING_F_MP_HTS_ENQ |
> RING_F_MC_HTS_DEQ,
> +		.enq = {
> +			.flegacy = rte_ring_enqueue_burst,
> +			.felem = rte_ring_enqueue_burst_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_dequeue_burst,
> +			.felem = rte_ring_dequeue_burst_elem,
> +		},
> +	},
> +};
> +
> +static unsigned int
> +test_ring_enq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n,
> +	unsigned int test_idx)
> +{
> +	if (esize == -1)
> +		return test_enqdeq_impl[test_idx].enq.flegacy(r, obj, n, NULL);
> +	else
> +		return test_enqdeq_impl[test_idx].enq.felem(r, obj, esize, n,
> +			NULL);
> +}
> +
> +static unsigned int
> +test_ring_deq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n,
> +	unsigned int test_idx)
> +{
> +	if (esize == -1)
> +		return test_enqdeq_impl[test_idx].deq.flegacy(r, obj, n, NULL);
> +	else
> +		return test_enqdeq_impl[test_idx].deq.felem(r, obj, esize, n,
> +			NULL);
> +}
> +
>  static void**
>  test_ring_inc_ptr(void **obj, int esize, unsigned int n)  { @@ -203,8 +378,7
> @@ test_ring_negative_tests(void)
>   * Random number of elements are enqueued and dequeued.
>   */
>  static int
> -test_ring_burst_bulk_tests1(unsigned int api_type, unsigned int create_flags,
> -	const char *tname)
> +test_ring_burst_bulk_tests1(unsigned int test_idx)
>  {
>  	struct rte_ring *r;
>  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> @@ -214,11 +388,13 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> unsigned int create_flags,
>  	const unsigned int rsz = RING_SIZE - 1;
> 
>  	for (i = 0; i < RTE_DIM(esize); i++) {
> -		test_ring_print_test_string(tname, api_type, esize[i]);
> +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> 
>  		/* Create the ring */
>  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> -					RING_SIZE, SOCKET_ID_ANY,
> create_flags);
> +				RING_SIZE, SOCKET_ID_ANY,
> +				test_enqdeq_impl[test_idx].create_flags);
> 
>  		/* alloc dummy object pointers */
>  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -240,17
> +416,17 @@ test_ring_burst_bulk_tests1(unsigned int api_type, unsigned int
> create_flags,
>  			rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL);
>  			printf("%s: iteration %u, random shift: %u;\n",
>  			    __func__, i, rand);
> -			ret = test_ring_enqueue(r, cur_src, esize[i], rand,
> -							api_type);
> +			ret = test_ring_enq_impl(r, cur_src, esize[i], rand,
> +							test_idx);
>  			TEST_RING_VERIFY(ret != 0);
> 
> -			ret = test_ring_dequeue(r, cur_dst, esize[i], rand,
> -							api_type);
> +			ret = test_ring_deq_impl(r, cur_dst, esize[i], rand,
> +							test_idx);
>  			TEST_RING_VERIFY(ret == rand);
> 
>  			/* fill the ring */
> -			ret = test_ring_enqueue(r, cur_src, esize[i], rsz,
> -							api_type);
> +			ret = test_ring_enq_impl(r, cur_src, esize[i], rsz,
> +							test_idx);
>  			TEST_RING_VERIFY(ret != 0);
> 
>  			TEST_RING_VERIFY(rte_ring_free_count(r) == 0); @@
> -259,8 +435,8 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> unsigned int create_flags,
>  			TEST_RING_VERIFY(rte_ring_empty(r) == 0);
> 
>  			/* empty the ring */
> -			ret = test_ring_dequeue(r, cur_dst, esize[i], rsz,
> -							api_type);
> +			ret = test_ring_deq_impl(r, cur_dst, esize[i], rsz,
> +							test_idx);
>  			TEST_RING_VERIFY(ret == (int)rsz);
>  			TEST_RING_VERIFY(rsz == rte_ring_free_count(r));
>  			TEST_RING_VERIFY(rte_ring_count(r) == 0); @@ -
> 294,8 +470,7 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> unsigned int create_flags,
>   * dequeued data.
>   */
>  static int
> -test_ring_burst_bulk_tests2(unsigned int api_type, unsigned int create_flags,
> -	const char *tname)
> +test_ring_burst_bulk_tests2(unsigned int test_idx)
>  {
>  	struct rte_ring *r;
>  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> @@ -303,11 +478,13 @@ test_ring_burst_bulk_tests2(unsigned int api_type,
> unsigned int create_flags,
>  	unsigned int i;
> 
>  	for (i = 0; i < RTE_DIM(esize); i++) {
> -		test_ring_print_test_string(tname, api_type, esize[i]);
> +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> 
>  		/* Create the ring */
>  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> -					RING_SIZE, SOCKET_ID_ANY,
> create_flags);
> +				RING_SIZE, SOCKET_ID_ANY,
> +				test_enqdeq_impl[test_idx].create_flags);
> 
>  		/* alloc dummy object pointers */
>  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -323,39
> +500,39 @@ test_ring_burst_bulk_tests2(unsigned int api_type, unsigned int
> create_flags,
>  		cur_dst = dst;
> 
>  		printf("enqueue 1 obj\n");
> -		ret = test_ring_enqueue(r, cur_src, esize[i], 1, api_type);
> +		ret = test_ring_enq_impl(r, cur_src, esize[i], 1, test_idx);
>  		if (ret != 1)
>  			goto fail;
>  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
> 
>  		printf("enqueue 2 objs\n");
> -		ret = test_ring_enqueue(r, cur_src, esize[i], 2, api_type);
> +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
>  		if (ret != 2)
>  			goto fail;
>  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
> 
>  		printf("enqueue MAX_BULK objs\n");
> -		ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
> -						api_type);
> +		ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
> +						test_idx);
>  		if (ret != MAX_BULK)
>  			goto fail;
>  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK);
> 
>  		printf("dequeue 1 obj\n");
> -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1, api_type);
> +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1, test_idx);
>  		if (ret != 1)
>  			goto fail;
>  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
> 
>  		printf("dequeue 2 objs\n");
> -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2, api_type);
> +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
>  		if (ret != 2)
>  			goto fail;
>  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
> 
>  		printf("dequeue MAX_BULK objs\n");
> -		ret = test_ring_dequeue(r, cur_dst, esize[i], MAX_BULK,
> -						api_type);
> +		ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
> +						test_idx);
>  		if (ret != MAX_BULK)
>  			goto fail;
>  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK); @@
> -390,8 +567,7 @@ test_ring_burst_bulk_tests2(unsigned int api_type,
> unsigned int create_flags,
>   * Enqueue and dequeue to cover the entire ring length.
>   */
>  static int
> -test_ring_burst_bulk_tests3(unsigned int api_type, unsigned int create_flags,
> -	const char *tname)
> +test_ring_burst_bulk_tests3(unsigned int test_idx)
>  {
>  	struct rte_ring *r;
>  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> @@ -399,11 +575,13 @@ test_ring_burst_bulk_tests3(unsigned int api_type,
> unsigned int create_flags,
>  	unsigned int i, j;
> 
>  	for (i = 0; i < RTE_DIM(esize); i++) {
> -		test_ring_print_test_string(tname, api_type, esize[i]);
> +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> 
>  		/* Create the ring */
>  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> -					RING_SIZE, SOCKET_ID_ANY,
> create_flags);
> +				RING_SIZE, SOCKET_ID_ANY,
> +				test_enqdeq_impl[test_idx].create_flags);
> 
>  		/* alloc dummy object pointers */
>  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -420,15
> +598,15 @@ test_ring_burst_bulk_tests3(unsigned int api_type, unsigned int
> create_flags,
> 
>  		printf("fill and empty the ring\n");
>  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> -			ret = test_ring_enqueue(r, cur_src, esize[i],
> MAX_BULK,
> -							api_type);
> +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> MAX_BULK,
> +							test_idx);
>  			if (ret != MAX_BULK)
>  				goto fail;
>  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
>  								MAX_BULK);
> 
> -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> MAX_BULK,
> -							api_type);
> +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> MAX_BULK,
> +							test_idx);
>  			if (ret != MAX_BULK)
>  				goto fail;
>  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> 465,21 +643,24 @@ test_ring_burst_bulk_tests3(unsigned int api_type,
> unsigned int create_flags,
>   * Enqueue till the ring is full and dequeue till the ring becomes empty.
>   */
>  static int
> -test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int create_flags,
> -	const char *tname)
> +test_ring_burst_bulk_tests4(unsigned int test_idx)
>  {
>  	struct rte_ring *r;
>  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
>  	int ret;
>  	unsigned int i, j;
> -	unsigned int num_elems;
> +	unsigned int api_type, num_elems;
> +
> +	api_type = test_enqdeq_impl[test_idx].api_type;
> 
>  	for (i = 0; i < RTE_DIM(esize); i++) {
> -		test_ring_print_test_string(tname, api_type, esize[i]);
> +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> 
>  		/* Create the ring */
>  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> -					RING_SIZE, SOCKET_ID_ANY,
> create_flags);
> +				RING_SIZE, SOCKET_ID_ANY,
> +				test_enqdeq_impl[test_idx].create_flags);
> 
>  		/* alloc dummy object pointers */
>  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -496,8
> +677,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int
> create_flags,
> 
>  		printf("Test enqueue without enough memory space\n");
>  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
> -			ret = test_ring_enqueue(r, cur_src, esize[i],
> MAX_BULK,
> -							api_type);
> +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> MAX_BULK,
> +							test_idx);
>  			if (ret != MAX_BULK)
>  				goto fail;
>  			cur_src = test_ring_inc_ptr(cur_src, esize[i], @@ -
> 505,7 +686,7 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> unsigned int create_flags,
>  		}
> 
>  		printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n");
> -		ret = test_ring_enqueue(r, cur_src, esize[i], 2, api_type);
> +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
>  		if (ret != 2)
>  			goto fail;
>  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); @@ -517,8
> +698,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int
> create_flags,
>  		else
>  			num_elems = MAX_BULK;
>  		/* Always one free entry left */
> -		ret = test_ring_enqueue(r, cur_src, esize[i], num_elems,
> -						api_type);
> +		ret = test_ring_enq_impl(r, cur_src, esize[i], num_elems,
> +						test_idx);
>  		if (ret != MAX_BULK - 3)
>  			goto fail;
>  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK - 3);
> @@ -528,15 +709,15 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> unsigned int create_flags,
>  			goto fail;
> 
>  		printf("Test enqueue for a full entry\n");
> -		ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
> -						api_type);
> +		ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
> +						test_idx);
>  		if (ret != 0)
>  			goto fail;
> 
>  		printf("Test dequeue without enough objects\n");
>  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> MAX_BULK,
> -							api_type);
> +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> MAX_BULK,
> +							test_idx);
>  			if (ret != MAX_BULK)
>  				goto fail;
>  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> 544,7 +725,7 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> unsigned int create_flags,
>  		}
> 
>  		/* Available memory space for the exact MAX_BULK entries
> */
> -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2, api_type);
> +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
>  		if (ret != 2)
>  			goto fail;
>  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); @@ -554,8
> +735,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int
> create_flags,
>  			num_elems = MAX_BULK - 3;
>  		else
>  			num_elems = MAX_BULK;
> -		ret = test_ring_dequeue(r, cur_dst, esize[i], num_elems,
> -						api_type);
> +		ret = test_ring_deq_impl(r, cur_dst, esize[i], num_elems,
> +						test_idx);
>  		if (ret != MAX_BULK - 3)
>  			goto fail;
>  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK - 3);
> @@ -816,22 +997,7 @@ static int
>  test_ring(void)
>  {
>  	int32_t rc;
> -	unsigned int i, j;
> -	const char *tname;
> -
> -	static const struct {
> -		uint32_t create_flags;
> -		const char *name;
> -	} test_sync_modes[] = {
> -		{
> -			RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ,
> -			"Test MT_RTS ring",
> -		},
> -		{
> -			RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ,
> -			"Test MT_HTS ring",
> -		},
> -	};
> +	unsigned int i;
> 
>  	/* Negative test cases */
>  	if (test_ring_negative_tests() < 0)
> @@ -848,65 +1014,24 @@ test_ring(void)
>  	 * The test cases are split into smaller test cases to
>  	 * help clang compile faster.
>  	 */
> -	tname = "Test standard ring";
> -
> -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> -		for (i = TEST_RING_THREAD_DEF;
> -					i <= TEST_RING_THREAD_MPMC; i
> <<= 1)
> -			if (test_ring_burst_bulk_tests1(i | j, 0, tname) < 0)
> -				goto test_fail;
> -
> -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> -		for (i = TEST_RING_THREAD_DEF;
> -					i <= TEST_RING_THREAD_MPMC; i
> <<= 1)
> -			if (test_ring_burst_bulk_tests2(i | j, 0, tname) < 0)
> -				goto test_fail;
> -
> -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> -		for (i = TEST_RING_THREAD_DEF;
> -					i <= TEST_RING_THREAD_MPMC; i
> <<= 1)
> -			if (test_ring_burst_bulk_tests3(i | j, 0, tname) < 0)
> -				goto test_fail;
> -
> -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> -		for (i = TEST_RING_THREAD_DEF;
> -					i <= TEST_RING_THREAD_MPMC; i
> <<= 1)
> -			if (test_ring_burst_bulk_tests4(i | j, 0, tname) < 0)
> -				goto test_fail;
> -
> -	/* Burst and bulk operations with MT_RTS and MT_HTS sync modes
> */
> -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> -		for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> -				j <<= 1) {
> -
> -			rc = test_ring_burst_bulk_tests1(
> -				TEST_RING_THREAD_DEF | j,
> -				test_sync_modes[i].create_flags,
> -				test_sync_modes[i].name);
> -			if (rc < 0)
> -				goto test_fail;
> -
> -			rc = test_ring_burst_bulk_tests2(
> -				TEST_RING_THREAD_DEF | j,
> -				test_sync_modes[i].create_flags,
> -				test_sync_modes[i].name);
> -			if (rc < 0)
> -				goto test_fail;
> -
> -			rc = test_ring_burst_bulk_tests3(
> -				TEST_RING_THREAD_DEF | j,
> -				test_sync_modes[i].create_flags,
> -				test_sync_modes[i].name);
> -			if (rc < 0)
> -				goto test_fail;
> -
> -			rc = test_ring_burst_bulk_tests3(
> -				TEST_RING_THREAD_DEF | j,
> -				test_sync_modes[i].create_flags,
> -				test_sync_modes[i].name);
> -			if (rc < 0)
> -				goto test_fail;
> -		}
> +	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
> +
> +
> +		rc = test_ring_burst_bulk_tests1(i);
> +		if (rc < 0)
> +			goto test_fail;
> +
> +		rc = test_ring_burst_bulk_tests2(i);
> +		if (rc < 0)
> +			goto test_fail;
> +
> +		rc = test_ring_burst_bulk_tests3(i);
> +		if (rc < 0)
> +			goto test_fail;
> +
> +		rc = test_ring_burst_bulk_tests4(i);
> +		if (rc < 0)
> +			goto test_fail;
>  	}
> 
>  	/* dump the ring status */
> --
> 2.17.1
Aaron Conole April 29, 2020, 10:10 p.m. UTC | #2
Konstantin Ananyev <konstantin.ananyev@intel.com> writes:

> Rework test code to reduce code complexity for the compiler
> and bring down compilation time and memory consumption.
>
> Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> ---

I'll wait for Honnappa's review, but this looks good to me.  Consider
that I will ACK by the end of the week.
Honnappa Nagarahalli April 30, 2020, 1:57 a.m. UTC | #3
Hi Konstantin,
	I like the way the tests are organized and it looks good.

I am just wondering about the way it is being tested here. The intent to write the test cases the way they are currently is to mimic how the APIs would be used mostly. IMO, the APIs would be used with a constant value for element size so that the compiler will throw away the unwanted code (in the functions where the actual copy is being done).

With your method here, it looks to me like all the branches in the copy functions are kept and the branch decisions are done at run time. Is my understanding correct?

Can you please check this? https://patches.dpdk.org/patch/69567/

Thanks,
Honnappa

> -----Original Message-----
> From: Konstantin Ananyev <konstantin.ananyev@intel.com>
> Sent: Wednesday, April 29, 2020 12:57 PM
> To: dev@dpdk.org
> Cc: aconole@redhat.com; Honnappa Nagarahalli
> <Honnappa.Nagarahalli@arm.com>; Konstantin Ananyev
> <konstantin.ananyev@intel.com>
> Subject: [PATCH] test/ring: code rework to reduce compilation time
> 
> Rework test code to reduce code complexity for the compiler and bring down
> compilation time and memory consumption.
> 
> Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> ---
>  app/test/test_ring.c | 373 +++++++++++++++++++++++++++++--------------
>  1 file changed, 249 insertions(+), 124 deletions(-)
> 
> diff --git a/app/test/test_ring.c b/app/test/test_ring.c index
> e21557cd9..0ae97d341 100644
> --- a/app/test/test_ring.c
> +++ b/app/test/test_ring.c
> @@ -58,6 +58,181 @@
> 
>  static const int esize[] = {-1, 4, 8, 16, 20};
> 
> +static const struct {
> +	const char *desc;
> +	uint32_t api_type;
> +	uint32_t create_flags;
> +	struct {
> +		unsigned int (*flegacy)(struct rte_ring *r,
> +			void * const *obj_table, unsigned int n,
> +			unsigned int *free_space);
> +		unsigned int (*felem)(struct rte_ring *r, const void *obj_table,
> +			unsigned int esize, unsigned int n,
> +			unsigned int *free_space);
> +	} enq;
> +	struct {
> +		unsigned int (*flegacy)(struct rte_ring *r,
> +			void **obj_table, unsigned int n,
> +			unsigned int *available);
> +		unsigned int (*felem)(struct rte_ring *r, void *obj_table,
> +			unsigned int esize, unsigned int n,
> +			unsigned int *available);
> +	} deq;
> +} test_enqdeq_impl[] = {
> +	{
> +		.desc = "MP/MC sync mode",
Details about the tests are already printed by the function 'test_ring_print_test_string'. This string should be 'Test standard ring'.

> +		.api_type = TEST_RING_ELEM_BULK |
> TEST_RING_THREAD_DEF,
> +		.create_flags = 0,
> +		.enq = {
> +			.flegacy = rte_ring_enqueue_bulk,
> +			.felem = rte_ring_enqueue_bulk_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_dequeue_bulk,
> +			.felem = rte_ring_dequeue_bulk_elem,
> +		},
> +	},
> +	{
> +		.desc = "SP/SC sync mode",
> +		.api_type = TEST_RING_ELEM_BULK |
> TEST_RING_THREAD_SPSC,
> +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> +		.enq = {
> +			.flegacy = rte_ring_sp_enqueue_bulk,
> +			.felem = rte_ring_sp_enqueue_bulk_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_sc_dequeue_bulk,
> +			.felem = rte_ring_sc_dequeue_bulk_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP/MC sync mode",
> +		.api_type = TEST_RING_ELEM_BULK |
> TEST_RING_THREAD_MPMC,
> +		.create_flags = 0,
> +		.enq = {
> +			.flegacy = rte_ring_mp_enqueue_bulk,
> +			.felem = rte_ring_mp_enqueue_bulk_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_mc_dequeue_bulk,
> +			.felem = rte_ring_mc_dequeue_bulk_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP_RTS/MC_RTS sync mode",
> +		.api_type = TEST_RING_ELEM_BULK |
> TEST_RING_THREAD_DEF,
> +		.create_flags = RING_F_MP_RTS_ENQ |
> RING_F_MC_RTS_DEQ,
> +		.enq = {
> +			.flegacy = rte_ring_enqueue_bulk,
> +			.felem = rte_ring_enqueue_bulk_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_dequeue_bulk,
> +			.felem = rte_ring_dequeue_bulk_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP_HTS/MC_HTS sync mode",
> +		.api_type = TEST_RING_ELEM_BULK |
> TEST_RING_THREAD_DEF,
> +		.create_flags = RING_F_MP_HTS_ENQ |
> RING_F_MC_HTS_DEQ,
> +		.enq = {
> +			.flegacy = rte_ring_enqueue_bulk,
> +			.felem = rte_ring_enqueue_bulk_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_dequeue_bulk,
> +			.felem = rte_ring_dequeue_bulk_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP/MC sync mode",
> +		.api_type = TEST_RING_ELEM_BURST |
> TEST_RING_THREAD_DEF,
> +		.create_flags = 0,
> +		.enq = {
> +			.flegacy = rte_ring_enqueue_burst,
> +			.felem = rte_ring_enqueue_burst_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_dequeue_burst,
> +			.felem = rte_ring_dequeue_burst_elem,
> +		},
> +	},
> +	{
> +		.desc = "SP/SC sync mode",
> +		.api_type = TEST_RING_ELEM_BURST |
> TEST_RING_THREAD_SPSC,
> +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> +		.enq = {
> +			.flegacy = rte_ring_sp_enqueue_burst,
> +			.felem = rte_ring_sp_enqueue_burst_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_sc_dequeue_burst,
> +			.felem = rte_ring_sc_dequeue_burst_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP/MC sync mode",
> +		.api_type = TEST_RING_ELEM_BURST |
> TEST_RING_THREAD_MPMC,
> +		.create_flags = 0,
> +		.enq = {
> +			.flegacy = rte_ring_mp_enqueue_burst,
> +			.felem = rte_ring_mp_enqueue_burst_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_mc_dequeue_burst,
> +			.felem = rte_ring_mc_dequeue_burst_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP_RTS/MC_RTS sync mode",
> +		.api_type = TEST_RING_ELEM_BURST |
> TEST_RING_THREAD_DEF,
> +		.create_flags = RING_F_MP_RTS_ENQ |
> RING_F_MC_RTS_DEQ,
> +		.enq = {
> +			.flegacy = rte_ring_enqueue_burst,
> +			.felem = rte_ring_enqueue_burst_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_dequeue_burst,
> +			.felem = rte_ring_dequeue_burst_elem,
> +		},
> +	},
> +	{
> +		.desc = "MP_HTS/MC_HTS sync mode",
> +		.api_type = TEST_RING_ELEM_BURST |
> TEST_RING_THREAD_DEF,
> +		.create_flags = RING_F_MP_HTS_ENQ |
> RING_F_MC_HTS_DEQ,
> +		.enq = {
> +			.flegacy = rte_ring_enqueue_burst,
> +			.felem = rte_ring_enqueue_burst_elem,
> +		},
> +		.deq = {
> +			.flegacy = rte_ring_dequeue_burst,
> +			.felem = rte_ring_dequeue_burst_elem,
> +		},
> +	},
> +};
> +
> +static unsigned int
> +test_ring_enq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n,
> +	unsigned int test_idx)
> +{
> +	if (esize == -1)
> +		return test_enqdeq_impl[test_idx].enq.flegacy(r, obj, n, NULL);
> +	else
> +		return test_enqdeq_impl[test_idx].enq.felem(r, obj, esize, n,
> +			NULL);
> +}
> +
> +static unsigned int
> +test_ring_deq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n,
> +	unsigned int test_idx)
> +{
> +	if (esize == -1)
> +		return test_enqdeq_impl[test_idx].deq.flegacy(r, obj, n, NULL);
> +	else
> +		return test_enqdeq_impl[test_idx].deq.felem(r, obj, esize, n,
> +			NULL);
> +}
> +
>  static void**
>  test_ring_inc_ptr(void **obj, int esize, unsigned int n)  { @@ -203,8 +378,7
> @@ test_ring_negative_tests(void)
>   * Random number of elements are enqueued and dequeued.
>   */
>  static int
> -test_ring_burst_bulk_tests1(unsigned int api_type, unsigned int create_flags,
> -	const char *tname)
> +test_ring_burst_bulk_tests1(unsigned int test_idx)
>  {
>  	struct rte_ring *r;
>  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> @@ -214,11 +388,13 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> unsigned int create_flags,
>  	const unsigned int rsz = RING_SIZE - 1;
> 
>  	for (i = 0; i < RTE_DIM(esize); i++) {
> -		test_ring_print_test_string(tname, api_type, esize[i]);
> +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> 
>  		/* Create the ring */
>  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> -					RING_SIZE, SOCKET_ID_ANY,
> create_flags);
> +				RING_SIZE, SOCKET_ID_ANY,
> +				test_enqdeq_impl[test_idx].create_flags);
> 
>  		/* alloc dummy object pointers */
>  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -240,17
> +416,17 @@ test_ring_burst_bulk_tests1(unsigned int api_type, unsigned int
> create_flags,
>  			rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL);
>  			printf("%s: iteration %u, random shift: %u;\n",
>  			    __func__, i, rand);
> -			ret = test_ring_enqueue(r, cur_src, esize[i], rand,
> -							api_type);
> +			ret = test_ring_enq_impl(r, cur_src, esize[i], rand,
> +							test_idx);
>  			TEST_RING_VERIFY(ret != 0);
> 
> -			ret = test_ring_dequeue(r, cur_dst, esize[i], rand,
> -							api_type);
> +			ret = test_ring_deq_impl(r, cur_dst, esize[i], rand,
> +							test_idx);
>  			TEST_RING_VERIFY(ret == rand);
> 
>  			/* fill the ring */
> -			ret = test_ring_enqueue(r, cur_src, esize[i], rsz,
> -							api_type);
> +			ret = test_ring_enq_impl(r, cur_src, esize[i], rsz,
> +							test_idx);
>  			TEST_RING_VERIFY(ret != 0);
> 
>  			TEST_RING_VERIFY(rte_ring_free_count(r) == 0); @@
> -259,8 +435,8 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> unsigned int create_flags,
>  			TEST_RING_VERIFY(rte_ring_empty(r) == 0);
> 
>  			/* empty the ring */
> -			ret = test_ring_dequeue(r, cur_dst, esize[i], rsz,
> -							api_type);
> +			ret = test_ring_deq_impl(r, cur_dst, esize[i], rsz,
> +							test_idx);
>  			TEST_RING_VERIFY(ret == (int)rsz);
>  			TEST_RING_VERIFY(rsz == rte_ring_free_count(r));
>  			TEST_RING_VERIFY(rte_ring_count(r) == 0); @@ -
> 294,8 +470,7 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> unsigned int create_flags,
>   * dequeued data.
>   */
>  static int
> -test_ring_burst_bulk_tests2(unsigned int api_type, unsigned int create_flags,
> -	const char *tname)
> +test_ring_burst_bulk_tests2(unsigned int test_idx)
>  {
>  	struct rte_ring *r;
>  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> @@ -303,11 +478,13 @@ test_ring_burst_bulk_tests2(unsigned int api_type,
> unsigned int create_flags,
>  	unsigned int i;
> 
>  	for (i = 0; i < RTE_DIM(esize); i++) {
> -		test_ring_print_test_string(tname, api_type, esize[i]);
> +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> 
>  		/* Create the ring */
>  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> -					RING_SIZE, SOCKET_ID_ANY,
> create_flags);
> +				RING_SIZE, SOCKET_ID_ANY,
> +				test_enqdeq_impl[test_idx].create_flags);
> 
>  		/* alloc dummy object pointers */
>  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -323,39
> +500,39 @@ test_ring_burst_bulk_tests2(unsigned int api_type, unsigned int
> create_flags,
>  		cur_dst = dst;
> 
>  		printf("enqueue 1 obj\n");
> -		ret = test_ring_enqueue(r, cur_src, esize[i], 1, api_type);
> +		ret = test_ring_enq_impl(r, cur_src, esize[i], 1, test_idx);
>  		if (ret != 1)
>  			goto fail;
>  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
> 
>  		printf("enqueue 2 objs\n");
> -		ret = test_ring_enqueue(r, cur_src, esize[i], 2, api_type);
> +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
>  		if (ret != 2)
>  			goto fail;
>  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
> 
>  		printf("enqueue MAX_BULK objs\n");
> -		ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
> -						api_type);
> +		ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
> +						test_idx);
>  		if (ret != MAX_BULK)
>  			goto fail;
>  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK);
> 
>  		printf("dequeue 1 obj\n");
> -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1, api_type);
> +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1, test_idx);
>  		if (ret != 1)
>  			goto fail;
>  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
> 
>  		printf("dequeue 2 objs\n");
> -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2, api_type);
> +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
>  		if (ret != 2)
>  			goto fail;
>  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
> 
>  		printf("dequeue MAX_BULK objs\n");
> -		ret = test_ring_dequeue(r, cur_dst, esize[i], MAX_BULK,
> -						api_type);
> +		ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
> +						test_idx);
>  		if (ret != MAX_BULK)
>  			goto fail;
>  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK); @@
> -390,8 +567,7 @@ test_ring_burst_bulk_tests2(unsigned int api_type,
> unsigned int create_flags,
>   * Enqueue and dequeue to cover the entire ring length.
>   */
>  static int
> -test_ring_burst_bulk_tests3(unsigned int api_type, unsigned int create_flags,
> -	const char *tname)
> +test_ring_burst_bulk_tests3(unsigned int test_idx)
>  {
>  	struct rte_ring *r;
>  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> @@ -399,11 +575,13 @@ test_ring_burst_bulk_tests3(unsigned int api_type,
> unsigned int create_flags,
>  	unsigned int i, j;
> 
>  	for (i = 0; i < RTE_DIM(esize); i++) {
> -		test_ring_print_test_string(tname, api_type, esize[i]);
> +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> 
>  		/* Create the ring */
>  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> -					RING_SIZE, SOCKET_ID_ANY,
> create_flags);
> +				RING_SIZE, SOCKET_ID_ANY,
> +				test_enqdeq_impl[test_idx].create_flags);
> 
>  		/* alloc dummy object pointers */
>  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -420,15
> +598,15 @@ test_ring_burst_bulk_tests3(unsigned int api_type, unsigned int
> create_flags,
> 
>  		printf("fill and empty the ring\n");
>  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> -			ret = test_ring_enqueue(r, cur_src, esize[i],
> MAX_BULK,
> -							api_type);
> +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> MAX_BULK,
> +							test_idx);
>  			if (ret != MAX_BULK)
>  				goto fail;
>  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
>  								MAX_BULK);
> 
> -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> MAX_BULK,
> -							api_type);
> +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> MAX_BULK,
> +							test_idx);
>  			if (ret != MAX_BULK)
>  				goto fail;
>  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> 465,21 +643,24 @@ test_ring_burst_bulk_tests3(unsigned int api_type,
> unsigned int create_flags,
>   * Enqueue till the ring is full and dequeue till the ring becomes empty.
>   */
>  static int
> -test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int create_flags,
> -	const char *tname)
> +test_ring_burst_bulk_tests4(unsigned int test_idx)
>  {
>  	struct rte_ring *r;
>  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
>  	int ret;
>  	unsigned int i, j;
> -	unsigned int num_elems;
> +	unsigned int api_type, num_elems;
> +
> +	api_type = test_enqdeq_impl[test_idx].api_type;
> 
>  	for (i = 0; i < RTE_DIM(esize); i++) {
> -		test_ring_print_test_string(tname, api_type, esize[i]);
> +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> 
>  		/* Create the ring */
>  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> -					RING_SIZE, SOCKET_ID_ANY,
> create_flags);
> +				RING_SIZE, SOCKET_ID_ANY,
> +				test_enqdeq_impl[test_idx].create_flags);
> 
>  		/* alloc dummy object pointers */
>  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -496,8
> +677,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int
> create_flags,
> 
>  		printf("Test enqueue without enough memory space\n");
>  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
> -			ret = test_ring_enqueue(r, cur_src, esize[i],
> MAX_BULK,
> -							api_type);
> +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> MAX_BULK,
> +							test_idx);
>  			if (ret != MAX_BULK)
>  				goto fail;
>  			cur_src = test_ring_inc_ptr(cur_src, esize[i], @@ -
> 505,7 +686,7 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> unsigned int create_flags,
>  		}
> 
>  		printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n");
> -		ret = test_ring_enqueue(r, cur_src, esize[i], 2, api_type);
> +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
>  		if (ret != 2)
>  			goto fail;
>  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); @@ -517,8
> +698,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int
> create_flags,
>  		else
>  			num_elems = MAX_BULK;
>  		/* Always one free entry left */
> -		ret = test_ring_enqueue(r, cur_src, esize[i], num_elems,
> -						api_type);
> +		ret = test_ring_enq_impl(r, cur_src, esize[i], num_elems,
> +						test_idx);
>  		if (ret != MAX_BULK - 3)
>  			goto fail;
>  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK - 3);
> @@ -528,15 +709,15 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> unsigned int create_flags,
>  			goto fail;
> 
>  		printf("Test enqueue for a full entry\n");
> -		ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
> -						api_type);
> +		ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
> +						test_idx);
>  		if (ret != 0)
>  			goto fail;
> 
>  		printf("Test dequeue without enough objects\n");
>  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> MAX_BULK,
> -							api_type);
> +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> MAX_BULK,
> +							test_idx);
>  			if (ret != MAX_BULK)
>  				goto fail;
>  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> 544,7 +725,7 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> unsigned int create_flags,
>  		}
> 
>  		/* Available memory space for the exact MAX_BULK entries
> */
> -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2, api_type);
> +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
>  		if (ret != 2)
>  			goto fail;
>  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); @@ -554,8
> +735,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int
> create_flags,
>  			num_elems = MAX_BULK - 3;
>  		else
>  			num_elems = MAX_BULK;
> -		ret = test_ring_dequeue(r, cur_dst, esize[i], num_elems,
> -						api_type);
> +		ret = test_ring_deq_impl(r, cur_dst, esize[i], num_elems,
> +						test_idx);
>  		if (ret != MAX_BULK - 3)
>  			goto fail;
>  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK - 3);
> @@ -816,22 +997,7 @@ static int
>  test_ring(void)
>  {
>  	int32_t rc;
> -	unsigned int i, j;
> -	const char *tname;
> -
> -	static const struct {
> -		uint32_t create_flags;
> -		const char *name;
> -	} test_sync_modes[] = {
> -		{
> -			RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ,
> -			"Test MT_RTS ring",
> -		},
> -		{
> -			RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ,
> -			"Test MT_HTS ring",
> -		},
> -	};
> +	unsigned int i;
> 
>  	/* Negative test cases */
>  	if (test_ring_negative_tests() < 0)
> @@ -848,65 +1014,24 @@ test_ring(void)
>  	 * The test cases are split into smaller test cases to
>  	 * help clang compile faster.
>  	 */
> -	tname = "Test standard ring";
> -
> -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> -		for (i = TEST_RING_THREAD_DEF;
> -					i <= TEST_RING_THREAD_MPMC; i
> <<= 1)
> -			if (test_ring_burst_bulk_tests1(i | j, 0, tname) < 0)
> -				goto test_fail;
> -
> -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> -		for (i = TEST_RING_THREAD_DEF;
> -					i <= TEST_RING_THREAD_MPMC; i
> <<= 1)
> -			if (test_ring_burst_bulk_tests2(i | j, 0, tname) < 0)
> -				goto test_fail;
> -
> -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> -		for (i = TEST_RING_THREAD_DEF;
> -					i <= TEST_RING_THREAD_MPMC; i
> <<= 1)
> -			if (test_ring_burst_bulk_tests3(i | j, 0, tname) < 0)
> -				goto test_fail;
> -
> -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> -		for (i = TEST_RING_THREAD_DEF;
> -					i <= TEST_RING_THREAD_MPMC; i
> <<= 1)
> -			if (test_ring_burst_bulk_tests4(i | j, 0, tname) < 0)
> -				goto test_fail;
> -
> -	/* Burst and bulk operations with MT_RTS and MT_HTS sync modes
> */
> -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> -		for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> -				j <<= 1) {
> -
> -			rc = test_ring_burst_bulk_tests1(
> -				TEST_RING_THREAD_DEF | j,
> -				test_sync_modes[i].create_flags,
> -				test_sync_modes[i].name);
> -			if (rc < 0)
> -				goto test_fail;
> -
> -			rc = test_ring_burst_bulk_tests2(
> -				TEST_RING_THREAD_DEF | j,
> -				test_sync_modes[i].create_flags,
> -				test_sync_modes[i].name);
> -			if (rc < 0)
> -				goto test_fail;
> -
> -			rc = test_ring_burst_bulk_tests3(
> -				TEST_RING_THREAD_DEF | j,
> -				test_sync_modes[i].create_flags,
> -				test_sync_modes[i].name);
> -			if (rc < 0)
> -				goto test_fail;
> -
> -			rc = test_ring_burst_bulk_tests3(
> -				TEST_RING_THREAD_DEF | j,
> -				test_sync_modes[i].create_flags,
> -				test_sync_modes[i].name);
> -			if (rc < 0)
> -				goto test_fail;
> -		}
> +	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
> +
> +
> +		rc = test_ring_burst_bulk_tests1(i);
> +		if (rc < 0)
> +			goto test_fail;
> +
> +		rc = test_ring_burst_bulk_tests2(i);
> +		if (rc < 0)
> +			goto test_fail;
> +
> +		rc = test_ring_burst_bulk_tests3(i);
> +		if (rc < 0)
> +			goto test_fail;
> +
> +		rc = test_ring_burst_bulk_tests4(i);
> +		if (rc < 0)
> +			goto test_fail;
>  	}
> 
>  	/* dump the ring status */
> --
> 2.17.1
Ananyev, Konstantin April 30, 2020, 2:43 p.m. UTC | #4
Hi Honnappa,
 
> Hi Konstantin,
> 	I like the way the tests are organized and it looks good.
> 
> I am just wondering about the way it is being tested here. The intent to write the test cases the way they are currently is to mimic how the
> APIs would be used mostly. IMO, the APIs would be used with a constant value for element size so that the compiler will throw away the
> unwanted code (in the functions where the actual copy is being done).
> 
> With your method here, it looks to me like all the branches in the copy functions are kept and the branch decisions are done at run time.
> Is  my understanding correct?

You mean branching on esize[] values?
Actually from what I've seen that happens for both cases:
before and after the patch (gcc 7.3 -O3).

Main intention in my changes was to avoid using test_ring_enqueue/test_ring_dequeue,
as it seems too many branches here and it takes compiler a lot of effort to resolve all
of them at compile time.
So I replaced it with  array of function pointers (test_enqdeq_impl[]) and iterating over it.
That way compiler knows straightway which function to use.
 
> Can you please check this? https://patches.dpdk.org/patch/69567/

As I can see your approach reduces number of test-cases by factor of 5:
now each of test_ring_burst_bulk_tests[1-4] is executed only with just
one esize value, correct?
In term of compilation speed - it helps.
On my box with (gcc 7.3 -O3)  compiling test_ring.c takes:
orig code:                             ~100s
with 69567 (your patch):  < 20s
with 69559 (my patch):    < 10s

Konstantin
 
> 
> > -----Original Message-----
> > From: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > Sent: Wednesday, April 29, 2020 12:57 PM
> > To: dev@dpdk.org
> > Cc: aconole@redhat.com; Honnappa Nagarahalli
> > <Honnappa.Nagarahalli@arm.com>; Konstantin Ananyev
> > <konstantin.ananyev@intel.com>
> > Subject: [PATCH] test/ring: code rework to reduce compilation time
> >
> > Rework test code to reduce code complexity for the compiler and bring down
> > compilation time and memory consumption.
> >
> > Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > ---
> >  app/test/test_ring.c | 373 +++++++++++++++++++++++++++++--------------
> >  1 file changed, 249 insertions(+), 124 deletions(-)
> >
> > diff --git a/app/test/test_ring.c b/app/test/test_ring.c index
> > e21557cd9..0ae97d341 100644
> > --- a/app/test/test_ring.c
> > +++ b/app/test/test_ring.c
> > @@ -58,6 +58,181 @@
> >
> >  static const int esize[] = {-1, 4, 8, 16, 20};
> >
> > +static const struct {
> > +	const char *desc;
> > +	uint32_t api_type;
> > +	uint32_t create_flags;
> > +	struct {
> > +		unsigned int (*flegacy)(struct rte_ring *r,
> > +			void * const *obj_table, unsigned int n,
> > +			unsigned int *free_space);
> > +		unsigned int (*felem)(struct rte_ring *r, const void *obj_table,
> > +			unsigned int esize, unsigned int n,
> > +			unsigned int *free_space);
> > +	} enq;
> > +	struct {
> > +		unsigned int (*flegacy)(struct rte_ring *r,
> > +			void **obj_table, unsigned int n,
> > +			unsigned int *available);
> > +		unsigned int (*felem)(struct rte_ring *r, void *obj_table,
> > +			unsigned int esize, unsigned int n,
> > +			unsigned int *available);
> > +	} deq;
> > +} test_enqdeq_impl[] = {
> > +	{
> > +		.desc = "MP/MC sync mode",
> Details about the tests are already printed by the function 'test_ring_print_test_string'. This string should be 'Test standard ring'.
> 
> > +		.api_type = TEST_RING_ELEM_BULK |
> > TEST_RING_THREAD_DEF,
> > +		.create_flags = 0,
> > +		.enq = {
> > +			.flegacy = rte_ring_enqueue_bulk,
> > +			.felem = rte_ring_enqueue_bulk_elem,
> > +		},
> > +		.deq = {
> > +			.flegacy = rte_ring_dequeue_bulk,
> > +			.felem = rte_ring_dequeue_bulk_elem,
> > +		},
> > +	},
> > +	{
> > +		.desc = "SP/SC sync mode",
> > +		.api_type = TEST_RING_ELEM_BULK |
> > TEST_RING_THREAD_SPSC,
> > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > +		.enq = {
> > +			.flegacy = rte_ring_sp_enqueue_bulk,
> > +			.felem = rte_ring_sp_enqueue_bulk_elem,
> > +		},
> > +		.deq = {
> > +			.flegacy = rte_ring_sc_dequeue_bulk,
> > +			.felem = rte_ring_sc_dequeue_bulk_elem,
> > +		},
> > +	},
> > +	{
> > +		.desc = "MP/MC sync mode",
> > +		.api_type = TEST_RING_ELEM_BULK |
> > TEST_RING_THREAD_MPMC,
> > +		.create_flags = 0,
> > +		.enq = {
> > +			.flegacy = rte_ring_mp_enqueue_bulk,
> > +			.felem = rte_ring_mp_enqueue_bulk_elem,
> > +		},
> > +		.deq = {
> > +			.flegacy = rte_ring_mc_dequeue_bulk,
> > +			.felem = rte_ring_mc_dequeue_bulk_elem,
> > +		},
> > +	},
> > +	{
> > +		.desc = "MP_RTS/MC_RTS sync mode",
> > +		.api_type = TEST_RING_ELEM_BULK |
> > TEST_RING_THREAD_DEF,
> > +		.create_flags = RING_F_MP_RTS_ENQ |
> > RING_F_MC_RTS_DEQ,
> > +		.enq = {
> > +			.flegacy = rte_ring_enqueue_bulk,
> > +			.felem = rte_ring_enqueue_bulk_elem,
> > +		},
> > +		.deq = {
> > +			.flegacy = rte_ring_dequeue_bulk,
> > +			.felem = rte_ring_dequeue_bulk_elem,
> > +		},
> > +	},
> > +	{
> > +		.desc = "MP_HTS/MC_HTS sync mode",
> > +		.api_type = TEST_RING_ELEM_BULK |
> > TEST_RING_THREAD_DEF,
> > +		.create_flags = RING_F_MP_HTS_ENQ |
> > RING_F_MC_HTS_DEQ,
> > +		.enq = {
> > +			.flegacy = rte_ring_enqueue_bulk,
> > +			.felem = rte_ring_enqueue_bulk_elem,
> > +		},
> > +		.deq = {
> > +			.flegacy = rte_ring_dequeue_bulk,
> > +			.felem = rte_ring_dequeue_bulk_elem,
> > +		},
> > +	},
> > +	{
> > +		.desc = "MP/MC sync mode",
> > +		.api_type = TEST_RING_ELEM_BURST |
> > TEST_RING_THREAD_DEF,
> > +		.create_flags = 0,
> > +		.enq = {
> > +			.flegacy = rte_ring_enqueue_burst,
> > +			.felem = rte_ring_enqueue_burst_elem,
> > +		},
> > +		.deq = {
> > +			.flegacy = rte_ring_dequeue_burst,
> > +			.felem = rte_ring_dequeue_burst_elem,
> > +		},
> > +	},
> > +	{
> > +		.desc = "SP/SC sync mode",
> > +		.api_type = TEST_RING_ELEM_BURST |
> > TEST_RING_THREAD_SPSC,
> > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > +		.enq = {
> > +			.flegacy = rte_ring_sp_enqueue_burst,
> > +			.felem = rte_ring_sp_enqueue_burst_elem,
> > +		},
> > +		.deq = {
> > +			.flegacy = rte_ring_sc_dequeue_burst,
> > +			.felem = rte_ring_sc_dequeue_burst_elem,
> > +		},
> > +	},
> > +	{
> > +		.desc = "MP/MC sync mode",
> > +		.api_type = TEST_RING_ELEM_BURST |
> > TEST_RING_THREAD_MPMC,
> > +		.create_flags = 0,
> > +		.enq = {
> > +			.flegacy = rte_ring_mp_enqueue_burst,
> > +			.felem = rte_ring_mp_enqueue_burst_elem,
> > +		},
> > +		.deq = {
> > +			.flegacy = rte_ring_mc_dequeue_burst,
> > +			.felem = rte_ring_mc_dequeue_burst_elem,
> > +		},
> > +	},
> > +	{
> > +		.desc = "MP_RTS/MC_RTS sync mode",
> > +		.api_type = TEST_RING_ELEM_BURST |
> > TEST_RING_THREAD_DEF,
> > +		.create_flags = RING_F_MP_RTS_ENQ |
> > RING_F_MC_RTS_DEQ,
> > +		.enq = {
> > +			.flegacy = rte_ring_enqueue_burst,
> > +			.felem = rte_ring_enqueue_burst_elem,
> > +		},
> > +		.deq = {
> > +			.flegacy = rte_ring_dequeue_burst,
> > +			.felem = rte_ring_dequeue_burst_elem,
> > +		},
> > +	},
> > +	{
> > +		.desc = "MP_HTS/MC_HTS sync mode",
> > +		.api_type = TEST_RING_ELEM_BURST |
> > TEST_RING_THREAD_DEF,
> > +		.create_flags = RING_F_MP_HTS_ENQ |
> > RING_F_MC_HTS_DEQ,
> > +		.enq = {
> > +			.flegacy = rte_ring_enqueue_burst,
> > +			.felem = rte_ring_enqueue_burst_elem,
> > +		},
> > +		.deq = {
> > +			.flegacy = rte_ring_dequeue_burst,
> > +			.felem = rte_ring_dequeue_burst_elem,
> > +		},
> > +	},
> > +};
> > +
> > +static unsigned int
> > +test_ring_enq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n,
> > +	unsigned int test_idx)
> > +{
> > +	if (esize == -1)
> > +		return test_enqdeq_impl[test_idx].enq.flegacy(r, obj, n, NULL);
> > +	else
> > +		return test_enqdeq_impl[test_idx].enq.felem(r, obj, esize, n,
> > +			NULL);
> > +}
> > +
> > +static unsigned int
> > +test_ring_deq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n,
> > +	unsigned int test_idx)
> > +{
> > +	if (esize == -1)
> > +		return test_enqdeq_impl[test_idx].deq.flegacy(r, obj, n, NULL);
> > +	else
> > +		return test_enqdeq_impl[test_idx].deq.felem(r, obj, esize, n,
> > +			NULL);
> > +}
> > +
> >  static void**
> >  test_ring_inc_ptr(void **obj, int esize, unsigned int n)  { @@ -203,8 +378,7
> > @@ test_ring_negative_tests(void)
> >   * Random number of elements are enqueued and dequeued.
> >   */
> >  static int
> > -test_ring_burst_bulk_tests1(unsigned int api_type, unsigned int create_flags,
> > -	const char *tname)
> > +test_ring_burst_bulk_tests1(unsigned int test_idx)
> >  {
> >  	struct rte_ring *r;
> >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> > @@ -214,11 +388,13 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> > unsigned int create_flags,
> >  	const unsigned int rsz = RING_SIZE - 1;
> >
> >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> >
> >  		/* Create the ring */
> >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > -					RING_SIZE, SOCKET_ID_ANY,
> > create_flags);
> > +				RING_SIZE, SOCKET_ID_ANY,
> > +				test_enqdeq_impl[test_idx].create_flags);
> >
> >  		/* alloc dummy object pointers */
> >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -240,17
> > +416,17 @@ test_ring_burst_bulk_tests1(unsigned int api_type, unsigned int
> > create_flags,
> >  			rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL);
> >  			printf("%s: iteration %u, random shift: %u;\n",
> >  			    __func__, i, rand);
> > -			ret = test_ring_enqueue(r, cur_src, esize[i], rand,
> > -							api_type);
> > +			ret = test_ring_enq_impl(r, cur_src, esize[i], rand,
> > +							test_idx);
> >  			TEST_RING_VERIFY(ret != 0);
> >
> > -			ret = test_ring_dequeue(r, cur_dst, esize[i], rand,
> > -							api_type);
> > +			ret = test_ring_deq_impl(r, cur_dst, esize[i], rand,
> > +							test_idx);
> >  			TEST_RING_VERIFY(ret == rand);
> >
> >  			/* fill the ring */
> > -			ret = test_ring_enqueue(r, cur_src, esize[i], rsz,
> > -							api_type);
> > +			ret = test_ring_enq_impl(r, cur_src, esize[i], rsz,
> > +							test_idx);
> >  			TEST_RING_VERIFY(ret != 0);
> >
> >  			TEST_RING_VERIFY(rte_ring_free_count(r) == 0); @@
> > -259,8 +435,8 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> > unsigned int create_flags,
> >  			TEST_RING_VERIFY(rte_ring_empty(r) == 0);
> >
> >  			/* empty the ring */
> > -			ret = test_ring_dequeue(r, cur_dst, esize[i], rsz,
> > -							api_type);
> > +			ret = test_ring_deq_impl(r, cur_dst, esize[i], rsz,
> > +							test_idx);
> >  			TEST_RING_VERIFY(ret == (int)rsz);
> >  			TEST_RING_VERIFY(rsz == rte_ring_free_count(r));
> >  			TEST_RING_VERIFY(rte_ring_count(r) == 0); @@ -
> > 294,8 +470,7 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> > unsigned int create_flags,
> >   * dequeued data.
> >   */
> >  static int
> > -test_ring_burst_bulk_tests2(unsigned int api_type, unsigned int create_flags,
> > -	const char *tname)
> > +test_ring_burst_bulk_tests2(unsigned int test_idx)
> >  {
> >  	struct rte_ring *r;
> >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> > @@ -303,11 +478,13 @@ test_ring_burst_bulk_tests2(unsigned int api_type,
> > unsigned int create_flags,
> >  	unsigned int i;
> >
> >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> >
> >  		/* Create the ring */
> >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > -					RING_SIZE, SOCKET_ID_ANY,
> > create_flags);
> > +				RING_SIZE, SOCKET_ID_ANY,
> > +				test_enqdeq_impl[test_idx].create_flags);
> >
> >  		/* alloc dummy object pointers */
> >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -323,39
> > +500,39 @@ test_ring_burst_bulk_tests2(unsigned int api_type, unsigned int
> > create_flags,
> >  		cur_dst = dst;
> >
> >  		printf("enqueue 1 obj\n");
> > -		ret = test_ring_enqueue(r, cur_src, esize[i], 1, api_type);
> > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 1, test_idx);
> >  		if (ret != 1)
> >  			goto fail;
> >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
> >
> >  		printf("enqueue 2 objs\n");
> > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2, api_type);
> > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
> >  		if (ret != 2)
> >  			goto fail;
> >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
> >
> >  		printf("enqueue MAX_BULK objs\n");
> > -		ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
> > -						api_type);
> > +		ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
> > +						test_idx);
> >  		if (ret != MAX_BULK)
> >  			goto fail;
> >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK);
> >
> >  		printf("dequeue 1 obj\n");
> > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1, api_type);
> > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1, test_idx);
> >  		if (ret != 1)
> >  			goto fail;
> >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
> >
> >  		printf("dequeue 2 objs\n");
> > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2, api_type);
> > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
> >  		if (ret != 2)
> >  			goto fail;
> >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
> >
> >  		printf("dequeue MAX_BULK objs\n");
> > -		ret = test_ring_dequeue(r, cur_dst, esize[i], MAX_BULK,
> > -						api_type);
> > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
> > +						test_idx);
> >  		if (ret != MAX_BULK)
> >  			goto fail;
> >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK); @@
> > -390,8 +567,7 @@ test_ring_burst_bulk_tests2(unsigned int api_type,
> > unsigned int create_flags,
> >   * Enqueue and dequeue to cover the entire ring length.
> >   */
> >  static int
> > -test_ring_burst_bulk_tests3(unsigned int api_type, unsigned int create_flags,
> > -	const char *tname)
> > +test_ring_burst_bulk_tests3(unsigned int test_idx)
> >  {
> >  	struct rte_ring *r;
> >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> > @@ -399,11 +575,13 @@ test_ring_burst_bulk_tests3(unsigned int api_type,
> > unsigned int create_flags,
> >  	unsigned int i, j;
> >
> >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> >
> >  		/* Create the ring */
> >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > -					RING_SIZE, SOCKET_ID_ANY,
> > create_flags);
> > +				RING_SIZE, SOCKET_ID_ANY,
> > +				test_enqdeq_impl[test_idx].create_flags);
> >
> >  		/* alloc dummy object pointers */
> >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -420,15
> > +598,15 @@ test_ring_burst_bulk_tests3(unsigned int api_type, unsigned int
> > create_flags,
> >
> >  		printf("fill and empty the ring\n");
> >  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > MAX_BULK,
> > -							api_type);
> > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > MAX_BULK,
> > +							test_idx);
> >  			if (ret != MAX_BULK)
> >  				goto fail;
> >  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
> >  								MAX_BULK);
> >
> > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > MAX_BULK,
> > -							api_type);
> > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > MAX_BULK,
> > +							test_idx);
> >  			if (ret != MAX_BULK)
> >  				goto fail;
> >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> > 465,21 +643,24 @@ test_ring_burst_bulk_tests3(unsigned int api_type,
> > unsigned int create_flags,
> >   * Enqueue till the ring is full and dequeue till the ring becomes empty.
> >   */
> >  static int
> > -test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int create_flags,
> > -	const char *tname)
> > +test_ring_burst_bulk_tests4(unsigned int test_idx)
> >  {
> >  	struct rte_ring *r;
> >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> >  	int ret;
> >  	unsigned int i, j;
> > -	unsigned int num_elems;
> > +	unsigned int api_type, num_elems;
> > +
> > +	api_type = test_enqdeq_impl[test_idx].api_type;
> >
> >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> >
> >  		/* Create the ring */
> >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > -					RING_SIZE, SOCKET_ID_ANY,
> > create_flags);
> > +				RING_SIZE, SOCKET_ID_ANY,
> > +				test_enqdeq_impl[test_idx].create_flags);
> >
> >  		/* alloc dummy object pointers */
> >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -496,8
> > +677,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int
> > create_flags,
> >
> >  		printf("Test enqueue without enough memory space\n");
> >  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
> > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > MAX_BULK,
> > -							api_type);
> > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > MAX_BULK,
> > +							test_idx);
> >  			if (ret != MAX_BULK)
> >  				goto fail;
> >  			cur_src = test_ring_inc_ptr(cur_src, esize[i], @@ -
> > 505,7 +686,7 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > unsigned int create_flags,
> >  		}
> >
> >  		printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n");
> > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2, api_type);
> > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
> >  		if (ret != 2)
> >  			goto fail;
> >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); @@ -517,8
> > +698,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int
> > create_flags,
> >  		else
> >  			num_elems = MAX_BULK;
> >  		/* Always one free entry left */
> > -		ret = test_ring_enqueue(r, cur_src, esize[i], num_elems,
> > -						api_type);
> > +		ret = test_ring_enq_impl(r, cur_src, esize[i], num_elems,
> > +						test_idx);
> >  		if (ret != MAX_BULK - 3)
> >  			goto fail;
> >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK - 3);
> > @@ -528,15 +709,15 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > unsigned int create_flags,
> >  			goto fail;
> >
> >  		printf("Test enqueue for a full entry\n");
> > -		ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
> > -						api_type);
> > +		ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
> > +						test_idx);
> >  		if (ret != 0)
> >  			goto fail;
> >
> >  		printf("Test dequeue without enough objects\n");
> >  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > MAX_BULK,
> > -							api_type);
> > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > MAX_BULK,
> > +							test_idx);
> >  			if (ret != MAX_BULK)
> >  				goto fail;
> >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> > 544,7 +725,7 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > unsigned int create_flags,
> >  		}
> >
> >  		/* Available memory space for the exact MAX_BULK entries
> > */
> > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2, api_type);
> > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
> >  		if (ret != 2)
> >  			goto fail;
> >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); @@ -554,8
> > +735,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int
> > create_flags,
> >  			num_elems = MAX_BULK - 3;
> >  		else
> >  			num_elems = MAX_BULK;
> > -		ret = test_ring_dequeue(r, cur_dst, esize[i], num_elems,
> > -						api_type);
> > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], num_elems,
> > +						test_idx);
> >  		if (ret != MAX_BULK - 3)
> >  			goto fail;
> >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK - 3);
> > @@ -816,22 +997,7 @@ static int
> >  test_ring(void)
> >  {
> >  	int32_t rc;
> > -	unsigned int i, j;
> > -	const char *tname;
> > -
> > -	static const struct {
> > -		uint32_t create_flags;
> > -		const char *name;
> > -	} test_sync_modes[] = {
> > -		{
> > -			RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ,
> > -			"Test MT_RTS ring",
> > -		},
> > -		{
> > -			RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ,
> > -			"Test MT_HTS ring",
> > -		},
> > -	};
> > +	unsigned int i;
> >
> >  	/* Negative test cases */
> >  	if (test_ring_negative_tests() < 0)
> > @@ -848,65 +1014,24 @@ test_ring(void)
> >  	 * The test cases are split into smaller test cases to
> >  	 * help clang compile faster.
> >  	 */
> > -	tname = "Test standard ring";
> > -
> > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> > -		for (i = TEST_RING_THREAD_DEF;
> > -					i <= TEST_RING_THREAD_MPMC; i
> > <<= 1)
> > -			if (test_ring_burst_bulk_tests1(i | j, 0, tname) < 0)
> > -				goto test_fail;
> > -
> > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> > -		for (i = TEST_RING_THREAD_DEF;
> > -					i <= TEST_RING_THREAD_MPMC; i
> > <<= 1)
> > -			if (test_ring_burst_bulk_tests2(i | j, 0, tname) < 0)
> > -				goto test_fail;
> > -
> > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> > -		for (i = TEST_RING_THREAD_DEF;
> > -					i <= TEST_RING_THREAD_MPMC; i
> > <<= 1)
> > -			if (test_ring_burst_bulk_tests3(i | j, 0, tname) < 0)
> > -				goto test_fail;
> > -
> > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> > -		for (i = TEST_RING_THREAD_DEF;
> > -					i <= TEST_RING_THREAD_MPMC; i
> > <<= 1)
> > -			if (test_ring_burst_bulk_tests4(i | j, 0, tname) < 0)
> > -				goto test_fail;
> > -
> > -	/* Burst and bulk operations with MT_RTS and MT_HTS sync modes
> > */
> > -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> > -		for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > -				j <<= 1) {
> > -
> > -			rc = test_ring_burst_bulk_tests1(
> > -				TEST_RING_THREAD_DEF | j,
> > -				test_sync_modes[i].create_flags,
> > -				test_sync_modes[i].name);
> > -			if (rc < 0)
> > -				goto test_fail;
> > -
> > -			rc = test_ring_burst_bulk_tests2(
> > -				TEST_RING_THREAD_DEF | j,
> > -				test_sync_modes[i].create_flags,
> > -				test_sync_modes[i].name);
> > -			if (rc < 0)
> > -				goto test_fail;
> > -
> > -			rc = test_ring_burst_bulk_tests3(
> > -				TEST_RING_THREAD_DEF | j,
> > -				test_sync_modes[i].create_flags,
> > -				test_sync_modes[i].name);
> > -			if (rc < 0)
> > -				goto test_fail;
> > -
> > -			rc = test_ring_burst_bulk_tests3(
> > -				TEST_RING_THREAD_DEF | j,
> > -				test_sync_modes[i].create_flags,
> > -				test_sync_modes[i].name);
> > -			if (rc < 0)
> > -				goto test_fail;
> > -		}
> > +	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
> > +
> > +
> > +		rc = test_ring_burst_bulk_tests1(i);
> > +		if (rc < 0)
> > +			goto test_fail;
> > +
> > +		rc = test_ring_burst_bulk_tests2(i);
> > +		if (rc < 0)
> > +			goto test_fail;
> > +
> > +		rc = test_ring_burst_bulk_tests3(i);
> > +		if (rc < 0)
> > +			goto test_fail;
> > +
> > +		rc = test_ring_burst_bulk_tests4(i);
> > +		if (rc < 0)
> > +			goto test_fail;
> >  	}
> >
> >  	/* dump the ring status */
> > --
> > 2.17.1
Honnappa Nagarahalli May 1, 2020, 5:48 p.m. UTC | #5
<snip>

> 
> 
> Hi Honnappa,
> 
> > Hi Konstantin,
> > 	I like the way the tests are organized and it looks good.
> >
> > I am just wondering about the way it is being tested here. The intent
> > to write the test cases the way they are currently is to mimic how the
> > APIs would be used mostly. IMO, the APIs would be used with a constant
> value for element size so that the compiler will throw away the unwanted
> code (in the functions where the actual copy is being done).
> >
> > With your method here, it looks to me like all the branches in the copy
> functions are kept and the branch decisions are done at run time.
> > Is  my understanding correct?
> 
> You mean branching on esize[] values?
Yes

> Actually from what I've seen that happens for both cases:
> before and after the patch (gcc 7.3 -O3).
I did not look at the generated code. If it is happening with your patch too, I think we can go with your patch. But, can you do similar change to test_ring_perf.c to keep it consistent?

> 
> Main intention in my changes was to avoid using
> test_ring_enqueue/test_ring_dequeue,
> as it seems too many branches here and it takes compiler a lot of effort to
> resolve all of them at compile time.
> So I replaced it with  array of function pointers (test_enqdeq_impl[]) and
> iterating over it.
> That way compiler knows straightway which function to use.
> 
> > Can you please check this? https://patches.dpdk.org/patch/69567/
> 
> As I can see your approach reduces number of test-cases by factor of 5:
> now each of test_ring_burst_bulk_tests[1-4] is executed only with just one
> esize value, correct?
Yes, basically test_ring_burst_bulk_tests[1-4] were covering different scenarios with the same APIs. So, distributed the esize across different test functions.

> In term of compilation speed - it helps.
> On my box with (gcc 7.3 -O3)  compiling test_ring.c takes:
> orig code:                             ~100s
> with 69567 (your patch):  < 20s
> with 69559 (my patch):    < 10s
> 
> Konstantin
> 
> >
> > > -----Original Message-----
> > > From: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > > Sent: Wednesday, April 29, 2020 12:57 PM
> > > To: dev@dpdk.org
> > > Cc: aconole@redhat.com; Honnappa Nagarahalli
> > > <Honnappa.Nagarahalli@arm.com>; Konstantin Ananyev
> > > <konstantin.ananyev@intel.com>
> > > Subject: [PATCH] test/ring: code rework to reduce compilation time
> > >
> > > Rework test code to reduce code complexity for the compiler and
> > > bring down compilation time and memory consumption.
> > >
> > > Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > > ---
> > >  app/test/test_ring.c | 373
> > > +++++++++++++++++++++++++++++--------------
> > >  1 file changed, 249 insertions(+), 124 deletions(-)
> > >
> > > diff --git a/app/test/test_ring.c b/app/test/test_ring.c index
> > > e21557cd9..0ae97d341 100644
> > > --- a/app/test/test_ring.c
> > > +++ b/app/test/test_ring.c
> > > @@ -58,6 +58,181 @@
> > >
> > >  static const int esize[] = {-1, 4, 8, 16, 20};
> > >
> > > +static const struct {
> > > +	const char *desc;
> > > +	uint32_t api_type;
> > > +	uint32_t create_flags;
> > > +	struct {
> > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > +			void * const *obj_table, unsigned int n,
> > > +			unsigned int *free_space);
> > > +		unsigned int (*felem)(struct rte_ring *r, const void *obj_table,
> > > +			unsigned int esize, unsigned int n,
> > > +			unsigned int *free_space);
> > > +	} enq;
> > > +	struct {
> > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > +			void **obj_table, unsigned int n,
> > > +			unsigned int *available);
> > > +		unsigned int (*felem)(struct rte_ring *r, void *obj_table,
> > > +			unsigned int esize, unsigned int n,
> > > +			unsigned int *available);
> > > +	} deq;
> > > +} test_enqdeq_impl[] = {
> > > +	{
> > > +		.desc = "MP/MC sync mode",
> > Details about the tests are already printed by the function
> 'test_ring_print_test_string'. This string should be 'Test standard ring'.
> >
> > > +		.api_type = TEST_RING_ELEM_BULK |
> > > TEST_RING_THREAD_DEF,
> > > +		.create_flags = 0,
> > > +		.enq = {
> > > +			.flegacy = rte_ring_enqueue_bulk,
> > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > +		},
> > > +		.deq = {
> > > +			.flegacy = rte_ring_dequeue_bulk,
> > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > +		},
> > > +	},
> > > +	{
> > > +		.desc = "SP/SC sync mode",
> > > +		.api_type = TEST_RING_ELEM_BULK |
> > > TEST_RING_THREAD_SPSC,
> > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > +		.enq = {
> > > +			.flegacy = rte_ring_sp_enqueue_bulk,
> > > +			.felem = rte_ring_sp_enqueue_bulk_elem,
> > > +		},
> > > +		.deq = {
> > > +			.flegacy = rte_ring_sc_dequeue_bulk,
> > > +			.felem = rte_ring_sc_dequeue_bulk_elem,
> > > +		},
> > > +	},
> > > +	{
> > > +		.desc = "MP/MC sync mode",
> > > +		.api_type = TEST_RING_ELEM_BULK |
> > > TEST_RING_THREAD_MPMC,
> > > +		.create_flags = 0,
> > > +		.enq = {
> > > +			.flegacy = rte_ring_mp_enqueue_bulk,
> > > +			.felem = rte_ring_mp_enqueue_bulk_elem,
> > > +		},
> > > +		.deq = {
> > > +			.flegacy = rte_ring_mc_dequeue_bulk,
> > > +			.felem = rte_ring_mc_dequeue_bulk_elem,
> > > +		},
> > > +	},
> > > +	{
> > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > +		.api_type = TEST_RING_ELEM_BULK |
> > > TEST_RING_THREAD_DEF,
> > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > RING_F_MC_RTS_DEQ,
> > > +		.enq = {
> > > +			.flegacy = rte_ring_enqueue_bulk,
> > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > +		},
> > > +		.deq = {
> > > +			.flegacy = rte_ring_dequeue_bulk,
> > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > +		},
> > > +	},
> > > +	{
> > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > +		.api_type = TEST_RING_ELEM_BULK |
> > > TEST_RING_THREAD_DEF,
> > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > RING_F_MC_HTS_DEQ,
> > > +		.enq = {
> > > +			.flegacy = rte_ring_enqueue_bulk,
> > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > +		},
> > > +		.deq = {
> > > +			.flegacy = rte_ring_dequeue_bulk,
> > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > +		},
> > > +	},
> > > +	{
> > > +		.desc = "MP/MC sync mode",
> > > +		.api_type = TEST_RING_ELEM_BURST |
> > > TEST_RING_THREAD_DEF,
> > > +		.create_flags = 0,
> > > +		.enq = {
> > > +			.flegacy = rte_ring_enqueue_burst,
> > > +			.felem = rte_ring_enqueue_burst_elem,
> > > +		},
> > > +		.deq = {
> > > +			.flegacy = rte_ring_dequeue_burst,
> > > +			.felem = rte_ring_dequeue_burst_elem,
> > > +		},
> > > +	},
> > > +	{
> > > +		.desc = "SP/SC sync mode",
> > > +		.api_type = TEST_RING_ELEM_BURST |
> > > TEST_RING_THREAD_SPSC,
> > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > +		.enq = {
> > > +			.flegacy = rte_ring_sp_enqueue_burst,
> > > +			.felem = rte_ring_sp_enqueue_burst_elem,
> > > +		},
> > > +		.deq = {
> > > +			.flegacy = rte_ring_sc_dequeue_burst,
> > > +			.felem = rte_ring_sc_dequeue_burst_elem,
> > > +		},
> > > +	},
> > > +	{
> > > +		.desc = "MP/MC sync mode",
> > > +		.api_type = TEST_RING_ELEM_BURST |
> > > TEST_RING_THREAD_MPMC,
> > > +		.create_flags = 0,
> > > +		.enq = {
> > > +			.flegacy = rte_ring_mp_enqueue_burst,
> > > +			.felem = rte_ring_mp_enqueue_burst_elem,
> > > +		},
> > > +		.deq = {
> > > +			.flegacy = rte_ring_mc_dequeue_burst,
> > > +			.felem = rte_ring_mc_dequeue_burst_elem,
> > > +		},
> > > +	},
> > > +	{
> > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > +		.api_type = TEST_RING_ELEM_BURST |
> > > TEST_RING_THREAD_DEF,
> > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > RING_F_MC_RTS_DEQ,
> > > +		.enq = {
> > > +			.flegacy = rte_ring_enqueue_burst,
> > > +			.felem = rte_ring_enqueue_burst_elem,
> > > +		},
> > > +		.deq = {
> > > +			.flegacy = rte_ring_dequeue_burst,
> > > +			.felem = rte_ring_dequeue_burst_elem,
> > > +		},
> > > +	},
> > > +	{
> > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > +		.api_type = TEST_RING_ELEM_BURST |
> > > TEST_RING_THREAD_DEF,
> > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > RING_F_MC_HTS_DEQ,
> > > +		.enq = {
> > > +			.flegacy = rte_ring_enqueue_burst,
> > > +			.felem = rte_ring_enqueue_burst_elem,
> > > +		},
> > > +		.deq = {
> > > +			.flegacy = rte_ring_dequeue_burst,
> > > +			.felem = rte_ring_dequeue_burst_elem,
> > > +		},
> > > +	},
> > > +};
> > > +
> > > +static unsigned int
> > > +test_ring_enq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n,
> > > +	unsigned int test_idx)
> > > +{
> > > +	if (esize == -1)
> > > +		return test_enqdeq_impl[test_idx].enq.flegacy(r, obj, n, NULL);
> > > +	else
> > > +		return test_enqdeq_impl[test_idx].enq.felem(r, obj, esize, n,
> > > +			NULL);
> > > +}
> > > +
> > > +static unsigned int
> > > +test_ring_deq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n,
> > > +	unsigned int test_idx)
> > > +{
> > > +	if (esize == -1)
> > > +		return test_enqdeq_impl[test_idx].deq.flegacy(r, obj, n, NULL);
> > > +	else
> > > +		return test_enqdeq_impl[test_idx].deq.felem(r, obj, esize, n,
> > > +			NULL);
> > > +}
> > > +
> > >  static void**
> > >  test_ring_inc_ptr(void **obj, int esize, unsigned int n)  { @@
> > > -203,8 +378,7 @@ test_ring_negative_tests(void)
> > >   * Random number of elements are enqueued and dequeued.
> > >   */
> > >  static int
> > > -test_ring_burst_bulk_tests1(unsigned int api_type, unsigned int
> create_flags,
> > > -	const char *tname)
> > > +test_ring_burst_bulk_tests1(unsigned int test_idx)
> > >  {
> > >  	struct rte_ring *r;
> > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst =
> > > NULL; @@ -214,11 +388,13 @@ test_ring_burst_bulk_tests1(unsigned int
> > > api_type, unsigned int create_flags,
> > >  	const unsigned int rsz = RING_SIZE - 1;
> > >
> > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > >
> > >  		/* Create the ring */
> > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > -					RING_SIZE, SOCKET_ID_ANY,
> > > create_flags);
> > > +				RING_SIZE, SOCKET_ID_ANY,
> > > +				test_enqdeq_impl[test_idx].create_flags);
> > >
> > >  		/* alloc dummy object pointers */
> > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -240,17
> > > +416,17 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> > > +unsigned int
> > > create_flags,
> > >  			rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL);
> > >  			printf("%s: iteration %u, random shift: %u;\n",
> > >  			    __func__, i, rand);
> > > -			ret = test_ring_enqueue(r, cur_src, esize[i], rand,
> > > -							api_type);
> > > +			ret = test_ring_enq_impl(r, cur_src, esize[i], rand,
> > > +							test_idx);
> > >  			TEST_RING_VERIFY(ret != 0);
> > >
> > > -			ret = test_ring_dequeue(r, cur_dst, esize[i], rand,
> > > -							api_type);
> > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i], rand,
> > > +							test_idx);
> > >  			TEST_RING_VERIFY(ret == rand);
> > >
> > >  			/* fill the ring */
> > > -			ret = test_ring_enqueue(r, cur_src, esize[i], rsz,
> > > -							api_type);
> > > +			ret = test_ring_enq_impl(r, cur_src, esize[i], rsz,
> > > +							test_idx);
> > >  			TEST_RING_VERIFY(ret != 0);
> > >
> > >  			TEST_RING_VERIFY(rte_ring_free_count(r) == 0); @@
> > > -259,8 +435,8 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> > > unsigned int create_flags,
> > >  			TEST_RING_VERIFY(rte_ring_empty(r) == 0);
> > >
> > >  			/* empty the ring */
> > > -			ret = test_ring_dequeue(r, cur_dst, esize[i], rsz,
> > > -							api_type);
> > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i], rsz,
> > > +							test_idx);
> > >  			TEST_RING_VERIFY(ret == (int)rsz);
> > >  			TEST_RING_VERIFY(rsz == rte_ring_free_count(r));
> > >  			TEST_RING_VERIFY(rte_ring_count(r) == 0); @@ -
> > > 294,8 +470,7 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> > > unsigned int create_flags,
> > >   * dequeued data.
> > >   */
> > >  static int
> > > -test_ring_burst_bulk_tests2(unsigned int api_type, unsigned int
> create_flags,
> > > -	const char *tname)
> > > +test_ring_burst_bulk_tests2(unsigned int test_idx)
> > >  {
> > >  	struct rte_ring *r;
> > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst =
> > > NULL; @@ -303,11 +478,13 @@ test_ring_burst_bulk_tests2(unsigned int
> > > api_type, unsigned int create_flags,
> > >  	unsigned int i;
> > >
> > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > >
> > >  		/* Create the ring */
> > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > -					RING_SIZE, SOCKET_ID_ANY,
> > > create_flags);
> > > +				RING_SIZE, SOCKET_ID_ANY,
> > > +				test_enqdeq_impl[test_idx].create_flags);
> > >
> > >  		/* alloc dummy object pointers */
> > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -323,39
> > > +500,39 @@ test_ring_burst_bulk_tests2(unsigned int api_type,
> > > +unsigned int
> > > create_flags,
> > >  		cur_dst = dst;
> > >
> > >  		printf("enqueue 1 obj\n");
> > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 1, api_type);
> > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 1, test_idx);
> > >  		if (ret != 1)
> > >  			goto fail;
> > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
> > >
> > >  		printf("enqueue 2 objs\n");
> > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2, api_type);
> > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
> > >  		if (ret != 2)
> > >  			goto fail;
> > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
> > >
> > >  		printf("enqueue MAX_BULK objs\n");
> > > -		ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
> > > -						api_type);
> > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
> > > +						test_idx);
> > >  		if (ret != MAX_BULK)
> > >  			goto fail;
> > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK);
> > >
> > >  		printf("dequeue 1 obj\n");
> > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1, api_type);
> > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1, test_idx);
> > >  		if (ret != 1)
> > >  			goto fail;
> > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
> > >
> > >  		printf("dequeue 2 objs\n");
> > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2, api_type);
> > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
> > >  		if (ret != 2)
> > >  			goto fail;
> > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
> > >
> > >  		printf("dequeue MAX_BULK objs\n");
> > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], MAX_BULK,
> > > -						api_type);
> > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
> > > +						test_idx);
> > >  		if (ret != MAX_BULK)
> > >  			goto fail;
> > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK); @@
> > > -390,8 +567,7 @@ test_ring_burst_bulk_tests2(unsigned int api_type,
> > > unsigned int create_flags,
> > >   * Enqueue and dequeue to cover the entire ring length.
> > >   */
> > >  static int
> > > -test_ring_burst_bulk_tests3(unsigned int api_type, unsigned int
> create_flags,
> > > -	const char *tname)
> > > +test_ring_burst_bulk_tests3(unsigned int test_idx)
> > >  {
> > >  	struct rte_ring *r;
> > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst =
> > > NULL; @@ -399,11 +575,13 @@ test_ring_burst_bulk_tests3(unsigned int
> > > api_type, unsigned int create_flags,
> > >  	unsigned int i, j;
> > >
> > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > >
> > >  		/* Create the ring */
> > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > -					RING_SIZE, SOCKET_ID_ANY,
> > > create_flags);
> > > +				RING_SIZE, SOCKET_ID_ANY,
> > > +				test_enqdeq_impl[test_idx].create_flags);
> > >
> > >  		/* alloc dummy object pointers */
> > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -420,15
> > > +598,15 @@ test_ring_burst_bulk_tests3(unsigned int api_type,
> > > +unsigned int
> > > create_flags,
> > >
> > >  		printf("fill and empty the ring\n");
> > >  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > MAX_BULK,
> > > -							api_type);
> > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > MAX_BULK,
> > > +							test_idx);
> > >  			if (ret != MAX_BULK)
> > >  				goto fail;
> > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > >  								MAX_BULK);
> > >
> > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > MAX_BULK,
> > > -							api_type);
> > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > MAX_BULK,
> > > +							test_idx);
> > >  			if (ret != MAX_BULK)
> > >  				goto fail;
> > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> > > 465,21 +643,24 @@ test_ring_burst_bulk_tests3(unsigned int api_type,
> > > unsigned int create_flags,
> > >   * Enqueue till the ring is full and dequeue till the ring becomes empty.
> > >   */
> > >  static int
> > > -test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int
> create_flags,
> > > -	const char *tname)
> > > +test_ring_burst_bulk_tests4(unsigned int test_idx)
> > >  {
> > >  	struct rte_ring *r;
> > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> > >  	int ret;
> > >  	unsigned int i, j;
> > > -	unsigned int num_elems;
> > > +	unsigned int api_type, num_elems;
> > > +
> > > +	api_type = test_enqdeq_impl[test_idx].api_type;
> > >
> > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > >
> > >  		/* Create the ring */
> > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > -					RING_SIZE, SOCKET_ID_ANY,
> > > create_flags);
> > > +				RING_SIZE, SOCKET_ID_ANY,
> > > +				test_enqdeq_impl[test_idx].create_flags);
> > >
> > >  		/* alloc dummy object pointers */
> > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -496,8
> > > +677,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > +unsigned int
> > > create_flags,
> > >
> > >  		printf("Test enqueue without enough memory space\n");
> > >  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
> > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > MAX_BULK,
> > > -							api_type);
> > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > MAX_BULK,
> > > +							test_idx);
> > >  			if (ret != MAX_BULK)
> > >  				goto fail;
> > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i], @@ -
> > > 505,7 +686,7 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > unsigned int create_flags,
> > >  		}
> > >
> > >  		printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n");
> > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2, api_type);
> > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
> > >  		if (ret != 2)
> > >  			goto fail;
> > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); @@ -517,8
> > > +698,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > +unsigned int
> > > create_flags,
> > >  		else
> > >  			num_elems = MAX_BULK;
> > >  		/* Always one free entry left */
> > > -		ret = test_ring_enqueue(r, cur_src, esize[i], num_elems,
> > > -						api_type);
> > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], num_elems,
> > > +						test_idx);
> > >  		if (ret != MAX_BULK - 3)
> > >  			goto fail;
> > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK - 3);
> @@
> > > -528,15 +709,15 @@ test_ring_burst_bulk_tests4(unsigned int
> > > api_type, unsigned int create_flags,
> > >  			goto fail;
> > >
> > >  		printf("Test enqueue for a full entry\n");
> > > -		ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
> > > -						api_type);
> > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
> > > +						test_idx);
> > >  		if (ret != 0)
> > >  			goto fail;
> > >
> > >  		printf("Test dequeue without enough objects\n");
> > >  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > MAX_BULK,
> > > -							api_type);
> > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > MAX_BULK,
> > > +							test_idx);
> > >  			if (ret != MAX_BULK)
> > >  				goto fail;
> > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> > > 544,7 +725,7 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > unsigned int create_flags,
> > >  		}
> > >
> > >  		/* Available memory space for the exact MAX_BULK entries
> */
> > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2, api_type);
> > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
> > >  		if (ret != 2)
> > >  			goto fail;
> > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); @@ -554,8
> > > +735,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > +unsigned int
> > > create_flags,
> > >  			num_elems = MAX_BULK - 3;
> > >  		else
> > >  			num_elems = MAX_BULK;
> > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], num_elems,
> > > -						api_type);
> > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], num_elems,
> > > +						test_idx);
> > >  		if (ret != MAX_BULK - 3)
> > >  			goto fail;
> > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK - 3);
> @@
> > > -816,22 +997,7 @@ static int
> > >  test_ring(void)
> > >  {
> > >  	int32_t rc;
> > > -	unsigned int i, j;
> > > -	const char *tname;
> > > -
> > > -	static const struct {
> > > -		uint32_t create_flags;
> > > -		const char *name;
> > > -	} test_sync_modes[] = {
> > > -		{
> > > -			RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ,
> > > -			"Test MT_RTS ring",
> > > -		},
> > > -		{
> > > -			RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ,
> > > -			"Test MT_HTS ring",
> > > -		},
> > > -	};
> > > +	unsigned int i;
> > >
> > >  	/* Negative test cases */
> > >  	if (test_ring_negative_tests() < 0) @@ -848,65 +1014,24 @@
> > > test_ring(void)
> > >  	 * The test cases are split into smaller test cases to
> > >  	 * help clang compile faster.
> > >  	 */
> > > -	tname = "Test standard ring";
> > > -
> > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> > > -		for (i = TEST_RING_THREAD_DEF;
> > > -					i <= TEST_RING_THREAD_MPMC; i
> > > <<= 1)
> > > -			if (test_ring_burst_bulk_tests1(i | j, 0, tname) < 0)
> > > -				goto test_fail;
> > > -
> > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> > > -		for (i = TEST_RING_THREAD_DEF;
> > > -					i <= TEST_RING_THREAD_MPMC; i
> > > <<= 1)
> > > -			if (test_ring_burst_bulk_tests2(i | j, 0, tname) < 0)
> > > -				goto test_fail;
> > > -
> > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> > > -		for (i = TEST_RING_THREAD_DEF;
> > > -					i <= TEST_RING_THREAD_MPMC; i
> > > <<= 1)
> > > -			if (test_ring_burst_bulk_tests3(i | j, 0, tname) < 0)
> > > -				goto test_fail;
> > > -
> > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> > > -		for (i = TEST_RING_THREAD_DEF;
> > > -					i <= TEST_RING_THREAD_MPMC; i
> > > <<= 1)
> > > -			if (test_ring_burst_bulk_tests4(i | j, 0, tname) < 0)
> > > -				goto test_fail;
> > > -
> > > -	/* Burst and bulk operations with MT_RTS and MT_HTS sync modes
> > > */
> > > -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> > > -		for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > > -				j <<= 1) {
> > > -
> > > -			rc = test_ring_burst_bulk_tests1(
> > > -				TEST_RING_THREAD_DEF | j,
> > > -				test_sync_modes[i].create_flags,
> > > -				test_sync_modes[i].name);
> > > -			if (rc < 0)
> > > -				goto test_fail;
> > > -
> > > -			rc = test_ring_burst_bulk_tests2(
> > > -				TEST_RING_THREAD_DEF | j,
> > > -				test_sync_modes[i].create_flags,
> > > -				test_sync_modes[i].name);
> > > -			if (rc < 0)
> > > -				goto test_fail;
> > > -
> > > -			rc = test_ring_burst_bulk_tests3(
> > > -				TEST_RING_THREAD_DEF | j,
> > > -				test_sync_modes[i].create_flags,
> > > -				test_sync_modes[i].name);
> > > -			if (rc < 0)
> > > -				goto test_fail;
> > > -
> > > -			rc = test_ring_burst_bulk_tests3(
> > > -				TEST_RING_THREAD_DEF | j,
> > > -				test_sync_modes[i].create_flags,
> > > -				test_sync_modes[i].name);
> > > -			if (rc < 0)
> > > -				goto test_fail;
> > > -		}
> > > +	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
> > > +
> > > +
> > > +		rc = test_ring_burst_bulk_tests1(i);
> > > +		if (rc < 0)
> > > +			goto test_fail;
> > > +
> > > +		rc = test_ring_burst_bulk_tests2(i);
> > > +		if (rc < 0)
> > > +			goto test_fail;
> > > +
> > > +		rc = test_ring_burst_bulk_tests3(i);
> > > +		if (rc < 0)
> > > +			goto test_fail;
> > > +
> > > +		rc = test_ring_burst_bulk_tests4(i);
> > > +		if (rc < 0)
> > > +			goto test_fail;
> > >  	}
> > >
> > >  	/* dump the ring status */
> > > --
> > > 2.17.1
Thomas Monjalon May 4, 2020, 9:03 a.m. UTC | #6
30/04/2020 16:43, Ananyev, Konstantin:
> 
> Hi Honnappa,
>  
> > Hi Konstantin,
> > 	I like the way the tests are organized and it looks good.
> > 
> > I am just wondering about the way it is being tested here. The intent to write the test cases the way they are currently is to mimic how the
> > APIs would be used mostly. IMO, the APIs would be used with a constant value for element size so that the compiler will throw away the
> > unwanted code (in the functions where the actual copy is being done).
> > 
> > With your method here, it looks to me like all the branches in the copy functions are kept and the branch decisions are done at run time.
> > Is  my understanding correct?
> 
> You mean branching on esize[] values?
> Actually from what I've seen that happens for both cases:
> before and after the patch (gcc 7.3 -O3).
> 
> Main intention in my changes was to avoid using test_ring_enqueue/test_ring_dequeue,
> as it seems too many branches here and it takes compiler a lot of effort to resolve all
> of them at compile time.
> So I replaced it with  array of function pointers (test_enqdeq_impl[]) and iterating over it.
> That way compiler knows straightway which function to use.

In case we choose this solution, please make a v2 including such explanations.
Ananyev, Konstantin May 5, 2020, 11:59 a.m. UTC | #7
> >
> > > Hi Konstantin,
> > > 	I like the way the tests are organized and it looks good.
> > >
> > > I am just wondering about the way it is being tested here. The intent
> > > to write the test cases the way they are currently is to mimic how the
> > > APIs would be used mostly. IMO, the APIs would be used with a constant
> > value for element size so that the compiler will throw away the unwanted
> > code (in the functions where the actual copy is being done).
> > >
> > > With your method here, it looks to me like all the branches in the copy
> > functions are kept and the branch decisions are done at run time.
> > > Is  my understanding correct?
> >
> > You mean branching on esize[] values?
> Yes
> 
> > Actually from what I've seen that happens for both cases:
> > before and after the patch (gcc 7.3 -O3).
> I did not look at the generated code. If it is happening with your patch too, I think we can go with your patch.

Just to clarify, what I meant:
For both binaries (without the patch and with the patch) inside test_ring()
I see runtime branches on esize value.
Literally the code that corresponds to:
if (esize == 8) {...}
else if (esize == 16) {...}
else {...} 

Probably gcc wasn't able to remove it because we use esize[]
instead of hard-coded values, might be there is some other reason,
I don't know for sure. 
As it is a functional (not performance) test, I didn't dig further.

> But, can you do similar
> change to test_ring_perf.c to keep it consistent?

In principle it is doable, but needs extra care.
We need to make sure that compiler will be able to inline functions via pointers.
AFAIK, gcc does that with -O3', but not with '-O2'.
Don't know what the story with clang and different versions of the compiler.
Is there any real need for that?
On my box test_ring_perf.c compilation takes ~8s.
Konstantin
   

> 
> >
> > Main intention in my changes was to avoid using
> > test_ring_enqueue/test_ring_dequeue,
> > as it seems too many branches here and it takes compiler a lot of effort to
> > resolve all of them at compile time.
> > So I replaced it with  array of function pointers (test_enqdeq_impl[]) and
> > iterating over it.
> > That way compiler knows straightway which function to use.
> >
> > > Can you please check this? https://patches.dpdk.org/patch/69567/
> >
> > As I can see your approach reduces number of test-cases by factor of 5:
> > now each of test_ring_burst_bulk_tests[1-4] is executed only with just one
> > esize value, correct?
> Yes, basically test_ring_burst_bulk_tests[1-4] were covering different scenarios with the same APIs. So, distributed the esize across
> different test functions.
> 
> > In term of compilation speed - it helps.
> > On my box with (gcc 7.3 -O3)  compiling test_ring.c takes:
> > orig code:                             ~100s
> > with 69567 (your patch):  < 20s
> > with 69559 (my patch):    < 10s
> >
> > Konstantin
> >
> > >
> > > > -----Original Message-----
> > > > From: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > > > Sent: Wednesday, April 29, 2020 12:57 PM
> > > > To: dev@dpdk.org
> > > > Cc: aconole@redhat.com; Honnappa Nagarahalli
> > > > <Honnappa.Nagarahalli@arm.com>; Konstantin Ananyev
> > > > <konstantin.ananyev@intel.com>
> > > > Subject: [PATCH] test/ring: code rework to reduce compilation time
> > > >
> > > > Rework test code to reduce code complexity for the compiler and
> > > > bring down compilation time and memory consumption.
> > > >
> > > > Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > > > ---
> > > >  app/test/test_ring.c | 373
> > > > +++++++++++++++++++++++++++++--------------
> > > >  1 file changed, 249 insertions(+), 124 deletions(-)
> > > >
> > > > diff --git a/app/test/test_ring.c b/app/test/test_ring.c index
> > > > e21557cd9..0ae97d341 100644
> > > > --- a/app/test/test_ring.c
> > > > +++ b/app/test/test_ring.c
> > > > @@ -58,6 +58,181 @@
> > > >
> > > >  static const int esize[] = {-1, 4, 8, 16, 20};
> > > >
> > > > +static const struct {
> > > > +	const char *desc;
> > > > +	uint32_t api_type;
> > > > +	uint32_t create_flags;
> > > > +	struct {
> > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > +			void * const *obj_table, unsigned int n,
> > > > +			unsigned int *free_space);
> > > > +		unsigned int (*felem)(struct rte_ring *r, const void *obj_table,
> > > > +			unsigned int esize, unsigned int n,
> > > > +			unsigned int *free_space);
> > > > +	} enq;
> > > > +	struct {
> > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > +			void **obj_table, unsigned int n,
> > > > +			unsigned int *available);
> > > > +		unsigned int (*felem)(struct rte_ring *r, void *obj_table,
> > > > +			unsigned int esize, unsigned int n,
> > > > +			unsigned int *available);
> > > > +	} deq;
> > > > +} test_enqdeq_impl[] = {
> > > > +	{
> > > > +		.desc = "MP/MC sync mode",
> > > Details about the tests are already printed by the function
> > 'test_ring_print_test_string'. This string should be 'Test standard ring'.
> > >
> > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > TEST_RING_THREAD_DEF,
> > > > +		.create_flags = 0,
> > > > +		.enq = {
> > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > +		},
> > > > +		.deq = {
> > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > +		},
> > > > +	},
> > > > +	{
> > > > +		.desc = "SP/SC sync mode",
> > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > TEST_RING_THREAD_SPSC,
> > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > +		.enq = {
> > > > +			.flegacy = rte_ring_sp_enqueue_bulk,
> > > > +			.felem = rte_ring_sp_enqueue_bulk_elem,
> > > > +		},
> > > > +		.deq = {
> > > > +			.flegacy = rte_ring_sc_dequeue_bulk,
> > > > +			.felem = rte_ring_sc_dequeue_bulk_elem,
> > > > +		},
> > > > +	},
> > > > +	{
> > > > +		.desc = "MP/MC sync mode",
> > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > TEST_RING_THREAD_MPMC,
> > > > +		.create_flags = 0,
> > > > +		.enq = {
> > > > +			.flegacy = rte_ring_mp_enqueue_bulk,
> > > > +			.felem = rte_ring_mp_enqueue_bulk_elem,
> > > > +		},
> > > > +		.deq = {
> > > > +			.flegacy = rte_ring_mc_dequeue_bulk,
> > > > +			.felem = rte_ring_mc_dequeue_bulk_elem,
> > > > +		},
> > > > +	},
> > > > +	{
> > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > TEST_RING_THREAD_DEF,
> > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > RING_F_MC_RTS_DEQ,
> > > > +		.enq = {
> > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > +		},
> > > > +		.deq = {
> > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > +		},
> > > > +	},
> > > > +	{
> > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > TEST_RING_THREAD_DEF,
> > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > RING_F_MC_HTS_DEQ,
> > > > +		.enq = {
> > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > +		},
> > > > +		.deq = {
> > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > +		},
> > > > +	},
> > > > +	{
> > > > +		.desc = "MP/MC sync mode",
> > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > TEST_RING_THREAD_DEF,
> > > > +		.create_flags = 0,
> > > > +		.enq = {
> > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > +		},
> > > > +		.deq = {
> > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > +		},
> > > > +	},
> > > > +	{
> > > > +		.desc = "SP/SC sync mode",
> > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > TEST_RING_THREAD_SPSC,
> > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > +		.enq = {
> > > > +			.flegacy = rte_ring_sp_enqueue_burst,
> > > > +			.felem = rte_ring_sp_enqueue_burst_elem,
> > > > +		},
> > > > +		.deq = {
> > > > +			.flegacy = rte_ring_sc_dequeue_burst,
> > > > +			.felem = rte_ring_sc_dequeue_burst_elem,
> > > > +		},
> > > > +	},
> > > > +	{
> > > > +		.desc = "MP/MC sync mode",
> > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > TEST_RING_THREAD_MPMC,
> > > > +		.create_flags = 0,
> > > > +		.enq = {
> > > > +			.flegacy = rte_ring_mp_enqueue_burst,
> > > > +			.felem = rte_ring_mp_enqueue_burst_elem,
> > > > +		},
> > > > +		.deq = {
> > > > +			.flegacy = rte_ring_mc_dequeue_burst,
> > > > +			.felem = rte_ring_mc_dequeue_burst_elem,
> > > > +		},
> > > > +	},
> > > > +	{
> > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > TEST_RING_THREAD_DEF,
> > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > RING_F_MC_RTS_DEQ,
> > > > +		.enq = {
> > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > +		},
> > > > +		.deq = {
> > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > +		},
> > > > +	},
> > > > +	{
> > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > TEST_RING_THREAD_DEF,
> > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > RING_F_MC_HTS_DEQ,
> > > > +		.enq = {
> > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > +		},
> > > > +		.deq = {
> > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > +		},
> > > > +	},
> > > > +};
> > > > +
> > > > +static unsigned int
> > > > +test_ring_enq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n,
> > > > +	unsigned int test_idx)
> > > > +{
> > > > +	if (esize == -1)
> > > > +		return test_enqdeq_impl[test_idx].enq.flegacy(r, obj, n, NULL);
> > > > +	else
> > > > +		return test_enqdeq_impl[test_idx].enq.felem(r, obj, esize, n,
> > > > +			NULL);
> > > > +}
> > > > +
> > > > +static unsigned int
> > > > +test_ring_deq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n,
> > > > +	unsigned int test_idx)
> > > > +{
> > > > +	if (esize == -1)
> > > > +		return test_enqdeq_impl[test_idx].deq.flegacy(r, obj, n, NULL);
> > > > +	else
> > > > +		return test_enqdeq_impl[test_idx].deq.felem(r, obj, esize, n,
> > > > +			NULL);
> > > > +}
> > > > +
> > > >  static void**
> > > >  test_ring_inc_ptr(void **obj, int esize, unsigned int n)  { @@
> > > > -203,8 +378,7 @@ test_ring_negative_tests(void)
> > > >   * Random number of elements are enqueued and dequeued.
> > > >   */
> > > >  static int
> > > > -test_ring_burst_bulk_tests1(unsigned int api_type, unsigned int
> > create_flags,
> > > > -	const char *tname)
> > > > +test_ring_burst_bulk_tests1(unsigned int test_idx)
> > > >  {
> > > >  	struct rte_ring *r;
> > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst =
> > > > NULL; @@ -214,11 +388,13 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > api_type, unsigned int create_flags,
> > > >  	const unsigned int rsz = RING_SIZE - 1;
> > > >
> > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > >
> > > >  		/* Create the ring */
> > > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > create_flags);
> > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > +				test_enqdeq_impl[test_idx].create_flags);
> > > >
> > > >  		/* alloc dummy object pointers */
> > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -240,17
> > > > +416,17 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> > > > +unsigned int
> > > > create_flags,
> > > >  			rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL);
> > > >  			printf("%s: iteration %u, random shift: %u;\n",
> > > >  			    __func__, i, rand);
> > > > -			ret = test_ring_enqueue(r, cur_src, esize[i], rand,
> > > > -							api_type);
> > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i], rand,
> > > > +							test_idx);
> > > >  			TEST_RING_VERIFY(ret != 0);
> > > >
> > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i], rand,
> > > > -							api_type);
> > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i], rand,
> > > > +							test_idx);
> > > >  			TEST_RING_VERIFY(ret == rand);
> > > >
> > > >  			/* fill the ring */
> > > > -			ret = test_ring_enqueue(r, cur_src, esize[i], rsz,
> > > > -							api_type);
> > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i], rsz,
> > > > +							test_idx);
> > > >  			TEST_RING_VERIFY(ret != 0);
> > > >
> > > >  			TEST_RING_VERIFY(rte_ring_free_count(r) == 0); @@
> > > > -259,8 +435,8 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> > > > unsigned int create_flags,
> > > >  			TEST_RING_VERIFY(rte_ring_empty(r) == 0);
> > > >
> > > >  			/* empty the ring */
> > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i], rsz,
> > > > -							api_type);
> > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i], rsz,
> > > > +							test_idx);
> > > >  			TEST_RING_VERIFY(ret == (int)rsz);
> > > >  			TEST_RING_VERIFY(rsz == rte_ring_free_count(r));
> > > >  			TEST_RING_VERIFY(rte_ring_count(r) == 0); @@ -
> > > > 294,8 +470,7 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> > > > unsigned int create_flags,
> > > >   * dequeued data.
> > > >   */
> > > >  static int
> > > > -test_ring_burst_bulk_tests2(unsigned int api_type, unsigned int
> > create_flags,
> > > > -	const char *tname)
> > > > +test_ring_burst_bulk_tests2(unsigned int test_idx)
> > > >  {
> > > >  	struct rte_ring *r;
> > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst =
> > > > NULL; @@ -303,11 +478,13 @@ test_ring_burst_bulk_tests2(unsigned int
> > > > api_type, unsigned int create_flags,
> > > >  	unsigned int i;
> > > >
> > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > >
> > > >  		/* Create the ring */
> > > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > create_flags);
> > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > +				test_enqdeq_impl[test_idx].create_flags);
> > > >
> > > >  		/* alloc dummy object pointers */
> > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -323,39
> > > > +500,39 @@ test_ring_burst_bulk_tests2(unsigned int api_type,
> > > > +unsigned int
> > > > create_flags,
> > > >  		cur_dst = dst;
> > > >
> > > >  		printf("enqueue 1 obj\n");
> > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 1, api_type);
> > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 1, test_idx);
> > > >  		if (ret != 1)
> > > >  			goto fail;
> > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
> > > >
> > > >  		printf("enqueue 2 objs\n");
> > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2, api_type);
> > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
> > > >  		if (ret != 2)
> > > >  			goto fail;
> > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
> > > >
> > > >  		printf("enqueue MAX_BULK objs\n");
> > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
> > > > -						api_type);
> > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
> > > > +						test_idx);
> > > >  		if (ret != MAX_BULK)
> > > >  			goto fail;
> > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK);
> > > >
> > > >  		printf("dequeue 1 obj\n");
> > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1, api_type);
> > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1, test_idx);
> > > >  		if (ret != 1)
> > > >  			goto fail;
> > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
> > > >
> > > >  		printf("dequeue 2 objs\n");
> > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2, api_type);
> > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
> > > >  		if (ret != 2)
> > > >  			goto fail;
> > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
> > > >
> > > >  		printf("dequeue MAX_BULK objs\n");
> > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], MAX_BULK,
> > > > -						api_type);
> > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
> > > > +						test_idx);
> > > >  		if (ret != MAX_BULK)
> > > >  			goto fail;
> > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK); @@
> > > > -390,8 +567,7 @@ test_ring_burst_bulk_tests2(unsigned int api_type,
> > > > unsigned int create_flags,
> > > >   * Enqueue and dequeue to cover the entire ring length.
> > > >   */
> > > >  static int
> > > > -test_ring_burst_bulk_tests3(unsigned int api_type, unsigned int
> > create_flags,
> > > > -	const char *tname)
> > > > +test_ring_burst_bulk_tests3(unsigned int test_idx)
> > > >  {
> > > >  	struct rte_ring *r;
> > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst =
> > > > NULL; @@ -399,11 +575,13 @@ test_ring_burst_bulk_tests3(unsigned int
> > > > api_type, unsigned int create_flags,
> > > >  	unsigned int i, j;
> > > >
> > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > >
> > > >  		/* Create the ring */
> > > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > create_flags);
> > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > +				test_enqdeq_impl[test_idx].create_flags);
> > > >
> > > >  		/* alloc dummy object pointers */
> > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -420,15
> > > > +598,15 @@ test_ring_burst_bulk_tests3(unsigned int api_type,
> > > > +unsigned int
> > > > create_flags,
> > > >
> > > >  		printf("fill and empty the ring\n");
> > > >  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > MAX_BULK,
> > > > -							api_type);
> > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > MAX_BULK,
> > > > +							test_idx);
> > > >  			if (ret != MAX_BULK)
> > > >  				goto fail;
> > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > >  								MAX_BULK);
> > > >
> > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > MAX_BULK,
> > > > -							api_type);
> > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > MAX_BULK,
> > > > +							test_idx);
> > > >  			if (ret != MAX_BULK)
> > > >  				goto fail;
> > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> > > > 465,21 +643,24 @@ test_ring_burst_bulk_tests3(unsigned int api_type,
> > > > unsigned int create_flags,
> > > >   * Enqueue till the ring is full and dequeue till the ring becomes empty.
> > > >   */
> > > >  static int
> > > > -test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int
> > create_flags,
> > > > -	const char *tname)
> > > > +test_ring_burst_bulk_tests4(unsigned int test_idx)
> > > >  {
> > > >  	struct rte_ring *r;
> > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> > > >  	int ret;
> > > >  	unsigned int i, j;
> > > > -	unsigned int num_elems;
> > > > +	unsigned int api_type, num_elems;
> > > > +
> > > > +	api_type = test_enqdeq_impl[test_idx].api_type;
> > > >
> > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > +		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > >
> > > >  		/* Create the ring */
> > > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > create_flags);
> > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > +				test_enqdeq_impl[test_idx].create_flags);
> > > >
> > > >  		/* alloc dummy object pointers */
> > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -496,8
> > > > +677,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > +unsigned int
> > > > create_flags,
> > > >
> > > >  		printf("Test enqueue without enough memory space\n");
> > > >  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
> > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > MAX_BULK,
> > > > -							api_type);
> > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > MAX_BULK,
> > > > +							test_idx);
> > > >  			if (ret != MAX_BULK)
> > > >  				goto fail;
> > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i], @@ -
> > > > 505,7 +686,7 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > unsigned int create_flags,
> > > >  		}
> > > >
> > > >  		printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n");
> > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2, api_type);
> > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
> > > >  		if (ret != 2)
> > > >  			goto fail;
> > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); @@ -517,8
> > > > +698,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > +unsigned int
> > > > create_flags,
> > > >  		else
> > > >  			num_elems = MAX_BULK;
> > > >  		/* Always one free entry left */
> > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], num_elems,
> > > > -						api_type);
> > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], num_elems,
> > > > +						test_idx);
> > > >  		if (ret != MAX_BULK - 3)
> > > >  			goto fail;
> > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK - 3);
> > @@
> > > > -528,15 +709,15 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > api_type, unsigned int create_flags,
> > > >  			goto fail;
> > > >
> > > >  		printf("Test enqueue for a full entry\n");
> > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
> > > > -						api_type);
> > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
> > > > +						test_idx);
> > > >  		if (ret != 0)
> > > >  			goto fail;
> > > >
> > > >  		printf("Test dequeue without enough objects\n");
> > > >  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > MAX_BULK,
> > > > -							api_type);
> > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > MAX_BULK,
> > > > +							test_idx);
> > > >  			if (ret != MAX_BULK)
> > > >  				goto fail;
> > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> > > > 544,7 +725,7 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > unsigned int create_flags,
> > > >  		}
> > > >
> > > >  		/* Available memory space for the exact MAX_BULK entries
> > */
> > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2, api_type);
> > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
> > > >  		if (ret != 2)
> > > >  			goto fail;
> > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); @@ -554,8
> > > > +735,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > +unsigned int
> > > > create_flags,
> > > >  			num_elems = MAX_BULK - 3;
> > > >  		else
> > > >  			num_elems = MAX_BULK;
> > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], num_elems,
> > > > -						api_type);
> > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], num_elems,
> > > > +						test_idx);
> > > >  		if (ret != MAX_BULK - 3)
> > > >  			goto fail;
> > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK - 3);
> > @@
> > > > -816,22 +997,7 @@ static int
> > > >  test_ring(void)
> > > >  {
> > > >  	int32_t rc;
> > > > -	unsigned int i, j;
> > > > -	const char *tname;
> > > > -
> > > > -	static const struct {
> > > > -		uint32_t create_flags;
> > > > -		const char *name;
> > > > -	} test_sync_modes[] = {
> > > > -		{
> > > > -			RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ,
> > > > -			"Test MT_RTS ring",
> > > > -		},
> > > > -		{
> > > > -			RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ,
> > > > -			"Test MT_HTS ring",
> > > > -		},
> > > > -	};
> > > > +	unsigned int i;
> > > >
> > > >  	/* Negative test cases */
> > > >  	if (test_ring_negative_tests() < 0) @@ -848,65 +1014,24 @@
> > > > test_ring(void)
> > > >  	 * The test cases are split into smaller test cases to
> > > >  	 * help clang compile faster.
> > > >  	 */
> > > > -	tname = "Test standard ring";
> > > > -
> > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > -					i <= TEST_RING_THREAD_MPMC; i
> > > > <<= 1)
> > > > -			if (test_ring_burst_bulk_tests1(i | j, 0, tname) < 0)
> > > > -				goto test_fail;
> > > > -
> > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > -					i <= TEST_RING_THREAD_MPMC; i
> > > > <<= 1)
> > > > -			if (test_ring_burst_bulk_tests2(i | j, 0, tname) < 0)
> > > > -				goto test_fail;
> > > > -
> > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > -					i <= TEST_RING_THREAD_MPMC; i
> > > > <<= 1)
> > > > -			if (test_ring_burst_bulk_tests3(i | j, 0, tname) < 0)
> > > > -				goto test_fail;
> > > > -
> > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
> > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > -					i <= TEST_RING_THREAD_MPMC; i
> > > > <<= 1)
> > > > -			if (test_ring_burst_bulk_tests4(i | j, 0, tname) < 0)
> > > > -				goto test_fail;
> > > > -
> > > > -	/* Burst and bulk operations with MT_RTS and MT_HTS sync modes
> > > > */
> > > > -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> > > > -		for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > > > -				j <<= 1) {
> > > > -
> > > > -			rc = test_ring_burst_bulk_tests1(
> > > > -				TEST_RING_THREAD_DEF | j,
> > > > -				test_sync_modes[i].create_flags,
> > > > -				test_sync_modes[i].name);
> > > > -			if (rc < 0)
> > > > -				goto test_fail;
> > > > -
> > > > -			rc = test_ring_burst_bulk_tests2(
> > > > -				TEST_RING_THREAD_DEF | j,
> > > > -				test_sync_modes[i].create_flags,
> > > > -				test_sync_modes[i].name);
> > > > -			if (rc < 0)
> > > > -				goto test_fail;
> > > > -
> > > > -			rc = test_ring_burst_bulk_tests3(
> > > > -				TEST_RING_THREAD_DEF | j,
> > > > -				test_sync_modes[i].create_flags,
> > > > -				test_sync_modes[i].name);
> > > > -			if (rc < 0)
> > > > -				goto test_fail;
> > > > -
> > > > -			rc = test_ring_burst_bulk_tests3(
> > > > -				TEST_RING_THREAD_DEF | j,
> > > > -				test_sync_modes[i].create_flags,
> > > > -				test_sync_modes[i].name);
> > > > -			if (rc < 0)
> > > > -				goto test_fail;
> > > > -		}
> > > > +	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
> > > > +
> > > > +
> > > > +		rc = test_ring_burst_bulk_tests1(i);
> > > > +		if (rc < 0)
> > > > +			goto test_fail;
> > > > +
> > > > +		rc = test_ring_burst_bulk_tests2(i);
> > > > +		if (rc < 0)
> > > > +			goto test_fail;
> > > > +
> > > > +		rc = test_ring_burst_bulk_tests3(i);
> > > > +		if (rc < 0)
> > > > +			goto test_fail;
> > > > +
> > > > +		rc = test_ring_burst_bulk_tests4(i);
> > > > +		if (rc < 0)
> > > > +			goto test_fail;
> > > >  	}
> > > >
> > > >  	/* dump the ring status */
> > > > --
> > > > 2.17.1
Honnappa Nagarahalli May 5, 2020, 2:17 p.m. UTC | #8
<snip>

> > >
> > > > Hi Konstantin,
> > > > 	I like the way the tests are organized and it looks good.
> > > >
> > > > I am just wondering about the way it is being tested here. The
> > > > intent to write the test cases the way they are currently is to
> > > > mimic how the APIs would be used mostly. IMO, the APIs would be
> > > > used with a constant
> > > value for element size so that the compiler will throw away the
> > > unwanted code (in the functions where the actual copy is being done).
> > > >
> > > > With your method here, it looks to me like all the branches in the
> > > > copy
> > > functions are kept and the branch decisions are done at run time.
> > > > Is  my understanding correct?
> > >
> > > You mean branching on esize[] values?
> > Yes
> >
> > > Actually from what I've seen that happens for both cases:
> > > before and after the patch (gcc 7.3 -O3).
> > I did not look at the generated code. If it is happening with your patch too, I
> think we can go with your patch.
> 
> Just to clarify, what I meant:
> For both binaries (without the patch and with the patch) inside test_ring() I
> see runtime branches on esize value.
> Literally the code that corresponds to:
> if (esize == 8) {...}
> else if (esize == 16) {...}
> else {...}
Do you see this in the actual ring library functions? I want to make sure that the library functions '__rte_ring_enqueue_elems' and '__rte_ring_dequeue_elems' are optimized.

> 
> Probably gcc wasn't able to remove it because we use esize[] instead of hard-
> coded values, might be there is some other reason, I don't know for sure.
> As it is a functional (not performance) test, I didn't dig further.
The esize[] array is declared as a const. The compiler should be able to see that it is a compile time constant.

> 
> > But, can you do similar
> > change to test_ring_perf.c to keep it consistent?
> 
> In principle it is doable, but needs extra care.
> We need to make sure that compiler will be able to inline functions via
> pointers.
> AFAIK, gcc does that with -O3', but not with '-O2'.
If the unwanted code is not removed during compilation, we will see it affect the performance numbers.

> Don't know what the story with clang and different versions of the compiler.
> Is there any real need for that?
> On my box test_ring_perf.c compilation takes ~8s.
> Konstantin
> 
> 
> >
> > >
> > > Main intention in my changes was to avoid using
> > > test_ring_enqueue/test_ring_dequeue,
> > > as it seems too many branches here and it takes compiler a lot of
> > > effort to resolve all of them at compile time.
> > > So I replaced it with  array of function pointers
> > > (test_enqdeq_impl[]) and iterating over it.
> > > That way compiler knows straightway which function to use.
> > >
> > > > Can you please check this? https://patches.dpdk.org/patch/69567/
> > >
> > > As I can see your approach reduces number of test-cases by factor of 5:
> > > now each of test_ring_burst_bulk_tests[1-4] is executed only with
> > > just one esize value, correct?
> > Yes, basically test_ring_burst_bulk_tests[1-4] were covering different
> > scenarios with the same APIs. So, distributed the esize across different test
> functions.
> >
> > > In term of compilation speed - it helps.
> > > On my box with (gcc 7.3 -O3)  compiling test_ring.c takes:
> > > orig code:                             ~100s
> > > with 69567 (your patch):  < 20s
> > > with 69559 (my patch):    < 10s
> > >
> > > Konstantin
> > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > > > > Sent: Wednesday, April 29, 2020 12:57 PM
> > > > > To: dev@dpdk.org
> > > > > Cc: aconole@redhat.com; Honnappa Nagarahalli
> > > > > <Honnappa.Nagarahalli@arm.com>; Konstantin Ananyev
> > > > > <konstantin.ananyev@intel.com>
> > > > > Subject: [PATCH] test/ring: code rework to reduce compilation
> > > > > time
> > > > >
> > > > > Rework test code to reduce code complexity for the compiler and
> > > > > bring down compilation time and memory consumption.
> > > > >
> > > > > Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > > > > ---
> > > > >  app/test/test_ring.c | 373
> > > > > +++++++++++++++++++++++++++++--------------
> > > > >  1 file changed, 249 insertions(+), 124 deletions(-)
> > > > >
> > > > > diff --git a/app/test/test_ring.c b/app/test/test_ring.c index
> > > > > e21557cd9..0ae97d341 100644
> > > > > --- a/app/test/test_ring.c
> > > > > +++ b/app/test/test_ring.c
> > > > > @@ -58,6 +58,181 @@
> > > > >
> > > > >  static const int esize[] = {-1, 4, 8, 16, 20};
> > > > >
> > > > > +static const struct {
> > > > > +	const char *desc;
> > > > > +	uint32_t api_type;
> > > > > +	uint32_t create_flags;
> > > > > +	struct {
> > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > +			void * const *obj_table, unsigned int n,
> > > > > +			unsigned int *free_space);
> > > > > +		unsigned int (*felem)(struct rte_ring *r, const void
> *obj_table,
> > > > > +			unsigned int esize, unsigned int n,
> > > > > +			unsigned int *free_space);
> > > > > +	} enq;
> > > > > +	struct {
> > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > +			void **obj_table, unsigned int n,
> > > > > +			unsigned int *available);
> > > > > +		unsigned int (*felem)(struct rte_ring *r, void
> *obj_table,
> > > > > +			unsigned int esize, unsigned int n,
> > > > > +			unsigned int *available);
> > > > > +	} deq;
> > > > > +} test_enqdeq_impl[] = {
> > > > > +	{
> > > > > +		.desc = "MP/MC sync mode",
> > > > Details about the tests are already printed by the function
> > > 'test_ring_print_test_string'. This string should be 'Test standard ring'.
> > > >
> > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > TEST_RING_THREAD_DEF,
> > > > > +		.create_flags = 0,
> > > > > +		.enq = {
> > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > +		},
> > > > > +		.deq = {
> > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > +		},
> > > > > +	},
> > > > > +	{
> > > > > +		.desc = "SP/SC sync mode",
> > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > TEST_RING_THREAD_SPSC,
> > > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > > +		.enq = {
> > > > > +			.flegacy = rte_ring_sp_enqueue_bulk,
> > > > > +			.felem = rte_ring_sp_enqueue_bulk_elem,
> > > > > +		},
> > > > > +		.deq = {
> > > > > +			.flegacy = rte_ring_sc_dequeue_bulk,
> > > > > +			.felem = rte_ring_sc_dequeue_bulk_elem,
> > > > > +		},
> > > > > +	},
> > > > > +	{
> > > > > +		.desc = "MP/MC sync mode",
> > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > TEST_RING_THREAD_MPMC,
> > > > > +		.create_flags = 0,
> > > > > +		.enq = {
> > > > > +			.flegacy = rte_ring_mp_enqueue_bulk,
> > > > > +			.felem = rte_ring_mp_enqueue_bulk_elem,
> > > > > +		},
> > > > > +		.deq = {
> > > > > +			.flegacy = rte_ring_mc_dequeue_bulk,
> > > > > +			.felem = rte_ring_mc_dequeue_bulk_elem,
> > > > > +		},
> > > > > +	},
> > > > > +	{
> > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > TEST_RING_THREAD_DEF,
> > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > RING_F_MC_RTS_DEQ,
> > > > > +		.enq = {
> > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > +		},
> > > > > +		.deq = {
> > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > +		},
> > > > > +	},
> > > > > +	{
> > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > TEST_RING_THREAD_DEF,
> > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > RING_F_MC_HTS_DEQ,
> > > > > +		.enq = {
> > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > +		},
> > > > > +		.deq = {
> > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > +		},
> > > > > +	},
> > > > > +	{
> > > > > +		.desc = "MP/MC sync mode",
> > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > TEST_RING_THREAD_DEF,
> > > > > +		.create_flags = 0,
> > > > > +		.enq = {
> > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > +		},
> > > > > +		.deq = {
> > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > +		},
> > > > > +	},
> > > > > +	{
> > > > > +		.desc = "SP/SC sync mode",
> > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > TEST_RING_THREAD_SPSC,
> > > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > > +		.enq = {
> > > > > +			.flegacy = rte_ring_sp_enqueue_burst,
> > > > > +			.felem = rte_ring_sp_enqueue_burst_elem,
> > > > > +		},
> > > > > +		.deq = {
> > > > > +			.flegacy = rte_ring_sc_dequeue_burst,
> > > > > +			.felem = rte_ring_sc_dequeue_burst_elem,
> > > > > +		},
> > > > > +	},
> > > > > +	{
> > > > > +		.desc = "MP/MC sync mode",
> > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > TEST_RING_THREAD_MPMC,
> > > > > +		.create_flags = 0,
> > > > > +		.enq = {
> > > > > +			.flegacy = rte_ring_mp_enqueue_burst,
> > > > > +			.felem = rte_ring_mp_enqueue_burst_elem,
> > > > > +		},
> > > > > +		.deq = {
> > > > > +			.flegacy = rte_ring_mc_dequeue_burst,
> > > > > +			.felem = rte_ring_mc_dequeue_burst_elem,
> > > > > +		},
> > > > > +	},
> > > > > +	{
> > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > TEST_RING_THREAD_DEF,
> > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > RING_F_MC_RTS_DEQ,
> > > > > +		.enq = {
> > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > +		},
> > > > > +		.deq = {
> > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > +		},
> > > > > +	},
> > > > > +	{
> > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > TEST_RING_THREAD_DEF,
> > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > RING_F_MC_HTS_DEQ,
> > > > > +		.enq = {
> > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > +		},
> > > > > +		.deq = {
> > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > +		},
> > > > > +	},
> > > > > +};
> > > > > +
> > > > > +static unsigned int
> > > > > +test_ring_enq_impl(struct rte_ring *r, void **obj, int esize, unsigned
> int n,
> > > > > +	unsigned int test_idx)
> > > > > +{
> > > > > +	if (esize == -1)
> > > > > +		return test_enqdeq_impl[test_idx].enq.flegacy(r, obj,
> n, NULL);
> > > > > +	else
> > > > > +		return test_enqdeq_impl[test_idx].enq.felem(r, obj,
> esize, n,
> > > > > +			NULL);
> > > > > +}
> > > > > +
> > > > > +static unsigned int
> > > > > +test_ring_deq_impl(struct rte_ring *r, void **obj, int esize, unsigned
> int n,
> > > > > +	unsigned int test_idx)
> > > > > +{
> > > > > +	if (esize == -1)
> > > > > +		return test_enqdeq_impl[test_idx].deq.flegacy(r, obj,
> n, NULL);
> > > > > +	else
> > > > > +		return test_enqdeq_impl[test_idx].deq.felem(r, obj,
> esize, n,
> > > > > +			NULL);
> > > > > +}
> > > > > +
> > > > >  static void**
> > > > >  test_ring_inc_ptr(void **obj, int esize, unsigned int n)  { @@
> > > > > -203,8 +378,7 @@ test_ring_negative_tests(void)
> > > > >   * Random number of elements are enqueued and dequeued.
> > > > >   */
> > > > >  static int
> > > > > -test_ring_burst_bulk_tests1(unsigned int api_type, unsigned int
> > > create_flags,
> > > > > -	const char *tname)
> > > > > +test_ring_burst_bulk_tests1(unsigned int test_idx)
> > > > >  {
> > > > >  	struct rte_ring *r;
> > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst =
> > > > > NULL; @@ -214,11 +388,13 @@
> test_ring_burst_bulk_tests1(unsigned
> > > > > int api_type, unsigned int create_flags,
> > > > >  	const unsigned int rsz = RING_SIZE - 1;
> > > > >
> > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > +
> 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > >
> > > > >  		/* Create the ring */
> > > > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > create_flags);
> > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > +
> 	test_enqdeq_impl[test_idx].create_flags);
> > > > >
> > > > >  		/* alloc dummy object pointers */
> > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -240,17
> > > > > +416,17 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> > > > > +unsigned int
> > > > > create_flags,
> > > > >  			rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL);
> > > > >  			printf("%s: iteration %u, random shift: %u;\n",
> > > > >  			    __func__, i, rand);
> > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> rand,
> > > > > -							api_type);
> > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> rand,
> > > > > +							test_idx);
> > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > >
> > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> rand,
> > > > > -							api_type);
> > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> rand,
> > > > > +							test_idx);
> > > > >  			TEST_RING_VERIFY(ret == rand);
> > > > >
> > > > >  			/* fill the ring */
> > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i], rsz,
> > > > > -							api_type);
> > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> rsz,
> > > > > +							test_idx);
> > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > >
> > > > >  			TEST_RING_VERIFY(rte_ring_free_count(r) == 0); @@
> > > > > -259,8 +435,8 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > api_type, unsigned int create_flags,
> > > > >  			TEST_RING_VERIFY(rte_ring_empty(r) == 0);
> > > > >
> > > > >  			/* empty the ring */
> > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i], rsz,
> > > > > -							api_type);
> > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> rsz,
> > > > > +							test_idx);
> > > > >  			TEST_RING_VERIFY(ret == (int)rsz);
> > > > >  			TEST_RING_VERIFY(rsz == rte_ring_free_count(r));
> > > > >  			TEST_RING_VERIFY(rte_ring_count(r) == 0); @@ -
> > > > > 294,8 +470,7 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > api_type, unsigned int create_flags,
> > > > >   * dequeued data.
> > > > >   */
> > > > >  static int
> > > > > -test_ring_burst_bulk_tests2(unsigned int api_type, unsigned int
> > > create_flags,
> > > > > -	const char *tname)
> > > > > +test_ring_burst_bulk_tests2(unsigned int test_idx)
> > > > >  {
> > > > >  	struct rte_ring *r;
> > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst =
> > > > > NULL; @@ -303,11 +478,13 @@
> test_ring_burst_bulk_tests2(unsigned
> > > > > int api_type, unsigned int create_flags,
> > > > >  	unsigned int i;
> > > > >
> > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > +
> 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > >
> > > > >  		/* Create the ring */
> > > > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > create_flags);
> > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > +
> 	test_enqdeq_impl[test_idx].create_flags);
> > > > >
> > > > >  		/* alloc dummy object pointers */
> > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -323,39
> > > > > +500,39 @@ test_ring_burst_bulk_tests2(unsigned int api_type,
> > > > > +unsigned int
> > > > > create_flags,
> > > > >  		cur_dst = dst;
> > > > >
> > > > >  		printf("enqueue 1 obj\n");
> > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 1,
> api_type);
> > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 1,
> test_idx);
> > > > >  		if (ret != 1)
> > > > >  			goto fail;
> > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
> > > > >
> > > > >  		printf("enqueue 2 objs\n");
> > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> api_type);
> > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> test_idx);
> > > > >  		if (ret != 2)
> > > > >  			goto fail;
> > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
> > > > >
> > > > >  		printf("enqueue MAX_BULK objs\n");
> > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> MAX_BULK,
> > > > > -						api_type);
> > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> MAX_BULK,
> > > > > +						test_idx);
> > > > >  		if (ret != MAX_BULK)
> > > > >  			goto fail;
> > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK);
> > > > >
> > > > >  		printf("dequeue 1 obj\n");
> > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1,
> api_type);
> > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1,
> test_idx);
> > > > >  		if (ret != 1)
> > > > >  			goto fail;
> > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
> > > > >
> > > > >  		printf("dequeue 2 objs\n");
> > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> api_type);
> > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> test_idx);
> > > > >  		if (ret != 2)
> > > > >  			goto fail;
> > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
> > > > >
> > > > >  		printf("dequeue MAX_BULK objs\n");
> > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> MAX_BULK,
> > > > > -						api_type);
> > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> MAX_BULK,
> > > > > +						test_idx);
> > > > >  		if (ret != MAX_BULK)
> > > > >  			goto fail;
> > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK); @@
> > > > > -390,8 +567,7 @@ test_ring_burst_bulk_tests2(unsigned int
> > > > > api_type, unsigned int create_flags,
> > > > >   * Enqueue and dequeue to cover the entire ring length.
> > > > >   */
> > > > >  static int
> > > > > -test_ring_burst_bulk_tests3(unsigned int api_type, unsigned int
> > > create_flags,
> > > > > -	const char *tname)
> > > > > +test_ring_burst_bulk_tests3(unsigned int test_idx)
> > > > >  {
> > > > >  	struct rte_ring *r;
> > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst =
> > > > > NULL; @@ -399,11 +575,13 @@
> test_ring_burst_bulk_tests3(unsigned
> > > > > int api_type, unsigned int create_flags,
> > > > >  	unsigned int i, j;
> > > > >
> > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > +
> 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > >
> > > > >  		/* Create the ring */
> > > > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > create_flags);
> > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > +
> 	test_enqdeq_impl[test_idx].create_flags);
> > > > >
> > > > >  		/* alloc dummy object pointers */
> > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -420,15
> > > > > +598,15 @@ test_ring_burst_bulk_tests3(unsigned int api_type,
> > > > > +unsigned int
> > > > > create_flags,
> > > > >
> > > > >  		printf("fill and empty the ring\n");
> > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > MAX_BULK,
> > > > > -							api_type);
> > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > MAX_BULK,
> > > > > +							test_idx);
> > > > >  			if (ret != MAX_BULK)
> > > > >  				goto fail;
> > > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > >  								MAX_BULK);
> > > > >
> > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > MAX_BULK,
> > > > > -							api_type);
> > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > MAX_BULK,
> > > > > +							test_idx);
> > > > >  			if (ret != MAX_BULK)
> > > > >  				goto fail;
> > > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> > > > > 465,21 +643,24 @@ test_ring_burst_bulk_tests3(unsigned int
> > > > > api_type, unsigned int create_flags,
> > > > >   * Enqueue till the ring is full and dequeue till the ring becomes empty.
> > > > >   */
> > > > >  static int
> > > > > -test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int
> > > create_flags,
> > > > > -	const char *tname)
> > > > > +test_ring_burst_bulk_tests4(unsigned int test_idx)
> > > > >  {
> > > > >  	struct rte_ring *r;
> > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> > > > >  	int ret;
> > > > >  	unsigned int i, j;
> > > > > -	unsigned int num_elems;
> > > > > +	unsigned int api_type, num_elems;
> > > > > +
> > > > > +	api_type = test_enqdeq_impl[test_idx].api_type;
> > > > >
> > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > +
> 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > >
> > > > >  		/* Create the ring */
> > > > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > create_flags);
> > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > +
> 	test_enqdeq_impl[test_idx].create_flags);
> > > > >
> > > > >  		/* alloc dummy object pointers */
> > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -496,8
> > > > > +677,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > +unsigned int
> > > > > create_flags,
> > > > >
> > > > >  		printf("Test enqueue without enough memory space\n");
> > > > >  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
> > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > MAX_BULK,
> > > > > -							api_type);
> > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > MAX_BULK,
> > > > > +							test_idx);
> > > > >  			if (ret != MAX_BULK)
> > > > >  				goto fail;
> > > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i], @@ -
> > > > > 505,7 +686,7 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > api_type, unsigned int create_flags,
> > > > >  		}
> > > > >
> > > > >  		printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n");
> > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> api_type);
> > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> test_idx);
> > > > >  		if (ret != 2)
> > > > >  			goto fail;
> > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); @@ -517,8
> > > > > +698,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > +unsigned int
> > > > > create_flags,
> > > > >  		else
> > > > >  			num_elems = MAX_BULK;
> > > > >  		/* Always one free entry left */
> > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> num_elems,
> > > > > -						api_type);
> > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> num_elems,
> > > > > +						test_idx);
> > > > >  		if (ret != MAX_BULK - 3)
> > > > >  			goto fail;
> > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK - 3);
> > > @@
> > > > > -528,15 +709,15 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > api_type, unsigned int create_flags,
> > > > >  			goto fail;
> > > > >
> > > > >  		printf("Test enqueue for a full entry\n");
> > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> MAX_BULK,
> > > > > -						api_type);
> > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> MAX_BULK,
> > > > > +						test_idx);
> > > > >  		if (ret != 0)
> > > > >  			goto fail;
> > > > >
> > > > >  		printf("Test dequeue without enough objects\n");
> > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > MAX_BULK,
> > > > > -							api_type);
> > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > MAX_BULK,
> > > > > +							test_idx);
> > > > >  			if (ret != MAX_BULK)
> > > > >  				goto fail;
> > > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> > > > > 544,7 +725,7 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > api_type, unsigned int create_flags,
> > > > >  		}
> > > > >
> > > > >  		/* Available memory space for the exact MAX_BULK entries
> > > */
> > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> api_type);
> > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> test_idx);
> > > > >  		if (ret != 2)
> > > > >  			goto fail;
> > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); @@ -554,8
> > > > > +735,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > +unsigned int
> > > > > create_flags,
> > > > >  			num_elems = MAX_BULK - 3;
> > > > >  		else
> > > > >  			num_elems = MAX_BULK;
> > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> num_elems,
> > > > > -						api_type);
> > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> num_elems,
> > > > > +						test_idx);
> > > > >  		if (ret != MAX_BULK - 3)
> > > > >  			goto fail;
> > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK - 3);
> > > @@
> > > > > -816,22 +997,7 @@ static int
> > > > >  test_ring(void)
> > > > >  {
> > > > >  	int32_t rc;
> > > > > -	unsigned int i, j;
> > > > > -	const char *tname;
> > > > > -
> > > > > -	static const struct {
> > > > > -		uint32_t create_flags;
> > > > > -		const char *name;
> > > > > -	} test_sync_modes[] = {
> > > > > -		{
> > > > > -			RING_F_MP_RTS_ENQ |
> RING_F_MC_RTS_DEQ,
> > > > > -			"Test MT_RTS ring",
> > > > > -		},
> > > > > -		{
> > > > > -			RING_F_MP_HTS_ENQ |
> RING_F_MC_HTS_DEQ,
> > > > > -			"Test MT_HTS ring",
> > > > > -		},
> > > > > -	};
> > > > > +	unsigned int i;
> > > > >
> > > > >  	/* Negative test cases */
> > > > >  	if (test_ring_negative_tests() < 0) @@ -848,65 +1014,24 @@
> > > > > test_ring(void)
> > > > >  	 * The test cases are split into smaller test cases to
> > > > >  	 * help clang compile faster.
> > > > >  	 */
> > > > > -	tname = "Test standard ring";
> > > > > -
> > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> j <<= 1)
> > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > -					i <=
> TEST_RING_THREAD_MPMC; i
> > > > > <<= 1)
> > > > > -			if (test_ring_burst_bulk_tests1(i | j, 0, tname)
> < 0)
> > > > > -				goto test_fail;
> > > > > -
> > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> j <<= 1)
> > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > -					i <=
> TEST_RING_THREAD_MPMC; i
> > > > > <<= 1)
> > > > > -			if (test_ring_burst_bulk_tests2(i | j, 0, tname)
> < 0)
> > > > > -				goto test_fail;
> > > > > -
> > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> j <<= 1)
> > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > -					i <=
> TEST_RING_THREAD_MPMC; i
> > > > > <<= 1)
> > > > > -			if (test_ring_burst_bulk_tests3(i | j, 0, tname)
> < 0)
> > > > > -				goto test_fail;
> > > > > -
> > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> j <<= 1)
> > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > -					i <=
> TEST_RING_THREAD_MPMC; i
> > > > > <<= 1)
> > > > > -			if (test_ring_burst_bulk_tests4(i | j, 0, tname)
> < 0)
> > > > > -				goto test_fail;
> > > > > -
> > > > > -	/* Burst and bulk operations with MT_RTS and MT_HTS sync
> modes
> > > > > */
> > > > > -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> > > > > -		for (j = TEST_RING_ELEM_BULK; j <=
> TEST_RING_ELEM_BURST;
> > > > > -				j <<= 1) {
> > > > > -
> > > > > -			rc = test_ring_burst_bulk_tests1(
> > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > -				test_sync_modes[i].create_flags,
> > > > > -				test_sync_modes[i].name);
> > > > > -			if (rc < 0)
> > > > > -				goto test_fail;
> > > > > -
> > > > > -			rc = test_ring_burst_bulk_tests2(
> > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > -				test_sync_modes[i].create_flags,
> > > > > -				test_sync_modes[i].name);
> > > > > -			if (rc < 0)
> > > > > -				goto test_fail;
> > > > > -
> > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > -				test_sync_modes[i].create_flags,
> > > > > -				test_sync_modes[i].name);
> > > > > -			if (rc < 0)
> > > > > -				goto test_fail;
> > > > > -
> > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > -				test_sync_modes[i].create_flags,
> > > > > -				test_sync_modes[i].name);
> > > > > -			if (rc < 0)
> > > > > -				goto test_fail;
> > > > > -		}
> > > > > +	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
> > > > > +
> > > > > +
> > > > > +		rc = test_ring_burst_bulk_tests1(i);
> > > > > +		if (rc < 0)
> > > > > +			goto test_fail;
> > > > > +
> > > > > +		rc = test_ring_burst_bulk_tests2(i);
> > > > > +		if (rc < 0)
> > > > > +			goto test_fail;
> > > > > +
> > > > > +		rc = test_ring_burst_bulk_tests3(i);
> > > > > +		if (rc < 0)
> > > > > +			goto test_fail;
> > > > > +
> > > > > +		rc = test_ring_burst_bulk_tests4(i);
> > > > > +		if (rc < 0)
> > > > > +			goto test_fail;
> > > > >  	}
> > > > >
> > > > >  	/* dump the ring status */
> > > > > --
> > > > > 2.17.1
Ananyev, Konstantin May 5, 2020, 2:27 p.m. UTC | #9
> > > >
> > > > > Hi Konstantin,
> > > > > 	I like the way the tests are organized and it looks good.
> > > > >
> > > > > I am just wondering about the way it is being tested here. The
> > > > > intent to write the test cases the way they are currently is to
> > > > > mimic how the APIs would be used mostly. IMO, the APIs would be
> > > > > used with a constant
> > > > value for element size so that the compiler will throw away the
> > > > unwanted code (in the functions where the actual copy is being done).
> > > > >
> > > > > With your method here, it looks to me like all the branches in the
> > > > > copy
> > > > functions are kept and the branch decisions are done at run time.
> > > > > Is  my understanding correct?
> > > >
> > > > You mean branching on esize[] values?
> > > Yes
> > >
> > > > Actually from what I've seen that happens for both cases:
> > > > before and after the patch (gcc 7.3 -O3).
> > > I did not look at the generated code. If it is happening with your patch too, I
> > think we can go with your patch.
> >
> > Just to clarify, what I meant:
> > For both binaries (without the patch and with the patch) inside test_ring() I
> > see runtime branches on esize value.
> > Literally the code that corresponds to:
> > if (esize == 8) {...}
> > else if (esize == 16) {...}
> > else {...}
> Do you see this in the actual ring library functions?

Which ones? AFAIK all ring dequeue/enqueue functions are inline right now.

> I want to make sure that the library functions '__rte_ring_enqueue_elems' and
> '__rte_ring_dequeue_elems' are optimized.
> 
> >
> > Probably gcc wasn't able to remove it because we use esize[] instead of hard-
> > coded values, might be there is some other reason, I don't know for sure.
> > As it is a functional (not performance) test, I didn't dig further.
> The esize[] array is declared as a const. The compiler should be able to see that it is a compile time constant.

That was my expectation too, but that not what I am seeing.
 
> >
> > > But, can you do similar
> > > change to test_ring_perf.c to keep it consistent?
> >
> > In principle it is doable, but needs extra care.
> > We need to make sure that compiler will be able to inline functions via
> > pointers.
> > AFAIK, gcc does that with -O3', but not with '-O2'.
> If the unwanted code is not removed during compilation, we will see it affect the performance numbers.

Exactly. 
The last thing I want - someone who uses older version of compiler, etc.,
will start to see lower performance numbers with that test. 
 
> > Don't know what the story with clang and different versions of the compiler.
> > Is there any real need for that?
> > On my box test_ring_perf.c compilation takes ~8s.
> > Konstantin
> >
> >
> > >
> > > >
> > > > Main intention in my changes was to avoid using
> > > > test_ring_enqueue/test_ring_dequeue,
> > > > as it seems too many branches here and it takes compiler a lot of
> > > > effort to resolve all of them at compile time.
> > > > So I replaced it with  array of function pointers
> > > > (test_enqdeq_impl[]) and iterating over it.
> > > > That way compiler knows straightway which function to use.
> > > >
> > > > > Can you please check this? https://patches.dpdk.org/patch/69567/
> > > >
> > > > As I can see your approach reduces number of test-cases by factor of 5:
> > > > now each of test_ring_burst_bulk_tests[1-4] is executed only with
> > > > just one esize value, correct?
> > > Yes, basically test_ring_burst_bulk_tests[1-4] were covering different
> > > scenarios with the same APIs. So, distributed the esize across different test
> > functions.
> > >
> > > > In term of compilation speed - it helps.
> > > > On my box with (gcc 7.3 -O3)  compiling test_ring.c takes:
> > > > orig code:                             ~100s
> > > > with 69567 (your patch):  < 20s
> > > > with 69559 (my patch):    < 10s
> > > >
> > > > Konstantin
> > > >
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > > > > > Sent: Wednesday, April 29, 2020 12:57 PM
> > > > > > To: dev@dpdk.org
> > > > > > Cc: aconole@redhat.com; Honnappa Nagarahalli
> > > > > > <Honnappa.Nagarahalli@arm.com>; Konstantin Ananyev
> > > > > > <konstantin.ananyev@intel.com>
> > > > > > Subject: [PATCH] test/ring: code rework to reduce compilation
> > > > > > time
> > > > > >
> > > > > > Rework test code to reduce code complexity for the compiler and
> > > > > > bring down compilation time and memory consumption.
> > > > > >
> > > > > > Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > > > > > ---
> > > > > >  app/test/test_ring.c | 373
> > > > > > +++++++++++++++++++++++++++++--------------
> > > > > >  1 file changed, 249 insertions(+), 124 deletions(-)
> > > > > >
> > > > > > diff --git a/app/test/test_ring.c b/app/test/test_ring.c index
> > > > > > e21557cd9..0ae97d341 100644
> > > > > > --- a/app/test/test_ring.c
> > > > > > +++ b/app/test/test_ring.c
> > > > > > @@ -58,6 +58,181 @@
> > > > > >
> > > > > >  static const int esize[] = {-1, 4, 8, 16, 20};
> > > > > >
> > > > > > +static const struct {
> > > > > > +	const char *desc;
> > > > > > +	uint32_t api_type;
> > > > > > +	uint32_t create_flags;
> > > > > > +	struct {
> > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > +			void * const *obj_table, unsigned int n,
> > > > > > +			unsigned int *free_space);
> > > > > > +		unsigned int (*felem)(struct rte_ring *r, const void
> > *obj_table,
> > > > > > +			unsigned int esize, unsigned int n,
> > > > > > +			unsigned int *free_space);
> > > > > > +	} enq;
> > > > > > +	struct {
> > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > +			void **obj_table, unsigned int n,
> > > > > > +			unsigned int *available);
> > > > > > +		unsigned int (*felem)(struct rte_ring *r, void
> > *obj_table,
> > > > > > +			unsigned int esize, unsigned int n,
> > > > > > +			unsigned int *available);
> > > > > > +	} deq;
> > > > > > +} test_enqdeq_impl[] = {
> > > > > > +	{
> > > > > > +		.desc = "MP/MC sync mode",
> > > > > Details about the tests are already printed by the function
> > > > 'test_ring_print_test_string'. This string should be 'Test standard ring'.
> > > > >
> > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > TEST_RING_THREAD_DEF,
> > > > > > +		.create_flags = 0,
> > > > > > +		.enq = {
> > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > +		},
> > > > > > +		.deq = {
> > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > +		},
> > > > > > +	},
> > > > > > +	{
> > > > > > +		.desc = "SP/SC sync mode",
> > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > TEST_RING_THREAD_SPSC,
> > > > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > > > +		.enq = {
> > > > > > +			.flegacy = rte_ring_sp_enqueue_bulk,
> > > > > > +			.felem = rte_ring_sp_enqueue_bulk_elem,
> > > > > > +		},
> > > > > > +		.deq = {
> > > > > > +			.flegacy = rte_ring_sc_dequeue_bulk,
> > > > > > +			.felem = rte_ring_sc_dequeue_bulk_elem,
> > > > > > +		},
> > > > > > +	},
> > > > > > +	{
> > > > > > +		.desc = "MP/MC sync mode",
> > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > TEST_RING_THREAD_MPMC,
> > > > > > +		.create_flags = 0,
> > > > > > +		.enq = {
> > > > > > +			.flegacy = rte_ring_mp_enqueue_bulk,
> > > > > > +			.felem = rte_ring_mp_enqueue_bulk_elem,
> > > > > > +		},
> > > > > > +		.deq = {
> > > > > > +			.flegacy = rte_ring_mc_dequeue_bulk,
> > > > > > +			.felem = rte_ring_mc_dequeue_bulk_elem,
> > > > > > +		},
> > > > > > +	},
> > > > > > +	{
> > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > TEST_RING_THREAD_DEF,
> > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > RING_F_MC_RTS_DEQ,
> > > > > > +		.enq = {
> > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > +		},
> > > > > > +		.deq = {
> > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > +		},
> > > > > > +	},
> > > > > > +	{
> > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > TEST_RING_THREAD_DEF,
> > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > RING_F_MC_HTS_DEQ,
> > > > > > +		.enq = {
> > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > +		},
> > > > > > +		.deq = {
> > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > +		},
> > > > > > +	},
> > > > > > +	{
> > > > > > +		.desc = "MP/MC sync mode",
> > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > TEST_RING_THREAD_DEF,
> > > > > > +		.create_flags = 0,
> > > > > > +		.enq = {
> > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > +		},
> > > > > > +		.deq = {
> > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > +		},
> > > > > > +	},
> > > > > > +	{
> > > > > > +		.desc = "SP/SC sync mode",
> > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > TEST_RING_THREAD_SPSC,
> > > > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > > > +		.enq = {
> > > > > > +			.flegacy = rte_ring_sp_enqueue_burst,
> > > > > > +			.felem = rte_ring_sp_enqueue_burst_elem,
> > > > > > +		},
> > > > > > +		.deq = {
> > > > > > +			.flegacy = rte_ring_sc_dequeue_burst,
> > > > > > +			.felem = rte_ring_sc_dequeue_burst_elem,
> > > > > > +		},
> > > > > > +	},
> > > > > > +	{
> > > > > > +		.desc = "MP/MC sync mode",
> > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > TEST_RING_THREAD_MPMC,
> > > > > > +		.create_flags = 0,
> > > > > > +		.enq = {
> > > > > > +			.flegacy = rte_ring_mp_enqueue_burst,
> > > > > > +			.felem = rte_ring_mp_enqueue_burst_elem,
> > > > > > +		},
> > > > > > +		.deq = {
> > > > > > +			.flegacy = rte_ring_mc_dequeue_burst,
> > > > > > +			.felem = rte_ring_mc_dequeue_burst_elem,
> > > > > > +		},
> > > > > > +	},
> > > > > > +	{
> > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > TEST_RING_THREAD_DEF,
> > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > RING_F_MC_RTS_DEQ,
> > > > > > +		.enq = {
> > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > +		},
> > > > > > +		.deq = {
> > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > +		},
> > > > > > +	},
> > > > > > +	{
> > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > TEST_RING_THREAD_DEF,
> > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > RING_F_MC_HTS_DEQ,
> > > > > > +		.enq = {
> > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > +		},
> > > > > > +		.deq = {
> > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > +		},
> > > > > > +	},
> > > > > > +};
> > > > > > +
> > > > > > +static unsigned int
> > > > > > +test_ring_enq_impl(struct rte_ring *r, void **obj, int esize, unsigned
> > int n,
> > > > > > +	unsigned int test_idx)
> > > > > > +{
> > > > > > +	if (esize == -1)
> > > > > > +		return test_enqdeq_impl[test_idx].enq.flegacy(r, obj,
> > n, NULL);
> > > > > > +	else
> > > > > > +		return test_enqdeq_impl[test_idx].enq.felem(r, obj,
> > esize, n,
> > > > > > +			NULL);
> > > > > > +}
> > > > > > +
> > > > > > +static unsigned int
> > > > > > +test_ring_deq_impl(struct rte_ring *r, void **obj, int esize, unsigned
> > int n,
> > > > > > +	unsigned int test_idx)
> > > > > > +{
> > > > > > +	if (esize == -1)
> > > > > > +		return test_enqdeq_impl[test_idx].deq.flegacy(r, obj,
> > n, NULL);
> > > > > > +	else
> > > > > > +		return test_enqdeq_impl[test_idx].deq.felem(r, obj,
> > esize, n,
> > > > > > +			NULL);
> > > > > > +}
> > > > > > +
> > > > > >  static void**
> > > > > >  test_ring_inc_ptr(void **obj, int esize, unsigned int n)  { @@
> > > > > > -203,8 +378,7 @@ test_ring_negative_tests(void)
> > > > > >   * Random number of elements are enqueued and dequeued.
> > > > > >   */
> > > > > >  static int
> > > > > > -test_ring_burst_bulk_tests1(unsigned int api_type, unsigned int
> > > > create_flags,
> > > > > > -	const char *tname)
> > > > > > +test_ring_burst_bulk_tests1(unsigned int test_idx)
> > > > > >  {
> > > > > >  	struct rte_ring *r;
> > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst =
> > > > > > NULL; @@ -214,11 +388,13 @@
> > test_ring_burst_bulk_tests1(unsigned
> > > > > > int api_type, unsigned int create_flags,
> > > > > >  	const unsigned int rsz = RING_SIZE - 1;
> > > > > >
> > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > +
> > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > >
> > > > > >  		/* Create the ring */
> > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > create_flags);
> > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > +
> > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > >
> > > > > >  		/* alloc dummy object pointers */
> > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -240,17
> > > > > > +416,17 @@ test_ring_burst_bulk_tests1(unsigned int api_type,
> > > > > > +unsigned int
> > > > > > create_flags,
> > > > > >  			rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL);
> > > > > >  			printf("%s: iteration %u, random shift: %u;\n",
> > > > > >  			    __func__, i, rand);
> > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > rand,
> > > > > > -							api_type);
> > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > rand,
> > > > > > +							test_idx);
> > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > >
> > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > rand,
> > > > > > -							api_type);
> > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > rand,
> > > > > > +							test_idx);
> > > > > >  			TEST_RING_VERIFY(ret == rand);
> > > > > >
> > > > > >  			/* fill the ring */
> > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i], rsz,
> > > > > > -							api_type);
> > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > rsz,
> > > > > > +							test_idx);
> > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > >
> > > > > >  			TEST_RING_VERIFY(rte_ring_free_count(r) == 0); @@
> > > > > > -259,8 +435,8 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > api_type, unsigned int create_flags,
> > > > > >  			TEST_RING_VERIFY(rte_ring_empty(r) == 0);
> > > > > >
> > > > > >  			/* empty the ring */
> > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i], rsz,
> > > > > > -							api_type);
> > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > rsz,
> > > > > > +							test_idx);
> > > > > >  			TEST_RING_VERIFY(ret == (int)rsz);
> > > > > >  			TEST_RING_VERIFY(rsz == rte_ring_free_count(r));
> > > > > >  			TEST_RING_VERIFY(rte_ring_count(r) == 0); @@ -
> > > > > > 294,8 +470,7 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > api_type, unsigned int create_flags,
> > > > > >   * dequeued data.
> > > > > >   */
> > > > > >  static int
> > > > > > -test_ring_burst_bulk_tests2(unsigned int api_type, unsigned int
> > > > create_flags,
> > > > > > -	const char *tname)
> > > > > > +test_ring_burst_bulk_tests2(unsigned int test_idx)
> > > > > >  {
> > > > > >  	struct rte_ring *r;
> > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst =
> > > > > > NULL; @@ -303,11 +478,13 @@
> > test_ring_burst_bulk_tests2(unsigned
> > > > > > int api_type, unsigned int create_flags,
> > > > > >  	unsigned int i;
> > > > > >
> > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > +
> > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > >
> > > > > >  		/* Create the ring */
> > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > create_flags);
> > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > +
> > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > >
> > > > > >  		/* alloc dummy object pointers */
> > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -323,39
> > > > > > +500,39 @@ test_ring_burst_bulk_tests2(unsigned int api_type,
> > > > > > +unsigned int
> > > > > > create_flags,
> > > > > >  		cur_dst = dst;
> > > > > >
> > > > > >  		printf("enqueue 1 obj\n");
> > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 1,
> > api_type);
> > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 1,
> > test_idx);
> > > > > >  		if (ret != 1)
> > > > > >  			goto fail;
> > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
> > > > > >
> > > > > >  		printf("enqueue 2 objs\n");
> > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > api_type);
> > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > test_idx);
> > > > > >  		if (ret != 2)
> > > > > >  			goto fail;
> > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
> > > > > >
> > > > > >  		printf("enqueue MAX_BULK objs\n");
> > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > MAX_BULK,
> > > > > > -						api_type);
> > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > MAX_BULK,
> > > > > > +						test_idx);
> > > > > >  		if (ret != MAX_BULK)
> > > > > >  			goto fail;
> > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK);
> > > > > >
> > > > > >  		printf("dequeue 1 obj\n");
> > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1,
> > api_type);
> > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1,
> > test_idx);
> > > > > >  		if (ret != 1)
> > > > > >  			goto fail;
> > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
> > > > > >
> > > > > >  		printf("dequeue 2 objs\n");
> > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > api_type);
> > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > test_idx);
> > > > > >  		if (ret != 2)
> > > > > >  			goto fail;
> > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
> > > > > >
> > > > > >  		printf("dequeue MAX_BULK objs\n");
> > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > MAX_BULK,
> > > > > > -						api_type);
> > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > MAX_BULK,
> > > > > > +						test_idx);
> > > > > >  		if (ret != MAX_BULK)
> > > > > >  			goto fail;
> > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK); @@
> > > > > > -390,8 +567,7 @@ test_ring_burst_bulk_tests2(unsigned int
> > > > > > api_type, unsigned int create_flags,
> > > > > >   * Enqueue and dequeue to cover the entire ring length.
> > > > > >   */
> > > > > >  static int
> > > > > > -test_ring_burst_bulk_tests3(unsigned int api_type, unsigned int
> > > > create_flags,
> > > > > > -	const char *tname)
> > > > > > +test_ring_burst_bulk_tests3(unsigned int test_idx)
> > > > > >  {
> > > > > >  	struct rte_ring *r;
> > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst =
> > > > > > NULL; @@ -399,11 +575,13 @@
> > test_ring_burst_bulk_tests3(unsigned
> > > > > > int api_type, unsigned int create_flags,
> > > > > >  	unsigned int i, j;
> > > > > >
> > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > +
> > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > >
> > > > > >  		/* Create the ring */
> > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > create_flags);
> > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > +
> > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > >
> > > > > >  		/* alloc dummy object pointers */
> > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -420,15
> > > > > > +598,15 @@ test_ring_burst_bulk_tests3(unsigned int api_type,
> > > > > > +unsigned int
> > > > > > create_flags,
> > > > > >
> > > > > >  		printf("fill and empty the ring\n");
> > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > MAX_BULK,
> > > > > > -							api_type);
> > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > MAX_BULK,
> > > > > > +							test_idx);
> > > > > >  			if (ret != MAX_BULK)
> > > > > >  				goto fail;
> > > > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > >  								MAX_BULK);
> > > > > >
> > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > MAX_BULK,
> > > > > > -							api_type);
> > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > MAX_BULK,
> > > > > > +							test_idx);
> > > > > >  			if (ret != MAX_BULK)
> > > > > >  				goto fail;
> > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> > > > > > 465,21 +643,24 @@ test_ring_burst_bulk_tests3(unsigned int
> > > > > > api_type, unsigned int create_flags,
> > > > > >   * Enqueue till the ring is full and dequeue till the ring becomes empty.
> > > > > >   */
> > > > > >  static int
> > > > > > -test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int
> > > > create_flags,
> > > > > > -	const char *tname)
> > > > > > +test_ring_burst_bulk_tests4(unsigned int test_idx)
> > > > > >  {
> > > > > >  	struct rte_ring *r;
> > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> > > > > >  	int ret;
> > > > > >  	unsigned int i, j;
> > > > > > -	unsigned int num_elems;
> > > > > > +	unsigned int api_type, num_elems;
> > > > > > +
> > > > > > +	api_type = test_enqdeq_impl[test_idx].api_type;
> > > > > >
> > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > +
> > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > >
> > > > > >  		/* Create the ring */
> > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
> > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > create_flags);
> > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > +
> > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > >
> > > > > >  		/* alloc dummy object pointers */
> > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@ -496,8
> > > > > > +677,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > > +unsigned int
> > > > > > create_flags,
> > > > > >
> > > > > >  		printf("Test enqueue without enough memory space\n");
> > > > > >  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
> > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > MAX_BULK,
> > > > > > -							api_type);
> > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > MAX_BULK,
> > > > > > +							test_idx);
> > > > > >  			if (ret != MAX_BULK)
> > > > > >  				goto fail;
> > > > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i], @@ -
> > > > > > 505,7 +686,7 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > api_type, unsigned int create_flags,
> > > > > >  		}
> > > > > >
> > > > > >  		printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n");
> > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > api_type);
> > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > test_idx);
> > > > > >  		if (ret != 2)
> > > > > >  			goto fail;
> > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); @@ -517,8
> > > > > > +698,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > > +unsigned int
> > > > > > create_flags,
> > > > > >  		else
> > > > > >  			num_elems = MAX_BULK;
> > > > > >  		/* Always one free entry left */
> > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > num_elems,
> > > > > > -						api_type);
> > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > num_elems,
> > > > > > +						test_idx);
> > > > > >  		if (ret != MAX_BULK - 3)
> > > > > >  			goto fail;
> > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK - 3);
> > > > @@
> > > > > > -528,15 +709,15 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > api_type, unsigned int create_flags,
> > > > > >  			goto fail;
> > > > > >
> > > > > >  		printf("Test enqueue for a full entry\n");
> > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > MAX_BULK,
> > > > > > -						api_type);
> > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > MAX_BULK,
> > > > > > +						test_idx);
> > > > > >  		if (ret != 0)
> > > > > >  			goto fail;
> > > > > >
> > > > > >  		printf("Test dequeue without enough objects\n");
> > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > MAX_BULK,
> > > > > > -							api_type);
> > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > MAX_BULK,
> > > > > > +							test_idx);
> > > > > >  			if (ret != MAX_BULK)
> > > > > >  				goto fail;
> > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i], @@ -
> > > > > > 544,7 +725,7 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > api_type, unsigned int create_flags,
> > > > > >  		}
> > > > > >
> > > > > >  		/* Available memory space for the exact MAX_BULK entries
> > > > */
> > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > api_type);
> > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > test_idx);
> > > > > >  		if (ret != 2)
> > > > > >  			goto fail;
> > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); @@ -554,8
> > > > > > +735,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > > +unsigned int
> > > > > > create_flags,
> > > > > >  			num_elems = MAX_BULK - 3;
> > > > > >  		else
> > > > > >  			num_elems = MAX_BULK;
> > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > num_elems,
> > > > > > -						api_type);
> > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > num_elems,
> > > > > > +						test_idx);
> > > > > >  		if (ret != MAX_BULK - 3)
> > > > > >  			goto fail;
> > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK - 3);
> > > > @@
> > > > > > -816,22 +997,7 @@ static int
> > > > > >  test_ring(void)
> > > > > >  {
> > > > > >  	int32_t rc;
> > > > > > -	unsigned int i, j;
> > > > > > -	const char *tname;
> > > > > > -
> > > > > > -	static const struct {
> > > > > > -		uint32_t create_flags;
> > > > > > -		const char *name;
> > > > > > -	} test_sync_modes[] = {
> > > > > > -		{
> > > > > > -			RING_F_MP_RTS_ENQ |
> > RING_F_MC_RTS_DEQ,
> > > > > > -			"Test MT_RTS ring",
> > > > > > -		},
> > > > > > -		{
> > > > > > -			RING_F_MP_HTS_ENQ |
> > RING_F_MC_HTS_DEQ,
> > > > > > -			"Test MT_HTS ring",
> > > > > > -		},
> > > > > > -	};
> > > > > > +	unsigned int i;
> > > > > >
> > > > > >  	/* Negative test cases */
> > > > > >  	if (test_ring_negative_tests() < 0) @@ -848,65 +1014,24 @@
> > > > > > test_ring(void)
> > > > > >  	 * The test cases are split into smaller test cases to
> > > > > >  	 * help clang compile faster.
> > > > > >  	 */
> > > > > > -	tname = "Test standard ring";
> > > > > > -
> > > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > j <<= 1)
> > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > -					i <=
> > TEST_RING_THREAD_MPMC; i
> > > > > > <<= 1)
> > > > > > -			if (test_ring_burst_bulk_tests1(i | j, 0, tname)
> > < 0)
> > > > > > -				goto test_fail;
> > > > > > -
> > > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > j <<= 1)
> > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > -					i <=
> > TEST_RING_THREAD_MPMC; i
> > > > > > <<= 1)
> > > > > > -			if (test_ring_burst_bulk_tests2(i | j, 0, tname)
> > < 0)
> > > > > > -				goto test_fail;
> > > > > > -
> > > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > j <<= 1)
> > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > -					i <=
> > TEST_RING_THREAD_MPMC; i
> > > > > > <<= 1)
> > > > > > -			if (test_ring_burst_bulk_tests3(i | j, 0, tname)
> > < 0)
> > > > > > -				goto test_fail;
> > > > > > -
> > > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > j <<= 1)
> > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > -					i <=
> > TEST_RING_THREAD_MPMC; i
> > > > > > <<= 1)
> > > > > > -			if (test_ring_burst_bulk_tests4(i | j, 0, tname)
> > < 0)
> > > > > > -				goto test_fail;
> > > > > > -
> > > > > > -	/* Burst and bulk operations with MT_RTS and MT_HTS sync
> > modes
> > > > > > */
> > > > > > -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> > > > > > -		for (j = TEST_RING_ELEM_BULK; j <=
> > TEST_RING_ELEM_BURST;
> > > > > > -				j <<= 1) {
> > > > > > -
> > > > > > -			rc = test_ring_burst_bulk_tests1(
> > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > -				test_sync_modes[i].create_flags,
> > > > > > -				test_sync_modes[i].name);
> > > > > > -			if (rc < 0)
> > > > > > -				goto test_fail;
> > > > > > -
> > > > > > -			rc = test_ring_burst_bulk_tests2(
> > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > -				test_sync_modes[i].create_flags,
> > > > > > -				test_sync_modes[i].name);
> > > > > > -			if (rc < 0)
> > > > > > -				goto test_fail;
> > > > > > -
> > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > -				test_sync_modes[i].create_flags,
> > > > > > -				test_sync_modes[i].name);
> > > > > > -			if (rc < 0)
> > > > > > -				goto test_fail;
> > > > > > -
> > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > -				test_sync_modes[i].create_flags,
> > > > > > -				test_sync_modes[i].name);
> > > > > > -			if (rc < 0)
> > > > > > -				goto test_fail;
> > > > > > -		}
> > > > > > +	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
> > > > > > +
> > > > > > +
> > > > > > +		rc = test_ring_burst_bulk_tests1(i);
> > > > > > +		if (rc < 0)
> > > > > > +			goto test_fail;
> > > > > > +
> > > > > > +		rc = test_ring_burst_bulk_tests2(i);
> > > > > > +		if (rc < 0)
> > > > > > +			goto test_fail;
> > > > > > +
> > > > > > +		rc = test_ring_burst_bulk_tests3(i);
> > > > > > +		if (rc < 0)
> > > > > > +			goto test_fail;
> > > > > > +
> > > > > > +		rc = test_ring_burst_bulk_tests4(i);
> > > > > > +		if (rc < 0)
> > > > > > +			goto test_fail;
> > > > > >  	}
> > > > > >
> > > > > >  	/* dump the ring status */
> > > > > > --
> > > > > > 2.17.1
Honnappa Nagarahalli May 5, 2020, 6:13 p.m. UTC | #10
<snip>

> > > > >
> > > > > > Hi Konstantin,
> > > > > > 	I like the way the tests are organized and it looks good.
> > > > > >
> > > > > > I am just wondering about the way it is being tested here. The
> > > > > > intent to write the test cases the way they are currently is
> > > > > > to mimic how the APIs would be used mostly. IMO, the APIs
> > > > > > would be used with a constant
> > > > > value for element size so that the compiler will throw away the
> > > > > unwanted code (in the functions where the actual copy is being done).
> > > > > >
> > > > > > With your method here, it looks to me like all the branches in
> > > > > > the copy
> > > > > functions are kept and the branch decisions are done at run time.
> > > > > > Is  my understanding correct?
> > > > >
> > > > > You mean branching on esize[] values?
> > > > Yes
> > > >
> > > > > Actually from what I've seen that happens for both cases:
> > > > > before and after the patch (gcc 7.3 -O3).
> > > > I did not look at the generated code. If it is happening with your
> > > > patch too, I
> > > think we can go with your patch.
> > >
> > > Just to clarify, what I meant:
> > > For both binaries (without the patch and with the patch) inside
> > > test_ring() I see runtime branches on esize value.
> > > Literally the code that corresponds to:
> > > if (esize == 8) {...}
> > > else if (esize == 16) {...}
> > > else {...}
I am not concerned about the functions in test_ring.c.

> > Do you see this in the actual ring library functions?
> 
> Which ones? AFAIK all ring dequeue/enqueue functions are inline right now.
Please see below.

> 
> > I want to make sure that the library functions
> > '__rte_ring_enqueue_elems' and '__rte_ring_dequeue_elems' are optimized.
Each enqueue/dequeue function ultimately calls these 2 functions. The compiler here should remove the 'if (esize == 8) {...} else if (esize == 16) {...} else {...}' with just the required piece of code depending on the 'esize'. If we can validate that for at least one ring library function used in this patch, we should be good.

> >
> > >
> > > Probably gcc wasn't able to remove it because we use esize[] instead
> > > of hard- coded values, might be there is some other reason, I don't know
> for sure.
> > > As it is a functional (not performance) test, I didn't dig further.
> > The esize[] array is declared as a const. The compiler should be able to see
> that it is a compile time constant.
> 
> That was my expectation too, but that not what I am seeing.
> 
> > >
> > > > But, can you do similar
> > > > change to test_ring_perf.c to keep it consistent?
> > >
> > > In principle it is doable, but needs extra care.
> > > We need to make sure that compiler will be able to inline functions
> > > via pointers.
> > > AFAIK, gcc does that with -O3', but not with '-O2'.
> > If the unwanted code is not removed during compilation, we will see it
> affect the performance numbers.
> 
> Exactly.
> The last thing I want - someone who uses older version of compiler, etc., will
> start to see lower performance numbers with that test.
> 
> > > Don't know what the story with clang and different versions of the
> compiler.
> > > Is there any real need for that?
> > > On my box test_ring_perf.c compilation takes ~8s.
> > > Konstantin
> > >
> > >
> > > >
> > > > >
> > > > > Main intention in my changes was to avoid using
> > > > > test_ring_enqueue/test_ring_dequeue,
> > > > > as it seems too many branches here and it takes compiler a lot
> > > > > of effort to resolve all of them at compile time.
> > > > > So I replaced it with  array of function pointers
> > > > > (test_enqdeq_impl[]) and iterating over it.
> > > > > That way compiler knows straightway which function to use.
> > > > >
> > > > > > Can you please check this?
> > > > > > https://patches.dpdk.org/patch/69567/
> > > > >
> > > > > As I can see your approach reduces number of test-cases by factor of 5:
> > > > > now each of test_ring_burst_bulk_tests[1-4] is executed only
> > > > > with just one esize value, correct?
> > > > Yes, basically test_ring_burst_bulk_tests[1-4] were covering
> > > > different scenarios with the same APIs. So, distributed the esize
> > > > across different test
> > > functions.
> > > >
> > > > > In term of compilation speed - it helps.
> > > > > On my box with (gcc 7.3 -O3)  compiling test_ring.c takes:
> > > > > orig code:                             ~100s
> > > > > with 69567 (your patch):  < 20s
> > > > > with 69559 (my patch):    < 10s
> > > > >
> > > > > Konstantin
> > > > >
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > > > > > > Sent: Wednesday, April 29, 2020 12:57 PM
> > > > > > > To: dev@dpdk.org
> > > > > > > Cc: aconole@redhat.com; Honnappa Nagarahalli
> > > > > > > <Honnappa.Nagarahalli@arm.com>; Konstantin Ananyev
> > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > Subject: [PATCH] test/ring: code rework to reduce
> > > > > > > compilation time
> > > > > > >
> > > > > > > Rework test code to reduce code complexity for the compiler
> > > > > > > and bring down compilation time and memory consumption.
> > > > > > >
> > > > > > > Signed-off-by: Konstantin Ananyev
> > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > ---
> > > > > > >  app/test/test_ring.c | 373
> > > > > > > +++++++++++++++++++++++++++++--------------
> > > > > > >  1 file changed, 249 insertions(+), 124 deletions(-)
> > > > > > >
> > > > > > > diff --git a/app/test/test_ring.c b/app/test/test_ring.c
> > > > > > > index
> > > > > > > e21557cd9..0ae97d341 100644
> > > > > > > --- a/app/test/test_ring.c
> > > > > > > +++ b/app/test/test_ring.c
> > > > > > > @@ -58,6 +58,181 @@
> > > > > > >
> > > > > > >  static const int esize[] = {-1, 4, 8, 16, 20};
> > > > > > >
> > > > > > > +static const struct {
> > > > > > > +	const char *desc;
> > > > > > > +	uint32_t api_type;
> > > > > > > +	uint32_t create_flags;
> > > > > > > +	struct {
> > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > +			void * const *obj_table, unsigned int n,
> > > > > > > +			unsigned int *free_space);
> > > > > > > +		unsigned int (*felem)(struct rte_ring *r, const void
> > > *obj_table,
> > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > +			unsigned int *free_space);
> > > > > > > +	} enq;
> > > > > > > +	struct {
> > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > +			void **obj_table, unsigned int n,
> > > > > > > +			unsigned int *available);
> > > > > > > +		unsigned int (*felem)(struct rte_ring *r, void
> > > *obj_table,
> > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > +			unsigned int *available);
> > > > > > > +	} deq;
> > > > > > > +} test_enqdeq_impl[] = {
> > > > > > > +	{
> > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > Details about the tests are already printed by the function
> > > > > 'test_ring_print_test_string'. This string should be 'Test standard ring'.
> > > > > >
> > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > +		.create_flags = 0,
> > > > > > > +		.enq = {
> > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > +		},
> > > > > > > +		.deq = {
> > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > +		},
> > > > > > > +	},
> > > > > > > +	{
> > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > > > > +		.enq = {
> > > > > > > +			.flegacy = rte_ring_sp_enqueue_bulk,
> > > > > > > +			.felem = rte_ring_sp_enqueue_bulk_elem,
> > > > > > > +		},
> > > > > > > +		.deq = {
> > > > > > > +			.flegacy = rte_ring_sc_dequeue_bulk,
> > > > > > > +			.felem = rte_ring_sc_dequeue_bulk_elem,
> > > > > > > +		},
> > > > > > > +	},
> > > > > > > +	{
> > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > +		.create_flags = 0,
> > > > > > > +		.enq = {
> > > > > > > +			.flegacy = rte_ring_mp_enqueue_bulk,
> > > > > > > +			.felem = rte_ring_mp_enqueue_bulk_elem,
> > > > > > > +		},
> > > > > > > +		.deq = {
> > > > > > > +			.flegacy = rte_ring_mc_dequeue_bulk,
> > > > > > > +			.felem = rte_ring_mc_dequeue_bulk_elem,
> > > > > > > +		},
> > > > > > > +	},
> > > > > > > +	{
> > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > +		.enq = {
> > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > +		},
> > > > > > > +		.deq = {
> > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > +		},
> > > > > > > +	},
> > > > > > > +	{
> > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > +		.enq = {
> > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > +		},
> > > > > > > +		.deq = {
> > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > +		},
> > > > > > > +	},
> > > > > > > +	{
> > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > +		.create_flags = 0,
> > > > > > > +		.enq = {
> > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > > +		},
> > > > > > > +		.deq = {
> > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > > +		},
> > > > > > > +	},
> > > > > > > +	{
> > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > > > > +		.enq = {
> > > > > > > +			.flegacy = rte_ring_sp_enqueue_burst,
> > > > > > > +			.felem = rte_ring_sp_enqueue_burst_elem,
> > > > > > > +		},
> > > > > > > +		.deq = {
> > > > > > > +			.flegacy = rte_ring_sc_dequeue_burst,
> > > > > > > +			.felem = rte_ring_sc_dequeue_burst_elem,
> > > > > > > +		},
> > > > > > > +	},
> > > > > > > +	{
> > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > +		.create_flags = 0,
> > > > > > > +		.enq = {
> > > > > > > +			.flegacy = rte_ring_mp_enqueue_burst,
> > > > > > > +			.felem = rte_ring_mp_enqueue_burst_elem,
> > > > > > > +		},
> > > > > > > +		.deq = {
> > > > > > > +			.flegacy = rte_ring_mc_dequeue_burst,
> > > > > > > +			.felem = rte_ring_mc_dequeue_burst_elem,
> > > > > > > +		},
> > > > > > > +	},
> > > > > > > +	{
> > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > +		.enq = {
> > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > > +		},
> > > > > > > +		.deq = {
> > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > > +		},
> > > > > > > +	},
> > > > > > > +	{
> > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > +		.enq = {
> > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > > +		},
> > > > > > > +		.deq = {
> > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > > +		},
> > > > > > > +	},
> > > > > > > +};
> > > > > > > +
> > > > > > > +static unsigned int
> > > > > > > +test_ring_enq_impl(struct rte_ring *r, void **obj, int
> > > > > > > +esize, unsigned
> > > int n,
> > > > > > > +	unsigned int test_idx)
> > > > > > > +{
> > > > > > > +	if (esize == -1)
> > > > > > > +		return test_enqdeq_impl[test_idx].enq.flegacy(r, obj,
> > > n, NULL);
> > > > > > > +	else
> > > > > > > +		return test_enqdeq_impl[test_idx].enq.felem(r, obj,
> > > esize, n,
> > > > > > > +			NULL);
> > > > > > > +}
> > > > > > > +
> > > > > > > +static unsigned int
> > > > > > > +test_ring_deq_impl(struct rte_ring *r, void **obj, int
> > > > > > > +esize, unsigned
> > > int n,
> > > > > > > +	unsigned int test_idx)
> > > > > > > +{
> > > > > > > +	if (esize == -1)
> > > > > > > +		return test_enqdeq_impl[test_idx].deq.flegacy(r, obj,
> > > n, NULL);
> > > > > > > +	else
> > > > > > > +		return test_enqdeq_impl[test_idx].deq.felem(r, obj,
> > > esize, n,
> > > > > > > +			NULL);
> > > > > > > +}
> > > > > > > +
> > > > > > >  static void**
> > > > > > >  test_ring_inc_ptr(void **obj, int esize, unsigned int n)  {
> > > > > > > @@
> > > > > > > -203,8 +378,7 @@ test_ring_negative_tests(void)
> > > > > > >   * Random number of elements are enqueued and dequeued.
> > > > > > >   */
> > > > > > >  static int
> > > > > > > -test_ring_burst_bulk_tests1(unsigned int api_type, unsigned
> > > > > > > int
> > > > > create_flags,
> > > > > > > -	const char *tname)
> > > > > > > +test_ring_burst_bulk_tests1(unsigned int test_idx)
> > > > > > >  {
> > > > > > >  	struct rte_ring *r;
> > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > **cur_dst = NULL; @@ -214,11 +388,13 @@
> > > test_ring_burst_bulk_tests1(unsigned
> > > > > > > int api_type, unsigned int create_flags,
> > > > > > >  	const unsigned int rsz = RING_SIZE - 1;
> > > > > > >
> > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > +
> > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > >
> > > > > > >  		/* Create the ring */
> > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> esize[i],
> > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > create_flags);
> > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > +
> > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > >
> > > > > > >  		/* alloc dummy object pointers */
> > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > -240,17
> > > > > > > +416,17 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > > +api_type, unsigned int
> > > > > > > create_flags,
> > > > > > >  			rand = RTE_MAX(rte_rand() % RING_SIZE,
> 1UL);
> > > > > > >  			printf("%s: iteration %u, random shift: %u;\n",
> > > > > > >  			    __func__, i, rand);
> > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > rand,
> > > > > > > -							api_type);
> > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > rand,
> > > > > > > +							test_idx);
> > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > >
> > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > rand,
> > > > > > > -							api_type);
> > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > rand,
> > > > > > > +							test_idx);
> > > > > > >  			TEST_RING_VERIFY(ret == rand);
> > > > > > >
> > > > > > >  			/* fill the ring */
> > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i], rsz,
> > > > > > > -							api_type);
> > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > rsz,
> > > > > > > +							test_idx);
> > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > >
> > > > > > >  			TEST_RING_VERIFY(rte_ring_free_count(r) ==
> 0); @@
> > > > > > > -259,8 +435,8 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > > api_type, unsigned int create_flags,
> > > > > > >  			TEST_RING_VERIFY(rte_ring_empty(r) == 0);
> > > > > > >
> > > > > > >  			/* empty the ring */
> > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i], rsz,
> > > > > > > -							api_type);
> > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > rsz,
> > > > > > > +							test_idx);
> > > > > > >  			TEST_RING_VERIFY(ret == (int)rsz);
> > > > > > >  			TEST_RING_VERIFY(rsz ==
> rte_ring_free_count(r));
> > > > > > >  			TEST_RING_VERIFY(rte_ring_count(r) == 0);
> @@ -
> > > > > > > 294,8 +470,7 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > > api_type, unsigned int create_flags,
> > > > > > >   * dequeued data.
> > > > > > >   */
> > > > > > >  static int
> > > > > > > -test_ring_burst_bulk_tests2(unsigned int api_type, unsigned
> > > > > > > int
> > > > > create_flags,
> > > > > > > -	const char *tname)
> > > > > > > +test_ring_burst_bulk_tests2(unsigned int test_idx)
> > > > > > >  {
> > > > > > >  	struct rte_ring *r;
> > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > **cur_dst = NULL; @@ -303,11 +478,13 @@
> > > test_ring_burst_bulk_tests2(unsigned
> > > > > > > int api_type, unsigned int create_flags,
> > > > > > >  	unsigned int i;
> > > > > > >
> > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > +
> > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > >
> > > > > > >  		/* Create the ring */
> > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> esize[i],
> > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > create_flags);
> > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > +
> > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > >
> > > > > > >  		/* alloc dummy object pointers */
> > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > -323,39
> > > > > > > +500,39 @@ test_ring_burst_bulk_tests2(unsigned int
> > > > > > > +api_type, unsigned int
> > > > > > > create_flags,
> > > > > > >  		cur_dst = dst;
> > > > > > >
> > > > > > >  		printf("enqueue 1 obj\n");
> > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 1,
> > > api_type);
> > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 1,
> > > test_idx);
> > > > > > >  		if (ret != 1)
> > > > > > >  			goto fail;
> > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
> > > > > > >
> > > > > > >  		printf("enqueue 2 objs\n");
> > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > api_type);
> > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > > test_idx);
> > > > > > >  		if (ret != 2)
> > > > > > >  			goto fail;
> > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
> > > > > > >
> > > > > > >  		printf("enqueue MAX_BULK objs\n");
> > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > MAX_BULK,
> > > > > > > -						api_type);
> > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > MAX_BULK,
> > > > > > > +						test_idx);
> > > > > > >  		if (ret != MAX_BULK)
> > > > > > >  			goto fail;
> > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> MAX_BULK);
> > > > > > >
> > > > > > >  		printf("dequeue 1 obj\n");
> > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1,
> > > api_type);
> > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1,
> > > test_idx);
> > > > > > >  		if (ret != 1)
> > > > > > >  			goto fail;
> > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
> > > > > > >
> > > > > > >  		printf("dequeue 2 objs\n");
> > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > api_type);
> > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > > test_idx);
> > > > > > >  		if (ret != 2)
> > > > > > >  			goto fail;
> > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
> > > > > > >
> > > > > > >  		printf("dequeue MAX_BULK objs\n");
> > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > MAX_BULK,
> > > > > > > -						api_type);
> > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > MAX_BULK,
> > > > > > > +						test_idx);
> > > > > > >  		if (ret != MAX_BULK)
> > > > > > >  			goto fail;
> > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> MAX_BULK);
> > > > > > > @@
> > > > > > > -390,8 +567,7 @@ test_ring_burst_bulk_tests2(unsigned int
> > > > > > > api_type, unsigned int create_flags,
> > > > > > >   * Enqueue and dequeue to cover the entire ring length.
> > > > > > >   */
> > > > > > >  static int
> > > > > > > -test_ring_burst_bulk_tests3(unsigned int api_type, unsigned
> > > > > > > int
> > > > > create_flags,
> > > > > > > -	const char *tname)
> > > > > > > +test_ring_burst_bulk_tests3(unsigned int test_idx)
> > > > > > >  {
> > > > > > >  	struct rte_ring *r;
> > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > **cur_dst = NULL; @@ -399,11 +575,13 @@
> > > test_ring_burst_bulk_tests3(unsigned
> > > > > > > int api_type, unsigned int create_flags,
> > > > > > >  	unsigned int i, j;
> > > > > > >
> > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > +
> > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > >
> > > > > > >  		/* Create the ring */
> > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> esize[i],
> > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > create_flags);
> > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > +
> > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > >
> > > > > > >  		/* alloc dummy object pointers */
> > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > -420,15
> > > > > > > +598,15 @@ test_ring_burst_bulk_tests3(unsigned int
> > > > > > > +api_type, unsigned int
> > > > > > > create_flags,
> > > > > > >
> > > > > > >  		printf("fill and empty the ring\n");
> > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > -							api_type);
> > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > +							test_idx);
> > > > > > >  			if (ret != MAX_BULK)
> > > > > > >  				goto fail;
> > > > > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > > >
> 	MAX_BULK);
> > > > > > >
> > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > -							api_type);
> > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > +							test_idx);
> > > > > > >  			if (ret != MAX_BULK)
> > > > > > >  				goto fail;
> > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> @@ -
> > > > > > > 465,21 +643,24 @@ test_ring_burst_bulk_tests3(unsigned int
> > > > > > > api_type, unsigned int create_flags,
> > > > > > >   * Enqueue till the ring is full and dequeue till the ring becomes
> empty.
> > > > > > >   */
> > > > > > >  static int
> > > > > > > -test_ring_burst_bulk_tests4(unsigned int api_type, unsigned
> > > > > > > int
> > > > > create_flags,
> > > > > > > -	const char *tname)
> > > > > > > +test_ring_burst_bulk_tests4(unsigned int test_idx)
> > > > > > >  {
> > > > > > >  	struct rte_ring *r;
> > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst
> = NULL;
> > > > > > >  	int ret;
> > > > > > >  	unsigned int i, j;
> > > > > > > -	unsigned int num_elems;
> > > > > > > +	unsigned int api_type, num_elems;
> > > > > > > +
> > > > > > > +	api_type = test_enqdeq_impl[test_idx].api_type;
> > > > > > >
> > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > +
> > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > >
> > > > > > >  		/* Create the ring */
> > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> esize[i],
> > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > create_flags);
> > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > +
> > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > >
> > > > > > >  		/* alloc dummy object pointers */
> > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > -496,8
> > > > > > > +677,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > > > +unsigned int
> > > > > > > create_flags,
> > > > > > >
> > > > > > >  		printf("Test enqueue without enough memory
> space\n");
> > > > > > >  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
> > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > -							api_type);
> > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > +							test_idx);
> > > > > > >  			if (ret != MAX_BULK)
> > > > > > >  				goto fail;
> > > > > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
> @@ -
> > > > > > > 505,7 +686,7 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > api_type, unsigned int create_flags,
> > > > > > >  		}
> > > > > > >
> > > > > > >  		printf("Enqueue 2 objects, free entries = MAX_BULK -
> 2\n");
> > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > api_type);
> > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > > test_idx);
> > > > > > >  		if (ret != 2)
> > > > > > >  			goto fail;
> > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); @@
> > > > > > > -517,8
> > > > > > > +698,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > > > +unsigned int
> > > > > > > create_flags,
> > > > > > >  		else
> > > > > > >  			num_elems = MAX_BULK;
> > > > > > >  		/* Always one free entry left */
> > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > num_elems,
> > > > > > > -						api_type);
> > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > num_elems,
> > > > > > > +						test_idx);
> > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > >  			goto fail;
> > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> MAX_BULK -
> > > > > > > 3);
> > > > > @@
> > > > > > > -528,15 +709,15 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > api_type, unsigned int create_flags,
> > > > > > >  			goto fail;
> > > > > > >
> > > > > > >  		printf("Test enqueue for a full entry\n");
> > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > MAX_BULK,
> > > > > > > -						api_type);
> > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > MAX_BULK,
> > > > > > > +						test_idx);
> > > > > > >  		if (ret != 0)
> > > > > > >  			goto fail;
> > > > > > >
> > > > > > >  		printf("Test dequeue without enough objects\n");
> > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > -							api_type);
> > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > +							test_idx);
> > > > > > >  			if (ret != MAX_BULK)
> > > > > > >  				goto fail;
> > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> @@ -
> > > > > > > 544,7 +725,7 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > api_type, unsigned int create_flags,
> > > > > > >  		}
> > > > > > >
> > > > > > >  		/* Available memory space for the exact MAX_BULK
> entries
> > > > > */
> > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > api_type);
> > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > > test_idx);
> > > > > > >  		if (ret != 2)
> > > > > > >  			goto fail;
> > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); @@
> > > > > > > -554,8
> > > > > > > +735,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > > > +unsigned int
> > > > > > > create_flags,
> > > > > > >  			num_elems = MAX_BULK - 3;
> > > > > > >  		else
> > > > > > >  			num_elems = MAX_BULK;
> > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > num_elems,
> > > > > > > -						api_type);
> > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > num_elems,
> > > > > > > +						test_idx);
> > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > >  			goto fail;
> > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> MAX_BULK -
> > > > > > > 3);
> > > > > @@
> > > > > > > -816,22 +997,7 @@ static int
> > > > > > >  test_ring(void)
> > > > > > >  {
> > > > > > >  	int32_t rc;
> > > > > > > -	unsigned int i, j;
> > > > > > > -	const char *tname;
> > > > > > > -
> > > > > > > -	static const struct {
> > > > > > > -		uint32_t create_flags;
> > > > > > > -		const char *name;
> > > > > > > -	} test_sync_modes[] = {
> > > > > > > -		{
> > > > > > > -			RING_F_MP_RTS_ENQ |
> > > RING_F_MC_RTS_DEQ,
> > > > > > > -			"Test MT_RTS ring",
> > > > > > > -		},
> > > > > > > -		{
> > > > > > > -			RING_F_MP_HTS_ENQ |
> > > RING_F_MC_HTS_DEQ,
> > > > > > > -			"Test MT_HTS ring",
> > > > > > > -		},
> > > > > > > -	};
> > > > > > > +	unsigned int i;
> > > > > > >
> > > > > > >  	/* Negative test cases */
> > > > > > >  	if (test_ring_negative_tests() < 0) @@ -848,65 +1014,24 @@
> > > > > > > test_ring(void)
> > > > > > >  	 * The test cases are split into smaller test cases to
> > > > > > >  	 * help clang compile faster.
> > > > > > >  	 */
> > > > > > > -	tname = "Test standard ring";
> > > > > > > -
> > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > > j <<= 1)
> > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > -					i <=
> > > TEST_RING_THREAD_MPMC; i
> > > > > > > <<= 1)
> > > > > > > -			if (test_ring_burst_bulk_tests1(i | j, 0, tname)
> > > < 0)
> > > > > > > -				goto test_fail;
> > > > > > > -
> > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > > j <<= 1)
> > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > -					i <=
> > > TEST_RING_THREAD_MPMC; i
> > > > > > > <<= 1)
> > > > > > > -			if (test_ring_burst_bulk_tests2(i | j, 0, tname)
> > > < 0)
> > > > > > > -				goto test_fail;
> > > > > > > -
> > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > > j <<= 1)
> > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > -					i <=
> > > TEST_RING_THREAD_MPMC; i
> > > > > > > <<= 1)
> > > > > > > -			if (test_ring_burst_bulk_tests3(i | j, 0, tname)
> > > < 0)
> > > > > > > -				goto test_fail;
> > > > > > > -
> > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > > j <<= 1)
> > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > -					i <=
> > > TEST_RING_THREAD_MPMC; i
> > > > > > > <<= 1)
> > > > > > > -			if (test_ring_burst_bulk_tests4(i | j, 0, tname)
> > > < 0)
> > > > > > > -				goto test_fail;
> > > > > > > -
> > > > > > > -	/* Burst and bulk operations with MT_RTS and MT_HTS sync
> > > modes
> > > > > > > */
> > > > > > > -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> > > > > > > -		for (j = TEST_RING_ELEM_BULK; j <=
> > > TEST_RING_ELEM_BURST;
> > > > > > > -				j <<= 1) {
> > > > > > > -
> > > > > > > -			rc = test_ring_burst_bulk_tests1(
> > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > -				test_sync_modes[i].name);
> > > > > > > -			if (rc < 0)
> > > > > > > -				goto test_fail;
> > > > > > > -
> > > > > > > -			rc = test_ring_burst_bulk_tests2(
> > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > -				test_sync_modes[i].name);
> > > > > > > -			if (rc < 0)
> > > > > > > -				goto test_fail;
> > > > > > > -
> > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > -				test_sync_modes[i].name);
> > > > > > > -			if (rc < 0)
> > > > > > > -				goto test_fail;
> > > > > > > -
> > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > -				test_sync_modes[i].name);
> > > > > > > -			if (rc < 0)
> > > > > > > -				goto test_fail;
> > > > > > > -		}
> > > > > > > +	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
> > > > > > > +
> > > > > > > +
> > > > > > > +		rc = test_ring_burst_bulk_tests1(i);
> > > > > > > +		if (rc < 0)
> > > > > > > +			goto test_fail;
> > > > > > > +
> > > > > > > +		rc = test_ring_burst_bulk_tests2(i);
> > > > > > > +		if (rc < 0)
> > > > > > > +			goto test_fail;
> > > > > > > +
> > > > > > > +		rc = test_ring_burst_bulk_tests3(i);
> > > > > > > +		if (rc < 0)
> > > > > > > +			goto test_fail;
> > > > > > > +
> > > > > > > +		rc = test_ring_burst_bulk_tests4(i);
> > > > > > > +		if (rc < 0)
> > > > > > > +			goto test_fail;
> > > > > > >  	}
> > > > > > >
> > > > > > >  	/* dump the ring status */
> > > > > > > --
> > > > > > > 2.17.1
Ananyev, Konstantin May 5, 2020, 6:57 p.m. UTC | #11
> <snip>
> 
> > > > > >
> > > > > > > Hi Konstantin,
> > > > > > > 	I like the way the tests are organized and it looks good.
> > > > > > >
> > > > > > > I am just wondering about the way it is being tested here. The
> > > > > > > intent to write the test cases the way they are currently is
> > > > > > > to mimic how the APIs would be used mostly. IMO, the APIs
> > > > > > > would be used with a constant
> > > > > > value for element size so that the compiler will throw away the
> > > > > > unwanted code (in the functions where the actual copy is being done).
> > > > > > >
> > > > > > > With your method here, it looks to me like all the branches in
> > > > > > > the copy
> > > > > > functions are kept and the branch decisions are done at run time.
> > > > > > > Is  my understanding correct?
> > > > > >
> > > > > > You mean branching on esize[] values?
> > > > > Yes
> > > > >
> > > > > > Actually from what I've seen that happens for both cases:
> > > > > > before and after the patch (gcc 7.3 -O3).
> > > > > I did not look at the generated code. If it is happening with your
> > > > > patch too, I
> > > > think we can go with your patch.
> > > >
> > > > Just to clarify, what I meant:
> > > > For both binaries (without the patch and with the patch) inside
> > > > test_ring() I see runtime branches on esize value.
> > > > Literally the code that corresponds to:
> > > > if (esize == 8) {...}
> > > > else if (esize == 16) {...}
> > > > else {...}
> I am not concerned about the functions in test_ring.c.
> 
> > > Do you see this in the actual ring library functions?
> >
> > Which ones? AFAIK all ring dequeue/enqueue functions are inline right now.
> Please see below.
> 
> >
> > > I want to make sure that the library functions
> > > '__rte_ring_enqueue_elems' and '__rte_ring_dequeue_elems' are optimized.
> Each enqueue/dequeue function ultimately calls these 2 functions.

Yes, and then each instance of enqueue/dequeue functions that is used by upper layer
would be in-lined.
So what upper layer function (library or app) you asked me to check?   

> The compiler here should remove the 'if (esize == 8) {...} else if (esize ==
> 16) {...} else {...}' with just the required piece of code depending on the 'esize'.
> If we can validate that for at least one ring library function
> used in this patch, we should be good.
> 
> > >
> > > >
> > > > Probably gcc wasn't able to remove it because we use esize[] instead
> > > > of hard- coded values, might be there is some other reason, I don't know
> > for sure.
> > > > As it is a functional (not performance) test, I didn't dig further.
> > > The esize[] array is declared as a const. The compiler should be able to see
> > that it is a compile time constant.
> >
> > That was my expectation too, but that not what I am seeing.
> >
> > > >
> > > > > But, can you do similar
> > > > > change to test_ring_perf.c to keep it consistent?
> > > >
> > > > In principle it is doable, but needs extra care.
> > > > We need to make sure that compiler will be able to inline functions
> > > > via pointers.
> > > > AFAIK, gcc does that with -O3', but not with '-O2'.
> > > If the unwanted code is not removed during compilation, we will see it
> > affect the performance numbers.
> >
> > Exactly.
> > The last thing I want - someone who uses older version of compiler, etc., will
> > start to see lower performance numbers with that test.
> >
> > > > Don't know what the story with clang and different versions of the
> > compiler.
> > > > Is there any real need for that?
> > > > On my box test_ring_perf.c compilation takes ~8s.
> > > > Konstantin
> > > >
> > > >
> > > > >
> > > > > >
> > > > > > Main intention in my changes was to avoid using
> > > > > > test_ring_enqueue/test_ring_dequeue,
> > > > > > as it seems too many branches here and it takes compiler a lot
> > > > > > of effort to resolve all of them at compile time.
> > > > > > So I replaced it with  array of function pointers
> > > > > > (test_enqdeq_impl[]) and iterating over it.
> > > > > > That way compiler knows straightway which function to use.
> > > > > >
> > > > > > > Can you please check this?
> > > > > > > https://patches.dpdk.org/patch/69567/
> > > > > >
> > > > > > As I can see your approach reduces number of test-cases by factor of 5:
> > > > > > now each of test_ring_burst_bulk_tests[1-4] is executed only
> > > > > > with just one esize value, correct?
> > > > > Yes, basically test_ring_burst_bulk_tests[1-4] were covering
> > > > > different scenarios with the same APIs. So, distributed the esize
> > > > > across different test
> > > > functions.
> > > > >
> > > > > > In term of compilation speed - it helps.
> > > > > > On my box with (gcc 7.3 -O3)  compiling test_ring.c takes:
> > > > > > orig code:                             ~100s
> > > > > > with 69567 (your patch):  < 20s
> > > > > > with 69559 (my patch):    < 10s
> > > > > >
> > > > > > Konstantin
> > > > > >
> > > > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > > > > > > > Sent: Wednesday, April 29, 2020 12:57 PM
> > > > > > > > To: dev@dpdk.org
> > > > > > > > Cc: aconole@redhat.com; Honnappa Nagarahalli
> > > > > > > > <Honnappa.Nagarahalli@arm.com>; Konstantin Ananyev
> > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > Subject: [PATCH] test/ring: code rework to reduce
> > > > > > > > compilation time
> > > > > > > >
> > > > > > > > Rework test code to reduce code complexity for the compiler
> > > > > > > > and bring down compilation time and memory consumption.
> > > > > > > >
> > > > > > > > Signed-off-by: Konstantin Ananyev
> > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > ---
> > > > > > > >  app/test/test_ring.c | 373
> > > > > > > > +++++++++++++++++++++++++++++--------------
> > > > > > > >  1 file changed, 249 insertions(+), 124 deletions(-)
> > > > > > > >
> > > > > > > > diff --git a/app/test/test_ring.c b/app/test/test_ring.c
> > > > > > > > index
> > > > > > > > e21557cd9..0ae97d341 100644
> > > > > > > > --- a/app/test/test_ring.c
> > > > > > > > +++ b/app/test/test_ring.c
> > > > > > > > @@ -58,6 +58,181 @@
> > > > > > > >
> > > > > > > >  static const int esize[] = {-1, 4, 8, 16, 20};
> > > > > > > >
> > > > > > > > +static const struct {
> > > > > > > > +	const char *desc;
> > > > > > > > +	uint32_t api_type;
> > > > > > > > +	uint32_t create_flags;
> > > > > > > > +	struct {
> > > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > > +			void * const *obj_table, unsigned int n,
> > > > > > > > +			unsigned int *free_space);
> > > > > > > > +		unsigned int (*felem)(struct rte_ring *r, const void
> > > > *obj_table,
> > > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > > +			unsigned int *free_space);
> > > > > > > > +	} enq;
> > > > > > > > +	struct {
> > > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > > +			void **obj_table, unsigned int n,
> > > > > > > > +			unsigned int *available);
> > > > > > > > +		unsigned int (*felem)(struct rte_ring *r, void
> > > > *obj_table,
> > > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > > +			unsigned int *available);
> > > > > > > > +	} deq;
> > > > > > > > +} test_enqdeq_impl[] = {
> > > > > > > > +	{
> > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > Details about the tests are already printed by the function
> > > > > > 'test_ring_print_test_string'. This string should be 'Test standard ring'.
> > > > > > >
> > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > +		.create_flags = 0,
> > > > > > > > +		.enq = {
> > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > +		},
> > > > > > > > +		.deq = {
> > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > +		},
> > > > > > > > +	},
> > > > > > > > +	{
> > > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > > > > > +		.enq = {
> > > > > > > > +			.flegacy = rte_ring_sp_enqueue_bulk,
> > > > > > > > +			.felem = rte_ring_sp_enqueue_bulk_elem,
> > > > > > > > +		},
> > > > > > > > +		.deq = {
> > > > > > > > +			.flegacy = rte_ring_sc_dequeue_bulk,
> > > > > > > > +			.felem = rte_ring_sc_dequeue_bulk_elem,
> > > > > > > > +		},
> > > > > > > > +	},
> > > > > > > > +	{
> > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > > +		.create_flags = 0,
> > > > > > > > +		.enq = {
> > > > > > > > +			.flegacy = rte_ring_mp_enqueue_bulk,
> > > > > > > > +			.felem = rte_ring_mp_enqueue_bulk_elem,
> > > > > > > > +		},
> > > > > > > > +		.deq = {
> > > > > > > > +			.flegacy = rte_ring_mc_dequeue_bulk,
> > > > > > > > +			.felem = rte_ring_mc_dequeue_bulk_elem,
> > > > > > > > +		},
> > > > > > > > +	},
> > > > > > > > +	{
> > > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > +		.enq = {
> > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > +		},
> > > > > > > > +		.deq = {
> > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > +		},
> > > > > > > > +	},
> > > > > > > > +	{
> > > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > +		.enq = {
> > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > +		},
> > > > > > > > +		.deq = {
> > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > +		},
> > > > > > > > +	},
> > > > > > > > +	{
> > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > +		.create_flags = 0,
> > > > > > > > +		.enq = {
> > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > > > +		},
> > > > > > > > +		.deq = {
> > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > > > +		},
> > > > > > > > +	},
> > > > > > > > +	{
> > > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > > > > > +		.enq = {
> > > > > > > > +			.flegacy = rte_ring_sp_enqueue_burst,
> > > > > > > > +			.felem = rte_ring_sp_enqueue_burst_elem,
> > > > > > > > +		},
> > > > > > > > +		.deq = {
> > > > > > > > +			.flegacy = rte_ring_sc_dequeue_burst,
> > > > > > > > +			.felem = rte_ring_sc_dequeue_burst_elem,
> > > > > > > > +		},
> > > > > > > > +	},
> > > > > > > > +	{
> > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > > +		.create_flags = 0,
> > > > > > > > +		.enq = {
> > > > > > > > +			.flegacy = rte_ring_mp_enqueue_burst,
> > > > > > > > +			.felem = rte_ring_mp_enqueue_burst_elem,
> > > > > > > > +		},
> > > > > > > > +		.deq = {
> > > > > > > > +			.flegacy = rte_ring_mc_dequeue_burst,
> > > > > > > > +			.felem = rte_ring_mc_dequeue_burst_elem,
> > > > > > > > +		},
> > > > > > > > +	},
> > > > > > > > +	{
> > > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > +		.enq = {
> > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > > > +		},
> > > > > > > > +		.deq = {
> > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > > > +		},
> > > > > > > > +	},
> > > > > > > > +	{
> > > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > +		.enq = {
> > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > > > +		},
> > > > > > > > +		.deq = {
> > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > > > +		},
> > > > > > > > +	},
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +static unsigned int
> > > > > > > > +test_ring_enq_impl(struct rte_ring *r, void **obj, int
> > > > > > > > +esize, unsigned
> > > > int n,
> > > > > > > > +	unsigned int test_idx)
> > > > > > > > +{
> > > > > > > > +	if (esize == -1)
> > > > > > > > +		return test_enqdeq_impl[test_idx].enq.flegacy(r, obj,
> > > > n, NULL);
> > > > > > > > +	else
> > > > > > > > +		return test_enqdeq_impl[test_idx].enq.felem(r, obj,
> > > > esize, n,
> > > > > > > > +			NULL);
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static unsigned int
> > > > > > > > +test_ring_deq_impl(struct rte_ring *r, void **obj, int
> > > > > > > > +esize, unsigned
> > > > int n,
> > > > > > > > +	unsigned int test_idx)
> > > > > > > > +{
> > > > > > > > +	if (esize == -1)
> > > > > > > > +		return test_enqdeq_impl[test_idx].deq.flegacy(r, obj,
> > > > n, NULL);
> > > > > > > > +	else
> > > > > > > > +		return test_enqdeq_impl[test_idx].deq.felem(r, obj,
> > > > esize, n,
> > > > > > > > +			NULL);
> > > > > > > > +}
> > > > > > > > +
> > > > > > > >  static void**
> > > > > > > >  test_ring_inc_ptr(void **obj, int esize, unsigned int n)  {
> > > > > > > > @@
> > > > > > > > -203,8 +378,7 @@ test_ring_negative_tests(void)
> > > > > > > >   * Random number of elements are enqueued and dequeued.
> > > > > > > >   */
> > > > > > > >  static int
> > > > > > > > -test_ring_burst_bulk_tests1(unsigned int api_type, unsigned
> > > > > > > > int
> > > > > > create_flags,
> > > > > > > > -	const char *tname)
> > > > > > > > +test_ring_burst_bulk_tests1(unsigned int test_idx)
> > > > > > > >  {
> > > > > > > >  	struct rte_ring *r;
> > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > **cur_dst = NULL; @@ -214,11 +388,13 @@
> > > > test_ring_burst_bulk_tests1(unsigned
> > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > >  	const unsigned int rsz = RING_SIZE - 1;
> > > > > > > >
> > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > > +
> > > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > > >
> > > > > > > >  		/* Create the ring */
> > > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> > esize[i],
> > > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > create_flags);
> > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > +
> > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > >
> > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > > -240,17
> > > > > > > > +416,17 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > > > +api_type, unsigned int
> > > > > > > > create_flags,
> > > > > > > >  			rand = RTE_MAX(rte_rand() % RING_SIZE,
> > 1UL);
> > > > > > > >  			printf("%s: iteration %u, random shift: %u;\n",
> > > > > > > >  			    __func__, i, rand);
> > > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > rand,
> > > > > > > > -							api_type);
> > > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > rand,
> > > > > > > > +							test_idx);
> > > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > > >
> > > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > rand,
> > > > > > > > -							api_type);
> > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > rand,
> > > > > > > > +							test_idx);
> > > > > > > >  			TEST_RING_VERIFY(ret == rand);
> > > > > > > >
> > > > > > > >  			/* fill the ring */
> > > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i], rsz,
> > > > > > > > -							api_type);
> > > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > rsz,
> > > > > > > > +							test_idx);
> > > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > > >
> > > > > > > >  			TEST_RING_VERIFY(rte_ring_free_count(r) ==
> > 0); @@
> > > > > > > > -259,8 +435,8 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > > > api_type, unsigned int create_flags,
> > > > > > > >  			TEST_RING_VERIFY(rte_ring_empty(r) == 0);
> > > > > > > >
> > > > > > > >  			/* empty the ring */
> > > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i], rsz,
> > > > > > > > -							api_type);
> > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > rsz,
> > > > > > > > +							test_idx);
> > > > > > > >  			TEST_RING_VERIFY(ret == (int)rsz);
> > > > > > > >  			TEST_RING_VERIFY(rsz ==
> > rte_ring_free_count(r));
> > > > > > > >  			TEST_RING_VERIFY(rte_ring_count(r) == 0);
> > @@ -
> > > > > > > > 294,8 +470,7 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > > > api_type, unsigned int create_flags,
> > > > > > > >   * dequeued data.
> > > > > > > >   */
> > > > > > > >  static int
> > > > > > > > -test_ring_burst_bulk_tests2(unsigned int api_type, unsigned
> > > > > > > > int
> > > > > > create_flags,
> > > > > > > > -	const char *tname)
> > > > > > > > +test_ring_burst_bulk_tests2(unsigned int test_idx)
> > > > > > > >  {
> > > > > > > >  	struct rte_ring *r;
> > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > **cur_dst = NULL; @@ -303,11 +478,13 @@
> > > > test_ring_burst_bulk_tests2(unsigned
> > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > >  	unsigned int i;
> > > > > > > >
> > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > > +
> > > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > > >
> > > > > > > >  		/* Create the ring */
> > > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> > esize[i],
> > > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > create_flags);
> > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > +
> > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > >
> > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > > -323,39
> > > > > > > > +500,39 @@ test_ring_burst_bulk_tests2(unsigned int
> > > > > > > > +api_type, unsigned int
> > > > > > > > create_flags,
> > > > > > > >  		cur_dst = dst;
> > > > > > > >
> > > > > > > >  		printf("enqueue 1 obj\n");
> > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 1,
> > > > api_type);
> > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 1,
> > > > test_idx);
> > > > > > > >  		if (ret != 1)
> > > > > > > >  			goto fail;
> > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
> > > > > > > >
> > > > > > > >  		printf("enqueue 2 objs\n");
> > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > > api_type);
> > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > > > test_idx);
> > > > > > > >  		if (ret != 2)
> > > > > > > >  			goto fail;
> > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
> > > > > > > >
> > > > > > > >  		printf("enqueue MAX_BULK objs\n");
> > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > MAX_BULK,
> > > > > > > > -						api_type);
> > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > MAX_BULK,
> > > > > > > > +						test_idx);
> > > > > > > >  		if (ret != MAX_BULK)
> > > > > > > >  			goto fail;
> > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > MAX_BULK);
> > > > > > > >
> > > > > > > >  		printf("dequeue 1 obj\n");
> > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1,
> > > > api_type);
> > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1,
> > > > test_idx);
> > > > > > > >  		if (ret != 1)
> > > > > > > >  			goto fail;
> > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
> > > > > > > >
> > > > > > > >  		printf("dequeue 2 objs\n");
> > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > > api_type);
> > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > > > test_idx);
> > > > > > > >  		if (ret != 2)
> > > > > > > >  			goto fail;
> > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
> > > > > > > >
> > > > > > > >  		printf("dequeue MAX_BULK objs\n");
> > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > MAX_BULK,
> > > > > > > > -						api_type);
> > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > MAX_BULK,
> > > > > > > > +						test_idx);
> > > > > > > >  		if (ret != MAX_BULK)
> > > > > > > >  			goto fail;
> > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > MAX_BULK);
> > > > > > > > @@
> > > > > > > > -390,8 +567,7 @@ test_ring_burst_bulk_tests2(unsigned int
> > > > > > > > api_type, unsigned int create_flags,
> > > > > > > >   * Enqueue and dequeue to cover the entire ring length.
> > > > > > > >   */
> > > > > > > >  static int
> > > > > > > > -test_ring_burst_bulk_tests3(unsigned int api_type, unsigned
> > > > > > > > int
> > > > > > create_flags,
> > > > > > > > -	const char *tname)
> > > > > > > > +test_ring_burst_bulk_tests3(unsigned int test_idx)
> > > > > > > >  {
> > > > > > > >  	struct rte_ring *r;
> > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > **cur_dst = NULL; @@ -399,11 +575,13 @@
> > > > test_ring_burst_bulk_tests3(unsigned
> > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > >  	unsigned int i, j;
> > > > > > > >
> > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > > +
> > > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > > >
> > > > > > > >  		/* Create the ring */
> > > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> > esize[i],
> > > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > create_flags);
> > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > +
> > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > >
> > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > > -420,15
> > > > > > > > +598,15 @@ test_ring_burst_bulk_tests3(unsigned int
> > > > > > > > +api_type, unsigned int
> > > > > > > > create_flags,
> > > > > > > >
> > > > > > > >  		printf("fill and empty the ring\n");
> > > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> > > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > -							api_type);
> > > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > +							test_idx);
> > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > >  				goto fail;
> > > > > > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > > > >
> > 	MAX_BULK);
> > > > > > > >
> > > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > -							api_type);
> > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > +							test_idx);
> > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > >  				goto fail;
> > > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > @@ -
> > > > > > > > 465,21 +643,24 @@ test_ring_burst_bulk_tests3(unsigned int
> > > > > > > > api_type, unsigned int create_flags,
> > > > > > > >   * Enqueue till the ring is full and dequeue till the ring becomes
> > empty.
> > > > > > > >   */
> > > > > > > >  static int
> > > > > > > > -test_ring_burst_bulk_tests4(unsigned int api_type, unsigned
> > > > > > > > int
> > > > > > create_flags,
> > > > > > > > -	const char *tname)
> > > > > > > > +test_ring_burst_bulk_tests4(unsigned int test_idx)
> > > > > > > >  {
> > > > > > > >  	struct rte_ring *r;
> > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst
> > = NULL;
> > > > > > > >  	int ret;
> > > > > > > >  	unsigned int i, j;
> > > > > > > > -	unsigned int num_elems;
> > > > > > > > +	unsigned int api_type, num_elems;
> > > > > > > > +
> > > > > > > > +	api_type = test_enqdeq_impl[test_idx].api_type;
> > > > > > > >
> > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > > +
> > > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > > >
> > > > > > > >  		/* Create the ring */
> > > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> > esize[i],
> > > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > create_flags);
> > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > +
> > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > >
> > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > > -496,8
> > > > > > > > +677,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > > > > +unsigned int
> > > > > > > > create_flags,
> > > > > > > >
> > > > > > > >  		printf("Test enqueue without enough memory
> > space\n");
> > > > > > > >  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
> > > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > -							api_type);
> > > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > +							test_idx);
> > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > >  				goto fail;
> > > > > > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > @@ -
> > > > > > > > 505,7 +686,7 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > api_type, unsigned int create_flags,
> > > > > > > >  		}
> > > > > > > >
> > > > > > > >  		printf("Enqueue 2 objects, free entries = MAX_BULK -
> > 2\n");
> > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > > api_type);
> > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > > > test_idx);
> > > > > > > >  		if (ret != 2)
> > > > > > > >  			goto fail;
> > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); @@
> > > > > > > > -517,8
> > > > > > > > +698,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > > > > +unsigned int
> > > > > > > > create_flags,
> > > > > > > >  		else
> > > > > > > >  			num_elems = MAX_BULK;
> > > > > > > >  		/* Always one free entry left */
> > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > num_elems,
> > > > > > > > -						api_type);
> > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > num_elems,
> > > > > > > > +						test_idx);
> > > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > > >  			goto fail;
> > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > MAX_BULK -
> > > > > > > > 3);
> > > > > > @@
> > > > > > > > -528,15 +709,15 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > api_type, unsigned int create_flags,
> > > > > > > >  			goto fail;
> > > > > > > >
> > > > > > > >  		printf("Test enqueue for a full entry\n");
> > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > MAX_BULK,
> > > > > > > > -						api_type);
> > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > MAX_BULK,
> > > > > > > > +						test_idx);
> > > > > > > >  		if (ret != 0)
> > > > > > > >  			goto fail;
> > > > > > > >
> > > > > > > >  		printf("Test dequeue without enough objects\n");
> > > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> > > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > -							api_type);
> > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > +							test_idx);
> > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > >  				goto fail;
> > > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > @@ -
> > > > > > > > 544,7 +725,7 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > api_type, unsigned int create_flags,
> > > > > > > >  		}
> > > > > > > >
> > > > > > > >  		/* Available memory space for the exact MAX_BULK
> > entries
> > > > > > */
> > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > > api_type);
> > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > > > test_idx);
> > > > > > > >  		if (ret != 2)
> > > > > > > >  			goto fail;
> > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); @@
> > > > > > > > -554,8
> > > > > > > > +735,8 @@ test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > > > > +unsigned int
> > > > > > > > create_flags,
> > > > > > > >  			num_elems = MAX_BULK - 3;
> > > > > > > >  		else
> > > > > > > >  			num_elems = MAX_BULK;
> > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > num_elems,
> > > > > > > > -						api_type);
> > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > num_elems,
> > > > > > > > +						test_idx);
> > > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > > >  			goto fail;
> > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > MAX_BULK -
> > > > > > > > 3);
> > > > > > @@
> > > > > > > > -816,22 +997,7 @@ static int
> > > > > > > >  test_ring(void)
> > > > > > > >  {
> > > > > > > >  	int32_t rc;
> > > > > > > > -	unsigned int i, j;
> > > > > > > > -	const char *tname;
> > > > > > > > -
> > > > > > > > -	static const struct {
> > > > > > > > -		uint32_t create_flags;
> > > > > > > > -		const char *name;
> > > > > > > > -	} test_sync_modes[] = {
> > > > > > > > -		{
> > > > > > > > -			RING_F_MP_RTS_ENQ |
> > > > RING_F_MC_RTS_DEQ,
> > > > > > > > -			"Test MT_RTS ring",
> > > > > > > > -		},
> > > > > > > > -		{
> > > > > > > > -			RING_F_MP_HTS_ENQ |
> > > > RING_F_MC_HTS_DEQ,
> > > > > > > > -			"Test MT_HTS ring",
> > > > > > > > -		},
> > > > > > > > -	};
> > > > > > > > +	unsigned int i;
> > > > > > > >
> > > > > > > >  	/* Negative test cases */
> > > > > > > >  	if (test_ring_negative_tests() < 0) @@ -848,65 +1014,24 @@
> > > > > > > > test_ring(void)
> > > > > > > >  	 * The test cases are split into smaller test cases to
> > > > > > > >  	 * help clang compile faster.
> > > > > > > >  	 */
> > > > > > > > -	tname = "Test standard ring";
> > > > > > > > -
> > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > > > j <<= 1)
> > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > -					i <=
> > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > <<= 1)
> > > > > > > > -			if (test_ring_burst_bulk_tests1(i | j, 0, tname)
> > > > < 0)
> > > > > > > > -				goto test_fail;
> > > > > > > > -
> > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > > > j <<= 1)
> > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > -					i <=
> > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > <<= 1)
> > > > > > > > -			if (test_ring_burst_bulk_tests2(i | j, 0, tname)
> > > > < 0)
> > > > > > > > -				goto test_fail;
> > > > > > > > -
> > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > > > j <<= 1)
> > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > -					i <=
> > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > <<= 1)
> > > > > > > > -			if (test_ring_burst_bulk_tests3(i | j, 0, tname)
> > > > < 0)
> > > > > > > > -				goto test_fail;
> > > > > > > > -
> > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
> > > > j <<= 1)
> > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > -					i <=
> > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > <<= 1)
> > > > > > > > -			if (test_ring_burst_bulk_tests4(i | j, 0, tname)
> > > > < 0)
> > > > > > > > -				goto test_fail;
> > > > > > > > -
> > > > > > > > -	/* Burst and bulk operations with MT_RTS and MT_HTS sync
> > > > modes
> > > > > > > > */
> > > > > > > > -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> > > > > > > > -		for (j = TEST_RING_ELEM_BULK; j <=
> > > > TEST_RING_ELEM_BURST;
> > > > > > > > -				j <<= 1) {
> > > > > > > > -
> > > > > > > > -			rc = test_ring_burst_bulk_tests1(
> > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > -			if (rc < 0)
> > > > > > > > -				goto test_fail;
> > > > > > > > -
> > > > > > > > -			rc = test_ring_burst_bulk_tests2(
> > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > -			if (rc < 0)
> > > > > > > > -				goto test_fail;
> > > > > > > > -
> > > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > -			if (rc < 0)
> > > > > > > > -				goto test_fail;
> > > > > > > > -
> > > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > -			if (rc < 0)
> > > > > > > > -				goto test_fail;
> > > > > > > > -		}
> > > > > > > > +	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
> > > > > > > > +
> > > > > > > > +
> > > > > > > > +		rc = test_ring_burst_bulk_tests1(i);
> > > > > > > > +		if (rc < 0)
> > > > > > > > +			goto test_fail;
> > > > > > > > +
> > > > > > > > +		rc = test_ring_burst_bulk_tests2(i);
> > > > > > > > +		if (rc < 0)
> > > > > > > > +			goto test_fail;
> > > > > > > > +
> > > > > > > > +		rc = test_ring_burst_bulk_tests3(i);
> > > > > > > > +		if (rc < 0)
> > > > > > > > +			goto test_fail;
> > > > > > > > +
> > > > > > > > +		rc = test_ring_burst_bulk_tests4(i);
> > > > > > > > +		if (rc < 0)
> > > > > > > > +			goto test_fail;
> > > > > > > >  	}
> > > > > > > >
> > > > > > > >  	/* dump the ring status */
> > > > > > > > --
> > > > > > > > 2.17.1
Honnappa Nagarahalli May 8, 2020, 5:32 a.m. UTC | #12
> > <snip>
> >
> > > > > > >
> > > > > > > > Hi Konstantin,
> > > > > > > > 	I like the way the tests are organized and it looks good.
> > > > > > > >
> > > > > > > > I am just wondering about the way it is being tested here.
> > > > > > > > The intent to write the test cases the way they are
> > > > > > > > currently is to mimic how the APIs would be used mostly.
> > > > > > > > IMO, the APIs would be used with a constant
> > > > > > > value for element size so that the compiler will throw away
> > > > > > > the unwanted code (in the functions where the actual copy is being
> done).
> > > > > > > >
> > > > > > > > With your method here, it looks to me like all the
> > > > > > > > branches in the copy
> > > > > > > functions are kept and the branch decisions are done at run time.
> > > > > > > > Is  my understanding correct?
> > > > > > >
> > > > > > > You mean branching on esize[] values?
> > > > > > Yes
I was wondering where is the confusion. I interpreted as referring to the esize parameter in rte_ring_xxx_elem APIs. Anyway, please see below.

> > > > > >
> > > > > > > Actually from what I've seen that happens for both cases:
> > > > > > > before and after the patch (gcc 7.3 -O3).
> > > > > > I did not look at the generated code. If it is happening with
> > > > > > your patch too, I
> > > > > think we can go with your patch.
> > > > >
> > > > > Just to clarify, what I meant:
> > > > > For both binaries (without the patch and with the patch) inside
> > > > > test_ring() I see runtime branches on esize value.
> > > > > Literally the code that corresponds to:
> > > > > if (esize == 8) {...}
> > > > > else if (esize == 16) {...}
> > > > > else {...}
> > I am not concerned about the functions in test_ring.c.
> >
> > > > Do you see this in the actual ring library functions?
> > >
> > > Which ones? AFAIK all ring dequeue/enqueue functions are inline right
> now.
> > Please see below.
> >
> > >
> > > > I want to make sure that the library functions
> > > > '__rte_ring_enqueue_elems' and '__rte_ring_dequeue_elems' are
> optimized.
> > Each enqueue/dequeue function ultimately calls these 2 functions.
> 
> Yes, and then each instance of enqueue/dequeue functions that is used by
> upper layer would be in-lined.
> So what upper layer function (library or app) you asked me to check?
I am not bothered much about upper layer functions. I looked at the generate code for the function __rte_ring_enqueue_elems.
Existing code has the if checks for 8 and 16.
Your patch also has the checks.
My patch does not have the checks as it passes the constants directly without using esize[] array in functions test_ring_burst_bulk_tests4.

> 
> > The compiler here should remove the 'if (esize == 8) {...} else if
> > (esize ==
> > 16) {...} else {...}' with just the required piece of code depending on the
> 'esize'.
> > If we can validate that for at least one ring library function used in
> > this patch, we should be good.
> >
> > > >
> > > > >
> > > > > Probably gcc wasn't able to remove it because we use esize[]
> > > > > instead of hard- coded values, might be there is some other
> > > > > reason, I don't know
> > > for sure.
> > > > > As it is a functional (not performance) test, I didn't dig further.
> > > > The esize[] array is declared as a const. The compiler should be
> > > > able to see
> > > that it is a compile time constant.
> > >
> > > That was my expectation too, but that not what I am seeing.
> > >
> > > > >
> > > > > > But, can you do similar
> > > > > > change to test_ring_perf.c to keep it consistent?
> > > > >
> > > > > In principle it is doable, but needs extra care.
> > > > > We need to make sure that compiler will be able to inline
> > > > > functions via pointers.
> > > > > AFAIK, gcc does that with -O3', but not with '-O2'.
> > > > If the unwanted code is not removed during compilation, we will
> > > > see it
> > > affect the performance numbers.
> > >
> > > Exactly.
> > > The last thing I want - someone who uses older version of compiler,
> > > etc., will start to see lower performance numbers with that test.
> > >
> > > > > Don't know what the story with clang and different versions of
> > > > > the
> > > compiler.
> > > > > Is there any real need for that?
> > > > > On my box test_ring_perf.c compilation takes ~8s.
> > > > > Konstantin
> > > > >
> > > > >
> > > > > >
> > > > > > >
> > > > > > > Main intention in my changes was to avoid using
> > > > > > > test_ring_enqueue/test_ring_dequeue,
> > > > > > > as it seems too many branches here and it takes compiler a
> > > > > > > lot of effort to resolve all of them at compile time.
> > > > > > > So I replaced it with  array of function pointers
> > > > > > > (test_enqdeq_impl[]) and iterating over it.
> > > > > > > That way compiler knows straightway which function to use.
> > > > > > >
> > > > > > > > Can you please check this?
> > > > > > > > https://patches.dpdk.org/patch/69567/
> > > > > > >
> > > > > > > As I can see your approach reduces number of test-cases by factor
> of 5:
> > > > > > > now each of test_ring_burst_bulk_tests[1-4] is executed only
> > > > > > > with just one esize value, correct?
> > > > > > Yes, basically test_ring_burst_bulk_tests[1-4] were covering
> > > > > > different scenarios with the same APIs. So, distributed the
> > > > > > esize across different test
> > > > > functions.
> > > > > >
> > > > > > > In term of compilation speed - it helps.
> > > > > > > On my box with (gcc 7.3 -O3)  compiling test_ring.c takes:
> > > > > > > orig code:                             ~100s
> > > > > > > with 69567 (your patch):  < 20s
> > > > > > > with 69559 (my patch):    < 10s
> > > > > > >
> > > > > > > Konstantin
> > > > > > >
> > > > > > > >
> > > > > > > > > -----Original Message-----
> > > > > > > > > From: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > > > > > > > > Sent: Wednesday, April 29, 2020 12:57 PM
> > > > > > > > > To: dev@dpdk.org
> > > > > > > > > Cc: aconole@redhat.com; Honnappa Nagarahalli
> > > > > > > > > <Honnappa.Nagarahalli@arm.com>; Konstantin Ananyev
> > > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > > Subject: [PATCH] test/ring: code rework to reduce
> > > > > > > > > compilation time
> > > > > > > > >
> > > > > > > > > Rework test code to reduce code complexity for the
> > > > > > > > > compiler and bring down compilation time and memory
> consumption.
> > > > > > > > >
> > > > > > > > > Signed-off-by: Konstantin Ananyev
> > > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > > ---
> > > > > > > > >  app/test/test_ring.c | 373
> > > > > > > > > +++++++++++++++++++++++++++++--------------
> > > > > > > > >  1 file changed, 249 insertions(+), 124 deletions(-)
> > > > > > > > >
> > > > > > > > > diff --git a/app/test/test_ring.c b/app/test/test_ring.c
> > > > > > > > > index
> > > > > > > > > e21557cd9..0ae97d341 100644
> > > > > > > > > --- a/app/test/test_ring.c
> > > > > > > > > +++ b/app/test/test_ring.c
> > > > > > > > > @@ -58,6 +58,181 @@
> > > > > > > > >
> > > > > > > > >  static const int esize[] = {-1, 4, 8, 16, 20};
> > > > > > > > >
> > > > > > > > > +static const struct {
> > > > > > > > > +	const char *desc;
> > > > > > > > > +	uint32_t api_type;
> > > > > > > > > +	uint32_t create_flags;
> > > > > > > > > +	struct {
> > > > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > > > +			void * const *obj_table, unsigned int n,
> > > > > > > > > +			unsigned int *free_space);
> > > > > > > > > +		unsigned int (*felem)(struct rte_ring *r, const void
> > > > > *obj_table,
> > > > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > > > +			unsigned int *free_space);
> > > > > > > > > +	} enq;
> > > > > > > > > +	struct {
> > > > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > > > +			void **obj_table, unsigned int n,
> > > > > > > > > +			unsigned int *available);
> > > > > > > > > +		unsigned int (*felem)(struct rte_ring *r, void
> > > > > *obj_table,
> > > > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > > > +			unsigned int *available);
> > > > > > > > > +	} deq;
> > > > > > > > > +} test_enqdeq_impl[] = {
> > > > > > > > > +	{
> > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > Details about the tests are already printed by the
> > > > > > > > function
> > > > > > > 'test_ring_print_test_string'. This string should be 'Test standard
> ring'.
> > > > > > > >
> > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > +		.create_flags = 0,
> > > > > > > > > +		.enq = {
> > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > +		},
> > > > > > > > > +		.deq = {
> > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > +		},
> > > > > > > > > +	},
> > > > > > > > > +	{
> > > > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > > > > > > +		.enq = {
> > > > > > > > > +			.flegacy = rte_ring_sp_enqueue_bulk,
> > > > > > > > > +			.felem = rte_ring_sp_enqueue_bulk_elem,
> > > > > > > > > +		},
> > > > > > > > > +		.deq = {
> > > > > > > > > +			.flegacy = rte_ring_sc_dequeue_bulk,
> > > > > > > > > +			.felem = rte_ring_sc_dequeue_bulk_elem,
> > > > > > > > > +		},
> > > > > > > > > +	},
> > > > > > > > > +	{
> > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > > > +		.create_flags = 0,
> > > > > > > > > +		.enq = {
> > > > > > > > > +			.flegacy = rte_ring_mp_enqueue_bulk,
> > > > > > > > > +			.felem = rte_ring_mp_enqueue_bulk_elem,
> > > > > > > > > +		},
> > > > > > > > > +		.deq = {
> > > > > > > > > +			.flegacy = rte_ring_mc_dequeue_bulk,
> > > > > > > > > +			.felem = rte_ring_mc_dequeue_bulk_elem,
> > > > > > > > > +		},
> > > > > > > > > +	},
> > > > > > > > > +	{
> > > > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > +		.enq = {
> > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > +		},
> > > > > > > > > +		.deq = {
> > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > +		},
> > > > > > > > > +	},
> > > > > > > > > +	{
> > > > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > +		.enq = {
> > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > +		},
> > > > > > > > > +		.deq = {
> > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > +		},
> > > > > > > > > +	},
> > > > > > > > > +	{
> > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > +		.create_flags = 0,
> > > > > > > > > +		.enq = {
> > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > > > > +		},
> > > > > > > > > +		.deq = {
> > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > > > > +		},
> > > > > > > > > +	},
> > > > > > > > > +	{
> > > > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > > > > > > +		.enq = {
> > > > > > > > > +			.flegacy = rte_ring_sp_enqueue_burst,
> > > > > > > > > +			.felem = rte_ring_sp_enqueue_burst_elem,
> > > > > > > > > +		},
> > > > > > > > > +		.deq = {
> > > > > > > > > +			.flegacy = rte_ring_sc_dequeue_burst,
> > > > > > > > > +			.felem = rte_ring_sc_dequeue_burst_elem,
> > > > > > > > > +		},
> > > > > > > > > +	},
> > > > > > > > > +	{
> > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > > > +		.create_flags = 0,
> > > > > > > > > +		.enq = {
> > > > > > > > > +			.flegacy = rte_ring_mp_enqueue_burst,
> > > > > > > > > +			.felem = rte_ring_mp_enqueue_burst_elem,
> > > > > > > > > +		},
> > > > > > > > > +		.deq = {
> > > > > > > > > +			.flegacy = rte_ring_mc_dequeue_burst,
> > > > > > > > > +			.felem = rte_ring_mc_dequeue_burst_elem,
> > > > > > > > > +		},
> > > > > > > > > +	},
> > > > > > > > > +	{
> > > > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > +		.enq = {
> > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > > > > +		},
> > > > > > > > > +		.deq = {
> > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > > > > +		},
> > > > > > > > > +	},
> > > > > > > > > +	{
> > > > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > +		.enq = {
> > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > > > > +		},
> > > > > > > > > +		.deq = {
> > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > > > > +		},
> > > > > > > > > +	},
> > > > > > > > > +};
> > > > > > > > > +
> > > > > > > > > +static unsigned int
> > > > > > > > > +test_ring_enq_impl(struct rte_ring *r, void **obj, int
> > > > > > > > > +esize, unsigned
> > > > > int n,
> > > > > > > > > +	unsigned int test_idx) {
> > > > > > > > > +	if (esize == -1)
> > > > > > > > > +		return test_enqdeq_impl[test_idx].enq.flegacy(r, obj,
> > > > > n, NULL);
> > > > > > > > > +	else
> > > > > > > > > +		return test_enqdeq_impl[test_idx].enq.felem(r, obj,
> > > > > esize, n,
> > > > > > > > > +			NULL);
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > > +static unsigned int
> > > > > > > > > +test_ring_deq_impl(struct rte_ring *r, void **obj, int
> > > > > > > > > +esize, unsigned
> > > > > int n,
> > > > > > > > > +	unsigned int test_idx) {
> > > > > > > > > +	if (esize == -1)
> > > > > > > > > +		return test_enqdeq_impl[test_idx].deq.flegacy(r, obj,
> > > > > n, NULL);
> > > > > > > > > +	else
> > > > > > > > > +		return test_enqdeq_impl[test_idx].deq.felem(r, obj,
> > > > > esize, n,
> > > > > > > > > +			NULL);
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > >  static void**
> > > > > > > > >  test_ring_inc_ptr(void **obj, int esize, unsigned int
> > > > > > > > > n)  { @@
> > > > > > > > > -203,8 +378,7 @@ test_ring_negative_tests(void)
> > > > > > > > >   * Random number of elements are enqueued and dequeued.
> > > > > > > > >   */
> > > > > > > > >  static int
> > > > > > > > > -test_ring_burst_bulk_tests1(unsigned int api_type,
> > > > > > > > > unsigned int
> > > > > > > create_flags,
> > > > > > > > > -	const char *tname)
> > > > > > > > > +test_ring_burst_bulk_tests1(unsigned int test_idx)
> > > > > > > > >  {
> > > > > > > > >  	struct rte_ring *r;
> > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > **cur_dst = NULL; @@ -214,11 +388,13 @@
> > > > > test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > >  	const unsigned int rsz = RING_SIZE - 1;
> > > > > > > > >
> > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > > > +
> > > > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > > > >
> > > > > > > > >  		/* Create the ring */
> > > > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> > > esize[i],
> > > > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > create_flags);
> > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > +
> > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > >
> > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > > > -240,17
> > > > > > > > > +416,17 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > > > > +api_type, unsigned int
> > > > > > > > > create_flags,
> > > > > > > > >  			rand = RTE_MAX(rte_rand() % RING_SIZE,
> > > 1UL);
> > > > > > > > >  			printf("%s: iteration %u, random shift: %u;\n",
> > > > > > > > >  			    __func__, i, rand);
> > > > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > rand,
> > > > > > > > > -							api_type);
> > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > rand,
> > > > > > > > > +							test_idx);
> > > > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > > > >
> > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > rand,
> > > > > > > > > -							api_type);
> > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > rand,
> > > > > > > > > +							test_idx);
> > > > > > > > >  			TEST_RING_VERIFY(ret == rand);
> > > > > > > > >
> > > > > > > > >  			/* fill the ring */
> > > > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> rsz,
> > > > > > > > > -							api_type);
> > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > rsz,
> > > > > > > > > +							test_idx);
> > > > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > > > >
> > > > > > > > >  			TEST_RING_VERIFY(rte_ring_free_count(r) ==
> > > 0); @@
> > > > > > > > > -259,8 +435,8 @@ test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > >  			TEST_RING_VERIFY(rte_ring_empty(r) == 0);
> > > > > > > > >
> > > > > > > > >  			/* empty the ring */
> > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> rsz,
> > > > > > > > > -							api_type);
> > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > rsz,
> > > > > > > > > +							test_idx);
> > > > > > > > >  			TEST_RING_VERIFY(ret == (int)rsz);
> > > > > > > > >  			TEST_RING_VERIFY(rsz ==
> > > rte_ring_free_count(r));
> > > > > > > > >  			TEST_RING_VERIFY(rte_ring_count(r) == 0);
> > > @@ -
> > > > > > > > > 294,8 +470,7 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > > > > api_type, unsigned int create_flags,
> > > > > > > > >   * dequeued data.
> > > > > > > > >   */
> > > > > > > > >  static int
> > > > > > > > > -test_ring_burst_bulk_tests2(unsigned int api_type,
> > > > > > > > > unsigned int
> > > > > > > create_flags,
> > > > > > > > > -	const char *tname)
> > > > > > > > > +test_ring_burst_bulk_tests2(unsigned int test_idx)
> > > > > > > > >  {
> > > > > > > > >  	struct rte_ring *r;
> > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > **cur_dst = NULL; @@ -303,11 +478,13 @@
> > > > > test_ring_burst_bulk_tests2(unsigned
> > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > >  	unsigned int i;
> > > > > > > > >
> > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > > > +
> > > > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > > > >
> > > > > > > > >  		/* Create the ring */
> > > > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> > > esize[i],
> > > > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > create_flags);
> > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > +
> > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > >
> > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > > > -323,39
> > > > > > > > > +500,39 @@ test_ring_burst_bulk_tests2(unsigned int
> > > > > > > > > +api_type, unsigned int
> > > > > > > > > create_flags,
> > > > > > > > >  		cur_dst = dst;
> > > > > > > > >
> > > > > > > > >  		printf("enqueue 1 obj\n");
> > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 1,
> > > > > api_type);
> > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 1,
> > > > > test_idx);
> > > > > > > > >  		if (ret != 1)
> > > > > > > > >  			goto fail;
> > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
> > > > > > > > >
> > > > > > > > >  		printf("enqueue 2 objs\n");
> > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > > > api_type);
> > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > > > > test_idx);
> > > > > > > > >  		if (ret != 2)
> > > > > > > > >  			goto fail;
> > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
> > > > > > > > >
> > > > > > > > >  		printf("enqueue MAX_BULK objs\n");
> > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > MAX_BULK,
> > > > > > > > > -						api_type);
> > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > MAX_BULK,
> > > > > > > > > +						test_idx);
> > > > > > > > >  		if (ret != MAX_BULK)
> > > > > > > > >  			goto fail;
> > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > MAX_BULK);
> > > > > > > > >
> > > > > > > > >  		printf("dequeue 1 obj\n");
> > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1,
> > > > > api_type);
> > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1,
> > > > > test_idx);
> > > > > > > > >  		if (ret != 1)
> > > > > > > > >  			goto fail;
> > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
> > > > > > > > >
> > > > > > > > >  		printf("dequeue 2 objs\n");
> > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > > > api_type);
> > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > > > > test_idx);
> > > > > > > > >  		if (ret != 2)
> > > > > > > > >  			goto fail;
> > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
> > > > > > > > >
> > > > > > > > >  		printf("dequeue MAX_BULK objs\n");
> > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > MAX_BULK,
> > > > > > > > > -						api_type);
> > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > MAX_BULK,
> > > > > > > > > +						test_idx);
> > > > > > > > >  		if (ret != MAX_BULK)
> > > > > > > > >  			goto fail;
> > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > MAX_BULK);
> > > > > > > > > @@
> > > > > > > > > -390,8 +567,7 @@ test_ring_burst_bulk_tests2(unsigned
> > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > >   * Enqueue and dequeue to cover the entire ring length.
> > > > > > > > >   */
> > > > > > > > >  static int
> > > > > > > > > -test_ring_burst_bulk_tests3(unsigned int api_type,
> > > > > > > > > unsigned int
> > > > > > > create_flags,
> > > > > > > > > -	const char *tname)
> > > > > > > > > +test_ring_burst_bulk_tests3(unsigned int test_idx)
> > > > > > > > >  {
> > > > > > > > >  	struct rte_ring *r;
> > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > **cur_dst = NULL; @@ -399,11 +575,13 @@
> > > > > test_ring_burst_bulk_tests3(unsigned
> > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > >  	unsigned int i, j;
> > > > > > > > >
> > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > > > +
> > > > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > > > >
> > > > > > > > >  		/* Create the ring */
> > > > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> > > esize[i],
> > > > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > create_flags);
> > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > +
> > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > >
> > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > > > -420,15
> > > > > > > > > +598,15 @@ test_ring_burst_bulk_tests3(unsigned int
> > > > > > > > > +api_type, unsigned int
> > > > > > > > > create_flags,
> > > > > > > > >
> > > > > > > > >  		printf("fill and empty the ring\n");
> > > > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> > > > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > -							api_type);
> > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > +							test_idx);
> > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > >  				goto fail;
> > > > > > > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > > > > >
> > > 	MAX_BULK);
> > > > > > > > >
> > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > -							api_type);
> > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > +							test_idx);
> > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > >  				goto fail;
> > > > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > @@ -
> > > > > > > > > 465,21 +643,24 @@ test_ring_burst_bulk_tests3(unsigned
> > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > >   * Enqueue till the ring is full and dequeue till the
> > > > > > > > > ring becomes
> > > empty.
> > > > > > > > >   */
> > > > > > > > >  static int
> > > > > > > > > -test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > > > > > unsigned int
> > > > > > > create_flags,
> > > > > > > > > -	const char *tname)
> > > > > > > > > +test_ring_burst_bulk_tests4(unsigned int test_idx)
> > > > > > > > >  {
> > > > > > > > >  	struct rte_ring *r;
> > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > **cur_dst
> > > = NULL;
> > > > > > > > >  	int ret;
> > > > > > > > >  	unsigned int i, j;
> > > > > > > > > -	unsigned int num_elems;
> > > > > > > > > +	unsigned int api_type, num_elems;
> > > > > > > > > +
> > > > > > > > > +	api_type = test_enqdeq_impl[test_idx].api_type;
> > > > > > > > >
> > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > > > +
> > > > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > > > >
> > > > > > > > >  		/* Create the ring */
> > > > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> > > esize[i],
> > > > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > create_flags);
> > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > +
> > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > >
> > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > > > -496,8
> > > > > > > > > +677,8 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > +api_type, unsigned int
> > > > > > > > > create_flags,
> > > > > > > > >
> > > > > > > > >  		printf("Test enqueue without enough memory
> > > space\n");
> > > > > > > > >  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
> > > > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > -							api_type);
> > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > +							test_idx);
> > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > >  				goto fail;
> > > > > > > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > @@ -
> > > > > > > > > 505,7 +686,7 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > api_type, unsigned int create_flags,
> > > > > > > > >  		}
> > > > > > > > >
> > > > > > > > >  		printf("Enqueue 2 objects, free entries = MAX_BULK -
> > > 2\n");
> > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > > > api_type);
> > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > > > > test_idx);
> > > > > > > > >  		if (ret != 2)
> > > > > > > > >  			goto fail;
> > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); @@
> > > > > > > > > -517,8
> > > > > > > > > +698,8 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > +api_type, unsigned int
> > > > > > > > > create_flags,
> > > > > > > > >  		else
> > > > > > > > >  			num_elems = MAX_BULK;
> > > > > > > > >  		/* Always one free entry left */
> > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > num_elems,
> > > > > > > > > -						api_type);
> > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > num_elems,
> > > > > > > > > +						test_idx);
> > > > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > > > >  			goto fail;
> > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > MAX_BULK -
> > > > > > > > > 3);
> > > > > > > @@
> > > > > > > > > -528,15 +709,15 @@ test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > >  			goto fail;
> > > > > > > > >
> > > > > > > > >  		printf("Test enqueue for a full entry\n");
> > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > MAX_BULK,
> > > > > > > > > -						api_type);
> > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > MAX_BULK,
> > > > > > > > > +						test_idx);
> > > > > > > > >  		if (ret != 0)
> > > > > > > > >  			goto fail;
> > > > > > > > >
> > > > > > > > >  		printf("Test dequeue without enough objects\n");
> > > > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > -							api_type);
> > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > +							test_idx);
> > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > >  				goto fail;
> > > > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > @@ -
> > > > > > > > > 544,7 +725,7 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > api_type, unsigned int create_flags,
> > > > > > > > >  		}
> > > > > > > > >
> > > > > > > > >  		/* Available memory space for the exact MAX_BULK
> > > entries
> > > > > > > */
> > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > > > api_type);
> > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > > > > test_idx);
> > > > > > > > >  		if (ret != 2)
> > > > > > > > >  			goto fail;
> > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); @@
> > > > > > > > > -554,8
> > > > > > > > > +735,8 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > +api_type, unsigned int
> > > > > > > > > create_flags,
> > > > > > > > >  			num_elems = MAX_BULK - 3;
> > > > > > > > >  		else
> > > > > > > > >  			num_elems = MAX_BULK;
> > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > num_elems,
> > > > > > > > > -						api_type);
> > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > num_elems,
> > > > > > > > > +						test_idx);
> > > > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > > > >  			goto fail;
> > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > MAX_BULK -
> > > > > > > > > 3);
> > > > > > > @@
> > > > > > > > > -816,22 +997,7 @@ static int
> > > > > > > > >  test_ring(void)
> > > > > > > > >  {
> > > > > > > > >  	int32_t rc;
> > > > > > > > > -	unsigned int i, j;
> > > > > > > > > -	const char *tname;
> > > > > > > > > -
> > > > > > > > > -	static const struct {
> > > > > > > > > -		uint32_t create_flags;
> > > > > > > > > -		const char *name;
> > > > > > > > > -	} test_sync_modes[] = {
> > > > > > > > > -		{
> > > > > > > > > -			RING_F_MP_RTS_ENQ |
> > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > -			"Test MT_RTS ring",
> > > > > > > > > -		},
> > > > > > > > > -		{
> > > > > > > > > -			RING_F_MP_HTS_ENQ |
> > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > -			"Test MT_HTS ring",
> > > > > > > > > -		},
> > > > > > > > > -	};
> > > > > > > > > +	unsigned int i;
> > > > > > > > >
> > > > > > > > >  	/* Negative test cases */
> > > > > > > > >  	if (test_ring_negative_tests() < 0) @@ -848,65
> > > > > > > > > +1014,24 @@
> > > > > > > > > test_ring(void)
> > > > > > > > >  	 * The test cases are split into smaller test cases to
> > > > > > > > >  	 * help clang compile faster.
> > > > > > > > >  	 */
> > > > > > > > > -	tname = "Test standard ring";
> > > > > > > > > -
> > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> TEST_RING_ELEM_BURST;
> > > > > j <<= 1)
> > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > -					i <=
> > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > <<= 1)
> > > > > > > > > -			if (test_ring_burst_bulk_tests1(i | j, 0, tname)
> > > > > < 0)
> > > > > > > > > -				goto test_fail;
> > > > > > > > > -
> > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> TEST_RING_ELEM_BURST;
> > > > > j <<= 1)
> > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > -					i <=
> > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > <<= 1)
> > > > > > > > > -			if (test_ring_burst_bulk_tests2(i | j, 0, tname)
> > > > > < 0)
> > > > > > > > > -				goto test_fail;
> > > > > > > > > -
> > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> TEST_RING_ELEM_BURST;
> > > > > j <<= 1)
> > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > -					i <=
> > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > <<= 1)
> > > > > > > > > -			if (test_ring_burst_bulk_tests3(i | j, 0, tname)
> > > > > < 0)
> > > > > > > > > -				goto test_fail;
> > > > > > > > > -
> > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> TEST_RING_ELEM_BURST;
> > > > > j <<= 1)
> > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > -					i <=
> > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > <<= 1)
> > > > > > > > > -			if (test_ring_burst_bulk_tests4(i | j, 0, tname)
> > > > > < 0)
> > > > > > > > > -				goto test_fail;
> > > > > > > > > -
> > > > > > > > > -	/* Burst and bulk operations with MT_RTS and MT_HTS sync
> > > > > modes
> > > > > > > > > */
> > > > > > > > > -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> > > > > > > > > -		for (j = TEST_RING_ELEM_BULK; j <=
> > > > > TEST_RING_ELEM_BURST;
> > > > > > > > > -				j <<= 1) {
> > > > > > > > > -
> > > > > > > > > -			rc = test_ring_burst_bulk_tests1(
> > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > -			if (rc < 0)
> > > > > > > > > -				goto test_fail;
> > > > > > > > > -
> > > > > > > > > -			rc = test_ring_burst_bulk_tests2(
> > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > -			if (rc < 0)
> > > > > > > > > -				goto test_fail;
> > > > > > > > > -
> > > > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > -			if (rc < 0)
> > > > > > > > > -				goto test_fail;
> > > > > > > > > -
> > > > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > -			if (rc < 0)
> > > > > > > > > -				goto test_fail;
> > > > > > > > > -		}
> > > > > > > > > +	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
> > > > > > > > > +
> > > > > > > > > +
> > > > > > > > > +		rc = test_ring_burst_bulk_tests1(i);
> > > > > > > > > +		if (rc < 0)
> > > > > > > > > +			goto test_fail;
> > > > > > > > > +
> > > > > > > > > +		rc = test_ring_burst_bulk_tests2(i);
> > > > > > > > > +		if (rc < 0)
> > > > > > > > > +			goto test_fail;
> > > > > > > > > +
> > > > > > > > > +		rc = test_ring_burst_bulk_tests3(i);
> > > > > > > > > +		if (rc < 0)
> > > > > > > > > +			goto test_fail;
> > > > > > > > > +
> > > > > > > > > +		rc = test_ring_burst_bulk_tests4(i);
> > > > > > > > > +		if (rc < 0)
> > > > > > > > > +			goto test_fail;
> > > > > > > > >  	}
> > > > > > > > >
> > > > > > > > >  	/* dump the ring status */
> > > > > > > > > --
> > > > > > > > > 2.17.1
Ananyev, Konstantin May 8, 2020, 10:04 a.m. UTC | #13
> > > <snip>
> > >
> > > > > > > >
> > > > > > > > > Hi Konstantin,
> > > > > > > > > 	I like the way the tests are organized and it looks good.
> > > > > > > > >
> > > > > > > > > I am just wondering about the way it is being tested here.
> > > > > > > > > The intent to write the test cases the way they are
> > > > > > > > > currently is to mimic how the APIs would be used mostly.
> > > > > > > > > IMO, the APIs would be used with a constant
> > > > > > > > value for element size so that the compiler will throw away
> > > > > > > > the unwanted code (in the functions where the actual copy is being
> > done).
> > > > > > > > >
> > > > > > > > > With your method here, it looks to me like all the
> > > > > > > > > branches in the copy
> > > > > > > > functions are kept and the branch decisions are done at run time.
> > > > > > > > > Is  my understanding correct?
> > > > > > > >
> > > > > > > > You mean branching on esize[] values?
> > > > > > > Yes
> I was wondering where is the confusion. I interpreted as referring to the esize parameter in rte_ring_xxx_elem APIs. Anyway, please see
> below.
> 
> > > > > > >
> > > > > > > > Actually from what I've seen that happens for both cases:
> > > > > > > > before and after the patch (gcc 7.3 -O3).
> > > > > > > I did not look at the generated code. If it is happening with
> > > > > > > your patch too, I
> > > > > > think we can go with your patch.
> > > > > >
> > > > > > Just to clarify, what I meant:
> > > > > > For both binaries (without the patch and with the patch) inside
> > > > > > test_ring() I see runtime branches on esize value.
> > > > > > Literally the code that corresponds to:
> > > > > > if (esize == 8) {...}
> > > > > > else if (esize == 16) {...}
> > > > > > else {...}
> > > I am not concerned about the functions in test_ring.c.
> > >
> > > > > Do you see this in the actual ring library functions?
> > > >
> > > > Which ones? AFAIK all ring dequeue/enqueue functions are inline right
> > now.
> > > Please see below.
> > >
> > > >
> > > > > I want to make sure that the library functions
> > > > > '__rte_ring_enqueue_elems' and '__rte_ring_dequeue_elems' are
> > optimized.
> > > Each enqueue/dequeue function ultimately calls these 2 functions.
> >
> > Yes, and then each instance of enqueue/dequeue functions that is used by
> > upper layer would be in-lined.
> > So what upper layer function (library or app) you asked me to check?
> I am not bothered much about upper layer functions. I looked at the generate code for the function __rte_ring_enqueue_elems.
> Existing code has the if checks for 8 and 16.
> Your patch also has the checks.
> My patch does not have the checks as it passes the constants directly without using esize[] array in functions test_ring_burst_bulk_tests4.

For test_burst_bulk_test[1-4] - yes, for other test functions it is still there.
Though I don't think it is that important for functional test cases.
Anyway, I think we dragged away a bit in our discussion,
so with what patch should we go ahead?
My preference is 69559, as it compiles faster and doesn't reduce 
test coverage, but I can live with both.
Konstantin

> 
> >
> > > The compiler here should remove the 'if (esize == 8) {...} else if
> > > (esize ==
> > > 16) {...} else {...}' with just the required piece of code depending on the
> > 'esize'.
> > > If we can validate that for at least one ring library function used in
> > > this patch, we should be good.
> > >
> > > > >
> > > > > >
> > > > > > Probably gcc wasn't able to remove it because we use esize[]
> > > > > > instead of hard- coded values, might be there is some other
> > > > > > reason, I don't know
> > > > for sure.
> > > > > > As it is a functional (not performance) test, I didn't dig further.
> > > > > The esize[] array is declared as a const. The compiler should be
> > > > > able to see
> > > > that it is a compile time constant.
> > > >
> > > > That was my expectation too, but that not what I am seeing.
> > > >
> > > > > >
> > > > > > > But, can you do similar
> > > > > > > change to test_ring_perf.c to keep it consistent?
> > > > > >
> > > > > > In principle it is doable, but needs extra care.
> > > > > > We need to make sure that compiler will be able to inline
> > > > > > functions via pointers.
> > > > > > AFAIK, gcc does that with -O3', but not with '-O2'.
> > > > > If the unwanted code is not removed during compilation, we will
> > > > > see it
> > > > affect the performance numbers.
> > > >
> > > > Exactly.
> > > > The last thing I want - someone who uses older version of compiler,
> > > > etc., will start to see lower performance numbers with that test.
> > > >
> > > > > > Don't know what the story with clang and different versions of
> > > > > > the
> > > > compiler.
> > > > > > Is there any real need for that?
> > > > > > On my box test_ring_perf.c compilation takes ~8s.
> > > > > > Konstantin
> > > > > >
> > > > > >
> > > > > > >
> > > > > > > >
> > > > > > > > Main intention in my changes was to avoid using
> > > > > > > > test_ring_enqueue/test_ring_dequeue,
> > > > > > > > as it seems too many branches here and it takes compiler a
> > > > > > > > lot of effort to resolve all of them at compile time.
> > > > > > > > So I replaced it with  array of function pointers
> > > > > > > > (test_enqdeq_impl[]) and iterating over it.
> > > > > > > > That way compiler knows straightway which function to use.
> > > > > > > >
> > > > > > > > > Can you please check this?
> > > > > > > > > https://patches.dpdk.org/patch/69567/
> > > > > > > >
> > > > > > > > As I can see your approach reduces number of test-cases by factor
> > of 5:
> > > > > > > > now each of test_ring_burst_bulk_tests[1-4] is executed only
> > > > > > > > with just one esize value, correct?
> > > > > > > Yes, basically test_ring_burst_bulk_tests[1-4] were covering
> > > > > > > different scenarios with the same APIs. So, distributed the
> > > > > > > esize across different test
> > > > > > functions.
> > > > > > >
> > > > > > > > In term of compilation speed - it helps.
> > > > > > > > On my box with (gcc 7.3 -O3)  compiling test_ring.c takes:
> > > > > > > > orig code:                             ~100s
> > > > > > > > with 69567 (your patch):  < 20s
> > > > > > > > with 69559 (my patch):    < 10s
> > > > > > > >
> > > > > > > > Konstantin
> > > > > > > >
> > > > > > > > >
> > > > > > > > > > -----Original Message-----
> > > > > > > > > > From: Konstantin Ananyev <konstantin.ananyev@intel.com>
> > > > > > > > > > Sent: Wednesday, April 29, 2020 12:57 PM
> > > > > > > > > > To: dev@dpdk.org
> > > > > > > > > > Cc: aconole@redhat.com; Honnappa Nagarahalli
> > > > > > > > > > <Honnappa.Nagarahalli@arm.com>; Konstantin Ananyev
> > > > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > > > Subject: [PATCH] test/ring: code rework to reduce
> > > > > > > > > > compilation time
> > > > > > > > > >
> > > > > > > > > > Rework test code to reduce code complexity for the
> > > > > > > > > > compiler and bring down compilation time and memory
> > consumption.
> > > > > > > > > >
> > > > > > > > > > Signed-off-by: Konstantin Ananyev
> > > > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > > > ---
> > > > > > > > > >  app/test/test_ring.c | 373
> > > > > > > > > > +++++++++++++++++++++++++++++--------------
> > > > > > > > > >  1 file changed, 249 insertions(+), 124 deletions(-)
> > > > > > > > > >
> > > > > > > > > > diff --git a/app/test/test_ring.c b/app/test/test_ring.c
> > > > > > > > > > index
> > > > > > > > > > e21557cd9..0ae97d341 100644
> > > > > > > > > > --- a/app/test/test_ring.c
> > > > > > > > > > +++ b/app/test/test_ring.c
> > > > > > > > > > @@ -58,6 +58,181 @@
> > > > > > > > > >
> > > > > > > > > >  static const int esize[] = {-1, 4, 8, 16, 20};
> > > > > > > > > >
> > > > > > > > > > +static const struct {
> > > > > > > > > > +	const char *desc;
> > > > > > > > > > +	uint32_t api_type;
> > > > > > > > > > +	uint32_t create_flags;
> > > > > > > > > > +	struct {
> > > > > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > > > > +			void * const *obj_table, unsigned int n,
> > > > > > > > > > +			unsigned int *free_space);
> > > > > > > > > > +		unsigned int (*felem)(struct rte_ring *r, const void
> > > > > > *obj_table,
> > > > > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > > > > +			unsigned int *free_space);
> > > > > > > > > > +	} enq;
> > > > > > > > > > +	struct {
> > > > > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > > > > +			void **obj_table, unsigned int n,
> > > > > > > > > > +			unsigned int *available);
> > > > > > > > > > +		unsigned int (*felem)(struct rte_ring *r, void
> > > > > > *obj_table,
> > > > > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > > > > +			unsigned int *available);
> > > > > > > > > > +	} deq;
> > > > > > > > > > +} test_enqdeq_impl[] = {
> > > > > > > > > > +	{
> > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > Details about the tests are already printed by the
> > > > > > > > > function
> > > > > > > > 'test_ring_print_test_string'. This string should be 'Test standard
> > ring'.
> > > > > > > > >
> > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > +		.enq = {
> > > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +		.deq = {
> > > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +	},
> > > > > > > > > > +	{
> > > > > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > > > > > > > +		.enq = {
> > > > > > > > > > +			.flegacy = rte_ring_sp_enqueue_bulk,
> > > > > > > > > > +			.felem = rte_ring_sp_enqueue_bulk_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +		.deq = {
> > > > > > > > > > +			.flegacy = rte_ring_sc_dequeue_bulk,
> > > > > > > > > > +			.felem = rte_ring_sc_dequeue_bulk_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +	},
> > > > > > > > > > +	{
> > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > +		.enq = {
> > > > > > > > > > +			.flegacy = rte_ring_mp_enqueue_bulk,
> > > > > > > > > > +			.felem = rte_ring_mp_enqueue_bulk_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +		.deq = {
> > > > > > > > > > +			.flegacy = rte_ring_mc_dequeue_bulk,
> > > > > > > > > > +			.felem = rte_ring_mc_dequeue_bulk_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +	},
> > > > > > > > > > +	{
> > > > > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > > +		.enq = {
> > > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +		.deq = {
> > > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +	},
> > > > > > > > > > +	{
> > > > > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > > +		.enq = {
> > > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +		.deq = {
> > > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +	},
> > > > > > > > > > +	{
> > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > +		.enq = {
> > > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +		.deq = {
> > > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +	},
> > > > > > > > > > +	{
> > > > > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > > > > +		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
> > > > > > > > > > +		.enq = {
> > > > > > > > > > +			.flegacy = rte_ring_sp_enqueue_burst,
> > > > > > > > > > +			.felem = rte_ring_sp_enqueue_burst_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +		.deq = {
> > > > > > > > > > +			.flegacy = rte_ring_sc_dequeue_burst,
> > > > > > > > > > +			.felem = rte_ring_sc_dequeue_burst_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +	},
> > > > > > > > > > +	{
> > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > +		.enq = {
> > > > > > > > > > +			.flegacy = rte_ring_mp_enqueue_burst,
> > > > > > > > > > +			.felem = rte_ring_mp_enqueue_burst_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +		.deq = {
> > > > > > > > > > +			.flegacy = rte_ring_mc_dequeue_burst,
> > > > > > > > > > +			.felem = rte_ring_mc_dequeue_burst_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +	},
> > > > > > > > > > +	{
> > > > > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > > +		.enq = {
> > > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +		.deq = {
> > > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +	},
> > > > > > > > > > +	{
> > > > > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > > +		.enq = {
> > > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > > +			.felem = rte_ring_enqueue_burst_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +		.deq = {
> > > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > > +			.felem = rte_ring_dequeue_burst_elem,
> > > > > > > > > > +		},
> > > > > > > > > > +	},
> > > > > > > > > > +};
> > > > > > > > > > +
> > > > > > > > > > +static unsigned int
> > > > > > > > > > +test_ring_enq_impl(struct rte_ring *r, void **obj, int
> > > > > > > > > > +esize, unsigned
> > > > > > int n,
> > > > > > > > > > +	unsigned int test_idx) {
> > > > > > > > > > +	if (esize == -1)
> > > > > > > > > > +		return test_enqdeq_impl[test_idx].enq.flegacy(r, obj,
> > > > > > n, NULL);
> > > > > > > > > > +	else
> > > > > > > > > > +		return test_enqdeq_impl[test_idx].enq.felem(r, obj,
> > > > > > esize, n,
> > > > > > > > > > +			NULL);
> > > > > > > > > > +}
> > > > > > > > > > +
> > > > > > > > > > +static unsigned int
> > > > > > > > > > +test_ring_deq_impl(struct rte_ring *r, void **obj, int
> > > > > > > > > > +esize, unsigned
> > > > > > int n,
> > > > > > > > > > +	unsigned int test_idx) {
> > > > > > > > > > +	if (esize == -1)
> > > > > > > > > > +		return test_enqdeq_impl[test_idx].deq.flegacy(r, obj,
> > > > > > n, NULL);
> > > > > > > > > > +	else
> > > > > > > > > > +		return test_enqdeq_impl[test_idx].deq.felem(r, obj,
> > > > > > esize, n,
> > > > > > > > > > +			NULL);
> > > > > > > > > > +}
> > > > > > > > > > +
> > > > > > > > > >  static void**
> > > > > > > > > >  test_ring_inc_ptr(void **obj, int esize, unsigned int
> > > > > > > > > > n)  { @@
> > > > > > > > > > -203,8 +378,7 @@ test_ring_negative_tests(void)
> > > > > > > > > >   * Random number of elements are enqueued and dequeued.
> > > > > > > > > >   */
> > > > > > > > > >  static int
> > > > > > > > > > -test_ring_burst_bulk_tests1(unsigned int api_type,
> > > > > > > > > > unsigned int
> > > > > > > > create_flags,
> > > > > > > > > > -	const char *tname)
> > > > > > > > > > +test_ring_burst_bulk_tests1(unsigned int test_idx)
> > > > > > > > > >  {
> > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > > **cur_dst = NULL; @@ -214,11 +388,13 @@
> > > > > > test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > >  	const unsigned int rsz = RING_SIZE - 1;
> > > > > > > > > >
> > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > > > > +
> > > > > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > > > > >
> > > > > > > > > >  		/* Create the ring */
> > > > > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> > > > esize[i],
> > > > > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > create_flags);
> > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > +
> > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > >
> > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > > > > -240,17
> > > > > > > > > > +416,17 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > create_flags,
> > > > > > > > > >  			rand = RTE_MAX(rte_rand() % RING_SIZE,
> > > > 1UL);
> > > > > > > > > >  			printf("%s: iteration %u, random shift: %u;\n",
> > > > > > > > > >  			    __func__, i, rand);
> > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > rand,
> > > > > > > > > > -							api_type);
> > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > rand,
> > > > > > > > > > +							test_idx);
> > > > > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > > > > >
> > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > rand,
> > > > > > > > > > -							api_type);
> > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > rand,
> > > > > > > > > > +							test_idx);
> > > > > > > > > >  			TEST_RING_VERIFY(ret == rand);
> > > > > > > > > >
> > > > > > > > > >  			/* fill the ring */
> > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > rsz,
> > > > > > > > > > -							api_type);
> > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > rsz,
> > > > > > > > > > +							test_idx);
> > > > > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > > > > >
> > > > > > > > > >  			TEST_RING_VERIFY(rte_ring_free_count(r) ==
> > > > 0); @@
> > > > > > > > > > -259,8 +435,8 @@ test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > >  			TEST_RING_VERIFY(rte_ring_empty(r) == 0);
> > > > > > > > > >
> > > > > > > > > >  			/* empty the ring */
> > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > rsz,
> > > > > > > > > > -							api_type);
> > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > rsz,
> > > > > > > > > > +							test_idx);
> > > > > > > > > >  			TEST_RING_VERIFY(ret == (int)rsz);
> > > > > > > > > >  			TEST_RING_VERIFY(rsz ==
> > > > rte_ring_free_count(r));
> > > > > > > > > >  			TEST_RING_VERIFY(rte_ring_count(r) == 0);
> > > > @@ -
> > > > > > > > > > 294,8 +470,7 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > > > > > api_type, unsigned int create_flags,
> > > > > > > > > >   * dequeued data.
> > > > > > > > > >   */
> > > > > > > > > >  static int
> > > > > > > > > > -test_ring_burst_bulk_tests2(unsigned int api_type,
> > > > > > > > > > unsigned int
> > > > > > > > create_flags,
> > > > > > > > > > -	const char *tname)
> > > > > > > > > > +test_ring_burst_bulk_tests2(unsigned int test_idx)
> > > > > > > > > >  {
> > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > > **cur_dst = NULL; @@ -303,11 +478,13 @@
> > > > > > test_ring_burst_bulk_tests2(unsigned
> > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > >  	unsigned int i;
> > > > > > > > > >
> > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > > > > +
> > > > > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > > > > >
> > > > > > > > > >  		/* Create the ring */
> > > > > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> > > > esize[i],
> > > > > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > create_flags);
> > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > +
> > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > >
> > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > > > > -323,39
> > > > > > > > > > +500,39 @@ test_ring_burst_bulk_tests2(unsigned int
> > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > create_flags,
> > > > > > > > > >  		cur_dst = dst;
> > > > > > > > > >
> > > > > > > > > >  		printf("enqueue 1 obj\n");
> > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 1,
> > > > > > api_type);
> > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 1,
> > > > > > test_idx);
> > > > > > > > > >  		if (ret != 1)
> > > > > > > > > >  			goto fail;
> > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
> > > > > > > > > >
> > > > > > > > > >  		printf("enqueue 2 objs\n");
> > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > > > > api_type);
> > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > > > > > test_idx);
> > > > > > > > > >  		if (ret != 2)
> > > > > > > > > >  			goto fail;
> > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
> > > > > > > > > >
> > > > > > > > > >  		printf("enqueue MAX_BULK objs\n");
> > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > MAX_BULK,
> > > > > > > > > > -						api_type);
> > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > MAX_BULK,
> > > > > > > > > > +						test_idx);
> > > > > > > > > >  		if (ret != MAX_BULK)
> > > > > > > > > >  			goto fail;
> > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > MAX_BULK);
> > > > > > > > > >
> > > > > > > > > >  		printf("dequeue 1 obj\n");
> > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1,
> > > > > > api_type);
> > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1,
> > > > > > test_idx);
> > > > > > > > > >  		if (ret != 1)
> > > > > > > > > >  			goto fail;
> > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
> > > > > > > > > >
> > > > > > > > > >  		printf("dequeue 2 objs\n");
> > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > > > > api_type);
> > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > > > > > test_idx);
> > > > > > > > > >  		if (ret != 2)
> > > > > > > > > >  			goto fail;
> > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
> > > > > > > > > >
> > > > > > > > > >  		printf("dequeue MAX_BULK objs\n");
> > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > MAX_BULK,
> > > > > > > > > > -						api_type);
> > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > MAX_BULK,
> > > > > > > > > > +						test_idx);
> > > > > > > > > >  		if (ret != MAX_BULK)
> > > > > > > > > >  			goto fail;
> > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > MAX_BULK);
> > > > > > > > > > @@
> > > > > > > > > > -390,8 +567,7 @@ test_ring_burst_bulk_tests2(unsigned
> > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > >   * Enqueue and dequeue to cover the entire ring length.
> > > > > > > > > >   */
> > > > > > > > > >  static int
> > > > > > > > > > -test_ring_burst_bulk_tests3(unsigned int api_type,
> > > > > > > > > > unsigned int
> > > > > > > > create_flags,
> > > > > > > > > > -	const char *tname)
> > > > > > > > > > +test_ring_burst_bulk_tests3(unsigned int test_idx)
> > > > > > > > > >  {
> > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > > **cur_dst = NULL; @@ -399,11 +575,13 @@
> > > > > > test_ring_burst_bulk_tests3(unsigned
> > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > >  	unsigned int i, j;
> > > > > > > > > >
> > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > > > > +
> > > > > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > > > > >
> > > > > > > > > >  		/* Create the ring */
> > > > > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> > > > esize[i],
> > > > > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > create_flags);
> > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > +
> > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > >
> > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > > > > -420,15
> > > > > > > > > > +598,15 @@ test_ring_burst_bulk_tests3(unsigned int
> > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > create_flags,
> > > > > > > > > >
> > > > > > > > > >  		printf("fill and empty the ring\n");
> > > > > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > > > > MAX_BULK,
> > > > > > > > > > -							api_type);
> > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > > > > MAX_BULK,
> > > > > > > > > > +							test_idx);
> > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > >  				goto fail;
> > > > > > > > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > > > > > >
> > > > 	MAX_BULK);
> > > > > > > > > >
> > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > > > > MAX_BULK,
> > > > > > > > > > -							api_type);
> > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > > > > > MAX_BULK,
> > > > > > > > > > +							test_idx);
> > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > >  				goto fail;
> > > > > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > @@ -
> > > > > > > > > > 465,21 +643,24 @@ test_ring_burst_bulk_tests3(unsigned
> > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > >   * Enqueue till the ring is full and dequeue till the
> > > > > > > > > > ring becomes
> > > > empty.
> > > > > > > > > >   */
> > > > > > > > > >  static int
> > > > > > > > > > -test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > > > > > > unsigned int
> > > > > > > > create_flags,
> > > > > > > > > > -	const char *tname)
> > > > > > > > > > +test_ring_burst_bulk_tests4(unsigned int test_idx)
> > > > > > > > > >  {
> > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > > **cur_dst
> > > > = NULL;
> > > > > > > > > >  	int ret;
> > > > > > > > > >  	unsigned int i, j;
> > > > > > > > > > -	unsigned int num_elems;
> > > > > > > > > > +	unsigned int api_type, num_elems;
> > > > > > > > > > +
> > > > > > > > > > +	api_type = test_enqdeq_impl[test_idx].api_type;
> > > > > > > > > >
> > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > -		test_ring_print_test_string(tname, api_type, esize[i]);
> > > > > > > > > > +
> > > > > > 	test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type, esize[i]);
> > > > > > > > > >
> > > > > > > > > >  		/* Create the ring */
> > > > > > > > > >  		r = test_ring_create("test_ring_burst_bulk_tests",
> > > > esize[i],
> > > > > > > > > > -					RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > create_flags);
> > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > +
> > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > >
> > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]); @@
> > > > > > > > > > -496,8
> > > > > > > > > > +677,8 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > create_flags,
> > > > > > > > > >
> > > > > > > > > >  		printf("Test enqueue without enough memory
> > > > space\n");
> > > > > > > > > >  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
> > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > > > > MAX_BULK,
> > > > > > > > > > -							api_type);
> > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > > > > MAX_BULK,
> > > > > > > > > > +							test_idx);
> > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > >  				goto fail;
> > > > > > > > > >  			cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > @@ -
> > > > > > > > > > 505,7 +686,7 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > > api_type, unsigned int create_flags,
> > > > > > > > > >  		}
> > > > > > > > > >
> > > > > > > > > >  		printf("Enqueue 2 objects, free entries = MAX_BULK -
> > > > 2\n");
> > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > > > > api_type);
> > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > > > > > test_idx);
> > > > > > > > > >  		if (ret != 2)
> > > > > > > > > >  			goto fail;
> > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); @@
> > > > > > > > > > -517,8
> > > > > > > > > > +698,8 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > create_flags,
> > > > > > > > > >  		else
> > > > > > > > > >  			num_elems = MAX_BULK;
> > > > > > > > > >  		/* Always one free entry left */
> > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > num_elems,
> > > > > > > > > > -						api_type);
> > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > num_elems,
> > > > > > > > > > +						test_idx);
> > > > > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > > > > >  			goto fail;
> > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > MAX_BULK -
> > > > > > > > > > 3);
> > > > > > > > @@
> > > > > > > > > > -528,15 +709,15 @@ test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > >  			goto fail;
> > > > > > > > > >
> > > > > > > > > >  		printf("Test enqueue for a full entry\n");
> > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > MAX_BULK,
> > > > > > > > > > -						api_type);
> > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > MAX_BULK,
> > > > > > > > > > +						test_idx);
> > > > > > > > > >  		if (ret != 0)
> > > > > > > > > >  			goto fail;
> > > > > > > > > >
> > > > > > > > > >  		printf("Test dequeue without enough objects\n");
> > > > > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > > > > MAX_BULK,
> > > > > > > > > > -							api_type);
> > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > > > > > MAX_BULK,
> > > > > > > > > > +							test_idx);
> > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > >  				goto fail;
> > > > > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > @@ -
> > > > > > > > > > 544,7 +725,7 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > > api_type, unsigned int create_flags,
> > > > > > > > > >  		}
> > > > > > > > > >
> > > > > > > > > >  		/* Available memory space for the exact MAX_BULK
> > > > entries
> > > > > > > > */
> > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > > > > api_type);
> > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > > > > > test_idx);
> > > > > > > > > >  		if (ret != 2)
> > > > > > > > > >  			goto fail;
> > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); @@
> > > > > > > > > > -554,8
> > > > > > > > > > +735,8 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > create_flags,
> > > > > > > > > >  			num_elems = MAX_BULK - 3;
> > > > > > > > > >  		else
> > > > > > > > > >  			num_elems = MAX_BULK;
> > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > num_elems,
> > > > > > > > > > -						api_type);
> > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > num_elems,
> > > > > > > > > > +						test_idx);
> > > > > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > > > > >  			goto fail;
> > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > MAX_BULK -
> > > > > > > > > > 3);
> > > > > > > > @@
> > > > > > > > > > -816,22 +997,7 @@ static int
> > > > > > > > > >  test_ring(void)
> > > > > > > > > >  {
> > > > > > > > > >  	int32_t rc;
> > > > > > > > > > -	unsigned int i, j;
> > > > > > > > > > -	const char *tname;
> > > > > > > > > > -
> > > > > > > > > > -	static const struct {
> > > > > > > > > > -		uint32_t create_flags;
> > > > > > > > > > -		const char *name;
> > > > > > > > > > -	} test_sync_modes[] = {
> > > > > > > > > > -		{
> > > > > > > > > > -			RING_F_MP_RTS_ENQ |
> > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > > -			"Test MT_RTS ring",
> > > > > > > > > > -		},
> > > > > > > > > > -		{
> > > > > > > > > > -			RING_F_MP_HTS_ENQ |
> > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > > -			"Test MT_HTS ring",
> > > > > > > > > > -		},
> > > > > > > > > > -	};
> > > > > > > > > > +	unsigned int i;
> > > > > > > > > >
> > > > > > > > > >  	/* Negative test cases */
> > > > > > > > > >  	if (test_ring_negative_tests() < 0) @@ -848,65
> > > > > > > > > > +1014,24 @@
> > > > > > > > > > test_ring(void)
> > > > > > > > > >  	 * The test cases are split into smaller test cases to
> > > > > > > > > >  	 * help clang compile faster.
> > > > > > > > > >  	 */
> > > > > > > > > > -	tname = "Test standard ring";
> > > > > > > > > > -
> > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > TEST_RING_ELEM_BURST;
> > > > > > j <<= 1)
> > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > -					i <=
> > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > <<= 1)
> > > > > > > > > > -			if (test_ring_burst_bulk_tests1(i | j, 0, tname)
> > > > > > < 0)
> > > > > > > > > > -				goto test_fail;
> > > > > > > > > > -
> > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > TEST_RING_ELEM_BURST;
> > > > > > j <<= 1)
> > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > -					i <=
> > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > <<= 1)
> > > > > > > > > > -			if (test_ring_burst_bulk_tests2(i | j, 0, tname)
> > > > > > < 0)
> > > > > > > > > > -				goto test_fail;
> > > > > > > > > > -
> > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > TEST_RING_ELEM_BURST;
> > > > > > j <<= 1)
> > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > -					i <=
> > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > <<= 1)
> > > > > > > > > > -			if (test_ring_burst_bulk_tests3(i | j, 0, tname)
> > > > > > < 0)
> > > > > > > > > > -				goto test_fail;
> > > > > > > > > > -
> > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > TEST_RING_ELEM_BURST;
> > > > > > j <<= 1)
> > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > -					i <=
> > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > <<= 1)
> > > > > > > > > > -			if (test_ring_burst_bulk_tests4(i | j, 0, tname)
> > > > > > < 0)
> > > > > > > > > > -				goto test_fail;
> > > > > > > > > > -
> > > > > > > > > > -	/* Burst and bulk operations with MT_RTS and MT_HTS sync
> > > > > > modes
> > > > > > > > > > */
> > > > > > > > > > -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> > > > > > > > > > -		for (j = TEST_RING_ELEM_BULK; j <=
> > > > > > TEST_RING_ELEM_BURST;
> > > > > > > > > > -				j <<= 1) {
> > > > > > > > > > -
> > > > > > > > > > -			rc = test_ring_burst_bulk_tests1(
> > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > -				goto test_fail;
> > > > > > > > > > -
> > > > > > > > > > -			rc = test_ring_burst_bulk_tests2(
> > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > -				goto test_fail;
> > > > > > > > > > -
> > > > > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > -				goto test_fail;
> > > > > > > > > > -
> > > > > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > -				test_sync_modes[i].create_flags,
> > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > -				goto test_fail;
> > > > > > > > > > -		}
> > > > > > > > > > +	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
> > > > > > > > > > +
> > > > > > > > > > +
> > > > > > > > > > +		rc = test_ring_burst_bulk_tests1(i);
> > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > +			goto test_fail;
> > > > > > > > > > +
> > > > > > > > > > +		rc = test_ring_burst_bulk_tests2(i);
> > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > +			goto test_fail;
> > > > > > > > > > +
> > > > > > > > > > +		rc = test_ring_burst_bulk_tests3(i);
> > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > +			goto test_fail;
> > > > > > > > > > +
> > > > > > > > > > +		rc = test_ring_burst_bulk_tests4(i);
> > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > +			goto test_fail;
> > > > > > > > > >  	}
> > > > > > > > > >
> > > > > > > > > >  	/* dump the ring status */
> > > > > > > > > > --
> > > > > > > > > > 2.17.1
Honnappa Nagarahalli May 9, 2020, 12:33 a.m. UTC | #14
<snip>

> > > > <snip>
> > > >
> > > > > > > > >
> > > > > > > > > > Hi Konstantin,
> > > > > > > > > > 	I like the way the tests are organized and it looks
> good.
> > > > > > > > > >
> > > > > > > > > > I am just wondering about the way it is being tested here.
> > > > > > > > > > The intent to write the test cases the way they are
> > > > > > > > > > currently is to mimic how the APIs would be used mostly.
> > > > > > > > > > IMO, the APIs would be used with a constant
> > > > > > > > > value for element size so that the compiler will throw
> > > > > > > > > away the unwanted code (in the functions where the
> > > > > > > > > actual copy is being
> > > done).
> > > > > > > > > >
> > > > > > > > > > With your method here, it looks to me like all the
> > > > > > > > > > branches in the copy
> > > > > > > > > functions are kept and the branch decisions are done at run
> time.
> > > > > > > > > > Is  my understanding correct?
> > > > > > > > >
> > > > > > > > > You mean branching on esize[] values?
> > > > > > > > Yes
> > I was wondering where is the confusion. I interpreted as referring to
> > the esize parameter in rte_ring_xxx_elem APIs. Anyway, please see below.
> >
> > > > > > > >
> > > > > > > > > Actually from what I've seen that happens for both cases:
> > > > > > > > > before and after the patch (gcc 7.3 -O3).
> > > > > > > > I did not look at the generated code. If it is happening
> > > > > > > > with your patch too, I
> > > > > > > think we can go with your patch.
> > > > > > >
> > > > > > > Just to clarify, what I meant:
> > > > > > > For both binaries (without the patch and with the patch)
> > > > > > > inside
> > > > > > > test_ring() I see runtime branches on esize value.
> > > > > > > Literally the code that corresponds to:
> > > > > > > if (esize == 8) {...}
> > > > > > > else if (esize == 16) {...}
> > > > > > > else {...}
> > > > I am not concerned about the functions in test_ring.c.
> > > >
> > > > > > Do you see this in the actual ring library functions?
> > > > >
> > > > > Which ones? AFAIK all ring dequeue/enqueue functions are inline
> > > > > right
> > > now.
> > > > Please see below.
> > > >
> > > > >
> > > > > > I want to make sure that the library functions
> > > > > > '__rte_ring_enqueue_elems' and '__rte_ring_dequeue_elems' are
> > > optimized.
> > > > Each enqueue/dequeue function ultimately calls these 2 functions.
> > >
> > > Yes, and then each instance of enqueue/dequeue functions that is
> > > used by upper layer would be in-lined.
> > > So what upper layer function (library or app) you asked me to check?
> > I am not bothered much about upper layer functions. I looked at the
> generate code for the function __rte_ring_enqueue_elems.
> > Existing code has the if checks for 8 and 16.
> > Your patch also has the checks.
> > My patch does not have the checks as it passes the constants directly
> without using esize[] array in functions test_ring_burst_bulk_tests4.
> 
> For test_burst_bulk_test[1-4] - yes, for other test functions it is still there.
Agree. This should give coverage for some at least.

> Though I don't think it is that important for functional test cases.
> Anyway, I think we dragged away a bit in our discussion, so with what patch
> should we go ahead?
Agree, we dragged it. I tried to merge both the solutions (use your patch and constant esize), I was not successful. My guess, function pointers are not allowing for the optimization.

> My preference is 69559, as it compiles faster and doesn't reduce test
> coverage, but I can live with both.
test_burst_bulk_test[1-4] more or less call the same APIs. Spreading the size variation across four of them should be ok. It will test the way it will be used. 

> Konstantin
> 
> >
> > >
> > > > The compiler here should remove the 'if (esize == 8) {...} else if
> > > > (esize ==
> > > > 16) {...} else {...}' with just the required piece of code
> > > > depending on the
> > > 'esize'.
> > > > If we can validate that for at least one ring library function
> > > > used in this patch, we should be good.
> > > >
> > > > > >
> > > > > > >
> > > > > > > Probably gcc wasn't able to remove it because we use esize[]
> > > > > > > instead of hard- coded values, might be there is some other
> > > > > > > reason, I don't know
> > > > > for sure.
> > > > > > > As it is a functional (not performance) test, I didn't dig further.
> > > > > > The esize[] array is declared as a const. The compiler should
> > > > > > be able to see
> > > > > that it is a compile time constant.
> > > > >
> > > > > That was my expectation too, but that not what I am seeing.
> > > > >
> > > > > > >
> > > > > > > > But, can you do similar
> > > > > > > > change to test_ring_perf.c to keep it consistent?
> > > > > > >
> > > > > > > In principle it is doable, but needs extra care.
> > > > > > > We need to make sure that compiler will be able to inline
> > > > > > > functions via pointers.
> > > > > > > AFAIK, gcc does that with -O3', but not with '-O2'.
> > > > > > If the unwanted code is not removed during compilation, we
> > > > > > will see it
> > > > > affect the performance numbers.
> > > > >
> > > > > Exactly.
> > > > > The last thing I want - someone who uses older version of
> > > > > compiler, etc., will start to see lower performance numbers with that
> test.
> > > > >
> > > > > > > Don't know what the story with clang and different versions
> > > > > > > of the
> > > > > compiler.
> > > > > > > Is there any real need for that?
> > > > > > > On my box test_ring_perf.c compilation takes ~8s.
> > > > > > > Konstantin
> > > > > > >
> > > > > > >
> > > > > > > >
> > > > > > > > >
> > > > > > > > > Main intention in my changes was to avoid using
> > > > > > > > > test_ring_enqueue/test_ring_dequeue,
> > > > > > > > > as it seems too many branches here and it takes compiler
> > > > > > > > > a lot of effort to resolve all of them at compile time.
> > > > > > > > > So I replaced it with  array of function pointers
> > > > > > > > > (test_enqdeq_impl[]) and iterating over it.
> > > > > > > > > That way compiler knows straightway which function to use.
> > > > > > > > >
> > > > > > > > > > Can you please check this?
> > > > > > > > > > https://patches.dpdk.org/patch/69567/
> > > > > > > > >
> > > > > > > > > As I can see your approach reduces number of test-cases
> > > > > > > > > by factor
> > > of 5:
> > > > > > > > > now each of test_ring_burst_bulk_tests[1-4] is executed
> > > > > > > > > only with just one esize value, correct?
> > > > > > > > Yes, basically test_ring_burst_bulk_tests[1-4] were
> > > > > > > > covering different scenarios with the same APIs. So,
> > > > > > > > distributed the esize across different test
> > > > > > > functions.
> > > > > > > >
> > > > > > > > > In term of compilation speed - it helps.
> > > > > > > > > On my box with (gcc 7.3 -O3)  compiling test_ring.c takes:
> > > > > > > > > orig code:                             ~100s
> > > > > > > > > with 69567 (your patch):  < 20s
> > > > > > > > > with 69559 (my patch):    < 10s
> > > > > > > > >
> > > > > > > > > Konstantin
> > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > From: Konstantin Ananyev
> > > > > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > > > > Sent: Wednesday, April 29, 2020 12:57 PM
> > > > > > > > > > > To: dev@dpdk.org
> > > > > > > > > > > Cc: aconole@redhat.com; Honnappa Nagarahalli
> > > > > > > > > > > <Honnappa.Nagarahalli@arm.com>; Konstantin Ananyev
> > > > > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > > > > Subject: [PATCH] test/ring: code rework to reduce
> > > > > > > > > > > compilation time
> > > > > > > > > > >
> > > > > > > > > > > Rework test code to reduce code complexity for the
> > > > > > > > > > > compiler and bring down compilation time and memory
> > > consumption.
> > > > > > > > > > >
> > > > > > > > > > > Signed-off-by: Konstantin Ananyev
> > > > > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > > > > ---
> > > > > > > > > > >  app/test/test_ring.c | 373
> > > > > > > > > > > +++++++++++++++++++++++++++++--------------
> > > > > > > > > > >  1 file changed, 249 insertions(+), 124 deletions(-)
> > > > > > > > > > >
> > > > > > > > > > > diff --git a/app/test/test_ring.c
> > > > > > > > > > > b/app/test/test_ring.c index
> > > > > > > > > > > e21557cd9..0ae97d341 100644
> > > > > > > > > > > --- a/app/test/test_ring.c
> > > > > > > > > > > +++ b/app/test/test_ring.c
> > > > > > > > > > > @@ -58,6 +58,181 @@
> > > > > > > > > > >
> > > > > > > > > > >  static const int esize[] = {-1, 4, 8, 16, 20};
> > > > > > > > > > >
> > > > > > > > > > > +static const struct {
> > > > > > > > > > > +	const char *desc;
> > > > > > > > > > > +	uint32_t api_type;
> > > > > > > > > > > +	uint32_t create_flags;
> > > > > > > > > > > +	struct {
> > > > > > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > > > > > +			void * const *obj_table, unsigned int
> n,
> > > > > > > > > > > +			unsigned int *free_space);
> > > > > > > > > > > +		unsigned int (*felem)(struct rte_ring *r, const
> > > > > > > > > > > +void
> > > > > > > *obj_table,
> > > > > > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > > > > > +			unsigned int *free_space);
> > > > > > > > > > > +	} enq;
> > > > > > > > > > > +	struct {
> > > > > > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > > > > > +			void **obj_table, unsigned int n,
> > > > > > > > > > > +			unsigned int *available);
> > > > > > > > > > > +		unsigned int (*felem)(struct rte_ring *r, void
> > > > > > > *obj_table,
> > > > > > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > > > > > +			unsigned int *available);
> > > > > > > > > > > +	} deq;
> > > > > > > > > > > +} test_enqdeq_impl[] = {
> > > > > > > > > > > +	{
> > > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > Details about the tests are already printed by the
> > > > > > > > > > function
> > > > > > > > > 'test_ring_print_test_string'. This string should be
> > > > > > > > > 'Test standard
> > > ring'.
> > > > > > > > > >
> > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > > +		.enq = {
> > > > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +		.deq = {
> > > > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +	},
> > > > > > > > > > > +	{
> > > > > > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > > > > > +		.create_flags = RING_F_SP_ENQ |
> RING_F_SC_DEQ,
> > > > > > > > > > > +		.enq = {
> > > > > > > > > > > +			.flegacy = rte_ring_sp_enqueue_bulk,
> > > > > > > > > > > +			.felem =
> rte_ring_sp_enqueue_bulk_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +		.deq = {
> > > > > > > > > > > +			.flegacy = rte_ring_sc_dequeue_bulk,
> > > > > > > > > > > +			.felem =
> rte_ring_sc_dequeue_bulk_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +	},
> > > > > > > > > > > +	{
> > > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > > +		.enq = {
> > > > > > > > > > > +			.flegacy = rte_ring_mp_enqueue_bulk,
> > > > > > > > > > > +			.felem =
> rte_ring_mp_enqueue_bulk_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +		.deq = {
> > > > > > > > > > > +			.flegacy = rte_ring_mc_dequeue_bulk,
> > > > > > > > > > > +			.felem =
> rte_ring_mc_dequeue_bulk_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +	},
> > > > > > > > > > > +	{
> > > > > > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > > > +		.enq = {
> > > > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +		.deq = {
> > > > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +	},
> > > > > > > > > > > +	{
> > > > > > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > > > +		.enq = {
> > > > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +		.deq = {
> > > > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +	},
> > > > > > > > > > > +	{
> > > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > > +		.enq = {
> > > > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > > > +			.felem =
> rte_ring_enqueue_burst_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +		.deq = {
> > > > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > > > +			.felem =
> rte_ring_dequeue_burst_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +	},
> > > > > > > > > > > +	{
> > > > > > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > > > > > +		.create_flags = RING_F_SP_ENQ |
> RING_F_SC_DEQ,
> > > > > > > > > > > +		.enq = {
> > > > > > > > > > > +			.flegacy = rte_ring_sp_enqueue_burst,
> > > > > > > > > > > +			.felem =
> rte_ring_sp_enqueue_burst_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +		.deq = {
> > > > > > > > > > > +			.flegacy = rte_ring_sc_dequeue_burst,
> > > > > > > > > > > +			.felem =
> rte_ring_sc_dequeue_burst_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +	},
> > > > > > > > > > > +	{
> > > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > > +		.enq = {
> > > > > > > > > > > +			.flegacy =
> rte_ring_mp_enqueue_burst,
> > > > > > > > > > > +			.felem =
> rte_ring_mp_enqueue_burst_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +		.deq = {
> > > > > > > > > > > +			.flegacy =
> rte_ring_mc_dequeue_burst,
> > > > > > > > > > > +			.felem =
> rte_ring_mc_dequeue_burst_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +	},
> > > > > > > > > > > +	{
> > > > > > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > > > +		.enq = {
> > > > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > > > +			.felem =
> rte_ring_enqueue_burst_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +		.deq = {
> > > > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > > > +			.felem =
> rte_ring_dequeue_burst_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +	},
> > > > > > > > > > > +	{
> > > > > > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > > > +		.enq = {
> > > > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > > > +			.felem =
> rte_ring_enqueue_burst_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +		.deq = {
> > > > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > > > +			.felem =
> rte_ring_dequeue_burst_elem,
> > > > > > > > > > > +		},
> > > > > > > > > > > +	},
> > > > > > > > > > > +};
> > > > > > > > > > > +
> > > > > > > > > > > +static unsigned int test_ring_enq_impl(struct
> > > > > > > > > > > +rte_ring *r, void **obj, int esize, unsigned
> > > > > > > int n,
> > > > > > > > > > > +	unsigned int test_idx) {
> > > > > > > > > > > +	if (esize == -1)
> > > > > > > > > > > +		return
> test_enqdeq_impl[test_idx].enq.flegacy(r,
> > > > > > > > > > > +obj,
> > > > > > > n, NULL);
> > > > > > > > > > > +	else
> > > > > > > > > > > +		return
> test_enqdeq_impl[test_idx].enq.felem(r,
> > > > > > > > > > > +obj,
> > > > > > > esize, n,
> > > > > > > > > > > +			NULL);
> > > > > > > > > > > +}
> > > > > > > > > > > +
> > > > > > > > > > > +static unsigned int test_ring_deq_impl(struct
> > > > > > > > > > > +rte_ring *r, void **obj, int esize, unsigned
> > > > > > > int n,
> > > > > > > > > > > +	unsigned int test_idx) {
> > > > > > > > > > > +	if (esize == -1)
> > > > > > > > > > > +		return
> test_enqdeq_impl[test_idx].deq.flegacy(r,
> > > > > > > > > > > +obj,
> > > > > > > n, NULL);
> > > > > > > > > > > +	else
> > > > > > > > > > > +		return
> test_enqdeq_impl[test_idx].deq.felem(r,
> > > > > > > > > > > +obj,
> > > > > > > esize, n,
> > > > > > > > > > > +			NULL);
> > > > > > > > > > > +}
> > > > > > > > > > > +
> > > > > > > > > > >  static void**
> > > > > > > > > > >  test_ring_inc_ptr(void **obj, int esize, unsigned
> > > > > > > > > > > int
> > > > > > > > > > > n)  { @@
> > > > > > > > > > > -203,8 +378,7 @@ test_ring_negative_tests(void)
> > > > > > > > > > >   * Random number of elements are enqueued and
> dequeued.
> > > > > > > > > > >   */
> > > > > > > > > > >  static int
> > > > > > > > > > > -test_ring_burst_bulk_tests1(unsigned int api_type,
> > > > > > > > > > > unsigned int
> > > > > > > > > create_flags,
> > > > > > > > > > > -	const char *tname)
> > > > > > > > > > > +test_ring_burst_bulk_tests1(unsigned int test_idx)
> > > > > > > > > > >  {
> > > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > > > **cur_dst = NULL; @@ -214,11 +388,13 @@
> > > > > > > test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > >  	const unsigned int rsz = RING_SIZE - 1;
> > > > > > > > > > >
> > > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > > -		test_ring_print_test_string(tname, api_type,
> esize[i]);
> > > > > > > > > > > +
> > > > > > >
> > > > > > > test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type,
> esize[i]);
> > > > > > > > > > >
> > > > > > > > > > >  		/* Create the ring */
> > > > > > > > > > >  		r =
> > > > > > > > > > > test_ring_create("test_ring_burst_bulk_tests",
> > > > > esize[i],
> > > > > > > > > > > -					RING_SIZE,
> SOCKET_ID_ANY,
> > > > > > > > > > > create_flags);
> > > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > > +
> > > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > > >
> > > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]);
> > > > > > > > > > > @@
> > > > > > > > > > > -240,17
> > > > > > > > > > > +416,17 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > > create_flags,
> > > > > > > > > > >  			rand = RTE_MAX(rte_rand() %
> RING_SIZE,
> > > > > 1UL);
> > > > > > > > > > >  			printf("%s: iteration %u, random
> shift: %u;\n",
> > > > > > > > > > >  			    __func__, i, rand);
> > > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src,
> esize[i],
> > > > > > > rand,
> > > > > > > > > > > -
> 	api_type);
> > > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src,
> esize[i],
> > > > > > > rand,
> > > > > > > > > > > +
> 	test_idx);
> > > > > > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > > > > > >
> > > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst,
> esize[i],
> > > > > > > rand,
> > > > > > > > > > > -
> 	api_type);
> > > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst,
> esize[i],
> > > > > > > rand,
> > > > > > > > > > > +
> 	test_idx);
> > > > > > > > > > >  			TEST_RING_VERIFY(ret == rand);
> > > > > > > > > > >
> > > > > > > > > > >  			/* fill the ring */
> > > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src,
> esize[i],
> > > rsz,
> > > > > > > > > > > -
> 	api_type);
> > > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src,
> esize[i],
> > > > > > > rsz,
> > > > > > > > > > > +
> 	test_idx);
> > > > > > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > > > > > >
> > > > > > > > > > >
> 	TEST_RING_VERIFY(rte_ring_free_count(r) ==
> > > > > 0); @@
> > > > > > > > > > > -259,8 +435,8 @@
> > > > > > > > > > > test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > >  			TEST_RING_VERIFY(rte_ring_empty(r)
> == 0);
> > > > > > > > > > >
> > > > > > > > > > >  			/* empty the ring */
> > > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst,
> esize[i],
> > > rsz,
> > > > > > > > > > > -
> 	api_type);
> > > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst,
> esize[i],
> > > > > > > rsz,
> > > > > > > > > > > +
> 	test_idx);
> > > > > > > > > > >  			TEST_RING_VERIFY(ret == (int)rsz);
> > > > > > > > > > >  			TEST_RING_VERIFY(rsz ==
> > > > > rte_ring_free_count(r));
> > > > > > > > > > >  			TEST_RING_VERIFY(rte_ring_count(r)
> == 0);
> > > > > @@ -
> > > > > > > > > > > 294,8 +470,7 @@ test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > >   * dequeued data.
> > > > > > > > > > >   */
> > > > > > > > > > >  static int
> > > > > > > > > > > -test_ring_burst_bulk_tests2(unsigned int api_type,
> > > > > > > > > > > unsigned int
> > > > > > > > > create_flags,
> > > > > > > > > > > -	const char *tname)
> > > > > > > > > > > +test_ring_burst_bulk_tests2(unsigned int test_idx)
> > > > > > > > > > >  {
> > > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > > > **cur_dst = NULL; @@ -303,11 +478,13 @@
> > > > > > > test_ring_burst_bulk_tests2(unsigned
> > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > >  	unsigned int i;
> > > > > > > > > > >
> > > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > > -		test_ring_print_test_string(tname, api_type,
> esize[i]);
> > > > > > > > > > > +
> > > > > > >
> > > > > > > test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type,
> esize[i]);
> > > > > > > > > > >
> > > > > > > > > > >  		/* Create the ring */
> > > > > > > > > > >  		r =
> > > > > > > > > > > test_ring_create("test_ring_burst_bulk_tests",
> > > > > esize[i],
> > > > > > > > > > > -					RING_SIZE,
> SOCKET_ID_ANY,
> > > > > > > > > > > create_flags);
> > > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > > +
> > > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > > >
> > > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]);
> > > > > > > > > > > @@
> > > > > > > > > > > -323,39
> > > > > > > > > > > +500,39 @@ test_ring_burst_bulk_tests2(unsigned int
> > > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > > create_flags,
> > > > > > > > > > >  		cur_dst = dst;
> > > > > > > > > > >
> > > > > > > > > > >  		printf("enqueue 1 obj\n");
> > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 1,
> > > > > > > api_type);
> > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 1,
> > > > > > > test_idx);
> > > > > > > > > > >  		if (ret != 1)
> > > > > > > > > > >  			goto fail;
> > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > > > > > > > 1);
> > > > > > > > > > >
> > > > > > > > > > >  		printf("enqueue 2 objs\n");
> > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > > > > > api_type);
> > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > > > > > > test_idx);
> > > > > > > > > > >  		if (ret != 2)
> > > > > > > > > > >  			goto fail;
> > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > > > > > > > 2);
> > > > > > > > > > >
> > > > > > > > > > >  		printf("enqueue MAX_BULK objs\n");
> > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > > > > > -						api_type);
> > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > > > > > +						test_idx);
> > > > > > > > > > >  		if (ret != MAX_BULK)
> > > > > > > > > > >  			goto fail;
> > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > MAX_BULK);
> > > > > > > > > > >
> > > > > > > > > > >  		printf("dequeue 1 obj\n");
> > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1,
> > > > > > > api_type);
> > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1,
> > > > > > > test_idx);
> > > > > > > > > > >  		if (ret != 1)
> > > > > > > > > > >  			goto fail;
> > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > > > > > > > > 1);
> > > > > > > > > > >
> > > > > > > > > > >  		printf("dequeue 2 objs\n");
> > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > > > > > api_type);
> > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > > > > > > test_idx);
> > > > > > > > > > >  		if (ret != 2)
> > > > > > > > > > >  			goto fail;
> > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > > > > > > > > 2);
> > > > > > > > > > >
> > > > > > > > > > >  		printf("dequeue MAX_BULK objs\n");
> > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > > > > > -						api_type);
> > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > > > > > +						test_idx);
> > > > > > > > > > >  		if (ret != MAX_BULK)
> > > > > > > > > > >  			goto fail;
> > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > > MAX_BULK);
> > > > > > > > > > > @@
> > > > > > > > > > > -390,8 +567,7 @@
> > > > > > > > > > > test_ring_burst_bulk_tests2(unsigned
> > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > >   * Enqueue and dequeue to cover the entire ring length.
> > > > > > > > > > >   */
> > > > > > > > > > >  static int
> > > > > > > > > > > -test_ring_burst_bulk_tests3(unsigned int api_type,
> > > > > > > > > > > unsigned int
> > > > > > > > > create_flags,
> > > > > > > > > > > -	const char *tname)
> > > > > > > > > > > +test_ring_burst_bulk_tests3(unsigned int test_idx)
> > > > > > > > > > >  {
> > > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > > > **cur_dst = NULL; @@ -399,11 +575,13 @@
> > > > > > > test_ring_burst_bulk_tests3(unsigned
> > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > >  	unsigned int i, j;
> > > > > > > > > > >
> > > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > > -		test_ring_print_test_string(tname, api_type,
> esize[i]);
> > > > > > > > > > > +
> > > > > > >
> > > > > > > test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type,
> esize[i]);
> > > > > > > > > > >
> > > > > > > > > > >  		/* Create the ring */
> > > > > > > > > > >  		r =
> > > > > > > > > > > test_ring_create("test_ring_burst_bulk_tests",
> > > > > esize[i],
> > > > > > > > > > > -					RING_SIZE,
> SOCKET_ID_ANY,
> > > > > > > > > > > create_flags);
> > > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > > +
> > > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > > >
> > > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]);
> > > > > > > > > > > @@
> > > > > > > > > > > -420,15
> > > > > > > > > > > +598,15 @@ test_ring_burst_bulk_tests3(unsigned int
> > > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > > create_flags,
> > > > > > > > > > >
> > > > > > > > > > >  		printf("fill and empty the ring\n");
> > > > > > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> > > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src,
> esize[i],
> > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > -
> 	api_type);
> > > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src,
> esize[i],
> > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > +
> 	test_idx);
> > > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > > >  				goto fail;
> > > > > > > > > > >  			cur_src = test_ring_inc_ptr(cur_src,
> esize[i],
> > > > > > > > > > >
> > > > > 	MAX_BULK);
> > > > > > > > > > >
> > > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst,
> esize[i],
> > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > -
> 	api_type);
> > > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst,
> esize[i],
> > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > +
> 	test_idx);
> > > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > > >  				goto fail;
> > > > > > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst,
> esize[i],
> > > > > @@ -
> > > > > > > > > > > 465,21 +643,24 @@
> > > > > > > > > > > test_ring_burst_bulk_tests3(unsigned
> > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > >   * Enqueue till the ring is full and dequeue till
> > > > > > > > > > > the ring becomes
> > > > > empty.
> > > > > > > > > > >   */
> > > > > > > > > > >  static int
> > > > > > > > > > > -test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > > > > > > > unsigned int
> > > > > > > > > create_flags,
> > > > > > > > > > > -	const char *tname)
> > > > > > > > > > > +test_ring_burst_bulk_tests4(unsigned int test_idx)
> > > > > > > > > > >  {
> > > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > > > **cur_dst
> > > > > = NULL;
> > > > > > > > > > >  	int ret;
> > > > > > > > > > >  	unsigned int i, j;
> > > > > > > > > > > -	unsigned int num_elems;
> > > > > > > > > > > +	unsigned int api_type, num_elems;
> > > > > > > > > > > +
> > > > > > > > > > > +	api_type = test_enqdeq_impl[test_idx].api_type;
> > > > > > > > > > >
> > > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > > -		test_ring_print_test_string(tname, api_type,
> esize[i]);
> > > > > > > > > > > +
> > > > > > >
> > > > > > > test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type,
> esize[i]);
> > > > > > > > > > >
> > > > > > > > > > >  		/* Create the ring */
> > > > > > > > > > >  		r =
> > > > > > > > > > > test_ring_create("test_ring_burst_bulk_tests",
> > > > > esize[i],
> > > > > > > > > > > -					RING_SIZE,
> SOCKET_ID_ANY,
> > > > > > > > > > > create_flags);
> > > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > > +
> > > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > > >
> > > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]);
> > > > > > > > > > > @@
> > > > > > > > > > > -496,8
> > > > > > > > > > > +677,8 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > > create_flags,
> > > > > > > > > > >
> > > > > > > > > > >  		printf("Test enqueue without enough memory
> > > > > space\n");
> > > > > > > > > > >  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++)
> {
> > > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src,
> esize[i],
> > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > -
> 	api_type);
> > > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src,
> esize[i],
> > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > +
> 	test_idx);
> > > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > > >  				goto fail;
> > > > > > > > > > >  			cur_src = test_ring_inc_ptr(cur_src,
> esize[i],
> > > > > @@ -
> > > > > > > > > > > 505,7 +686,7 @@ test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > >  		}
> > > > > > > > > > >
> > > > > > > > > > >  		printf("Enqueue 2 objects, free entries =
> > > > > > > > > > > MAX_BULK -
> > > > > 2\n");
> > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > > > > > api_type);
> > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > > > > > > test_idx);
> > > > > > > > > > >  		if (ret != 2)
> > > > > > > > > > >  			goto fail;
> > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > > > > > > > 2); @@
> > > > > > > > > > > -517,8
> > > > > > > > > > > +698,8 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > > create_flags,
> > > > > > > > > > >  		else
> > > > > > > > > > >  			num_elems = MAX_BULK;
> > > > > > > > > > >  		/* Always one free entry left */
> > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > num_elems,
> > > > > > > > > > > -						api_type);
> > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > num_elems,
> > > > > > > > > > > +						test_idx);
> > > > > > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > > > > > >  			goto fail;
> > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > MAX_BULK -
> > > > > > > > > > > 3);
> > > > > > > > > @@
> > > > > > > > > > > -528,15 +709,15 @@
> > > > > > > > > > > test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > >  			goto fail;
> > > > > > > > > > >
> > > > > > > > > > >  		printf("Test enqueue for a full entry\n");
> > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > > > > > -						api_type);
> > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > MAX_BULK,
> > > > > > > > > > > +						test_idx);
> > > > > > > > > > >  		if (ret != 0)
> > > > > > > > > > >  			goto fail;
> > > > > > > > > > >
> > > > > > > > > > >  		printf("Test dequeue without enough
> objects\n");
> > > > > > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> > > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst,
> esize[i],
> > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > -
> 	api_type);
> > > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst,
> esize[i],
> > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > +
> 	test_idx);
> > > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > > >  				goto fail;
> > > > > > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst,
> esize[i],
> > > > > @@ -
> > > > > > > > > > > 544,7 +725,7 @@ test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > >  		}
> > > > > > > > > > >
> > > > > > > > > > >  		/* Available memory space for the exact
> MAX_BULK
> > > > > entries
> > > > > > > > > */
> > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > > > > > api_type);
> > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > > > > > > test_idx);
> > > > > > > > > > >  		if (ret != 2)
> > > > > > > > > > >  			goto fail;
> > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > > > > > > > > 2); @@
> > > > > > > > > > > -554,8
> > > > > > > > > > > +735,8 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > > create_flags,
> > > > > > > > > > >  			num_elems = MAX_BULK - 3;
> > > > > > > > > > >  		else
> > > > > > > > > > >  			num_elems = MAX_BULK;
> > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > num_elems,
> > > > > > > > > > > -						api_type);
> > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > > num_elems,
> > > > > > > > > > > +						test_idx);
> > > > > > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > > > > > >  			goto fail;
> > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > > MAX_BULK -
> > > > > > > > > > > 3);
> > > > > > > > > @@
> > > > > > > > > > > -816,22 +997,7 @@ static int
> > > > > > > > > > >  test_ring(void)
> > > > > > > > > > >  {
> > > > > > > > > > >  	int32_t rc;
> > > > > > > > > > > -	unsigned int i, j;
> > > > > > > > > > > -	const char *tname;
> > > > > > > > > > > -
> > > > > > > > > > > -	static const struct {
> > > > > > > > > > > -		uint32_t create_flags;
> > > > > > > > > > > -		const char *name;
> > > > > > > > > > > -	} test_sync_modes[] = {
> > > > > > > > > > > -		{
> > > > > > > > > > > -			RING_F_MP_RTS_ENQ |
> > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > > > -			"Test MT_RTS ring",
> > > > > > > > > > > -		},
> > > > > > > > > > > -		{
> > > > > > > > > > > -			RING_F_MP_HTS_ENQ |
> > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > > > -			"Test MT_HTS ring",
> > > > > > > > > > > -		},
> > > > > > > > > > > -	};
> > > > > > > > > > > +	unsigned int i;
> > > > > > > > > > >
> > > > > > > > > > >  	/* Negative test cases */
> > > > > > > > > > >  	if (test_ring_negative_tests() < 0) @@ -848,65
> > > > > > > > > > > +1014,24 @@
> > > > > > > > > > > test_ring(void)
> > > > > > > > > > >  	 * The test cases are split into smaller test cases to
> > > > > > > > > > >  	 * help clang compile faster.
> > > > > > > > > > >  	 */
> > > > > > > > > > > -	tname = "Test standard ring";
> > > > > > > > > > > -
> > > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > > TEST_RING_ELEM_BURST;
> > > > > > > j <<= 1)
> > > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > > -					i <=
> > > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > > <<= 1)
> > > > > > > > > > > -			if (test_ring_burst_bulk_tests1(i | j, 0,
> tname)
> > > > > > > < 0)
> > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > -
> > > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > > TEST_RING_ELEM_BURST;
> > > > > > > j <<= 1)
> > > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > > -					i <=
> > > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > > <<= 1)
> > > > > > > > > > > -			if (test_ring_burst_bulk_tests2(i | j, 0,
> tname)
> > > > > > > < 0)
> > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > -
> > > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > > TEST_RING_ELEM_BURST;
> > > > > > > j <<= 1)
> > > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > > -					i <=
> > > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > > <<= 1)
> > > > > > > > > > > -			if (test_ring_burst_bulk_tests3(i | j, 0,
> tname)
> > > > > > > < 0)
> > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > -
> > > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > > TEST_RING_ELEM_BURST;
> > > > > > > j <<= 1)
> > > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > > -					i <=
> > > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > > <<= 1)
> > > > > > > > > > > -			if (test_ring_burst_bulk_tests4(i | j, 0,
> tname)
> > > > > > > < 0)
> > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > -
> > > > > > > > > > > -	/* Burst and bulk operations with MT_RTS and
> MT_HTS sync
> > > > > > > modes
> > > > > > > > > > > */
> > > > > > > > > > > -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> > > > > > > > > > > -		for (j = TEST_RING_ELEM_BULK; j <=
> > > > > > > TEST_RING_ELEM_BURST;
> > > > > > > > > > > -				j <<= 1) {
> > > > > > > > > > > -
> > > > > > > > > > > -			rc = test_ring_burst_bulk_tests1(
> > > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > > -
> 	test_sync_modes[i].create_flags,
> > > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > -
> > > > > > > > > > > -			rc = test_ring_burst_bulk_tests2(
> > > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > > -
> 	test_sync_modes[i].create_flags,
> > > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > -
> > > > > > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > > -
> 	test_sync_modes[i].create_flags,
> > > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > -
> > > > > > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > > -
> 	test_sync_modes[i].create_flags,
> > > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > -		}
> > > > > > > > > > > +	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
> > > > > > > > > > > +
> > > > > > > > > > > +
> > > > > > > > > > > +		rc = test_ring_burst_bulk_tests1(i);
> > > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > > +			goto test_fail;
> > > > > > > > > > > +
> > > > > > > > > > > +		rc = test_ring_burst_bulk_tests2(i);
> > > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > > +			goto test_fail;
> > > > > > > > > > > +
> > > > > > > > > > > +		rc = test_ring_burst_bulk_tests3(i);
> > > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > > +			goto test_fail;
> > > > > > > > > > > +
> > > > > > > > > > > +		rc = test_ring_burst_bulk_tests4(i);
> > > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > > +			goto test_fail;
> > > > > > > > > > >  	}
> > > > > > > > > > >
> > > > > > > > > > >  	/* dump the ring status */
> > > > > > > > > > > --
> > > > > > > > > > > 2.17.1
Ananyev, Konstantin May 11, 2020, 11:35 a.m. UTC | #15
> > > > > > > > > >
> > > > > > > > > > > Hi Konstantin,
> > > > > > > > > > > 	I like the way the tests are organized and it looks
> > good.
> > > > > > > > > > >
> > > > > > > > > > > I am just wondering about the way it is being tested here.
> > > > > > > > > > > The intent to write the test cases the way they are
> > > > > > > > > > > currently is to mimic how the APIs would be used mostly.
> > > > > > > > > > > IMO, the APIs would be used with a constant
> > > > > > > > > > value for element size so that the compiler will throw
> > > > > > > > > > away the unwanted code (in the functions where the
> > > > > > > > > > actual copy is being
> > > > done).
> > > > > > > > > > >
> > > > > > > > > > > With your method here, it looks to me like all the
> > > > > > > > > > > branches in the copy
> > > > > > > > > > functions are kept and the branch decisions are done at run
> > time.
> > > > > > > > > > > Is  my understanding correct?
> > > > > > > > > >
> > > > > > > > > > You mean branching on esize[] values?
> > > > > > > > > Yes
> > > I was wondering where is the confusion. I interpreted as referring to
> > > the esize parameter in rte_ring_xxx_elem APIs. Anyway, please see below.
> > >
> > > > > > > > >
> > > > > > > > > > Actually from what I've seen that happens for both cases:
> > > > > > > > > > before and after the patch (gcc 7.3 -O3).
> > > > > > > > > I did not look at the generated code. If it is happening
> > > > > > > > > with your patch too, I
> > > > > > > > think we can go with your patch.
> > > > > > > >
> > > > > > > > Just to clarify, what I meant:
> > > > > > > > For both binaries (without the patch and with the patch)
> > > > > > > > inside
> > > > > > > > test_ring() I see runtime branches on esize value.
> > > > > > > > Literally the code that corresponds to:
> > > > > > > > if (esize == 8) {...}
> > > > > > > > else if (esize == 16) {...}
> > > > > > > > else {...}
> > > > > I am not concerned about the functions in test_ring.c.
> > > > >
> > > > > > > Do you see this in the actual ring library functions?
> > > > > >
> > > > > > Which ones? AFAIK all ring dequeue/enqueue functions are inline
> > > > > > right
> > > > now.
> > > > > Please see below.
> > > > >
> > > > > >
> > > > > > > I want to make sure that the library functions
> > > > > > > '__rte_ring_enqueue_elems' and '__rte_ring_dequeue_elems' are
> > > > optimized.
> > > > > Each enqueue/dequeue function ultimately calls these 2 functions.
> > > >
> > > > Yes, and then each instance of enqueue/dequeue functions that is
> > > > used by upper layer would be in-lined.
> > > > So what upper layer function (library or app) you asked me to check?
> > > I am not bothered much about upper layer functions. I looked at the
> > generate code for the function __rte_ring_enqueue_elems.
> > > Existing code has the if checks for 8 and 16.
> > > Your patch also has the checks.
> > > My patch does not have the checks as it passes the constants directly
> > without using esize[] array in functions test_ring_burst_bulk_tests4.
> >
> > For test_burst_bulk_test[1-4] - yes, for other test functions it is still there.
> Agree. This should give coverage for some at least.
> 
> > Though I don't think it is that important for functional test cases.
> > Anyway, I think we dragged away a bit in our discussion, so with what patch
> > should we go ahead?
> Agree, we dragged it. I tried to merge both the solutions (use your patch and constant esize), I was not successful. My guess, function
> pointers are not allowing for the optimization.

I think it can be done pretty easily by replacing loop over esize[],
with particular constant value in each of  test_ring_burst_bulk_tests[1-4]
functions. I.E:

test_ring_burst_bulk_tests2(unsigned int test_idx)
        struct rte_ring *r;
        void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
        int ret;
-       unsigned int i;
-
-       for (i = 0; i < RTE_DIM(esize); i++) {
-               test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
-                       test_enqdeq_impl[test_idx].api_type, esize[i]);
....

+       const int elem_size = 4;
+
+       test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
+               test_enqdeq_impl[test_idx].api_type, elem_size);

I just not very fond of idea to reduce number of test-cases,
just because compiler wasn't able to do some optimizations
we hoped it would.  

> 
> > My preference is 69559, as it compiles faster and doesn't reduce test
> > coverage, but I can live with both.
> test_burst_bulk_test[1-4] more or less call the same APIs. Spreading the size variation across four of them should be ok. It will test the way
> it will be used.
> 
> > Konstantin
> >
> > >
> > > >
> > > > > The compiler here should remove the 'if (esize == 8) {...} else if
> > > > > (esize ==
> > > > > 16) {...} else {...}' with just the required piece of code
> > > > > depending on the
> > > > 'esize'.
> > > > > If we can validate that for at least one ring library function
> > > > > used in this patch, we should be good.
> > > > >
> > > > > > >
> > > > > > > >
> > > > > > > > Probably gcc wasn't able to remove it because we use esize[]
> > > > > > > > instead of hard- coded values, might be there is some other
> > > > > > > > reason, I don't know
> > > > > > for sure.
> > > > > > > > As it is a functional (not performance) test, I didn't dig further.
> > > > > > > The esize[] array is declared as a const. The compiler should
> > > > > > > be able to see
> > > > > > that it is a compile time constant.
> > > > > >
> > > > > > That was my expectation too, but that not what I am seeing.
> > > > > >
> > > > > > > >
> > > > > > > > > But, can you do similar
> > > > > > > > > change to test_ring_perf.c to keep it consistent?
> > > > > > > >
> > > > > > > > In principle it is doable, but needs extra care.
> > > > > > > > We need to make sure that compiler will be able to inline
> > > > > > > > functions via pointers.
> > > > > > > > AFAIK, gcc does that with -O3', but not with '-O2'.
> > > > > > > If the unwanted code is not removed during compilation, we
> > > > > > > will see it
> > > > > > affect the performance numbers.
> > > > > >
> > > > > > Exactly.
> > > > > > The last thing I want - someone who uses older version of
> > > > > > compiler, etc., will start to see lower performance numbers with that
> > test.
> > > > > >
> > > > > > > > Don't know what the story with clang and different versions
> > > > > > > > of the
> > > > > > compiler.
> > > > > > > > Is there any real need for that?
> > > > > > > > On my box test_ring_perf.c compilation takes ~8s.
> > > > > > > > Konstantin
> > > > > > > >
> > > > > > > >
> > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > Main intention in my changes was to avoid using
> > > > > > > > > > test_ring_enqueue/test_ring_dequeue,
> > > > > > > > > > as it seems too many branches here and it takes compiler
> > > > > > > > > > a lot of effort to resolve all of them at compile time.
> > > > > > > > > > So I replaced it with  array of function pointers
> > > > > > > > > > (test_enqdeq_impl[]) and iterating over it.
> > > > > > > > > > That way compiler knows straightway which function to use.
> > > > > > > > > >
> > > > > > > > > > > Can you please check this?
> > > > > > > > > > > https://patches.dpdk.org/patch/69567/
> > > > > > > > > >
> > > > > > > > > > As I can see your approach reduces number of test-cases
> > > > > > > > > > by factor
> > > > of 5:
> > > > > > > > > > now each of test_ring_burst_bulk_tests[1-4] is executed
> > > > > > > > > > only with just one esize value, correct?
> > > > > > > > > Yes, basically test_ring_burst_bulk_tests[1-4] were
> > > > > > > > > covering different scenarios with the same APIs. So,
> > > > > > > > > distributed the esize across different test
> > > > > > > > functions.
> > > > > > > > >
> > > > > > > > > > In term of compilation speed - it helps.
> > > > > > > > > > On my box with (gcc 7.3 -O3)  compiling test_ring.c takes:
> > > > > > > > > > orig code:                             ~100s
> > > > > > > > > > with 69567 (your patch):  < 20s
> > > > > > > > > > with 69559 (my patch):    < 10s
> > > > > > > > > >
> > > > > > > > > > Konstantin
> > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > From: Konstantin Ananyev
> > > > > > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > > > > > Sent: Wednesday, April 29, 2020 12:57 PM
> > > > > > > > > > > > To: dev@dpdk.org
> > > > > > > > > > > > Cc: aconole@redhat.com; Honnappa Nagarahalli
> > > > > > > > > > > > <Honnappa.Nagarahalli@arm.com>; Konstantin Ananyev
> > > > > > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > > > > > Subject: [PATCH] test/ring: code rework to reduce
> > > > > > > > > > > > compilation time
> > > > > > > > > > > >
> > > > > > > > > > > > Rework test code to reduce code complexity for the
> > > > > > > > > > > > compiler and bring down compilation time and memory
> > > > consumption.
> > > > > > > > > > > >
> > > > > > > > > > > > Signed-off-by: Konstantin Ananyev
> > > > > > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > > > > > ---
> > > > > > > > > > > >  app/test/test_ring.c | 373
> > > > > > > > > > > > +++++++++++++++++++++++++++++--------------
> > > > > > > > > > > >  1 file changed, 249 insertions(+), 124 deletions(-)
> > > > > > > > > > > >
> > > > > > > > > > > > diff --git a/app/test/test_ring.c
> > > > > > > > > > > > b/app/test/test_ring.c index
> > > > > > > > > > > > e21557cd9..0ae97d341 100644
> > > > > > > > > > > > --- a/app/test/test_ring.c
> > > > > > > > > > > > +++ b/app/test/test_ring.c
> > > > > > > > > > > > @@ -58,6 +58,181 @@
> > > > > > > > > > > >
> > > > > > > > > > > >  static const int esize[] = {-1, 4, 8, 16, 20};
> > > > > > > > > > > >
> > > > > > > > > > > > +static const struct {
> > > > > > > > > > > > +	const char *desc;
> > > > > > > > > > > > +	uint32_t api_type;
> > > > > > > > > > > > +	uint32_t create_flags;
> > > > > > > > > > > > +	struct {
> > > > > > > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > > > > > > +			void * const *obj_table, unsigned int
> > n,
> > > > > > > > > > > > +			unsigned int *free_space);
> > > > > > > > > > > > +		unsigned int (*felem)(struct rte_ring *r, const
> > > > > > > > > > > > +void
> > > > > > > > *obj_table,
> > > > > > > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > > > > > > +			unsigned int *free_space);
> > > > > > > > > > > > +	} enq;
> > > > > > > > > > > > +	struct {
> > > > > > > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > > > > > > +			void **obj_table, unsigned int n,
> > > > > > > > > > > > +			unsigned int *available);
> > > > > > > > > > > > +		unsigned int (*felem)(struct rte_ring *r, void
> > > > > > > > *obj_table,
> > > > > > > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > > > > > > +			unsigned int *available);
> > > > > > > > > > > > +	} deq;
> > > > > > > > > > > > +} test_enqdeq_impl[] = {
> > > > > > > > > > > > +	{
> > > > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > > Details about the tests are already printed by the
> > > > > > > > > > > function
> > > > > > > > > > 'test_ring_print_test_string'. This string should be
> > > > > > > > > > 'Test standard
> > > > ring'.
> > > > > > > > > > >
> > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +	},
> > > > > > > > > > > > +	{
> > > > > > > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > > > > > > +		.create_flags = RING_F_SP_ENQ |
> > RING_F_SC_DEQ,
> > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_sp_enqueue_bulk,
> > > > > > > > > > > > +			.felem =
> > rte_ring_sp_enqueue_bulk_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_sc_dequeue_bulk,
> > > > > > > > > > > > +			.felem =
> > rte_ring_sc_dequeue_bulk_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +	},
> > > > > > > > > > > > +	{
> > > > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_mp_enqueue_bulk,
> > > > > > > > > > > > +			.felem =
> > rte_ring_mp_enqueue_bulk_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_mc_dequeue_bulk,
> > > > > > > > > > > > +			.felem =
> > rte_ring_mc_dequeue_bulk_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +	},
> > > > > > > > > > > > +	{
> > > > > > > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +	},
> > > > > > > > > > > > +	{
> > > > > > > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +	},
> > > > > > > > > > > > +	{
> > > > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > > > > +			.felem =
> > rte_ring_enqueue_burst_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > > > > +			.felem =
> > rte_ring_dequeue_burst_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +	},
> > > > > > > > > > > > +	{
> > > > > > > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > > > > > > +		.create_flags = RING_F_SP_ENQ |
> > RING_F_SC_DEQ,
> > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_sp_enqueue_burst,
> > > > > > > > > > > > +			.felem =
> > rte_ring_sp_enqueue_burst_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_sc_dequeue_burst,
> > > > > > > > > > > > +			.felem =
> > rte_ring_sc_dequeue_burst_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +	},
> > > > > > > > > > > > +	{
> > > > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > +			.flegacy =
> > rte_ring_mp_enqueue_burst,
> > > > > > > > > > > > +			.felem =
> > rte_ring_mp_enqueue_burst_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > +			.flegacy =
> > rte_ring_mc_dequeue_burst,
> > > > > > > > > > > > +			.felem =
> > rte_ring_mc_dequeue_burst_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +	},
> > > > > > > > > > > > +	{
> > > > > > > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > > > > +			.felem =
> > rte_ring_enqueue_burst_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > > > > +			.felem =
> > rte_ring_dequeue_burst_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +	},
> > > > > > > > > > > > +	{
> > > > > > > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > > > > +			.felem =
> > rte_ring_enqueue_burst_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > > > > +			.felem =
> > rte_ring_dequeue_burst_elem,
> > > > > > > > > > > > +		},
> > > > > > > > > > > > +	},
> > > > > > > > > > > > +};
> > > > > > > > > > > > +
> > > > > > > > > > > > +static unsigned int test_ring_enq_impl(struct
> > > > > > > > > > > > +rte_ring *r, void **obj, int esize, unsigned
> > > > > > > > int n,
> > > > > > > > > > > > +	unsigned int test_idx) {
> > > > > > > > > > > > +	if (esize == -1)
> > > > > > > > > > > > +		return
> > test_enqdeq_impl[test_idx].enq.flegacy(r,
> > > > > > > > > > > > +obj,
> > > > > > > > n, NULL);
> > > > > > > > > > > > +	else
> > > > > > > > > > > > +		return
> > test_enqdeq_impl[test_idx].enq.felem(r,
> > > > > > > > > > > > +obj,
> > > > > > > > esize, n,
> > > > > > > > > > > > +			NULL);
> > > > > > > > > > > > +}
> > > > > > > > > > > > +
> > > > > > > > > > > > +static unsigned int test_ring_deq_impl(struct
> > > > > > > > > > > > +rte_ring *r, void **obj, int esize, unsigned
> > > > > > > > int n,
> > > > > > > > > > > > +	unsigned int test_idx) {
> > > > > > > > > > > > +	if (esize == -1)
> > > > > > > > > > > > +		return
> > test_enqdeq_impl[test_idx].deq.flegacy(r,
> > > > > > > > > > > > +obj,
> > > > > > > > n, NULL);
> > > > > > > > > > > > +	else
> > > > > > > > > > > > +		return
> > test_enqdeq_impl[test_idx].deq.felem(r,
> > > > > > > > > > > > +obj,
> > > > > > > > esize, n,
> > > > > > > > > > > > +			NULL);
> > > > > > > > > > > > +}
> > > > > > > > > > > > +
> > > > > > > > > > > >  static void**
> > > > > > > > > > > >  test_ring_inc_ptr(void **obj, int esize, unsigned
> > > > > > > > > > > > int
> > > > > > > > > > > > n)  { @@
> > > > > > > > > > > > -203,8 +378,7 @@ test_ring_negative_tests(void)
> > > > > > > > > > > >   * Random number of elements are enqueued and
> > dequeued.
> > > > > > > > > > > >   */
> > > > > > > > > > > >  static int
> > > > > > > > > > > > -test_ring_burst_bulk_tests1(unsigned int api_type,
> > > > > > > > > > > > unsigned int
> > > > > > > > > > create_flags,
> > > > > > > > > > > > -	const char *tname)
> > > > > > > > > > > > +test_ring_burst_bulk_tests1(unsigned int test_idx)
> > > > > > > > > > > >  {
> > > > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > > > > **cur_dst = NULL; @@ -214,11 +388,13 @@
> > > > > > > > test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > >  	const unsigned int rsz = RING_SIZE - 1;
> > > > > > > > > > > >
> > > > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > > > -		test_ring_print_test_string(tname, api_type,
> > esize[i]);
> > > > > > > > > > > > +
> > > > > > > >
> > > > > > > > test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type,
> > esize[i]);
> > > > > > > > > > > >
> > > > > > > > > > > >  		/* Create the ring */
> > > > > > > > > > > >  		r =
> > > > > > > > > > > > test_ring_create("test_ring_burst_bulk_tests",
> > > > > > esize[i],
> > > > > > > > > > > > -					RING_SIZE,
> > SOCKET_ID_ANY,
> > > > > > > > > > > > create_flags);
> > > > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > > > +
> > > > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > > > >
> > > > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]);
> > > > > > > > > > > > @@
> > > > > > > > > > > > -240,17
> > > > > > > > > > > > +416,17 @@ test_ring_burst_bulk_tests1(unsigned int
> > > > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > > > create_flags,
> > > > > > > > > > > >  			rand = RTE_MAX(rte_rand() %
> > RING_SIZE,
> > > > > > 1UL);
> > > > > > > > > > > >  			printf("%s: iteration %u, random
> > shift: %u;\n",
> > > > > > > > > > > >  			    __func__, i, rand);
> > > > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src,
> > esize[i],
> > > > > > > > rand,
> > > > > > > > > > > > -
> > 	api_type);
> > > > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src,
> > esize[i],
> > > > > > > > rand,
> > > > > > > > > > > > +
> > 	test_idx);
> > > > > > > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > > > > > > >
> > > > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst,
> > esize[i],
> > > > > > > > rand,
> > > > > > > > > > > > -
> > 	api_type);
> > > > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst,
> > esize[i],
> > > > > > > > rand,
> > > > > > > > > > > > +
> > 	test_idx);
> > > > > > > > > > > >  			TEST_RING_VERIFY(ret == rand);
> > > > > > > > > > > >
> > > > > > > > > > > >  			/* fill the ring */
> > > > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src,
> > esize[i],
> > > > rsz,
> > > > > > > > > > > > -
> > 	api_type);
> > > > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src,
> > esize[i],
> > > > > > > > rsz,
> > > > > > > > > > > > +
> > 	test_idx);
> > > > > > > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > > > > > > >
> > > > > > > > > > > >
> > 	TEST_RING_VERIFY(rte_ring_free_count(r) ==
> > > > > > 0); @@
> > > > > > > > > > > > -259,8 +435,8 @@
> > > > > > > > > > > > test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > >  			TEST_RING_VERIFY(rte_ring_empty(r)
> > == 0);
> > > > > > > > > > > >
> > > > > > > > > > > >  			/* empty the ring */
> > > > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst,
> > esize[i],
> > > > rsz,
> > > > > > > > > > > > -
> > 	api_type);
> > > > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst,
> > esize[i],
> > > > > > > > rsz,
> > > > > > > > > > > > +
> > 	test_idx);
> > > > > > > > > > > >  			TEST_RING_VERIFY(ret == (int)rsz);
> > > > > > > > > > > >  			TEST_RING_VERIFY(rsz ==
> > > > > > rte_ring_free_count(r));
> > > > > > > > > > > >  			TEST_RING_VERIFY(rte_ring_count(r)
> > == 0);
> > > > > > @@ -
> > > > > > > > > > > > 294,8 +470,7 @@ test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > >   * dequeued data.
> > > > > > > > > > > >   */
> > > > > > > > > > > >  static int
> > > > > > > > > > > > -test_ring_burst_bulk_tests2(unsigned int api_type,
> > > > > > > > > > > > unsigned int
> > > > > > > > > > create_flags,
> > > > > > > > > > > > -	const char *tname)
> > > > > > > > > > > > +test_ring_burst_bulk_tests2(unsigned int test_idx)
> > > > > > > > > > > >  {
> > > > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > > > > **cur_dst = NULL; @@ -303,11 +478,13 @@
> > > > > > > > test_ring_burst_bulk_tests2(unsigned
> > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > >  	unsigned int i;
> > > > > > > > > > > >
> > > > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > > > -		test_ring_print_test_string(tname, api_type,
> > esize[i]);
> > > > > > > > > > > > +
> > > > > > > >
> > > > > > > > test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type,
> > esize[i]);
> > > > > > > > > > > >
> > > > > > > > > > > >  		/* Create the ring */
> > > > > > > > > > > >  		r =
> > > > > > > > > > > > test_ring_create("test_ring_burst_bulk_tests",
> > > > > > esize[i],
> > > > > > > > > > > > -					RING_SIZE,
> > SOCKET_ID_ANY,
> > > > > > > > > > > > create_flags);
> > > > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > > > +
> > > > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > > > >
> > > > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]);
> > > > > > > > > > > > @@
> > > > > > > > > > > > -323,39
> > > > > > > > > > > > +500,39 @@ test_ring_burst_bulk_tests2(unsigned int
> > > > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > > > create_flags,
> > > > > > > > > > > >  		cur_dst = dst;
> > > > > > > > > > > >
> > > > > > > > > > > >  		printf("enqueue 1 obj\n");
> > > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 1,
> > > > > > > > api_type);
> > > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 1,
> > > > > > > > test_idx);
> > > > > > > > > > > >  		if (ret != 1)
> > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > > > > > > > > 1);
> > > > > > > > > > > >
> > > > > > > > > > > >  		printf("enqueue 2 objs\n");
> > > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > > > > > > api_type);
> > > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > > > > > > > test_idx);
> > > > > > > > > > > >  		if (ret != 2)
> > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > > > > > > > > 2);
> > > > > > > > > > > >
> > > > > > > > > > > >  		printf("enqueue MAX_BULK objs\n");
> > > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > > > > > -						api_type);
> > > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > > > > > +						test_idx);
> > > > > > > > > > > >  		if (ret != MAX_BULK)
> > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > > MAX_BULK);
> > > > > > > > > > > >
> > > > > > > > > > > >  		printf("dequeue 1 obj\n");
> > > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1,
> > > > > > > > api_type);
> > > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1,
> > > > > > > > test_idx);
> > > > > > > > > > > >  		if (ret != 1)
> > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > > > > > > > > > 1);
> > > > > > > > > > > >
> > > > > > > > > > > >  		printf("dequeue 2 objs\n");
> > > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > > > > > > api_type);
> > > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > > > > > > > test_idx);
> > > > > > > > > > > >  		if (ret != 2)
> > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > > > > > > > > > 2);
> > > > > > > > > > > >
> > > > > > > > > > > >  		printf("dequeue MAX_BULK objs\n");
> > > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > > > > > -						api_type);
> > > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > > > > > +						test_idx);
> > > > > > > > > > > >  		if (ret != MAX_BULK)
> > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > > > MAX_BULK);
> > > > > > > > > > > > @@
> > > > > > > > > > > > -390,8 +567,7 @@
> > > > > > > > > > > > test_ring_burst_bulk_tests2(unsigned
> > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > >   * Enqueue and dequeue to cover the entire ring length.
> > > > > > > > > > > >   */
> > > > > > > > > > > >  static int
> > > > > > > > > > > > -test_ring_burst_bulk_tests3(unsigned int api_type,
> > > > > > > > > > > > unsigned int
> > > > > > > > > > create_flags,
> > > > > > > > > > > > -	const char *tname)
> > > > > > > > > > > > +test_ring_burst_bulk_tests3(unsigned int test_idx)
> > > > > > > > > > > >  {
> > > > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > > > > **cur_dst = NULL; @@ -399,11 +575,13 @@
> > > > > > > > test_ring_burst_bulk_tests3(unsigned
> > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > >  	unsigned int i, j;
> > > > > > > > > > > >
> > > > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > > > -		test_ring_print_test_string(tname, api_type,
> > esize[i]);
> > > > > > > > > > > > +
> > > > > > > >
> > > > > > > > test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type,
> > esize[i]);
> > > > > > > > > > > >
> > > > > > > > > > > >  		/* Create the ring */
> > > > > > > > > > > >  		r =
> > > > > > > > > > > > test_ring_create("test_ring_burst_bulk_tests",
> > > > > > esize[i],
> > > > > > > > > > > > -					RING_SIZE,
> > SOCKET_ID_ANY,
> > > > > > > > > > > > create_flags);
> > > > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > > > +
> > > > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > > > >
> > > > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]);
> > > > > > > > > > > > @@
> > > > > > > > > > > > -420,15
> > > > > > > > > > > > +598,15 @@ test_ring_burst_bulk_tests3(unsigned int
> > > > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > > > create_flags,
> > > > > > > > > > > >
> > > > > > > > > > > >  		printf("fill and empty the ring\n");
> > > > > > > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> > > > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src,
> > esize[i],
> > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > -
> > 	api_type);
> > > > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src,
> > esize[i],
> > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > +
> > 	test_idx);
> > > > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > > > >  				goto fail;
> > > > > > > > > > > >  			cur_src = test_ring_inc_ptr(cur_src,
> > esize[i],
> > > > > > > > > > > >
> > > > > > 	MAX_BULK);
> > > > > > > > > > > >
> > > > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst,
> > esize[i],
> > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > -
> > 	api_type);
> > > > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst,
> > esize[i],
> > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > +
> > 	test_idx);
> > > > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > > > >  				goto fail;
> > > > > > > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst,
> > esize[i],
> > > > > > @@ -
> > > > > > > > > > > > 465,21 +643,24 @@
> > > > > > > > > > > > test_ring_burst_bulk_tests3(unsigned
> > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > >   * Enqueue till the ring is full and dequeue till
> > > > > > > > > > > > the ring becomes
> > > > > > empty.
> > > > > > > > > > > >   */
> > > > > > > > > > > >  static int
> > > > > > > > > > > > -test_ring_burst_bulk_tests4(unsigned int api_type,
> > > > > > > > > > > > unsigned int
> > > > > > > > > > create_flags,
> > > > > > > > > > > > -	const char *tname)
> > > > > > > > > > > > +test_ring_burst_bulk_tests4(unsigned int test_idx)
> > > > > > > > > > > >  {
> > > > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst = NULL,
> > > > > > > > > > > > **cur_dst
> > > > > > = NULL;
> > > > > > > > > > > >  	int ret;
> > > > > > > > > > > >  	unsigned int i, j;
> > > > > > > > > > > > -	unsigned int num_elems;
> > > > > > > > > > > > +	unsigned int api_type, num_elems;
> > > > > > > > > > > > +
> > > > > > > > > > > > +	api_type = test_enqdeq_impl[test_idx].api_type;
> > > > > > > > > > > >
> > > > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > > > -		test_ring_print_test_string(tname, api_type,
> > esize[i]);
> > > > > > > > > > > > +
> > > > > > > >
> > > > > > > > test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > > > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type,
> > esize[i]);
> > > > > > > > > > > >
> > > > > > > > > > > >  		/* Create the ring */
> > > > > > > > > > > >  		r =
> > > > > > > > > > > > test_ring_create("test_ring_burst_bulk_tests",
> > > > > > esize[i],
> > > > > > > > > > > > -					RING_SIZE,
> > SOCKET_ID_ANY,
> > > > > > > > > > > > create_flags);
> > > > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > > > +
> > > > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > > > >
> > > > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2, esize[i]);
> > > > > > > > > > > > @@
> > > > > > > > > > > > -496,8
> > > > > > > > > > > > +677,8 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > > > create_flags,
> > > > > > > > > > > >
> > > > > > > > > > > >  		printf("Test enqueue without enough memory
> > > > > > space\n");
> > > > > > > > > > > >  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++)
> > {
> > > > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src,
> > esize[i],
> > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > -
> > 	api_type);
> > > > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src,
> > esize[i],
> > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > +
> > 	test_idx);
> > > > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > > > >  				goto fail;
> > > > > > > > > > > >  			cur_src = test_ring_inc_ptr(cur_src,
> > esize[i],
> > > > > > @@ -
> > > > > > > > > > > > 505,7 +686,7 @@ test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > >  		}
> > > > > > > > > > > >
> > > > > > > > > > > >  		printf("Enqueue 2 objects, free entries =
> > > > > > > > > > > > MAX_BULK -
> > > > > > 2\n");
> > > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > > > > > > api_type);
> > > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i], 2,
> > > > > > > > test_idx);
> > > > > > > > > > > >  		if (ret != 2)
> > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > > > > > > > > 2); @@
> > > > > > > > > > > > -517,8
> > > > > > > > > > > > +698,8 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > > > create_flags,
> > > > > > > > > > > >  		else
> > > > > > > > > > > >  			num_elems = MAX_BULK;
> > > > > > > > > > > >  		/* Always one free entry left */
> > > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > > num_elems,
> > > > > > > > > > > > -						api_type);
> > > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > > num_elems,
> > > > > > > > > > > > +						test_idx);
> > > > > > > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src, esize[i],
> > > > > > MAX_BULK -
> > > > > > > > > > > > 3);
> > > > > > > > > > @@
> > > > > > > > > > > > -528,15 +709,15 @@
> > > > > > > > > > > > test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > >
> > > > > > > > > > > >  		printf("Test enqueue for a full entry\n");
> > > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > > > > > -						api_type);
> > > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src, esize[i],
> > > > > > > > MAX_BULK,
> > > > > > > > > > > > +						test_idx);
> > > > > > > > > > > >  		if (ret != 0)
> > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > >
> > > > > > > > > > > >  		printf("Test dequeue without enough
> > objects\n");
> > > > > > > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> > > > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst,
> > esize[i],
> > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > -
> > 	api_type);
> > > > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst,
> > esize[i],
> > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > +
> > 	test_idx);
> > > > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > > > >  				goto fail;
> > > > > > > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst,
> > esize[i],
> > > > > > @@ -
> > > > > > > > > > > > 544,7 +725,7 @@ test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > >  		}
> > > > > > > > > > > >
> > > > > > > > > > > >  		/* Available memory space for the exact
> > MAX_BULK
> > > > > > entries
> > > > > > > > > > */
> > > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > > > > > > api_type);
> > > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2,
> > > > > > > > test_idx);
> > > > > > > > > > > >  		if (ret != 2)
> > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > > > > > > > > > 2); @@
> > > > > > > > > > > > -554,8
> > > > > > > > > > > > +735,8 @@ test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > > > > +api_type, unsigned int
> > > > > > > > > > > > create_flags,
> > > > > > > > > > > >  			num_elems = MAX_BULK - 3;
> > > > > > > > > > > >  		else
> > > > > > > > > > > >  			num_elems = MAX_BULK;
> > > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > > num_elems,
> > > > > > > > > > > > -						api_type);
> > > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst, esize[i],
> > > > > > > > num_elems,
> > > > > > > > > > > > +						test_idx);
> > > > > > > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
> > > > > > MAX_BULK -
> > > > > > > > > > > > 3);
> > > > > > > > > > @@
> > > > > > > > > > > > -816,22 +997,7 @@ static int
> > > > > > > > > > > >  test_ring(void)
> > > > > > > > > > > >  {
> > > > > > > > > > > >  	int32_t rc;
> > > > > > > > > > > > -	unsigned int i, j;
> > > > > > > > > > > > -	const char *tname;
> > > > > > > > > > > > -
> > > > > > > > > > > > -	static const struct {
> > > > > > > > > > > > -		uint32_t create_flags;
> > > > > > > > > > > > -		const char *name;
> > > > > > > > > > > > -	} test_sync_modes[] = {
> > > > > > > > > > > > -		{
> > > > > > > > > > > > -			RING_F_MP_RTS_ENQ |
> > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > > > > -			"Test MT_RTS ring",
> > > > > > > > > > > > -		},
> > > > > > > > > > > > -		{
> > > > > > > > > > > > -			RING_F_MP_HTS_ENQ |
> > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > > > > -			"Test MT_HTS ring",
> > > > > > > > > > > > -		},
> > > > > > > > > > > > -	};
> > > > > > > > > > > > +	unsigned int i;
> > > > > > > > > > > >
> > > > > > > > > > > >  	/* Negative test cases */
> > > > > > > > > > > >  	if (test_ring_negative_tests() < 0) @@ -848,65
> > > > > > > > > > > > +1014,24 @@
> > > > > > > > > > > > test_ring(void)
> > > > > > > > > > > >  	 * The test cases are split into smaller test cases to
> > > > > > > > > > > >  	 * help clang compile faster.
> > > > > > > > > > > >  	 */
> > > > > > > > > > > > -	tname = "Test standard ring";
> > > > > > > > > > > > -
> > > > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > > > TEST_RING_ELEM_BURST;
> > > > > > > > j <<= 1)
> > > > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > > > -					i <=
> > > > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > > > <<= 1)
> > > > > > > > > > > > -			if (test_ring_burst_bulk_tests1(i | j, 0,
> > tname)
> > > > > > > > < 0)
> > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > -
> > > > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > > > TEST_RING_ELEM_BURST;
> > > > > > > > j <<= 1)
> > > > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > > > -					i <=
> > > > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > > > <<= 1)
> > > > > > > > > > > > -			if (test_ring_burst_bulk_tests2(i | j, 0,
> > tname)
> > > > > > > > < 0)
> > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > -
> > > > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > > > TEST_RING_ELEM_BURST;
> > > > > > > > j <<= 1)
> > > > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > > > -					i <=
> > > > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > > > <<= 1)
> > > > > > > > > > > > -			if (test_ring_burst_bulk_tests3(i | j, 0,
> > tname)
> > > > > > > > < 0)
> > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > -
> > > > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > > > TEST_RING_ELEM_BURST;
> > > > > > > > j <<= 1)
> > > > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > > > -					i <=
> > > > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > > > <<= 1)
> > > > > > > > > > > > -			if (test_ring_burst_bulk_tests4(i | j, 0,
> > tname)
> > > > > > > > < 0)
> > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > -
> > > > > > > > > > > > -	/* Burst and bulk operations with MT_RTS and
> > MT_HTS sync
> > > > > > > > modes
> > > > > > > > > > > > */
> > > > > > > > > > > > -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> > > > > > > > > > > > -		for (j = TEST_RING_ELEM_BULK; j <=
> > > > > > > > TEST_RING_ELEM_BURST;
> > > > > > > > > > > > -				j <<= 1) {
> > > > > > > > > > > > -
> > > > > > > > > > > > -			rc = test_ring_burst_bulk_tests1(
> > > > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > > > -
> > 	test_sync_modes[i].create_flags,
> > > > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > -
> > > > > > > > > > > > -			rc = test_ring_burst_bulk_tests2(
> > > > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > > > -
> > 	test_sync_modes[i].create_flags,
> > > > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > -
> > > > > > > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > > > -
> > 	test_sync_modes[i].create_flags,
> > > > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > -
> > > > > > > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > > > -
> > 	test_sync_modes[i].create_flags,
> > > > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > -		}
> > > > > > > > > > > > +	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
> > > > > > > > > > > > +
> > > > > > > > > > > > +
> > > > > > > > > > > > +		rc = test_ring_burst_bulk_tests1(i);
> > > > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > > > +			goto test_fail;
> > > > > > > > > > > > +
> > > > > > > > > > > > +		rc = test_ring_burst_bulk_tests2(i);
> > > > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > > > +			goto test_fail;
> > > > > > > > > > > > +
> > > > > > > > > > > > +		rc = test_ring_burst_bulk_tests3(i);
> > > > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > > > +			goto test_fail;
> > > > > > > > > > > > +
> > > > > > > > > > > > +		rc = test_ring_burst_bulk_tests4(i);
> > > > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > > > +			goto test_fail;
> > > > > > > > > > > >  	}
> > > > > > > > > > > >
> > > > > > > > > > > >  	/* dump the ring status */
> > > > > > > > > > > > --
> > > > > > > > > > > > 2.17.1
Honnappa Nagarahalli May 13, 2020, 12:55 a.m. UTC | #16
<snip>
> 
> > > > > > > > > > >
> > > > > > > > > > > > Hi Konstantin,
> > > > > > > > > > > > 	I like the way the tests are organized and it
> > > > > > > > > > > > looks
> > > good.
> > > > > > > > > > > >
> > > > > > > > > > > > I am just wondering about the way it is being tested here.
> > > > > > > > > > > > The intent to write the test cases the way they
> > > > > > > > > > > > are currently is to mimic how the APIs would be used
> mostly.
> > > > > > > > > > > > IMO, the APIs would be used with a constant
> > > > > > > > > > > value for element size so that the compiler will
> > > > > > > > > > > throw away the unwanted code (in the functions where
> > > > > > > > > > > the actual copy is being
> > > > > done).
> > > > > > > > > > > >
> > > > > > > > > > > > With your method here, it looks to me like all the
> > > > > > > > > > > > branches in the copy
> > > > > > > > > > > functions are kept and the branch decisions are done
> > > > > > > > > > > at run
> > > time.
> > > > > > > > > > > > Is  my understanding correct?
> > > > > > > > > > >
> > > > > > > > > > > You mean branching on esize[] values?
> > > > > > > > > > Yes
> > > > I was wondering where is the confusion. I interpreted as referring
> > > > to the esize parameter in rte_ring_xxx_elem APIs. Anyway, please see
> below.
> > > >
> > > > > > > > > >
> > > > > > > > > > > Actually from what I've seen that happens for both cases:
> > > > > > > > > > > before and after the patch (gcc 7.3 -O3).
> > > > > > > > > > I did not look at the generated code. If it is
> > > > > > > > > > happening with your patch too, I
> > > > > > > > > think we can go with your patch.
> > > > > > > > >
> > > > > > > > > Just to clarify, what I meant:
> > > > > > > > > For both binaries (without the patch and with the patch)
> > > > > > > > > inside
> > > > > > > > > test_ring() I see runtime branches on esize value.
> > > > > > > > > Literally the code that corresponds to:
> > > > > > > > > if (esize == 8) {...}
> > > > > > > > > else if (esize == 16) {...} else {...}
> > > > > > I am not concerned about the functions in test_ring.c.
> > > > > >
> > > > > > > > Do you see this in the actual ring library functions?
> > > > > > >
> > > > > > > Which ones? AFAIK all ring dequeue/enqueue functions are
> > > > > > > inline right
> > > > > now.
> > > > > > Please see below.
> > > > > >
> > > > > > >
> > > > > > > > I want to make sure that the library functions
> > > > > > > > '__rte_ring_enqueue_elems' and '__rte_ring_dequeue_elems'
> > > > > > > > are
> > > > > optimized.
> > > > > > Each enqueue/dequeue function ultimately calls these 2 functions.
> > > > >
> > > > > Yes, and then each instance of enqueue/dequeue functions that is
> > > > > used by upper layer would be in-lined.
> > > > > So what upper layer function (library or app) you asked me to check?
> > > > I am not bothered much about upper layer functions. I looked at
> > > > the
> > > generate code for the function __rte_ring_enqueue_elems.
> > > > Existing code has the if checks for 8 and 16.
> > > > Your patch also has the checks.
> > > > My patch does not have the checks as it passes the constants
> > > > directly
> > > without using esize[] array in functions test_ring_burst_bulk_tests4.
> > >
> > > For test_burst_bulk_test[1-4] - yes, for other test functions it is still there.
> > Agree. This should give coverage for some at least.
> >
> > > Though I don't think it is that important for functional test cases.
> > > Anyway, I think we dragged away a bit in our discussion, so with
> > > what patch should we go ahead?
> > Agree, we dragged it. I tried to merge both the solutions (use your
> > patch and constant esize), I was not successful. My guess, function pointers
> are not allowing for the optimization.
> 
> I think it can be done pretty easily by replacing loop over esize[], with
> particular constant value in each of  test_ring_burst_bulk_tests[1-4] functions.
> I.E:
> 
> test_ring_burst_bulk_tests2(unsigned int test_idx)
>         struct rte_ring *r;
>         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
>         int ret;
> -       unsigned int i;
> -
> -       for (i = 0; i < RTE_DIM(esize); i++) {
> -               test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> -                       test_enqdeq_impl[test_idx].api_type, esize[i]);
> ....
> 
> +       const int elem_size = 4;
> +
> +       test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> +               test_enqdeq_impl[test_idx].api_type, elem_size);
> 
> I just not very fond of idea to reduce number of test-cases, just because
> compiler wasn't able to do some optimizations we hoped it would.
I had tried a similar variant, it did not work. This does not work as well. I am trying on Arm machines, did not try x86.

> 
> >
> > > My preference is 69559, as it compiles faster and doesn't reduce
> > > test coverage, but I can live with both.
> > test_burst_bulk_test[1-4] more or less call the same APIs. Spreading
> > the size variation across four of them should be ok. It will test the way it will
> be used.
> >
> > > Konstantin
> > >
> > > >
> > > > >
> > > > > > The compiler here should remove the 'if (esize == 8) {...}
> > > > > > else if (esize ==
> > > > > > 16) {...} else {...}' with just the required piece of code
> > > > > > depending on the
> > > > > 'esize'.
> > > > > > If we can validate that for at least one ring library function
> > > > > > used in this patch, we should be good.
> > > > > >
> > > > > > > >
> > > > > > > > >
> > > > > > > > > Probably gcc wasn't able to remove it because we use
> > > > > > > > > esize[] instead of hard- coded values, might be there is
> > > > > > > > > some other reason, I don't know
> > > > > > > for sure.
> > > > > > > > > As it is a functional (not performance) test, I didn't dig further.
> > > > > > > > The esize[] array is declared as a const. The compiler
> > > > > > > > should be able to see
> > > > > > > that it is a compile time constant.
> > > > > > >
> > > > > > > That was my expectation too, but that not what I am seeing.
> > > > > > >
> > > > > > > > >
> > > > > > > > > > But, can you do similar change to test_ring_perf.c to
> > > > > > > > > > keep it consistent?
> > > > > > > > >
> > > > > > > > > In principle it is doable, but needs extra care.
> > > > > > > > > We need to make sure that compiler will be able to
> > > > > > > > > inline functions via pointers.
> > > > > > > > > AFAIK, gcc does that with -O3', but not with '-O2'.
> > > > > > > > If the unwanted code is not removed during compilation, we
> > > > > > > > will see it
> > > > > > > affect the performance numbers.
> > > > > > >
> > > > > > > Exactly.
> > > > > > > The last thing I want - someone who uses older version of
> > > > > > > compiler, etc., will start to see lower performance numbers
> > > > > > > with that
> > > test.
> > > > > > >
> > > > > > > > > Don't know what the story with clang and different
> > > > > > > > > versions of the
> > > > > > > compiler.
> > > > > > > > > Is there any real need for that?
> > > > > > > > > On my box test_ring_perf.c compilation takes ~8s.
> > > > > > > > > Konstantin
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > Main intention in my changes was to avoid using
> > > > > > > > > > > test_ring_enqueue/test_ring_dequeue,
> > > > > > > > > > > as it seems too many branches here and it takes
> > > > > > > > > > > compiler a lot of effort to resolve all of them at compile
> time.
> > > > > > > > > > > So I replaced it with  array of function pointers
> > > > > > > > > > > (test_enqdeq_impl[]) and iterating over it.
> > > > > > > > > > > That way compiler knows straightway which function to use.
> > > > > > > > > > >
> > > > > > > > > > > > Can you please check this?
> > > > > > > > > > > > https://patches.dpdk.org/patch/69567/
> > > > > > > > > > >
> > > > > > > > > > > As I can see your approach reduces number of
> > > > > > > > > > > test-cases by factor
> > > > > of 5:
> > > > > > > > > > > now each of test_ring_burst_bulk_tests[1-4] is
> > > > > > > > > > > executed only with just one esize value, correct?
> > > > > > > > > > Yes, basically test_ring_burst_bulk_tests[1-4] were
> > > > > > > > > > covering different scenarios with the same APIs. So,
> > > > > > > > > > distributed the esize across different test
> > > > > > > > > functions.
> > > > > > > > > >
> > > > > > > > > > > In term of compilation speed - it helps.
> > > > > > > > > > > On my box with (gcc 7.3 -O3)  compiling test_ring.c takes:
> > > > > > > > > > > orig code:                             ~100s
> > > > > > > > > > > with 69567 (your patch):  < 20s
> > > > > > > > > > > with 69559 (my patch):    < 10s
> > > > > > > > > > >
> > > > > > > > > > > Konstantin
> > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > > From: Konstantin Ananyev
> > > > > > > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > > > > > > Sent: Wednesday, April 29, 2020 12:57 PM
> > > > > > > > > > > > > To: dev@dpdk.org
> > > > > > > > > > > > > Cc: aconole@redhat.com; Honnappa Nagarahalli
> > > > > > > > > > > > > <Honnappa.Nagarahalli@arm.com>; Konstantin
> > > > > > > > > > > > > Ananyev <konstantin.ananyev@intel.com>
> > > > > > > > > > > > > Subject: [PATCH] test/ring: code rework to
> > > > > > > > > > > > > reduce compilation time
> > > > > > > > > > > > >
> > > > > > > > > > > > > Rework test code to reduce code complexity for
> > > > > > > > > > > > > the compiler and bring down compilation time and
> > > > > > > > > > > > > memory
> > > > > consumption.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Signed-off-by: Konstantin Ananyev
> > > > > > > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > > > > > > ---
> > > > > > > > > > > > >  app/test/test_ring.c | 373
> > > > > > > > > > > > > +++++++++++++++++++++++++++++--------------
> > > > > > > > > > > > >  1 file changed, 249 insertions(+), 124
> > > > > > > > > > > > > deletions(-)
> > > > > > > > > > > > >
> > > > > > > > > > > > > diff --git a/app/test/test_ring.c
> > > > > > > > > > > > > b/app/test/test_ring.c index
> > > > > > > > > > > > > e21557cd9..0ae97d341 100644
> > > > > > > > > > > > > --- a/app/test/test_ring.c
> > > > > > > > > > > > > +++ b/app/test/test_ring.c
> > > > > > > > > > > > > @@ -58,6 +58,181 @@
> > > > > > > > > > > > >
> > > > > > > > > > > > >  static const int esize[] = {-1, 4, 8, 16, 20};
> > > > > > > > > > > > >
> > > > > > > > > > > > > +static const struct {
> > > > > > > > > > > > > +	const char *desc;
> > > > > > > > > > > > > +	uint32_t api_type;
> > > > > > > > > > > > > +	uint32_t create_flags;
> > > > > > > > > > > > > +	struct {
> > > > > > > > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > > > > > > > +			void * const *obj_table, unsigned int
> > > n,
> > > > > > > > > > > > > +			unsigned int *free_space);
> > > > > > > > > > > > > +		unsigned int (*felem)(struct rte_ring *r,
> > > > > > > > > > > > > +const void
> > > > > > > > > *obj_table,
> > > > > > > > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > > > > > > > +			unsigned int *free_space);
> > > > > > > > > > > > > +	} enq;
> > > > > > > > > > > > > +	struct {
> > > > > > > > > > > > > +		unsigned int (*flegacy)(struct rte_ring *r,
> > > > > > > > > > > > > +			void **obj_table, unsigned int n,
> > > > > > > > > > > > > +			unsigned int *available);
> > > > > > > > > > > > > +		unsigned int (*felem)(struct rte_ring *r,
> > > > > > > > > > > > > +void
> > > > > > > > > *obj_table,
> > > > > > > > > > > > > +			unsigned int esize, unsigned int n,
> > > > > > > > > > > > > +			unsigned int *available);
> > > > > > > > > > > > > +	} deq;
> > > > > > > > > > > > > +} test_enqdeq_impl[] = {
> > > > > > > > > > > > > +	{
> > > > > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > > > Details about the tests are already printed by the
> > > > > > > > > > > > function
> > > > > > > > > > > 'test_ring_print_test_string'. This string should be
> > > > > > > > > > > 'Test standard
> > > > > ring'.
> > > > > > > > > > > >
> > > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +	},
> > > > > > > > > > > > > +	{
> > > > > > > > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > > > > > > > +		.create_flags = RING_F_SP_ENQ |
> > > RING_F_SC_DEQ,
> > > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_sp_enqueue_bulk,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_sp_enqueue_bulk_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_sc_dequeue_bulk,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_sc_dequeue_bulk_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +	},
> > > > > > > > > > > > > +	{
> > > > > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_mp_enqueue_bulk,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_mp_enqueue_bulk_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_mc_dequeue_bulk,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_mc_dequeue_bulk_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +	},
> > > > > > > > > > > > > +	{
> > > > > > > > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +	},
> > > > > > > > > > > > > +	{
> > > > > > > > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BULK |
> > > > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_enqueue_bulk,
> > > > > > > > > > > > > +			.felem = rte_ring_enqueue_bulk_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_dequeue_bulk,
> > > > > > > > > > > > > +			.felem = rte_ring_dequeue_bulk_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +	},
> > > > > > > > > > > > > +	{
> > > > > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_enqueue_burst_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_dequeue_burst_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +	},
> > > > > > > > > > > > > +	{
> > > > > > > > > > > > > +		.desc = "SP/SC sync mode",
> > > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > > > TEST_RING_THREAD_SPSC,
> > > > > > > > > > > > > +		.create_flags = RING_F_SP_ENQ |
> > > RING_F_SC_DEQ,
> > > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_sp_enqueue_burst,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_sp_enqueue_burst_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_sc_dequeue_burst,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_sc_dequeue_burst_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +	},
> > > > > > > > > > > > > +	{
> > > > > > > > > > > > > +		.desc = "MP/MC sync mode",
> > > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > > > TEST_RING_THREAD_MPMC,
> > > > > > > > > > > > > +		.create_flags = 0,
> > > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > > +			.flegacy =
> > > rte_ring_mp_enqueue_burst,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_mp_enqueue_burst_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > > +			.flegacy =
> > > rte_ring_mc_dequeue_burst,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_mc_dequeue_burst_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +	},
> > > > > > > > > > > > > +	{
> > > > > > > > > > > > > +		.desc = "MP_RTS/MC_RTS sync mode",
> > > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > > > +		.create_flags = RING_F_MP_RTS_ENQ |
> > > > > > > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_enqueue_burst_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_dequeue_burst_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +	},
> > > > > > > > > > > > > +	{
> > > > > > > > > > > > > +		.desc = "MP_HTS/MC_HTS sync mode",
> > > > > > > > > > > > > +		.api_type = TEST_RING_ELEM_BURST |
> > > > > > > > > > > > > TEST_RING_THREAD_DEF,
> > > > > > > > > > > > > +		.create_flags = RING_F_MP_HTS_ENQ |
> > > > > > > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > > > > > +		.enq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_enqueue_burst,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_enqueue_burst_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +		.deq = {
> > > > > > > > > > > > > +			.flegacy = rte_ring_dequeue_burst,
> > > > > > > > > > > > > +			.felem =
> > > rte_ring_dequeue_burst_elem,
> > > > > > > > > > > > > +		},
> > > > > > > > > > > > > +	},
> > > > > > > > > > > > > +};
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +static unsigned int test_ring_enq_impl(struct
> > > > > > > > > > > > > +rte_ring *r, void **obj, int esize, unsigned
> > > > > > > > > int n,
> > > > > > > > > > > > > +	unsigned int test_idx) {
> > > > > > > > > > > > > +	if (esize == -1)
> > > > > > > > > > > > > +		return
> > > test_enqdeq_impl[test_idx].enq.flegacy(r,
> > > > > > > > > > > > > +obj,
> > > > > > > > > n, NULL);
> > > > > > > > > > > > > +	else
> > > > > > > > > > > > > +		return
> > > test_enqdeq_impl[test_idx].enq.felem(r,
> > > > > > > > > > > > > +obj,
> > > > > > > > > esize, n,
> > > > > > > > > > > > > +			NULL);
> > > > > > > > > > > > > +}
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +static unsigned int test_ring_deq_impl(struct
> > > > > > > > > > > > > +rte_ring *r, void **obj, int esize, unsigned
> > > > > > > > > int n,
> > > > > > > > > > > > > +	unsigned int test_idx) {
> > > > > > > > > > > > > +	if (esize == -1)
> > > > > > > > > > > > > +		return
> > > test_enqdeq_impl[test_idx].deq.flegacy(r,
> > > > > > > > > > > > > +obj,
> > > > > > > > > n, NULL);
> > > > > > > > > > > > > +	else
> > > > > > > > > > > > > +		return
> > > test_enqdeq_impl[test_idx].deq.felem(r,
> > > > > > > > > > > > > +obj,
> > > > > > > > > esize, n,
> > > > > > > > > > > > > +			NULL);
> > > > > > > > > > > > > +}
> > > > > > > > > > > > > +
> > > > > > > > > > > > >  static void**
> > > > > > > > > > > > >  test_ring_inc_ptr(void **obj, int esize,
> > > > > > > > > > > > > unsigned int
> > > > > > > > > > > > > n)  { @@
> > > > > > > > > > > > > -203,8 +378,7 @@ test_ring_negative_tests(void)
> > > > > > > > > > > > >   * Random number of elements are enqueued and
> > > dequeued.
> > > > > > > > > > > > >   */
> > > > > > > > > > > > >  static int
> > > > > > > > > > > > > -test_ring_burst_bulk_tests1(unsigned int
> > > > > > > > > > > > > api_type, unsigned int
> > > > > > > > > > > create_flags,
> > > > > > > > > > > > > -	const char *tname)
> > > > > > > > > > > > > +test_ring_burst_bulk_tests1(unsigned int
> > > > > > > > > > > > > +test_idx)
> > > > > > > > > > > > >  {
> > > > > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst =
> > > > > > > > > > > > > NULL, **cur_dst = NULL; @@ -214,11 +388,13 @@
> > > > > > > > > test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > > >  	const unsigned int rsz = RING_SIZE - 1;
> > > > > > > > > > > > >
> > > > > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > > > > -		test_ring_print_test_string(tname, api_type,
> > > esize[i]);
> > > > > > > > > > > > > +
> > > > > > > > >
> > > > > > > > > test_ring_print_test_string(test_enqdeq_impl[test_idx].d
> > > > > > > > > esc,
> > > > > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type,
> > > esize[i]);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		/* Create the ring */
> > > > > > > > > > > > >  		r =
> > > > > > > > > > > > > test_ring_create("test_ring_burst_bulk_tests",
> > > > > > > esize[i],
> > > > > > > > > > > > > -					RING_SIZE,
> > > SOCKET_ID_ANY,
> > > > > > > > > > > > > create_flags);
> > > > > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > > > > +
> > > > > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2,
> > > > > > > > > > > > > esize[i]); @@
> > > > > > > > > > > > > -240,17
> > > > > > > > > > > > > +416,17 @@ test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > > > > > +int api_type, unsigned int
> > > > > > > > > > > > > create_flags,
> > > > > > > > > > > > >  			rand = RTE_MAX(rte_rand() %
> > > RING_SIZE,
> > > > > > > 1UL);
> > > > > > > > > > > > >  			printf("%s: iteration %u, random
> > > shift: %u;\n",
> > > > > > > > > > > > >  			    __func__, i, rand);
> > > > > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src,
> > > esize[i],
> > > > > > > > > rand,
> > > > > > > > > > > > > -
> > > 	api_type);
> > > > > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src,
> > > esize[i],
> > > > > > > > > rand,
> > > > > > > > > > > > > +
> > > 	test_idx);
> > > > > > > > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > > > > > > > >
> > > > > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst,
> > > esize[i],
> > > > > > > > > rand,
> > > > > > > > > > > > > -
> > > 	api_type);
> > > > > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst,
> > > esize[i],
> > > > > > > > > rand,
> > > > > > > > > > > > > +
> > > 	test_idx);
> > > > > > > > > > > > >  			TEST_RING_VERIFY(ret == rand);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  			/* fill the ring */
> > > > > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src,
> > > esize[i],
> > > > > rsz,
> > > > > > > > > > > > > -
> > > 	api_type);
> > > > > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src,
> > > esize[i],
> > > > > > > > > rsz,
> > > > > > > > > > > > > +
> > > 	test_idx);
> > > > > > > > > > > > >  			TEST_RING_VERIFY(ret != 0);
> > > > > > > > > > > > >
> > > > > > > > > > > > >
> > > 	TEST_RING_VERIFY(rte_ring_free_count(r) ==
> > > > > > > 0); @@
> > > > > > > > > > > > > -259,8 +435,8 @@
> > > > > > > > > > > > > test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > > >  			TEST_RING_VERIFY(rte_ring_empty(r)
> > > == 0);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  			/* empty the ring */
> > > > > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst,
> > > esize[i],
> > > > > rsz,
> > > > > > > > > > > > > -
> > > 	api_type);
> > > > > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst,
> > > esize[i],
> > > > > > > > > rsz,
> > > > > > > > > > > > > +
> > > 	test_idx);
> > > > > > > > > > > > >  			TEST_RING_VERIFY(ret == (int)rsz);
> > > > > > > > > > > > >  			TEST_RING_VERIFY(rsz ==
> > > > > > > rte_ring_free_count(r));
> > > > > > > > > > > > >  			TEST_RING_VERIFY(rte_ring_count(r)
> > > == 0);
> > > > > > > @@ -
> > > > > > > > > > > > > 294,8 +470,7 @@
> > > > > > > > > > > > > test_ring_burst_bulk_tests1(unsigned
> > > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > > >   * dequeued data.
> > > > > > > > > > > > >   */
> > > > > > > > > > > > >  static int
> > > > > > > > > > > > > -test_ring_burst_bulk_tests2(unsigned int
> > > > > > > > > > > > > api_type, unsigned int
> > > > > > > > > > > create_flags,
> > > > > > > > > > > > > -	const char *tname)
> > > > > > > > > > > > > +test_ring_burst_bulk_tests2(unsigned int
> > > > > > > > > > > > > +test_idx)
> > > > > > > > > > > > >  {
> > > > > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst =
> > > > > > > > > > > > > NULL, **cur_dst = NULL; @@ -303,11 +478,13 @@
> > > > > > > > > test_ring_burst_bulk_tests2(unsigned
> > > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > > >  	unsigned int i;
> > > > > > > > > > > > >
> > > > > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > > > > -		test_ring_print_test_string(tname, api_type,
> > > esize[i]);
> > > > > > > > > > > > > +
> > > > > > > > >
> > > > > > > > > test_ring_print_test_string(test_enqdeq_impl[test_idx].d
> > > > > > > > > esc,
> > > > > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type,
> > > esize[i]);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		/* Create the ring */
> > > > > > > > > > > > >  		r =
> > > > > > > > > > > > > test_ring_create("test_ring_burst_bulk_tests",
> > > > > > > esize[i],
> > > > > > > > > > > > > -					RING_SIZE,
> > > SOCKET_ID_ANY,
> > > > > > > > > > > > > create_flags);
> > > > > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > > > > +
> > > > > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2,
> > > > > > > > > > > > > esize[i]); @@
> > > > > > > > > > > > > -323,39
> > > > > > > > > > > > > +500,39 @@ test_ring_burst_bulk_tests2(unsigned
> > > > > > > > > > > > > +int api_type, unsigned int
> > > > > > > > > > > > > create_flags,
> > > > > > > > > > > > >  		cur_dst = dst;
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		printf("enqueue 1 obj\n");
> > > > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 1,
> > > > > > > > > api_type);
> > > > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src,
> > > > > > > > > > > > > +esize[i], 1,
> > > > > > > > > test_idx);
> > > > > > > > > > > > >  		if (ret != 1)
> > > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src,
> > > > > > > > > > > > > esize[i], 1);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		printf("enqueue 2 objs\n");
> > > > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > > > > > > > api_type);
> > > > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src,
> > > > > > > > > > > > > +esize[i], 2,
> > > > > > > > > test_idx);
> > > > > > > > > > > > >  		if (ret != 2)
> > > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src,
> > > > > > > > > > > > > esize[i], 2);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		printf("enqueue MAX_BULK objs\n");
> > > > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > -						api_type);
> > > > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src,
> > > > > > > > > > > > > +esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > +						test_idx);
> > > > > > > > > > > > >  		if (ret != MAX_BULK)
> > > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src,
> > > > > > > > > > > > > esize[i],
> > > > > > > MAX_BULK);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		printf("dequeue 1 obj\n");
> > > > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 1,
> > > > > > > > > api_type);
> > > > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst,
> > > > > > > > > > > > > +esize[i], 1,
> > > > > > > > > test_idx);
> > > > > > > > > > > > >  		if (ret != 1)
> > > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst,
> > > > > > > > > > > > > esize[i], 1);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		printf("dequeue 2 objs\n");
> > > > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > > > > > > > api_type);
> > > > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst,
> > > > > > > > > > > > > +esize[i], 2,
> > > > > > > > > test_idx);
> > > > > > > > > > > > >  		if (ret != 2)
> > > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst,
> > > > > > > > > > > > > esize[i], 2);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		printf("dequeue MAX_BULK objs\n");
> > > > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > -						api_type);
> > > > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst,
> > > > > > > > > > > > > +esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > +						test_idx);
> > > > > > > > > > > > >  		if (ret != MAX_BULK)
> > > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst,
> > > > > > > > > > > > > esize[i],
> > > > > > > MAX_BULK);
> > > > > > > > > > > > > @@
> > > > > > > > > > > > > -390,8 +567,7 @@
> > > > > > > > > > > > > test_ring_burst_bulk_tests2(unsigned
> > > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > > >   * Enqueue and dequeue to cover the entire ring length.
> > > > > > > > > > > > >   */
> > > > > > > > > > > > >  static int
> > > > > > > > > > > > > -test_ring_burst_bulk_tests3(unsigned int
> > > > > > > > > > > > > api_type, unsigned int
> > > > > > > > > > > create_flags,
> > > > > > > > > > > > > -	const char *tname)
> > > > > > > > > > > > > +test_ring_burst_bulk_tests3(unsigned int
> > > > > > > > > > > > > +test_idx)
> > > > > > > > > > > > >  {
> > > > > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst =
> > > > > > > > > > > > > NULL, **cur_dst = NULL; @@ -399,11 +575,13 @@
> > > > > > > > > test_ring_burst_bulk_tests3(unsigned
> > > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > > >  	unsigned int i, j;
> > > > > > > > > > > > >
> > > > > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > > > > -		test_ring_print_test_string(tname, api_type,
> > > esize[i]);
> > > > > > > > > > > > > +
> > > > > > > > >
> > > > > > > > > test_ring_print_test_string(test_enqdeq_impl[test_idx].d
> > > > > > > > > esc,
> > > > > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type,
> > > esize[i]);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		/* Create the ring */
> > > > > > > > > > > > >  		r =
> > > > > > > > > > > > > test_ring_create("test_ring_burst_bulk_tests",
> > > > > > > esize[i],
> > > > > > > > > > > > > -					RING_SIZE,
> > > SOCKET_ID_ANY,
> > > > > > > > > > > > > create_flags);
> > > > > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > > > > +
> > > > > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2,
> > > > > > > > > > > > > esize[i]); @@
> > > > > > > > > > > > > -420,15
> > > > > > > > > > > > > +598,15 @@ test_ring_burst_bulk_tests3(unsigned
> > > > > > > > > > > > > +int api_type, unsigned int
> > > > > > > > > > > > > create_flags,
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		printf("fill and empty the ring\n");
> > > > > > > > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
> > > > > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src,
> > > esize[i],
> > > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > -
> > > 	api_type);
> > > > > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src,
> > > esize[i],
> > > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > +
> > > 	test_idx);
> > > > > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > > > > >  				goto fail;
> > > > > > > > > > > > >  			cur_src = test_ring_inc_ptr(cur_src,
> > > esize[i],
> > > > > > > > > > > > >
> > > > > > > 	MAX_BULK);
> > > > > > > > > > > > >
> > > > > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst,
> > > esize[i],
> > > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > -
> > > 	api_type);
> > > > > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst,
> > > esize[i],
> > > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > +
> > > 	test_idx);
> > > > > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > > > > >  				goto fail;
> > > > > > > > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst,
> > > esize[i],
> > > > > > > @@ -
> > > > > > > > > > > > > 465,21 +643,24 @@
> > > > > > > > > > > > > test_ring_burst_bulk_tests3(unsigned
> > > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > > >   * Enqueue till the ring is full and dequeue
> > > > > > > > > > > > > till the ring becomes
> > > > > > > empty.
> > > > > > > > > > > > >   */
> > > > > > > > > > > > >  static int
> > > > > > > > > > > > > -test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > > > > > api_type, unsigned int
> > > > > > > > > > > create_flags,
> > > > > > > > > > > > > -	const char *tname)
> > > > > > > > > > > > > +test_ring_burst_bulk_tests4(unsigned int
> > > > > > > > > > > > > +test_idx)
> > > > > > > > > > > > >  {
> > > > > > > > > > > > >  	struct rte_ring *r;
> > > > > > > > > > > > >  	void **src = NULL, **cur_src = NULL, **dst =
> > > > > > > > > > > > > NULL, **cur_dst
> > > > > > > = NULL;
> > > > > > > > > > > > >  	int ret;
> > > > > > > > > > > > >  	unsigned int i, j;
> > > > > > > > > > > > > -	unsigned int num_elems;
> > > > > > > > > > > > > +	unsigned int api_type, num_elems;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +	api_type =
> > > > > > > > > > > > > +test_enqdeq_impl[test_idx].api_type;
> > > > > > > > > > > > >
> > > > > > > > > > > > >  	for (i = 0; i < RTE_DIM(esize); i++) {
> > > > > > > > > > > > > -		test_ring_print_test_string(tname, api_type,
> > > esize[i]);
> > > > > > > > > > > > > +
> > > > > > > > >
> > > > > > > > > test_ring_print_test_string(test_enqdeq_impl[test_idx].d
> > > > > > > > > esc,
> > > > > > > > > > > > > +			test_enqdeq_impl[test_idx].api_type,
> > > esize[i]);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		/* Create the ring */
> > > > > > > > > > > > >  		r =
> > > > > > > > > > > > > test_ring_create("test_ring_burst_bulk_tests",
> > > > > > > esize[i],
> > > > > > > > > > > > > -					RING_SIZE,
> > > SOCKET_ID_ANY,
> > > > > > > > > > > > > create_flags);
> > > > > > > > > > > > > +				RING_SIZE, SOCKET_ID_ANY,
> > > > > > > > > > > > > +
> > > > > > > > > 	test_enqdeq_impl[test_idx].create_flags);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		/* alloc dummy object pointers */
> > > > > > > > > > > > >  		src = test_ring_calloc(RING_SIZE * 2,
> > > > > > > > > > > > > esize[i]); @@
> > > > > > > > > > > > > -496,8
> > > > > > > > > > > > > +677,8 @@ test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > > > > > +int api_type, unsigned int
> > > > > > > > > > > > > create_flags,
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		printf("Test enqueue without enough memory
> > > > > > > space\n");
> > > > > > > > > > > > >  		for (j = 0; j < (RING_SIZE/MAX_BULK - 1);
> > > > > > > > > > > > > j++)
> > > {
> > > > > > > > > > > > > -			ret = test_ring_enqueue(r, cur_src,
> > > esize[i],
> > > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > -
> > > 	api_type);
> > > > > > > > > > > > > +			ret = test_ring_enq_impl(r, cur_src,
> > > esize[i],
> > > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > +
> > > 	test_idx);
> > > > > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > > > > >  				goto fail;
> > > > > > > > > > > > >  			cur_src = test_ring_inc_ptr(cur_src,
> > > esize[i],
> > > > > > > @@ -
> > > > > > > > > > > > > 505,7 +686,7 @@
> > > > > > > > > > > > > test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > > >  		}
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		printf("Enqueue 2 objects, free entries =
> > > > > > > > > > > > > MAX_BULK -
> > > > > > > 2\n");
> > > > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i], 2,
> > > > > > > > > api_type);
> > > > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src,
> > > > > > > > > > > > > +esize[i], 2,
> > > > > > > > > test_idx);
> > > > > > > > > > > > >  		if (ret != 2)
> > > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src,
> > > > > > > > > > > > > esize[i], 2); @@
> > > > > > > > > > > > > -517,8
> > > > > > > > > > > > > +698,8 @@ test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > > > > > +int api_type, unsigned int
> > > > > > > > > > > > > create_flags,
> > > > > > > > > > > > >  		else
> > > > > > > > > > > > >  			num_elems = MAX_BULK;
> > > > > > > > > > > > >  		/* Always one free entry left */
> > > > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > > > num_elems,
> > > > > > > > > > > > > -						api_type);
> > > > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src,
> > > > > > > > > > > > > +esize[i],
> > > > > > > > > num_elems,
> > > > > > > > > > > > > +						test_idx);
> > > > > > > > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > > >  		cur_src = test_ring_inc_ptr(cur_src,
> > > > > > > > > > > > > esize[i],
> > > > > > > MAX_BULK -
> > > > > > > > > > > > > 3);
> > > > > > > > > > > @@
> > > > > > > > > > > > > -528,15 +709,15 @@
> > > > > > > > > > > > > test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		printf("Test enqueue for a full entry\n");
> > > > > > > > > > > > > -		ret = test_ring_enqueue(r, cur_src, esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > -						api_type);
> > > > > > > > > > > > > +		ret = test_ring_enq_impl(r, cur_src,
> > > > > > > > > > > > > +esize[i],
> > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > +						test_idx);
> > > > > > > > > > > > >  		if (ret != 0)
> > > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		printf("Test dequeue without enough
> > > objects\n");
> > > > > > > > > > > > >  		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
> > > > > > > > > > > > > -			ret = test_ring_dequeue(r, cur_dst,
> > > esize[i],
> > > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > -
> > > 	api_type);
> > > > > > > > > > > > > +			ret = test_ring_deq_impl(r, cur_dst,
> > > esize[i],
> > > > > > > > > > > > > MAX_BULK,
> > > > > > > > > > > > > +
> > > 	test_idx);
> > > > > > > > > > > > >  			if (ret != MAX_BULK)
> > > > > > > > > > > > >  				goto fail;
> > > > > > > > > > > > >  			cur_dst = test_ring_inc_ptr(cur_dst,
> > > esize[i],
> > > > > > > @@ -
> > > > > > > > > > > > > 544,7 +725,7 @@
> > > > > > > > > > > > > test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > > > > > int api_type, unsigned int create_flags,
> > > > > > > > > > > > >  		}
> > > > > > > > > > > > >
> > > > > > > > > > > > >  		/* Available memory space for the exact
> > > MAX_BULK
> > > > > > > entries
> > > > > > > > > > > */
> > > > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i], 2,
> > > > > > > > > api_type);
> > > > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst,
> > > > > > > > > > > > > +esize[i], 2,
> > > > > > > > > test_idx);
> > > > > > > > > > > > >  		if (ret != 2)
> > > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst,
> > > > > > > > > > > > > esize[i], 2); @@
> > > > > > > > > > > > > -554,8
> > > > > > > > > > > > > +735,8 @@ test_ring_burst_bulk_tests4(unsigned
> > > > > > > > > > > > > +int api_type, unsigned int
> > > > > > > > > > > > > create_flags,
> > > > > > > > > > > > >  			num_elems = MAX_BULK - 3;
> > > > > > > > > > > > >  		else
> > > > > > > > > > > > >  			num_elems = MAX_BULK;
> > > > > > > > > > > > > -		ret = test_ring_dequeue(r, cur_dst, esize[i],
> > > > > > > > > num_elems,
> > > > > > > > > > > > > -						api_type);
> > > > > > > > > > > > > +		ret = test_ring_deq_impl(r, cur_dst,
> > > > > > > > > > > > > +esize[i],
> > > > > > > > > num_elems,
> > > > > > > > > > > > > +						test_idx);
> > > > > > > > > > > > >  		if (ret != MAX_BULK - 3)
> > > > > > > > > > > > >  			goto fail;
> > > > > > > > > > > > >  		cur_dst = test_ring_inc_ptr(cur_dst,
> > > > > > > > > > > > > esize[i],
> > > > > > > MAX_BULK -
> > > > > > > > > > > > > 3);
> > > > > > > > > > > @@
> > > > > > > > > > > > > -816,22 +997,7 @@ static int
> > > > > > > > > > > > >  test_ring(void)  {
> > > > > > > > > > > > >  	int32_t rc;
> > > > > > > > > > > > > -	unsigned int i, j;
> > > > > > > > > > > > > -	const char *tname;
> > > > > > > > > > > > > -
> > > > > > > > > > > > > -	static const struct {
> > > > > > > > > > > > > -		uint32_t create_flags;
> > > > > > > > > > > > > -		const char *name;
> > > > > > > > > > > > > -	} test_sync_modes[] = {
> > > > > > > > > > > > > -		{
> > > > > > > > > > > > > -			RING_F_MP_RTS_ENQ |
> > > > > > > > > RING_F_MC_RTS_DEQ,
> > > > > > > > > > > > > -			"Test MT_RTS ring",
> > > > > > > > > > > > > -		},
> > > > > > > > > > > > > -		{
> > > > > > > > > > > > > -			RING_F_MP_HTS_ENQ |
> > > > > > > > > RING_F_MC_HTS_DEQ,
> > > > > > > > > > > > > -			"Test MT_HTS ring",
> > > > > > > > > > > > > -		},
> > > > > > > > > > > > > -	};
> > > > > > > > > > > > > +	unsigned int i;
> > > > > > > > > > > > >
> > > > > > > > > > > > >  	/* Negative test cases */
> > > > > > > > > > > > >  	if (test_ring_negative_tests() < 0) @@ -848,65
> > > > > > > > > > > > > +1014,24 @@
> > > > > > > > > > > > > test_ring(void)
> > > > > > > > > > > > >  	 * The test cases are split into smaller test cases to
> > > > > > > > > > > > >  	 * help clang compile faster.
> > > > > > > > > > > > >  	 */
> > > > > > > > > > > > > -	tname = "Test standard ring";
> > > > > > > > > > > > > -
> > > > > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > > > > TEST_RING_ELEM_BURST;
> > > > > > > > > j <<= 1)
> > > > > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > > > > -					i <=
> > > > > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > > > > <<= 1)
> > > > > > > > > > > > > -			if (test_ring_burst_bulk_tests1(i | j, 0,
> > > tname)
> > > > > > > > > < 0)
> > > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > > -
> > > > > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > > > > TEST_RING_ELEM_BURST;
> > > > > > > > > j <<= 1)
> > > > > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > > > > -					i <=
> > > > > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > > > > <<= 1)
> > > > > > > > > > > > > -			if (test_ring_burst_bulk_tests2(i | j, 0,
> > > tname)
> > > > > > > > > < 0)
> > > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > > -
> > > > > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > > > > TEST_RING_ELEM_BURST;
> > > > > > > > > j <<= 1)
> > > > > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > > > > -					i <=
> > > > > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > > > > <<= 1)
> > > > > > > > > > > > > -			if (test_ring_burst_bulk_tests3(i | j, 0,
> > > tname)
> > > > > > > > > < 0)
> > > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > > -
> > > > > > > > > > > > > -	for (j = TEST_RING_ELEM_BULK; j <=
> > > > > TEST_RING_ELEM_BURST;
> > > > > > > > > j <<= 1)
> > > > > > > > > > > > > -		for (i = TEST_RING_THREAD_DEF;
> > > > > > > > > > > > > -					i <=
> > > > > > > > > TEST_RING_THREAD_MPMC; i
> > > > > > > > > > > > > <<= 1)
> > > > > > > > > > > > > -			if (test_ring_burst_bulk_tests4(i | j, 0,
> > > tname)
> > > > > > > > > < 0)
> > > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > > -
> > > > > > > > > > > > > -	/* Burst and bulk operations with MT_RTS and
> > > MT_HTS sync
> > > > > > > > > modes
> > > > > > > > > > > > > */
> > > > > > > > > > > > > -	for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
> > > > > > > > > > > > > -		for (j = TEST_RING_ELEM_BULK; j <=
> > > > > > > > > TEST_RING_ELEM_BURST;
> > > > > > > > > > > > > -				j <<= 1) {
> > > > > > > > > > > > > -
> > > > > > > > > > > > > -			rc = test_ring_burst_bulk_tests1(
> > > > > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > > > > -
> > > 	test_sync_modes[i].create_flags,
> > > > > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > > -
> > > > > > > > > > > > > -			rc = test_ring_burst_bulk_tests2(
> > > > > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > > > > -
> > > 	test_sync_modes[i].create_flags,
> > > > > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > > -
> > > > > > > > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > > > > -
> > > 	test_sync_modes[i].create_flags,
> > > > > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > > -
> > > > > > > > > > > > > -			rc = test_ring_burst_bulk_tests3(
> > > > > > > > > > > > > -				TEST_RING_THREAD_DEF | j,
> > > > > > > > > > > > > -
> > > 	test_sync_modes[i].create_flags,
> > > > > > > > > > > > > -				test_sync_modes[i].name);
> > > > > > > > > > > > > -			if (rc < 0)
> > > > > > > > > > > > > -				goto test_fail;
> > > > > > > > > > > > > -		}
> > > > > > > > > > > > > +	for (i = 0; i != RTE_DIM(test_enqdeq_impl);
> > > > > > > > > > > > > +i++) {
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +		rc = test_ring_burst_bulk_tests1(i);
> > > > > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > > > > +			goto test_fail;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +		rc = test_ring_burst_bulk_tests2(i);
> > > > > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > > > > +			goto test_fail;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +		rc = test_ring_burst_bulk_tests3(i);
> > > > > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > > > > +			goto test_fail;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +		rc = test_ring_burst_bulk_tests4(i);
> > > > > > > > > > > > > +		if (rc < 0)
> > > > > > > > > > > > > +			goto test_fail;
> > > > > > > > > > > > >  	}
> > > > > > > > > > > > >
> > > > > > > > > > > > >  	/* dump the ring status */
> > > > > > > > > > > > > --
> > > > > > > > > > > > > 2.17.1
Ananyev, Konstantin May 13, 2020, 11:20 a.m. UTC | #17
> > > > > > > > > > > > > Hi Konstantin,
> > > > > > > > > > > > > 	I like the way the tests are organized and it
> > > > > > > > > > > > > looks
> > > > good.
> > > > > > > > > > > > >
> > > > > > > > > > > > > I am just wondering about the way it is being tested here.
> > > > > > > > > > > > > The intent to write the test cases the way they
> > > > > > > > > > > > > are currently is to mimic how the APIs would be used
> > mostly.
> > > > > > > > > > > > > IMO, the APIs would be used with a constant
> > > > > > > > > > > > value for element size so that the compiler will
> > > > > > > > > > > > throw away the unwanted code (in the functions where
> > > > > > > > > > > > the actual copy is being
> > > > > > done).
> > > > > > > > > > > > >
> > > > > > > > > > > > > With your method here, it looks to me like all the
> > > > > > > > > > > > > branches in the copy
> > > > > > > > > > > > functions are kept and the branch decisions are done
> > > > > > > > > > > > at run
> > > > time.
> > > > > > > > > > > > > Is  my understanding correct?
> > > > > > > > > > > >
> > > > > > > > > > > > You mean branching on esize[] values?
> > > > > > > > > > > Yes
> > > > > I was wondering where is the confusion. I interpreted as referring
> > > > > to the esize parameter in rte_ring_xxx_elem APIs. Anyway, please see
> > below.
> > > > >
> > > > > > > > > > >
> > > > > > > > > > > > Actually from what I've seen that happens for both cases:
> > > > > > > > > > > > before and after the patch (gcc 7.3 -O3).
> > > > > > > > > > > I did not look at the generated code. If it is
> > > > > > > > > > > happening with your patch too, I
> > > > > > > > > > think we can go with your patch.
> > > > > > > > > >
> > > > > > > > > > Just to clarify, what I meant:
> > > > > > > > > > For both binaries (without the patch and with the patch)
> > > > > > > > > > inside
> > > > > > > > > > test_ring() I see runtime branches on esize value.
> > > > > > > > > > Literally the code that corresponds to:
> > > > > > > > > > if (esize == 8) {...}
> > > > > > > > > > else if (esize == 16) {...} else {...}
> > > > > > > I am not concerned about the functions in test_ring.c.
> > > > > > >
> > > > > > > > > Do you see this in the actual ring library functions?
> > > > > > > >
> > > > > > > > Which ones? AFAIK all ring dequeue/enqueue functions are
> > > > > > > > inline right
> > > > > > now.
> > > > > > > Please see below.
> > > > > > >
> > > > > > > >
> > > > > > > > > I want to make sure that the library functions
> > > > > > > > > '__rte_ring_enqueue_elems' and '__rte_ring_dequeue_elems'
> > > > > > > > > are
> > > > > > optimized.
> > > > > > > Each enqueue/dequeue function ultimately calls these 2 functions.
> > > > > >
> > > > > > Yes, and then each instance of enqueue/dequeue functions that is
> > > > > > used by upper layer would be in-lined.
> > > > > > So what upper layer function (library or app) you asked me to check?
> > > > > I am not bothered much about upper layer functions. I looked at
> > > > > the
> > > > generate code for the function __rte_ring_enqueue_elems.
> > > > > Existing code has the if checks for 8 and 16.
> > > > > Your patch also has the checks.
> > > > > My patch does not have the checks as it passes the constants
> > > > > directly
> > > > without using esize[] array in functions test_ring_burst_bulk_tests4.
> > > >
> > > > For test_burst_bulk_test[1-4] - yes, for other test functions it is still there.
> > > Agree. This should give coverage for some at least.
> > >
> > > > Though I don't think it is that important for functional test cases.
> > > > Anyway, I think we dragged away a bit in our discussion, so with
> > > > what patch should we go ahead?
> > > Agree, we dragged it. I tried to merge both the solutions (use your
> > > patch and constant esize), I was not successful. My guess, function pointers
> > are not allowing for the optimization.
> >
> > I think it can be done pretty easily by replacing loop over esize[], with
> > particular constant value in each of  test_ring_burst_bulk_tests[1-4] functions.
> > I.E:
> >
> > test_ring_burst_bulk_tests2(unsigned int test_idx)
> >         struct rte_ring *r;
> >         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
> >         int ret;
> > -       unsigned int i;
> > -
> > -       for (i = 0; i < RTE_DIM(esize); i++) {
> > -               test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > -                       test_enqdeq_impl[test_idx].api_type, esize[i]);
> > ....
> >
> > +       const int elem_size = 4;
> > +
> > +       test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
> > +               test_enqdeq_impl[test_idx].api_type, elem_size);
> >
> > I just not very fond of idea to reduce number of test-cases, just because
> > compiler wasn't able to do some optimizations we hoped it would.
> I had tried a similar variant, it did not work. This does not work as well. I am trying on Arm machines, did not try x86.

Interesting... 
As I can see on x86 such approach does help (as long as you build with -O3 off course).

> 
> >
> > >
> > > > My preference is 69559, as it compiles faster and doesn't reduce
> > > > test coverage, but I can live with both.
> > > test_burst_bulk_test[1-4] more or less call the same APIs. Spreading
> > > the size variation across four of them should be ok. It will test the way it will
> > be used.
> > >
> > > > Konstantin
> > > >
> > > > >
> > > > > >
> > > > > > > The compiler here should remove the 'if (esize == 8) {...}
> > > > > > > else if (esize ==
> > > > > > > 16) {...} else {...}' with just the required piece of code
> > > > > > > depending on the
> > > > > > 'esize'.
> > > > > > > If we can validate that for at least one ring library function
> > > > > > > used in this patch, we should be good.
> > > > > > >
> > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > Probably gcc wasn't able to remove it because we use
> > > > > > > > > > esize[] instead of hard- coded values, might be there is
> > > > > > > > > > some other reason, I don't know
> > > > > > > > for sure.
> > > > > > > > > > As it is a functional (not performance) test, I didn't dig further.
> > > > > > > > > The esize[] array is declared as a const. The compiler
> > > > > > > > > should be able to see
> > > > > > > > that it is a compile time constant.
> > > > > > > >
> > > > > > > > That was my expectation too, but that not what I am seeing.
> > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > But, can you do similar change to test_ring_perf.c to
> > > > > > > > > > > keep it consistent?
> > > > > > > > > >
> > > > > > > > > > In principle it is doable, but needs extra care.
> > > > > > > > > > We need to make sure that compiler will be able to
> > > > > > > > > > inline functions via pointers.
> > > > > > > > > > AFAIK, gcc does that with -O3', but not with '-O2'.
> > > > > > > > > If the unwanted code is not removed during compilation, we
> > > > > > > > > will see it
> > > > > > > > affect the performance numbers.
> > > > > > > >
> > > > > > > > Exactly.
> > > > > > > > The last thing I want - someone who uses older version of
> > > > > > > > compiler, etc., will start to see lower performance numbers
> > > > > > > > with that
> > > > test.
> > > > > > > >
> > > > > > > > > > Don't know what the story with clang and different
> > > > > > > > > > versions of the
> > > > > > > > compiler.
> > > > > > > > > > Is there any real need for that?
> > > > > > > > > > On my box test_ring_perf.c compilation takes ~8s.
> > > > > > > > > > Konstantin
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > > Main intention in my changes was to avoid using
> > > > > > > > > > > > test_ring_enqueue/test_ring_dequeue,
> > > > > > > > > > > > as it seems too many branches here and it takes
> > > > > > > > > > > > compiler a lot of effort to resolve all of them at compile
> > time.
> > > > > > > > > > > > So I replaced it with  array of function pointers
> > > > > > > > > > > > (test_enqdeq_impl[]) and iterating over it.
> > > > > > > > > > > > That way compiler knows straightway which function to use.
> > > > > > > > > > > >
> > > > > > > > > > > > > Can you please check this?
> > > > > > > > > > > > > https://patches.dpdk.org/patch/69567/
> > > > > > > > > > > >
> > > > > > > > > > > > As I can see your approach reduces number of
> > > > > > > > > > > > test-cases by factor
> > > > > > of 5:
> > > > > > > > > > > > now each of test_ring_burst_bulk_tests[1-4] is
> > > > > > > > > > > > executed only with just one esize value, correct?
> > > > > > > > > > > Yes, basically test_ring_burst_bulk_tests[1-4] were
> > > > > > > > > > > covering different scenarios with the same APIs. So,
> > > > > > > > > > > distributed the esize across different test
> > > > > > > > > > functions.
> > > > > > > > > > >
> > > > > > > > > > > > In term of compilation speed - it helps.
> > > > > > > > > > > > On my box with (gcc 7.3 -O3)  compiling test_ring.c takes:
> > > > > > > > > > > > orig code:                             ~100s
> > > > > > > > > > > > with 69567 (your patch):  < 20s
> > > > > > > > > > > > with 69559 (my patch):    < 10s
> > > > > > > > > > > >
> > > > > > > > > > > > Konstantin
> > > > > > > > > > > >
> > > > > > > > > > > > >
> > > > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > > > From: Konstantin Ananyev
> > > > > > > > > > > > > > <konstantin.ananyev@intel.com>
> > > > > > > > > > > > > > Sent: Wednesday, April 29, 2020 12:57 PM
> > > > > > > > > > > > > > To: dev@dpdk.org
> > > > > > > > > > > > > > Cc: aconole@redhat.com; Honnappa Nagarahalli
> > > > > > > > > > > > > > <Honnappa.Nagarahalli@arm.com>; Konstantin
> > > > > > > > > > > > > > Ananyev <konstantin.ananyev@intel.com>
> > > > > > > > > > > > > > Subject: [PATCH] test/ring: code rework to
> > > > > > > > > > > > > > reduce compilation time
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > Rework test code to reduce code complexity for
> > > > > > > > > > > > > > the compiler and bring down compilation time and
> > > > > > > > > > > > > > memory<