Christophe's patch should be merged very soon so I'd base your revision on
that.

Bill

On Sunday, May 22, 2016, Yi He <yi...@linaro.org> wrote:

> Thanks Maxim and Bill, I'll update copyright to 2016 and remove Intel's
> copyright, just one question before I send the v3 patch:
>
>    - I saw Christophe's patches series, shall I update mine based on his
>    (with command line parameter parsing).
>    - Or wait until his patch series merged into master/next branch and
>    then write a new separate patch to add command line parameters parsing.
>
> Best Regards, Yi
>
>
> On 22 May 2016 at 23:52, Bill Fischofer <bill.fischo...@linaro.org
> <javascript:_e(%7B%7D,'cvml','bill.fischo...@linaro.org');>> wrote:
>
>> I concur with Maxim on the copyrights but other than that:
>>
>> Reviewed-and-tested-by: Bill Fischofer <bill.fischo...@linaro.org
>> <javascript:_e(%7B%7D,'cvml','bill.fischo...@linaro.org');>>
>>
>> Note that I'm unable to get this test to fail, so this may also be a fix
>> to
>> the issue discussed in
>> https://lists.linaro.org/pipermail/lng-odp/2016-May/023518.html
>>
>> Might need to resolve conflicts between this patch and Christophe's
>> changes
>> (I haven't tested to see what conflicts may exist).
>>
>> On Fri, May 20, 2016 at 7:59 AM, Maxim Uvarov <maxim.uva...@linaro.org
>> <javascript:_e(%7B%7D,'cvml','maxim.uva...@linaro.org');>>
>> wrote:
>>
>> > Linaros copyright has to be 2016 (in some places you have 2014 in other
>> > 2015).
>> >
>> > ringstress.c is new file and looks like it's pure ODP. Adding Intels
>> > copyright there is not right.
>> >
>> > Maxim.
>> >
>> >
>> > On 05/20/16 11:48, Yi He wrote:
>> >
>> >> Fixes: https://bugs.linaro.org/show_bug.cgi?id=2228
>> >>
>> >> Convert ring test program into cunit framework
>> >> Improve LCOV coverage for linux-generic/pktio/ring.c
>> >>
>> >> Signed-off-by: Yi He <yi...@linaro.org
>> <javascript:_e(%7B%7D,'cvml','yi...@linaro.org');>>
>> >> ---
>> >>   platform/linux-generic/test/Makefile.am        |   2 +-
>> >>   platform/linux-generic/test/ring/Makefile.am   |  20 +-
>> >>   platform/linux-generic/test/ring/ring_basic.c  | 392
>> >> ++++++++++++++++++++
>> >>   platform/linux-generic/test/ring/ring_main.c   |  12 +
>> >>   platform/linux-generic/test/ring/ring_stress.c | 270 ++++++++++++++
>> >>   platform/linux-generic/test/ring/ring_suites.c |  70 ++++
>> >>   platform/linux-generic/test/ring/ring_suites.h |  33 ++
>> >>   platform/linux-generic/test/ring/ringtest.c    | 493
>> >> -------------------------
>> >>   8 files changed, 787 insertions(+), 505 deletions(-)
>> >>   create mode 100644 platform/linux-generic/test/ring/ring_basic.c
>> >>   create mode 100644 platform/linux-generic/test/ring/ring_main.c
>> >>   create mode 100644 platform/linux-generic/test/ring/ring_stress.c
>> >>   create mode 100644 platform/linux-generic/test/ring/ring_suites.c
>> >>   create mode 100644 platform/linux-generic/test/ring/ring_suites.h
>> >>   delete mode 100644 platform/linux-generic/test/ring/ringtest.c
>> >>
>> >> diff --git a/platform/linux-generic/test/Makefile.am
>> >> b/platform/linux-generic/test/Makefile.am
>> >> index f74185d..2d58c57 100644
>> >> --- a/platform/linux-generic/test/Makefile.am
>> >> +++ b/platform/linux-generic/test/Makefile.am
>> >> @@ -8,7 +8,7 @@ ODP_MODULES = pktio \
>> >>   if test_vald
>> >>   TESTS = pktio/pktio_run.sh \
>> >>         pktio/pktio_run_tap.sh \
>> >> -       ring/ringtest$(EXEEXT) \
>> >> +       ring/ring_main$(EXEEXT) \
>> >>         shmem/shmem_linux \
>> >>         ${top_builddir}/test/validation/atomic/atomic_main$(EXEEXT) \
>> >>         ${top_builddir}/test/validation/barrier/barrier_main$(EXEEXT) \
>> >> diff --git a/platform/linux-generic/test/ring/Makefile.am
>> >> b/platform/linux-generic/test/ring/Makefile.am
>> >> index 5a949d0..c086584 100644
>> >> --- a/platform/linux-generic/test/ring/Makefile.am
>> >> +++ b/platform/linux-generic/test/ring/Makefile.am
>> >> @@ -1,16 +1,14 @@
>> >> -include $(top_srcdir)/test/validation/Makefile.inc
>> >> +include ../Makefile.inc
>> >>   -AM_CFLAGS += -I$(srcdir)/common
>> >> -AM_CFLAGS += -I$(top_srcdir)/test/validation/common
>> >> -AM_LDFLAGS += -static
>> >> +noinst_LTLIBRARIES = libtestring.la
>> >> +libtestring_la_SOURCES = ring_suites.c ring_basic.c ring_stress.c
>> >> +libtestring_la_CFLAGS = $(AM_CFLAGS) $(INCCUNIT_COMMON) $(INCODP)
>> >>   -COMPILE_ONLY =
>> >> +test_PROGRAMS = ring_main$(EXEEXT)
>> >> +dist_ring_main_SOURCES = ring_main.c
>> >>   -TESTSCRIPTS =
>> >> +ring_main_LDFLAGS = $(AM_LDFLAGS)
>> >> +ring_main_LDADD = libtestring.la $(LIBCUNIT_COMMON) $(LIBODP)
>> >>   -EXECUTABLES = ringtest$(EXEEXT)
>> >> +noinst_HEADERS = ring_suites.h
>> >>   -test_PROGRAMS = $(EXECUTABLES) $(COMPILE_ONLY)
>> >> -
>> >> -ringtest_SOURCES = ringtest.c
>> >> -ringtest_LDADD = $(LIBCUNIT_COMMON) $(LIBODP)
>> >> diff --git a/platform/linux-generic/test/ring/ring_basic.c
>> >> b/platform/linux-generic/test/ring/ring_basic.c
>> >> new file mode 100644
>> >> index 0000000..20d9786
>> >> --- /dev/null
>> >> +++ b/platform/linux-generic/test/ring/ring_basic.c
>> >> @@ -0,0 +1,392 @@
>> >> +/* Copyright (c) 2015, Linaro Limited
>> >> + * All rights reserved.
>> >> + *
>> >> + * SPDX-License-Identifier:     BSD-3-Clause
>> >> + */
>> >> +
>> >> +/*-
>> >> + *   BSD LICENSE
>> >> + *
>> >> + *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
>> >> + *   All rights reserved.
>> >> + *
>> >> + *   Redistribution and use in source and binary forms, with or
>> without
>> >> + *   modification, are permitted provided that the following
>> conditions
>> >> + *   are met:
>> >> + *
>> >> + *     * Redistributions of source code must retain the above
>> copyright
>> >> + *       notice, this list of conditions and the following disclaimer.
>> >> + *     * Redistributions in binary form must reproduce the above
>> >> copyright
>> >> + *       notice, this list of conditions and the following disclaimer
>> in
>> >> + *       the documentation and/or other materials provided with the
>> >> + *       distribution.
>> >> + *     * Neither the name of Intel Corporation nor the names of its
>> >> + *       contributors may be used to endorse or promote products
>> derived
>> >> + *       from this software without specific prior written permission.
>> >> + *
>> >> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
>> CONTRIBUTORS
>> >> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
>> >> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
>> >> FOR
>> >> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
>> COPYRIGHT
>> >> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
>> >> INCIDENTAL,
>> >> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>> >> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>> >> USE,
>> >> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
>> >> ANY
>> >> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>> TORT
>> >> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
>> >> USE
>> >> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
>> DAMAGE.
>> >> + */
>> >> +
>> >> +/**
>> >> + * @file
>> >> + *
>> >> + * ODP ring basic test
>> >> + */
>> >> +
>> >> +#include <stdlib.h>
>> >> +#include <stdio.h>
>> >> +#include <string.h>
>> >> +
>> >> +#include <test_debug.h>
>> >> +#include <odp_cunit_common.h>
>> >> +#include <odp_packet_io_ring_internal.h>
>> >> +
>> >> +#include "ring_suites.h"
>> >> +
>> >> +/* labor functions declaration */
>> >> +static void __do_basic_burst(_ring_t *r);
>> >> +static void __do_basic_bulk(_ring_t *r);
>> >> +static void __do_basic_watermark(_ring_t *r);
>> >> +
>> >> +/* dummy object pointers for enqueue and dequeue testing */
>> >> +static void **test_enq_data;
>> >> +static void **test_deq_data;
>> >> +
>> >> +/* create two rings: one for single thread usage scenario
>> >> + * and another for multiple thread usage scenario.
>> >> + * st - single thread usage scenario
>> >> + * mt - multiple thread usage scenario
>> >> + */
>> >> +static const char *st_ring_name = "ST basic ring";
>> >> +static const char *mt_ring_name = "MT basic ring";
>> >> +static _ring_t *st_ring, *mt_ring;
>> >> +
>> >> +int ring_test_basic_start(void)
>> >> +{
>> >> +       int i = 0;
>> >> +
>> >> +       /* alloc dummy object pointers for enqueue testing */
>> >> +       test_enq_data = malloc(RING_SIZE * 2 * sizeof(void *));
>> >> +       if (NULL == test_enq_data) {
>> >> +               LOG_ERR("failed to allocate basic test enqeue data\n");
>> >> +               return -1;
>> >> +       }
>> >> +
>> >> +       for (i = 0; i < RING_SIZE * 2; i++)
>> >> +               test_enq_data[i] = (void *)(unsigned long)i;
>> >> +
>> >> +       /* alloc dummy object pointers for dequeue testing */
>> >> +       test_deq_data = malloc(RING_SIZE * 2 * sizeof(void *));
>> >> +       if (NULL == test_deq_data) {
>> >> +               LOG_ERR("failed to allocate basic test dequeue
>> data\n");
>> >> +               free(test_enq_data); test_enq_data = NULL;
>> >> +               return -1;
>> >> +       }
>> >> +
>> >> +       memset(test_deq_data, 0, RING_SIZE * 2 * sizeof(void *));
>> >> +       return 0;
>> >> +}
>> >> +
>> >> +int ring_test_basic_end(void)
>> >> +{
>> >> +       free(test_enq_data);
>> >> +       free(test_deq_data);
>> >> +       return 0;
>> >> +}
>> >> +
>> >> +/* basic test cases */
>> >> +void ring_test_basic_create(void)
>> >> +{
>> >> +       /* prove illegal size shall fail */
>> >> +       st_ring = _ring_create(st_ring_name, ILLEGAL_SIZE, 0);
>> >> +       CU_ASSERT(NULL == st_ring);
>> >> +       CU_ASSERT(EINVAL == __odp_errno);
>> >> +
>> >> +       /* create ring for single thread usage scenario */
>> >> +       st_ring = _ring_create(st_ring_name, RING_SIZE,
>> >> +               _RING_F_SP_ENQ | _RING_F_SC_DEQ);
>> >> +
>> >> +       CU_ASSERT(NULL != st_ring);
>> >> +       CU_ASSERT(_ring_lookup(st_ring_name) == st_ring);
>> >> +
>> >> +       /* create ring for multiple thread usage scenario */
>> >> +       mt_ring = _ring_create(mt_ring_name, RING_SIZE,
>> >> +               0 /* not used, alignement
>> >> +                    taken care inside function: todo */);
>> >> +
>> >> +       CU_ASSERT(NULL != mt_ring);
>> >> +       CU_ASSERT(_ring_lookup(mt_ring_name) == mt_ring);
>> >> +}
>> >> +
>> >> +void ring_test_basic_burst(void)
>> >> +{
>> >> +       /* two rounds to cover both single
>> >> +        * thread and multiple thread APIs
>> >> +        */
>> >> +       __do_basic_burst(st_ring);
>> >> +       __do_basic_burst(mt_ring);
>> >> +}
>> >> +
>> >> +void ring_test_basic_bulk(void)
>> >> +{
>> >> +       __do_basic_bulk(st_ring);
>> >> +       __do_basic_bulk(mt_ring);
>> >> +}
>> >> +
>> >> +void ring_test_basic_watermark(void)
>> >> +{
>> >> +       __do_basic_watermark(st_ring);
>> >> +       __do_basic_watermark(mt_ring);
>> >> +}
>> >> +
>> >> +/* labor functions definition */
>> >> +static void __do_basic_burst(_ring_t *r)
>> >> +{
>> >> +       int result = 0;
>> >> +       unsigned int count = 0;
>> >> +       void * const *source = test_enq_data;
>> >> +       void * const *dest = test_deq_data;
>> >> +       void **enq = NULL, **deq = NULL;
>> >> +
>> >> +       enq = test_enq_data; deq = test_deq_data;
>> >> +
>> >> +       /* ring is empty */
>> >> +       CU_ASSERT(1 == _ring_empty(r));
>> >> +
>> >> +       /* enqueue 1 object */
>> >> +       result = _ring_enqueue_burst(r, enq, 1);
>> >> +       enq += 1;
>> >> +       CU_ASSERT(1 == (result & _RING_SZ_MASK));
>> >> +
>> >> +       /* enqueue 2 objects */
>> >> +       result = _ring_enqueue_burst(r, enq, 2);
>> >> +       enq += 2;
>> >> +       CU_ASSERT(2 == (result & _RING_SZ_MASK));
>> >> +
>> >> +       /* enqueue HALF_BULK objects */
>> >> +       result = _ring_enqueue_burst(r, enq, HALF_BULK);
>> >> +       enq += HALF_BULK;
>> >> +       CU_ASSERT(HALF_BULK == (result & _RING_SZ_MASK));
>> >> +
>> >> +       /* ring is neither empty nor full */
>> >> +       CU_ASSERT(0 == _ring_full(r));
>> >> +       CU_ASSERT(0 == _ring_empty(r));
>> >> +
>> >> +       /* _ring_count() equals enqueued */
>> >> +       count = (1 + 2 + HALF_BULK);
>> >> +       CU_ASSERT(count == _ring_count(r));
>> >> +       /* _ring_free_count() equals rooms left */
>> >> +       count = (RING_SIZE - 1) - count;
>> >> +       CU_ASSERT(count == _ring_free_count(r));
>> >> +
>> >> +       /* exceed the size, enquene as many as possible */
>> >> +       result = _ring_enqueue_burst(r, enq, HALF_BULK);
>> >> +       enq += count;
>> >> +       CU_ASSERT(count == (result & _RING_SZ_MASK));
>> >> +       CU_ASSERT(1 == _ring_full(r));
>> >> +
>> >> +       /* dequeue 1 object */
>> >> +       result = _ring_dequeue_burst(r, deq, 1);
>> >> +       deq += 1;
>> >> +       CU_ASSERT(1 == (result & _RING_SZ_MASK));
>> >> +
>> >> +       /* dequeue 2 objects */
>> >> +       result = _ring_dequeue_burst(r, deq, 2);
>> >> +       deq += 2;
>> >> +       CU_ASSERT(2 == (result & _RING_SZ_MASK));
>> >> +
>> >> +       /* dequeue HALF_BULK objects */
>> >> +       result = _ring_dequeue_burst(r, deq, HALF_BULK);
>> >> +       deq += HALF_BULK;
>> >> +       CU_ASSERT(HALF_BULK == (result & _RING_SZ_MASK));
>> >> +
>> >> +       /* _ring_free_count() equals dequeued */
>> >> +       count = (1 + 2 + HALF_BULK);
>> >> +       CU_ASSERT(count == _ring_free_count(r));
>> >> +       /* _ring_count() equals remained left */
>> >> +       count = (RING_SIZE - 1) - count;
>> >> +       CU_ASSERT(count == _ring_count(r));
>> >> +
>> >> +       /* underrun the size, dequeue as many as possible */
>> >> +       result = _ring_dequeue_burst(r, deq, HALF_BULK);
>> >> +       deq += count;
>> >> +       CU_ASSERT(count == (result & _RING_SZ_MASK));
>> >> +       CU_ASSERT(1 == _ring_empty(r));
>> >> +
>> >> +       /* check data */
>> >> +       CU_ASSERT(0 == memcmp(source, dest, deq - dest));
>> >> +
>> >> +       /* reset dequeue data */
>> >> +       memset(test_deq_data, 0, RING_SIZE * 2 * sizeof(void *));
>> >> +}
>> >> +
>> >> +/* incomplete ring API set: strange!
>> >> + * complement _ring_enqueue/dequeue_bulk to improve coverage
>> >> + */
>> >> +static inline int __ring_enqueue_bulk(
>> >> +       _ring_t *r, void * const *objects, unsigned bulk)
>> >> +{
>> >> +       if (r->prod.sp_enqueue)
>> >> +               return _ring_sp_enqueue_bulk(r, objects, bulk);
>> >> +       else
>> >> +               return _ring_mp_enqueue_bulk(r, objects, bulk);
>> >> +}
>> >> +
>> >> +static inline int __ring_dequeue_bulk(
>> >> +       _ring_t *r, void **objects, unsigned bulk)
>> >> +{
>> >> +       if (r->cons.sc_dequeue)
>> >> +               return _ring_sc_dequeue_bulk(r, objects, bulk);
>> >> +       else
>> >> +               return _ring_mc_dequeue_bulk(r, objects, bulk);
>> >> +}
>> >> +
>> >> +static void __do_basic_bulk(_ring_t *r)
>> >> +{
>> >> +       int result = 0;
>> >> +       unsigned int count = 0;
>> >> +       void * const *source = test_enq_data;
>> >> +       void * const *dest = test_deq_data;
>> >> +       void **enq = NULL, **deq = NULL;
>> >> +
>> >> +       enq = test_enq_data; deq = test_deq_data;
>> >> +
>> >> +       /* ring is empty */
>> >> +       CU_ASSERT(1 == _ring_empty(r));
>> >> +
>> >> +       /* enqueue 1 object */
>> >> +       result = __ring_enqueue_bulk(r, enq, 1);
>> >> +       enq += 1;
>> >> +       CU_ASSERT(0 == result);
>> >> +
>> >> +       /* enqueue 2 objects */
>> >> +       result = __ring_enqueue_bulk(r, enq, 2);
>> >> +       enq += 2;
>> >> +       CU_ASSERT(0 == result);
>> >> +
>> >> +       /* enqueue HALF_BULK objects */
>> >> +       result = __ring_enqueue_bulk(r, enq, HALF_BULK);
>> >> +       enq += HALF_BULK;
>> >> +       CU_ASSERT(0 == result);
>> >> +
>> >> +       /* ring is neither empty nor full */
>> >> +       CU_ASSERT(0 == _ring_full(r));
>> >> +       CU_ASSERT(0 == _ring_empty(r));
>> >> +
>> >> +       /* _ring_count() equals enqueued */
>> >> +       count = (1 + 2 + HALF_BULK);
>> >> +       CU_ASSERT(count == _ring_count(r));
>> >> +       /* _ring_free_count() equals rooms left */
>> >> +       count = (RING_SIZE - 1) - count;
>> >> +       CU_ASSERT(count == _ring_free_count(r));
>> >> +
>> >> +       /* exceed the size, enquene shall fail with -ENOBUFS */
>> >> +       result = __ring_enqueue_bulk(r, enq, HALF_BULK);
>> >> +       CU_ASSERT(-ENOBUFS == result);
>> >> +
>> >> +       /* fullful the ring */
>> >> +       result = __ring_enqueue_bulk(r, enq, count);
>> >> +       enq += count;
>> >> +       CU_ASSERT(0 == result);
>> >> +       CU_ASSERT(1 == _ring_full(r));
>> >> +
>> >> +       /* dequeue 1 object */
>> >> +       result = __ring_dequeue_bulk(r, deq, 1);
>> >> +       deq += 1;
>> >> +       CU_ASSERT(0 == result);
>> >> +
>> >> +       /* dequeue 2 objects */
>> >> +       result = __ring_dequeue_bulk(r, deq, 2);
>> >> +       deq += 2;
>> >> +       CU_ASSERT(0 == result);
>> >> +
>> >> +       /* dequeue HALF_BULK objects */
>> >> +       result = __ring_dequeue_bulk(r, deq, HALF_BULK);
>> >> +       deq += HALF_BULK;
>> >> +       CU_ASSERT(0 == result);
>> >> +
>> >> +       /* _ring_free_count() equals dequeued */
>> >> +       count = (1 + 2 + HALF_BULK);
>> >> +       CU_ASSERT(count == _ring_free_count(r));
>> >> +       /* _ring_count() equals remained left */
>> >> +       count = (RING_SIZE - 1) - count;
>> >> +       CU_ASSERT(count == _ring_count(r));
>> >> +
>> >> +       /* underrun the size, dequeue shall fail with -ENOENT */
>> >> +       result = __ring_dequeue_bulk(r, deq, HALF_BULK);
>> >> +       CU_ASSERT(-ENOENT == result);
>> >> +
>> >> +       /* empty the queue */
>> >> +       result = __ring_dequeue_bulk(r, deq, count);
>> >> +       deq += count;
>> >> +       CU_ASSERT(0 == result);
>> >> +       CU_ASSERT(1 == _ring_empty(r));
>> >> +
>> >> +       /* check data */
>> >> +       CU_ASSERT(0 == memcmp(source, dest, deq - dest));
>> >> +
>> >> +       /* reset dequeue data */
>> >> +       memset(test_deq_data, 0, RING_SIZE * 2 * sizeof(void *));
>> >> +}
>> >> +
>> >> +void __do_basic_watermark(_ring_t *r)
>> >> +{
>> >> +       int result = 0;
>> >> +       void * const *source = test_enq_data;
>> >> +       void * const *dest = test_deq_data;
>> >> +       void **enq = NULL, **deq = NULL;
>> >> +
>> >> +       enq = test_enq_data; deq = test_deq_data;
>> >> +
>> >> +       /* bulk = 3/4 watermark to trigger alarm on 2nd enqueue */
>> >> +       const unsigned watermark = PIECE_BULK;
>> >> +       const unsigned bulk = (watermark / 4) * 3;
>> >> +
>> >> +       /* watermark cannot exceed ring size */
>> >> +       result = _ring_set_water_mark(r, ILLEGAL_SIZE);
>> >> +       CU_ASSERT(-EINVAL == result);
>> >> +
>> >> +       /* set watermark */
>> >> +       result = _ring_set_water_mark(r, watermark);
>> >> +       CU_ASSERT(0 == result);
>> >> +
>> >> +       /* 1st enqueue shall succeed */
>> >> +       result = __ring_enqueue_bulk(r, enq, bulk);
>> >> +       enq += bulk;
>> >> +       CU_ASSERT(0 == result);
>> >> +
>> >> +       /* 2nd enqueue shall succeed but return -EDQUOT */
>> >> +       result = __ring_enqueue_bulk(r, enq, bulk);
>> >> +       enq += bulk;
>> >> +       CU_ASSERT(-EDQUOT == result);
>> >> +
>> >> +       /* dequeue 1st bulk */
>> >> +       result = __ring_dequeue_bulk(r, deq, bulk);
>> >> +       deq += bulk;
>> >> +       CU_ASSERT(0 == result);
>> >> +
>> >> +       /* dequeue 2nd bulk */
>> >> +       result = __ring_dequeue_bulk(r, deq, bulk);
>> >> +       deq += bulk;
>> >> +       CU_ASSERT(0 == result);
>> >> +
>> >> +       /* check data */
>> >> +       CU_ASSERT(0 == memcmp(source, dest, deq - dest));
>> >> +
>> >> +       /* reset watermark */
>> >> +       result = _ring_set_water_mark(r, 0);
>> >> +       CU_ASSERT(0 == result);
>> >> +
>> >> +       /* reset dequeue data */
>> >> +       memset(test_deq_data, 0, RING_SIZE * 2 * sizeof(void *));
>> >> +}
>> >> diff --git a/platform/linux-generic/test/ring/ring_main.c
>> >> b/platform/linux-generic/test/ring/ring_main.c
>> >> new file mode 100644
>> >> index 0000000..e465113
>> >> --- /dev/null
>> >> +++ b/platform/linux-generic/test/ring/ring_main.c
>> >> @@ -0,0 +1,12 @@
>> >> +/* Copyright (c) 2015, Linaro Limited
>> >> + * All rights reserved.
>> >> + *
>> >> + * SPDX-License-Identifier:     BSD-3-Clause
>> >> + */
>> >> +
>> >> +#include "ring_suites.h"
>> >> +
>> >> +int main(void)
>> >> +{
>> >> +       return ring_suites_main();
>> >> +}
>> >> diff --git a/platform/linux-generic/test/ring/ring_stress.c
>> >> b/platform/linux-generic/test/ring/ring_stress.c
>> >> new file mode 100644
>> >> index 0000000..a4753e9
>> >> --- /dev/null
>> >> +++ b/platform/linux-generic/test/ring/ring_stress.c
>> >> @@ -0,0 +1,270 @@
>> >> +/* Copyright (c) 2014, Linaro Limited
>> >> + * All rights reserved.
>> >> + *
>> >> + * SPDX-License-Identifier:     BSD-3-Clause
>> >> + */
>> >> +
>> >> +/*-
>> >> + *   BSD LICENSE
>> >> + *
>> >> + *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
>> >> + *   All rights reserved.
>> >> + *
>> >> + *   Redistribution and use in source and binary forms, with or
>> without
>> >> + *   modification, are permitted provided that the following
>> conditions
>> >> + *   are met:
>> >> + *
>> >> + *     * Redistributions of source code must retain the above
>> copyright
>> >> + *       notice, this list of conditions and the following disclaimer.
>> >> + *     * Redistributions in binary form must reproduce the above
>> >> copyright
>> >> + *       notice, this list of conditions and the following disclaimer
>> in
>> >> + *       the documentation and/or other materials provided with the
>> >> + *       distribution.
>> >> + *     * Neither the name of Intel Corporation nor the names of its
>> >> + *       contributors may be used to endorse or promote products
>> derived
>> >> + *       from this software without specific prior written permission.
>> >> + *
>> >> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
>> CONTRIBUTORS
>> >> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
>> >> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
>> >> FOR
>> >> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
>> COPYRIGHT
>> >> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
>> >> INCIDENTAL,
>> >> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>> >> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>> >> USE,
>> >> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
>> >> ANY
>> >> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>> TORT
>> >> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
>> >> USE
>> >> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
>> DAMAGE.
>> >> + */
>> >> +
>> >> +/**
>> >> + * @file
>> >> + *
>> >> + * ODP ring stress test
>> >> + */
>> >> +
>> >> +#include <stdlib.h>
>> >> +#include <stdio.h>
>> >> +#include <string.h>
>> >> +
>> >> +#include <odp_api.h>
>> >> +#include <odp/helper/linux.h>
>> >> +#include <odp_packet_io_ring_internal.h>
>> >> +#include <test_debug.h>
>> >> +#include <odp_cunit_common.h>
>> >> +
>> >> +#include "ring_suites.h"
>> >> +
>> >> +/*
>> >> + * Since cunit framework cannot work with multi-threading, ask workers
>> >> + * to save their results for delayed assertion after thread
>> collection.
>> >> + */
>> >> +static int worker_results[MAX_WORKERS];
>> >> +
>> >> +/*
>> >> + * Note : make sure that both enqueue and dequeue
>> >> + * operation starts at same time so to avoid data corruption
>> >> + * Its because atomic lock will protect only indexes, but if order of
>> >> + * read or write operation incorrect then data mismatch will happen
>> >> + * So its resposibility of application develop to take care of order
>> of
>> >> + * data read or write.
>> >> + */
>> >> +typedef enum {
>> >> +       STRESS_1_1_PRODUCER_CONSUMER,
>> >> +       STRESS_1_N_PRODUCER_CONSUMER,
>> >> +       STRESS_N_1_PRODUCER_CONSUMER,
>> >> +       STRESS_N_M_PRODUCER_CONSUMER
>> >> +} stress_case_t;
>> >> +
>> >> +/* worker function declarations */
>> >> +static void *stress_worker(void *_data);
>> >> +
>> >> +/* global name for later look up in workers' context */
>> >> +static const char *ring_name = "stress ring";
>> >> +
>> >> +int ring_test_stress_start(void)
>> >> +{
>> >> +       /* multiple thread usage scenario only */
>> >> +       _ring_t *r_stress = _ring_create(ring_name, RING_SIZE,
>> >> +               0 /* not used, alignement
>> >> +                    taken care inside function: todo */);
>> >> +       if (r_stress == NULL) {
>> >> +               LOG_ERR("create ring failed for stress.\n");
>> >> +               return -1;
>> >> +       }
>> >> +
>> >> +       return 0;
>> >> +}
>> >> +
>> >> +void ring_test_stress_1_1_producer_consumer(void)
>> >> +{
>> >> +       int i = 0;
>> >> +       odp_cpumask_t cpus;
>> >> +       pthrd_arg worker_param;
>> >> +
>> >> +       /* reset results for delayed assertion */
>> >> +       memset(worker_results, 0, sizeof(worker_results));
>> >> +
>> >> +       /* request 2 threads to run 1:1 stress */
>> >> +       worker_param.numthrds = odp_cpumask_default_worker(&cpus, 2);
>> >> +       worker_param.testcase = STRESS_1_1_PRODUCER_CONSUMER;
>> >> +
>> >> +       /* not failure, insufficient resource */
>> >> +       if (worker_param.numthrds < 2) {
>> >> +               LOG_ERR("insufficient cpu for 1:1 "
>> >> +                       "producer/consumer stress.\n");
>> >> +               return;
>> >> +       }
>> >> +
>> >> +       /* kick the workers */
>> >> +       odp_cunit_thread_create(stress_worker, &worker_param);
>> >> +
>> >> +       /* collect the results */
>> >> +       odp_cunit_thread_exit(&worker_param);
>> >> +
>> >> +       /* delayed assertion due to cunit limitation */
>> >> +       for (i = 0; i < worker_param.numthrds; i++)
>> >> +               CU_ASSERT(0 == worker_results[i]);
>> >> +}
>> >> +
>> >> +void ring_test_stress_N_M_producer_consumer(void)
>> >> +{
>> >> +       int i = 0;
>> >> +       odp_cpumask_t cpus;
>> >> +       pthrd_arg worker_param;
>> >> +
>> >> +       /* reset results for delayed assertion */
>> >> +       memset(worker_results, 0, sizeof(worker_results));
>> >> +
>> >> +       /* request MAX_WORKERS threads to run N:M stress */
>> >> +       worker_param.numthrds =
>> >> +               odp_cpumask_default_worker(&cpus, MAX_WORKERS);
>> >> +       worker_param.testcase = STRESS_N_M_PRODUCER_CONSUMER;
>> >> +
>> >> +       /* not failure, insufficient resource */
>> >> +       if (worker_param.numthrds < 3) {
>> >> +               LOG_ERR("insufficient cpu for N:M "
>> >> +                       "producer/consumer stress.\n");
>> >> +               return;
>> >> +       }
>> >> +
>> >> +       /* kick the workers */
>> >> +       odp_cunit_thread_create(stress_worker, &worker_param);
>> >> +
>> >> +       /* collect the results */
>> >> +       odp_cunit_thread_exit(&worker_param);
>> >> +
>> >> +       /* delayed assertion due to cunit limitation */
>> >> +       for (i = 0; i < worker_param.numthrds; i++)
>> >> +               CU_ASSERT(0 == worker_results[i]);
>> >> +}
>> >> +
>> >> +void ring_test_stress_1_N_producer_consumer(void)
>> >> +{
>> >> +}
>> >> +
>> >> +void ring_test_stress_N_1_producer_consumer(void)
>> >> +{
>> >> +}
>> >> +
>> >> +void ring_test_stress_ring_list_dump(void)
>> >> +{
>> >> +       /* improve code coverage */
>> >> +       _ring_list_dump();
>> >> +}
>> >> +
>> >> +/* worker function for multiple producer instances */
>> >> +static int do_producer(_ring_t *r)
>> >> +{
>> >> +       int i, result = 0;
>> >> +       void **enq = NULL;
>> >> +
>> >> +       /* allocate dummy object pointers for enqueue */
>> >> +       enq = malloc(PIECE_BULK * 2 * sizeof(void *));
>> >> +       if (NULL == enq) {
>> >> +               LOG_ERR("insufficient memory for producer enqueue.\n");
>> >> +               return 0; /* not failure, skip for insufficient memory
>> */
>> >> +       }
>> >> +
>> >> +       /* data pattern to be evaluated later in consumer */
>> >> +       for (i = 0; i < PIECE_BULK; i++)
>> >> +               enq[i] = (void *)(unsigned long)i;
>> >> +
>> >> +       do {
>> >> +               result = _ring_mp_enqueue_bulk(r, enq, PIECE_BULK);
>> >> +               if (0 == result) {
>> >> +                       free(enq);
>> >> +                       return 0;
>> >> +               }
>> >> +       } while (1);
>> >> +}
>> >> +
>> >> +/* worker function for multiple consumer instances */
>> >> +static int do_consumer(_ring_t *r)
>> >> +{
>> >> +       int i, result = 0;
>> >> +       void **deq = NULL;
>> >> +       const char *message = "test OK!";
>> >> +       const char *mismatch = "data mismatch..lockless enq/deq
>> failed.";
>> >> +
>> >> +       /* allocate dummy object pointers for dequeue */
>> >> +       deq = malloc(PIECE_BULK * 2 * sizeof(void *));
>> >> +       if (NULL == deq) {
>> >> +               LOG_ERR("insufficient memory for consumer dequeue.\n");
>> >> +               return 0; /* not failure, skip for insufficient memory
>> */
>> >> +       }
>> >> +
>> >> +       do {
>> >> +               result = _ring_mc_dequeue_bulk(r, deq, PIECE_BULK);
>> >> +               if (0 == result) {
>> >> +                       /* evaluate the data pattern */
>> >> +                       for (i = 0; i < PIECE_BULK; i++) {
>> >> +                               if (deq[i] != (void *)(unsigned
>> long)i) {
>> >> +                                       result = -1;
>> >> +                                       message = mismatch;
>> >> +                                       break;
>> >> +                               }
>> >> +                       }
>> >> +
>> >> +                       free(deq);
>> >> +                       LOG_ERR("%s\n", message);
>> >> +                       return result;
>> >> +               }
>> >> +       } while (1);
>> >> +}
>> >> +
>> >> +static void *stress_worker(void *_data)
>> >> +{
>> >> +       pthrd_arg *worker_param = (pthrd_arg *)_data;
>> >> +       _ring_t *r_stress = NULL;
>> >> +
>> >> +       int worker_id = odp_thread_id();
>> >> +       /* save the worker result for delayed assertion */
>> >> +       int *result = &worker_results[(worker_id %
>> >> worker_param->numthrds)];
>> >> +
>> >> +       /* verify ring lookup in worker context */
>> >> +       r_stress = _ring_lookup(ring_name);
>> >> +       if (NULL == r_stress) {
>> >> +               LOG_ERR("ring lookup %s not found\n", ring_name);
>> >> +               *result = -1;
>> >> +               return NULL;
>> >> +       }
>> >> +
>> >> +       switch (worker_param->testcase) {
>> >> +       case STRESS_1_1_PRODUCER_CONSUMER:
>> >> +       case STRESS_N_M_PRODUCER_CONSUMER:
>> >> +               /* interleaved producer/consumer */
>> >> +               if (0 == (worker_id % 2))
>> >> +                       *result = do_producer(r_stress);
>> >> +               else if (1 == (worker_id % 2))
>> >> +                       *result = do_consumer(r_stress);
>> >> +               break;
>> >> +       case STRESS_1_N_PRODUCER_CONSUMER:
>> >> +       case STRESS_N_1_PRODUCER_CONSUMER:
>> >> +       default:
>> >> +               LOG_ERR("invalid or not-implemented stress type
>> (%d)\n",
>> >> +                       worker_param->testcase);
>> >> +               break;
>> >> +       }
>> >> +       return NULL;
>> >> +}
>> >> diff --git a/platform/linux-generic/test/ring/ring_suites.c
>> >> b/platform/linux-generic/test/ring/ring_suites.c
>> >> new file mode 100644
>> >> index 0000000..b310843
>> >> --- /dev/null
>> >> +++ b/platform/linux-generic/test/ring/ring_suites.c
>> >> @@ -0,0 +1,70 @@
>> >> +/* Copyright (c) 2015, Linaro Limited
>> >> + * All rights reserved.
>> >> + *
>> >> + * SPDX-License-Identifier:     BSD-3-Clause
>> >> + */
>> >> +
>> >> +#include <stdlib.h>
>> >> +#include <stdio.h>
>> >> +#include <string.h>
>> >> +
>> >> +#include <odp_api.h>
>> >> +#include <test_debug.h>
>> >> +#include <odp_cunit_common.h>
>> >> +#include <odp_packet_io_ring_internal.h>
>> >> +
>> >> +#include "ring_suites.h"
>> >> +
>> >> +static int ring_suites_init(odp_instance_t *inst)
>> >> +{
>> >> +       if (0 != odp_init_global(inst, NULL, NULL)) {
>> >> +               LOG_ERR("error: odp_init_global() failed.\n");
>> >> +               return -1;
>> >> +       }
>> >> +       if (0 != odp_init_local(*inst, ODP_THREAD_CONTROL)) {
>> >> +               LOG_ERR("error: odp_init_local() failed.\n");
>> >> +               return -1;
>> >> +       }
>> >> +
>> >> +       _ring_tailq_init();
>> >> +       return 0;
>> >> +}
>> >> +
>> >> +static odp_testinfo_t ring_suite_basic[] = {
>> >> +       ODP_TEST_INFO(ring_test_basic_create),
>> >> +       ODP_TEST_INFO(ring_test_basic_burst),
>> >> +       ODP_TEST_INFO(ring_test_basic_bulk),
>> >> +       ODP_TEST_INFO(ring_test_basic_watermark),
>> >> +       ODP_TEST_INFO_NULL,
>> >> +};
>> >> +
>> >> +static odp_testinfo_t ring_suite_stress[] = {
>> >> +       ODP_TEST_INFO(ring_test_stress_1_1_producer_consumer),
>> >> +       ODP_TEST_INFO(ring_test_stress_1_N_producer_consumer),
>> >> +       ODP_TEST_INFO(ring_test_stress_N_1_producer_consumer),
>> >> +       ODP_TEST_INFO(ring_test_stress_N_M_producer_consumer),
>> >> +       ODP_TEST_INFO(ring_test_stress_ring_list_dump),
>> >> +       ODP_TEST_INFO_NULL,
>> >> +};
>> >> +
>> >> +static odp_suiteinfo_t ring_suites[] = {
>> >> +       {"ring basic", ring_test_basic_start,
>> >> +               ring_test_basic_end, ring_suite_basic},
>> >> +       {"ring stress", ring_test_stress_start,
>> >> +               NULL, ring_suite_stress},
>> >> +       ODP_SUITE_INFO_NULL
>> >> +};
>> >> +
>> >> +int ring_suites_main(void)
>> >> +{
>> >> +       int ret;
>> >> +
>> >> +       odp_cunit_register_global_init(ring_suites_init);
>> >> +
>> >> +       ret = odp_cunit_register(ring_suites);
>> >> +
>> >> +       if (ret == 0)
>> >> +               ret = odp_cunit_run();
>> >> +
>> >> +       return ret;
>> >> +}
>> >> diff --git a/platform/linux-generic/test/ring/ring_suites.h
>> >> b/platform/linux-generic/test/ring/ring_suites.h
>> >> new file mode 100644
>> >> index 0000000..e26b6e8
>> >> --- /dev/null
>> >> +++ b/platform/linux-generic/test/ring/ring_suites.h
>> >> @@ -0,0 +1,33 @@
>> >> +/* Copyright (c) 2015, Linaro Limited
>> >> + * All rights reserved.
>> >> + *
>> >> + * SPDX-License-Identifier:     BSD-3-Clause
>> >> + */
>> >> +
>> >> +#define RING_SIZE 4096
>> >> +#define PIECE_BULK 32
>> >> +
>> >> +#define HALF_BULK (RING_SIZE >> 1)
>> >> +#define ILLEGAL_SIZE (RING_SIZE | 0x3)
>> >> +
>> >> +/* test suite start and stop */
>> >> +int ring_test_basic_start(void);
>> >> +int ring_test_basic_end(void);
>> >> +
>> >> +/* basic test cases */
>> >> +void ring_test_basic_create(void);
>> >> +void ring_test_basic_burst(void);
>> >> +void ring_test_basic_bulk(void);
>> >> +void ring_test_basic_watermark(void);
>> >> +
>> >> +/* test suite start and stop */
>> >> +int ring_test_stress_start(void);
>> >> +
>> >> +/* stress test cases */
>> >> +void ring_test_stress_1_1_producer_consumer(void);
>> >> +void ring_test_stress_1_N_producer_consumer(void);
>> >> +void ring_test_stress_N_1_producer_consumer(void);
>> >> +void ring_test_stress_N_M_producer_consumer(void);
>> >> +void ring_test_stress_ring_list_dump(void);
>> >> +
>> >> +int ring_suites_main(void);
>> >> diff --git a/platform/linux-generic/test/ring/ringtest.c
>> >> b/platform/linux-generic/test/ring/ringtest.c
>> >> deleted file mode 100644
>> >> index ac0aa61..0000000
>> >> --- a/platform/linux-generic/test/ring/ringtest.c
>> >> +++ /dev/null
>> >> @@ -1,493 +0,0 @@
>> >> -/* Copyright (c) 2014, Linaro Limited
>> >> - * All rights reserved.
>> >> - *
>> >> - * SPDX-License-Identifier:     BSD-3-Clause
>> >> - */
>> >> -
>> >> -/*-
>> >> - *   BSD LICENSE
>> >> - *
>> >> - *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
>> >> - *   All rights reserved.
>> >> - *
>> >> - *   Redistribution and use in source and binary forms, with or
>> without
>> >> - *   modification, are permitted provided that the following
>> conditions
>> >> - *   are met:
>> >> - *
>> >> - *     * Redistributions of source code must retain the above
>> copyright
>> >> - *       notice, this list of conditions and the following disclaimer.
>> >> - *     * Redistributions in binary form must reproduce the above
>> >> copyright
>> >> - *       notice, this list of conditions and the following disclaimer
>> in
>> >> - *       the documentation and/or other materials provided with the
>> >> - *       distribution.
>> >> - *     * Neither the name of Intel Corporation nor the names of its
>> >> - *       contributors may be used to endorse or promote products
>> derived
>> >> - *       from this software without specific prior written permission.
>> >> - *
>> >> - *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
>> CONTRIBUTORS
>> >> - *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
>> >> - *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
>> >> FOR
>> >> - *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
>> COPYRIGHT
>> >> - *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
>> >> INCIDENTAL,
>> >> - *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>> >> - *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>> >> USE,
>> >> - *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
>> >> ANY
>> >> - *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>> TORT
>> >> - *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
>> >> USE
>> >> - *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
>> DAMAGE.
>> >> - */
>> >> -
>> >> -/**
>> >> - * @file
>> >> - *
>> >> - * ODP test ring
>> >> - */
>> >> -
>> >> -#include <stdlib.h>
>> >> -#include <stdio.h>
>> >> -#include <string.h>
>> >> -
>> >> -#include <odp_api.h>
>> >> -#include <odp/helper/linux.h>
>> >> -#include <odp_packet_io_ring_internal.h>
>> >> -#include <test_debug.h>
>> >> -#include <odp_cunit_common.h>
>> >> -
>> >> -#define RING_SIZE 4096
>> >> -#define MAX_BULK 32
>> >> -
>> >> -enum {
>> >> -       ODP_RING_TEST_BASIC,
>> >> -       ODP_RING_TEST_STRESS,
>> >> -};
>> >> -
>> >> -/* local struct for ring_thread argument */
>> >> -typedef struct {
>> >> -       pthrd_arg thrdarg;
>> >> -       int stress_type;
>> >> -} ring_arg_t;
>> >> -
>> >> -static int test_ring_basic(_ring_t *r)
>> >> -{
>> >> -       void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst =
>> >> NULL;
>> >> -       int ret;
>> >> -       unsigned i, num_elems;
>> >> -
>> >> -       /* alloc dummy object pointers */
>> >> -       src = malloc(RING_SIZE * 2 * sizeof(void *));
>> >> -       if (src == NULL) {
>> >> -               LOG_ERR("failed to allocate test ring src memory\n");
>> >> -               goto fail;
>> >> -       }
>> >> -       for (i = 0; i < RING_SIZE * 2; i++)
>> >> -               src[i] = (void *)(unsigned long)i;
>> >> -
>> >> -       cur_src = src;
>> >> -
>> >> -       /* alloc some room for copied objects */
>> >> -       dst = malloc(RING_SIZE * 2 * sizeof(void *));
>> >> -       if (dst == NULL) {
>> >> -               LOG_ERR("failed to allocate test ring dst memory\n");
>> >> -               goto fail;
>> >> -       }
>> >> -
>> >> -       memset(dst, 0, RING_SIZE * 2 * sizeof(void *));
>> >> -       cur_dst = dst;
>> >> -
>> >> -       printf("Test SP & SC basic functions\n");
>> >> -       printf("enqueue 1 obj\n");
>> >> -       ret = _ring_sp_enqueue_burst(r, cur_src, 1);
>> >> -       cur_src += 1;
>> >> -       if ((ret & _RING_SZ_MASK) != 1) {
>> >> -               LOG_ERR("sp_enq for 1 obj failed\n");
>> >> -               goto fail;
>> >> -       }
>> >> -
>> >> -       printf("enqueue 2 objs\n");
>> >> -       ret = _ring_sp_enqueue_burst(r, cur_src, 2);
>> >> -       cur_src += 2;
>> >> -       if ((ret & _RING_SZ_MASK) != 2) {
>> >> -               LOG_ERR("sp_enq for 2 obj failed\n");
>> >> -               goto fail;
>> >> -       }
>> >> -
>> >> -       printf("enqueue MAX_BULK objs\n");
>> >> -       ret = _ring_sp_enqueue_burst(r, cur_src, MAX_BULK);
>> >> -       if ((ret & _RING_SZ_MASK) != MAX_BULK) {
>> >> -               LOG_ERR("sp_enq for %d obj failed\n", MAX_BULK);
>> >> -               goto fail;
>> >> -       }
>> >> -
>> >> -       printf("dequeue 1 obj\n");
>> >> -       ret = _ring_sc_dequeue_burst(r, cur_dst, 1);
>> >> -       cur_dst += 1;
>> >> -       if ((ret & _RING_SZ_MASK) != 1) {
>> >> -               LOG_ERR("sc_deq for 1 obj failed\n");
>> >> -               goto fail;
>> >> -       }
>> >> -
>> >> -       printf("dequeue 2 objs\n");
>> >> -       ret = _ring_sc_dequeue_burst(r, cur_dst, 2);
>> >> -       cur_dst += 2;
>> >> -       if ((ret & _RING_SZ_MASK) != 2) {
>> >> -               LOG_ERR("sc_deq for 2 obj failed\n");
>> >> -               goto fail;
>> >> -       }
>> >> -
>> >> -       printf("dequeue MAX_BULK objs\n");
>> >> -       ret = _ring_sc_dequeue_burst(r, cur_dst, MAX_BULK);
>> >> -       cur_dst += MAX_BULK;
>> >> -       if ((ret & _RING_SZ_MASK) != MAX_BULK) {
>> >> -               LOG_ERR("sc_deq for %d obj failed\n", MAX_BULK);
>> >> -               goto fail;
>> >> -       }
>> >> -
>> >> -       /* check data */
>> >> -       if (memcmp(src, dst, cur_dst - dst)) {
>> >> -               LOG_ERR("data after dequeue is not the same\n");
>> >> -               goto fail;
>> >> -       }
>> >> -
>> >> -       cur_src = src;
>> >> -       cur_dst = dst;
>> >> -
>> >> -       printf("Test MP & MC basic functions\n");
>> >> -
>> >> -       printf("enqueue 1 obj\n");
>> >> -       ret = _ring_mp_enqueue_bulk(r, cur_src, 1);
>> >> -       cur_src += 1;
>> >> -       if (ret != 0) {
>> >> -               LOG_ERR("mp_enq for 1 obj failed\n");
>> >> -               goto fail;
>> >> -       }
>> >> -       printf("enqueue 2 objs\n");
>> >> -       ret = _ring_mp_enqueue_bulk(r, cur_src, 2);
>> >> -       cur_src += 2;
>> >> -       if (ret != 0) {
>> >> -               LOG_ERR("mp_enq for 2 obj failed\n");
>> >> -               goto fail;
>> >> -       }
>> >> -       printf("enqueue MAX_BULK objs\n");
>> >> -       ret = _ring_mp_enqueue_bulk(r, cur_src, MAX_BULK);
>> >> -       if (ret != 0) {
>> >> -               LOG_ERR("mp_enq for %d obj failed\n", MAX_BULK);
>> >> -               goto fail;
>> >> -       }
>> >> -       printf("dequeue 1 obj\n");
>> >> -       ret = _ring_mc_dequeue_bulk(r, cur_dst, 1);
>> >> -       cur_dst += 1;
>> >> -       if (ret != 0) {
>> >> -               LOG_ERR("mc_deq for 1 obj failed\n");
>> >> -               goto fail;
>> >> -       }
>> >> -       printf("dequeue 2 objs\n");
>> >> -       ret = _ring_mc_dequeue_bulk(r, cur_dst, 2);
>> >> -       cur_dst += 2;
>> >> -       if (ret != 0) {
>> >> -               LOG_ERR("mc_deq for 2 obj failed\n");
>> >> -               goto fail;
>> >> -       }
>> >> -       printf("dequeue MAX_BULK objs\n");
>> >> -       ret = _ring_mc_dequeue_bulk(r, cur_dst, MAX_BULK);
>> >> -       cur_dst += MAX_BULK;
>> >> -       if (ret != 0) {
>> >> -               LOG_ERR("mc_deq for %d obj failed\n", MAX_BULK);
>> >> -               goto fail;
>> >> -       }
>> >> -       /* check data */
>> >> -       if (memcmp(src, dst, cur_dst - dst)) {
>> >> -               LOG_ERR("data after dequeue is not the same\n");
>> >> -               goto fail;
>> >> -       }
>> >> -
>> >> -       printf("test watermark and default bulk enqueue / dequeue\n");
>> >> -       _ring_set_water_mark(r, 20);
>> >> -       num_elems = 16;
>> >> -
>> >> -       cur_src = src;
>> >> -       cur_dst = dst;
>> >> -
>> >> -       ret = _ring_mp_enqueue_bulk(r, cur_src, num_elems);
>> >> -       cur_src += num_elems;
>> >> -       if (ret != 0) {
>> >> -               LOG_ERR("Cannot enqueue\n");
>> >> -               goto fail;
>> >> -       }
>> >> -       ret = _ring_mp_enqueue_bulk(r, cur_src, num_elems);
>> >> -       if (ret != -EDQUOT) {
>> >> -               LOG_ERR("Watermark not exceeded\n");
>> >> -               goto fail;
>> >> -       }
>> >> -       ret = _ring_mc_dequeue_bulk(r, cur_dst, num_elems);
>> >> -       cur_dst += num_elems;
>> >> -       if (ret != 0) {
>> >> -               LOG_ERR("Cannot dequeue\n");
>> >> -               goto fail;
>> >> -       }
>> >> -       ret = _ring_mc_dequeue_bulk(r, cur_dst, num_elems);
>> >> -       cur_dst += num_elems;
>> >> -       if (ret != 0) {
>> >> -               LOG_ERR("Cannot dequeue2\n");
>> >> -               goto fail;
>> >> -       }
>> >> -
>> >> -       /* check data */
>> >> -       if (memcmp(src, dst, cur_dst - dst)) {
>> >> -               LOG_ERR("data after dequeue is not the same\n");
>> >> -               goto fail;
>> >> -       }
>> >> -
>> >> -       printf("basic enqueu, dequeue test for ring <%s>@%p passed\n",
>> >> -              r->name, r);
>> >> -
>> >> -       free(src);
>> >> -       free(dst);
>> >> -       return 0;
>> >> -
>> >> -fail:
>> >> -       free(src);
>> >> -       free(dst);
>> >> -       return -1;
>> >> -}
>> >> -
>> >> -/* global shared ring used for stress testing */
>> >> -static _ring_t *r_stress;
>> >> -
>> >> -/* Stress func for Multi producer only */
>> >> -static int producer_fn(void)
>> >> -{
>> >> -       unsigned i;
>> >> -
>> >> -       void **src = NULL;
>> >> -
>> >> -       /* alloc dummy object pointers */
>> >> -       src = malloc(MAX_BULK * 2 * sizeof(void *));
>> >> -       if (src == NULL) {
>> >> -               LOG_ERR("failed to allocate producer memory.\n");
>> >> -               return -1;
>> >> -       }
>> >> -       for (i = 0; i < MAX_BULK; i++)
>> >> -               src[i] = (void *)(unsigned long)i;
>> >> -
>> >> -       do {
>> >> -               i = _ring_mp_enqueue_bulk(r_stress, src, MAX_BULK);
>> >> -               if (i == 0) {
>> >> -                       free(src);
>> >> -                       return 0;
>> >> -               }
>> >> -       } while (1);
>> >> -}
>> >> -
>> >> -/* Stress func for Multi consumer only */
>> >> -static int consumer_fn(void)
>> >> -{
>> >> -       unsigned i;
>> >> -       void **src = NULL;
>> >> -
>> >> -       /* alloc dummy object pointers */
>> >> -       src = malloc(MAX_BULK * 2 * sizeof(void *));
>> >> -       if (src == NULL) {
>> >> -               LOG_ERR("failed to allocate consumer memory.\n");
>> >> -               return -1;
>> >> -       }
>> >> -
>> >> -       do {
>> >> -               i = _ring_mc_dequeue_bulk(r_stress, src, MAX_BULK);
>> >> -               if (i == 0) {
>> >> -                       for (i = 0; i < MAX_BULK; i++) {
>> >> -                               if (src[i] != (void *)(unsigned
>> long)i) {
>> >> -                                       free(src);
>> >> -                                       printf("data mismatch..
>> lockless
>> >> ops fail\n");
>> >> -                                       return -1;
>> >> -                               }
>> >> -                       }
>> >> -                       free(src);
>> >> -                       printf("\n Test OK !\n");
>> >> -                       return 0;
>> >> -               }
>> >> -       } while (1);
>> >> -}
>> >> -
>> >> -/*
>> >> - * Note : make sure that both enqueue and dequeue
>> >> - * operation starts at same time so to avoid data corruption
>> >> - * Its because atomic lock will protect only indexes, but if order of
>> >> - * read or write operation incorrect then data mismatch will happen
>> >> - * So its resposibility of application develop to take care of order
>> of
>> >> - * data read or write.
>> >> -*/
>> >> -typedef enum {
>> >> -       one_enq_one_deq,        /* One thread to enqueue one to
>> >> -                                  dequeu at same time */
>> >> -       one_enq_rest_deq,       /* one thread to enq rest to
>> >> -                                  dequeue at same time */
>> >> -       one_deq_rest_enq,       /* one to deq and rest enq at very same
>> >> time */
>> >> -       multi_enq_multi_deq     /* multiple enq,deq */
>> >> -} stress_type_t;
>> >> -
>> >> -static void test_ring_stress(stress_type_t type)
>> >> -{
>> >> -       int thr;
>> >> -
>> >> -       thr = odp_thread_id();
>> >> -
>> >> -       switch (type) {
>> >> -       case one_enq_one_deq:
>> >> -               if (thr == 1)
>> >> -                       producer_fn();
>> >> -               if (thr == 2)
>> >> -                       consumer_fn();
>> >> -               break;
>> >> -       case multi_enq_multi_deq:
>> >> -               if (thr % 2 == 0)
>> >> -                       producer_fn();
>> >> -               else
>> >> -                       consumer_fn();
>> >> -               break;
>> >> -       case one_deq_rest_enq:
>> >> -       case one_enq_rest_deq:/*TBD*/
>> >> -       default:
>> >> -               LOG_ERR("Invalid stress type or test case yet not
>> >> supported\n");
>> >> -       }
>> >> -}
>> >> -
>> >> -static void *test_ring(void *arg)
>> >> -{
>> >> -       ring_arg_t *parg = (ring_arg_t *)arg;
>> >> -       int thr;
>> >> -       char ring_name[_RING_NAMESIZE];
>> >> -       _ring_t *r;
>> >> -       int result = 0;
>> >> -
>> >> -       thr = odp_thread_id();
>> >> -
>> >> -       printf("Thread %i starts\n", thr);
>> >> -
>> >> -       switch (parg->thrdarg.testcase) {
>> >> -       case ODP_RING_TEST_BASIC:
>> >> -               snprintf(ring_name, sizeof(ring_name), "test_ring_%i",
>> >> thr);
>> >> -
>> >> -               r = _ring_create(ring_name, RING_SIZE,
>> >> -                                0 /* not used, alignement
>> >> -                                     taken care inside func : todo
>> */);
>> >> -               if (r == NULL) {
>> >> -                       LOG_ERR("ring create failed\n");
>> >> -                       result = -1;
>> >> -                       break;
>> >> -               }
>> >> -               /* lookup ring from its name */
>> >> -               if (_ring_lookup(ring_name) != r) {
>> >> -                       LOG_ERR("ring lookup failed\n");
>> >> -                       result = -1;
>> >> -                       break;
>> >> -               }
>> >> -
>> >> -               /* basic operations */
>> >> -               if (test_ring_basic(r) < 0) {
>> >> -                       LOG_ERR("ring basic enqueue/dequeu ops
>> failed\n");
>> >> -                       result = -1;
>> >> -               }
>> >> -
>> >> -               if (result)
>> >> -                       _ring_list_dump();
>> >> -
>> >> -               break;
>> >> -
>> >> -       case ODP_RING_TEST_STRESS:
>> >> -               test_ring_stress(parg->stress_type);
>> >> -
>> >> -               if (result)
>> >> -                       _ring_list_dump();
>> >> -               break;
>> >> -
>> >> -       default:
>> >> -               LOG_ERR("Invalid test case [%d]\n",
>> >> parg->thrdarg.testcase);
>> >> -               result = -1;
>> >> -               break;
>> >> -       }
>> >> -
>> >> -       LOG_DBG("result = %d\n", result);
>> >> -       if (result == 0)
>> >> -               printf("test_ring Result:pass\n");
>> >> -       else
>> >> -               printf("test_ring Result:fail\n");
>> >> -
>> >> -       fflush(stdout);
>> >> -
>> >> -       return parg;
>> >> -}
>> >> -
>> >> -int main(int argc TEST_UNUSED, char *argv[] TEST_UNUSED)
>> >> -{
>> >> -       ring_arg_t rarg;
>> >> -       odph_linux_pthread_t thread_tbl[MAX_WORKERS];
>> >> -       odp_cpumask_t cpu_mask;
>> >> -       int num_workers;
>> >> -       char ring_name[_RING_NAMESIZE];
>> >> -       odp_instance_t instance;
>> >> -       odph_linux_thr_params_t thr_params;
>> >> -
>> >> -       if (odp_init_global(&instance, NULL, NULL)) {
>> >> -               LOG_ERR("Error: ODP global init failed.\n");
>> >> -               exit(EXIT_FAILURE);
>> >> -       }
>> >> -
>> >> -       if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
>> >> -               LOG_ERR("Error: ODP local init failed.\n");
>> >> -               exit(EXIT_FAILURE);
>> >> -       }
>> >> -
>> >> -       _ring_tailq_init();
>> >> -
>> >> -       num_workers = odp_cpumask_default_worker(&cpu_mask,
>> MAX_WORKERS);
>> >> -       rarg.thrdarg.numthrds = rarg.thrdarg.numthrds;
>> >> -
>> >> -       rarg.thrdarg.testcase = ODP_RING_TEST_BASIC;
>> >> -
>> >> -       memset(&thr_params, 0, sizeof(thr_params));
>> >> -       thr_params.start    = test_ring;
>> >> -       thr_params.arg      = &rarg;
>> >> -       thr_params.thr_type = ODP_THREAD_WORKER;
>> >> -       thr_params.instance = instance;
>> >> -
>> >> -       printf("starting stess test type : %d..\n", rarg.stress_type);
>> >> -       odph_linux_pthread_create(&thread_tbl[0], &cpu_mask,
>> &thr_params);
>> >> -       odph_linux_pthread_join(thread_tbl, num_workers);
>> >> -
>> >> -       rarg.thrdarg.testcase = ODP_RING_TEST_STRESS;
>> >> -       rarg.stress_type = one_enq_one_deq;
>> >> -
>> >> -       printf("starting stess test type : %d..\n", rarg.stress_type);
>> >> -       snprintf(ring_name, sizeof(ring_name), "test_ring_stress");
>> >> -       r_stress = _ring_create(ring_name, RING_SIZE,
>> >> -                               0/* not used, alignement
>> >> -                                   taken care inside func : todo */);
>> >> -       if (r_stress == NULL) {
>> >> -               LOG_ERR("ring create failed\n");
>> >> -               goto fail;
>> >> -       }
>> >> -       /* lookup ring from its name */
>> >> -       if (_ring_lookup(ring_name) != r_stress) {
>> >> -               LOG_ERR("ring lookup failed\n");
>> >> -               goto fail;
>> >> -       }
>> >> -
>> >> -       thr_params.start = test_ring;
>> >> -       thr_params.arg   = &rarg;
>> >> -
>> >> -       odph_linux_pthread_create(&thread_tbl[0], &cpu_mask,
>> &thr_params);
>> >> -       odph_linux_pthread_join(thread_tbl, num_workers);
>> >> -
>> >> -fail:
>> >> -       if (odp_term_local()) {
>> >> -               LOG_ERR("Error: ODP local term failed.\n");
>> >> -               exit(EXIT_FAILURE);
>> >> -       }
>> >> -
>> >> -       if (odp_term_global(instance)) {
>> >> -               LOG_ERR("Error: ODP global term failed.\n");
>> >> -               exit(EXIT_FAILURE);
>> >> -       }
>> >> -
>> >> -       return 0;
>> >> -}
>> >>
>> >
>> > _______________________________________________
>> > lng-odp mailing list
>> > lng-odp@lists.linaro.org
>> <javascript:_e(%7B%7D,'cvml','lng-odp@lists.linaro.org');>
>> > https://lists.linaro.org/mailman/listinfo/lng-odp
>> >
>> _______________________________________________
>> lng-odp mailing list
>> lng-odp@lists.linaro.org
>> <javascript:_e(%7B%7D,'cvml','lng-odp@lists.linaro.org');>
>> https://lists.linaro.org/mailman/listinfo/lng-odp
>>
>
>
_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to