diff mbox

[1/2] validation: synchro tests split into 3 groups

Message ID 1450107982-30298-1-git-send-email-christophe.milard@linaro.org
State Superseded
Headers show

Commit Message

Christophe Milard Dec. 14, 2015, 3:46 p.m. UTC
No functionnal changes: just code reordering to match the ODP modules.

Signed-off-by: Christophe Milard <christophe.milard@linaro.org>
---
 configure.ac                            |    3 +
 platform/linux-generic/test/Makefile.am |    3 +
 test/validation/Makefile.am             |    5 +-
 test/validation/atomic/.gitignore       |    1 +
 test/validation/atomic/Makefile.am      |   10 +
 test/validation/atomic/atomic.c         |  441 ++++++++++++
 test/validation/atomic/atomic.h         |   33 +
 test/validation/atomic/atomic_main.c    |   12 +
 test/validation/barrier/.gitignore      |    1 +
 test/validation/barrier/Makefile.am     |   10 +
 test/validation/barrier/barrier.c       |  370 ++++++++++
 test/validation/barrier/barrier.h       |   28 +
 test/validation/barrier/barrier_main.c  |   12 +
 test/validation/lock/.gitignore         |    1 +
 test/validation/lock/Makefile.am        |   10 +
 test/validation/lock/lock.c             | 1135 +++++++++++++++++++++++++++++++
 test/validation/lock/lock.h             |   45 ++
 test/validation/lock/lock_main.c        |   12 +
 18 files changed, 2131 insertions(+), 1 deletion(-)
 create mode 100644 test/validation/atomic/.gitignore
 create mode 100644 test/validation/atomic/Makefile.am
 create mode 100644 test/validation/atomic/atomic.c
 create mode 100644 test/validation/atomic/atomic.h
 create mode 100644 test/validation/atomic/atomic_main.c
 create mode 100644 test/validation/barrier/.gitignore
 create mode 100644 test/validation/barrier/Makefile.am
 create mode 100644 test/validation/barrier/barrier.c
 create mode 100644 test/validation/barrier/barrier.h
 create mode 100644 test/validation/barrier/barrier_main.c
 create mode 100644 test/validation/lock/.gitignore
 create mode 100644 test/validation/lock/Makefile.am
 create mode 100644 test/validation/lock/lock.c
 create mode 100644 test/validation/lock/lock.h
 create mode 100644 test/validation/lock/lock_main.c

Comments

Bill Fischofer Dec. 17, 2015, 12:02 a.m. UTC | #1
Patch fails to apply.  Needs a rebase?

bill@Ubuntu15:~/linaro/christophe$ git am --reject
~/Mail/Incoming/Christophe/1
Applying: validation: synchro tests split into 3 groups
Checking patch configure.ac...
Hunk #1 succeeded at 348 (offset -1 lines).
error: while searching for:
test/validation/errno/Makefile
test/validation/hash/Makefile
test/validation/init/Makefile
test/validation/packet/Makefile
test/validation/pktio/Makefile
test/validation/pool/Makefile

error: patch failed: configure.ac:358
Checking patch platform/linux-generic/test/Makefile.am...
Hunk #2 succeeded at 17 (offset -1 lines).
Checking patch test/validation/Makefile.am...
error: while searching for:
     errno \
     hash \
     init \
     queue \
     packet \
     pktio \

error: patch failed: test/validation/Makefile.am:6
Checking patch test/validation/atomic/.gitignore...
Checking patch test/validation/atomic/Makefile.am...
Checking patch test/validation/atomic/atomic.c...
Checking patch test/validation/atomic/atomic.h...
Checking patch test/validation/atomic/atomic_main.c...
Checking patch test/validation/barrier/.gitignore...
Checking patch test/validation/barrier/Makefile.am...
Checking patch test/validation/barrier/barrier.c...
Checking patch test/validation/barrier/barrier.h...
Checking patch test/validation/barrier/barrier_main.c...
Checking patch test/validation/lock/.gitignore...
Checking patch test/validation/lock/Makefile.am...
Checking patch test/validation/lock/lock.c...
Checking patch test/validation/lock/lock.h...
Checking patch test/validation/lock/lock_main.c...
Applying patch configure.ac with 1 reject...
Hunk #1 applied cleanly.
Rejected hunk #2.
Applied patch platform/linux-generic/test/Makefile.am cleanly.
Applying patch test/validation/Makefile.am with 1 reject...
Hunk #1 applied cleanly.
Rejected hunk #2.
Applied patch test/validation/atomic/.gitignore cleanly.
Applied patch test/validation/atomic/Makefile.am cleanly.
Applied patch test/validation/atomic/atomic.c cleanly.
Applied patch test/validation/atomic/atomic.h cleanly.
Applied patch test/validation/atomic/atomic_main.c cleanly.
Applied patch test/validation/barrier/.gitignore cleanly.
Applied patch test/validation/barrier/Makefile.am cleanly.
Applied patch test/validation/barrier/barrier.c cleanly.
Applied patch test/validation/barrier/barrier.h cleanly.
Applied patch test/validation/barrier/barrier_main.c cleanly.
Applied patch test/validation/lock/.gitignore cleanly.
Applied patch test/validation/lock/Makefile.am cleanly.
Applied patch test/validation/lock/lock.c cleanly.
Applied patch test/validation/lock/lock.h cleanly.
Applied patch test/validation/lock/lock_main.c cleanly.
Patch failed at 0001 validation: synchro tests split into 3 groups


On Mon, Dec 14, 2015 at 9:46 AM, Christophe Milard <
christophe.milard@linaro.org> wrote:

> No functionnal changes: just code reordering to match the ODP modules.

>

> Signed-off-by: Christophe Milard <christophe.milard@linaro.org>

> ---

>  configure.ac                            |    3 +

>  platform/linux-generic/test/Makefile.am |    3 +

>  test/validation/Makefile.am             |    5 +-

>  test/validation/atomic/.gitignore       |    1 +

>  test/validation/atomic/Makefile.am      |   10 +

>  test/validation/atomic/atomic.c         |  441 ++++++++++++

>  test/validation/atomic/atomic.h         |   33 +

>  test/validation/atomic/atomic_main.c    |   12 +

>  test/validation/barrier/.gitignore      |    1 +

>  test/validation/barrier/Makefile.am     |   10 +

>  test/validation/barrier/barrier.c       |  370 ++++++++++

>  test/validation/barrier/barrier.h       |   28 +

>  test/validation/barrier/barrier_main.c  |   12 +

>  test/validation/lock/.gitignore         |    1 +

>  test/validation/lock/Makefile.am        |   10 +

>  test/validation/lock/lock.c             | 1135

> +++++++++++++++++++++++++++++++

>  test/validation/lock/lock.h             |   45 ++

>  test/validation/lock/lock_main.c        |   12 +

>  18 files changed, 2131 insertions(+), 1 deletion(-)

>  create mode 100644 test/validation/atomic/.gitignore

>  create mode 100644 test/validation/atomic/Makefile.am

>  create mode 100644 test/validation/atomic/atomic.c

>  create mode 100644 test/validation/atomic/atomic.h

>  create mode 100644 test/validation/atomic/atomic_main.c

>  create mode 100644 test/validation/barrier/.gitignore

>  create mode 100644 test/validation/barrier/Makefile.am

>  create mode 100644 test/validation/barrier/barrier.c

>  create mode 100644 test/validation/barrier/barrier.h

>  create mode 100644 test/validation/barrier/barrier_main.c

>  create mode 100644 test/validation/lock/.gitignore

>  create mode 100644 test/validation/lock/Makefile.am

>  create mode 100644 test/validation/lock/lock.c

>  create mode 100644 test/validation/lock/lock.h

>  create mode 100644 test/validation/lock/lock_main.c

>

> diff --git a/configure.ac b/configure.ac

> index 4f89f03..7a05574 100644

> --- a/configure.ac

> +++ b/configure.ac

> @@ -349,6 +349,8 @@ AC_CONFIG_FILES([Makefile

>                  test/api_test/Makefile

>                  test/performance/Makefile

>                  test/validation/Makefile

> +                test/validation/atomic/Makefile

> +                test/validation/barrier/Makefile

>                  test/validation/buffer/Makefile

>                  test/validation/classification/Makefile

>                  test/validation/config/Makefile

> @@ -358,6 +360,7 @@ AC_CONFIG_FILES([Makefile

>                  test/validation/errno/Makefile

>                  test/validation/hash/Makefile

>                  test/validation/init/Makefile

> +                test/validation/lock/Makefile

>                  test/validation/packet/Makefile

>                  test/validation/pktio/Makefile

>                  test/validation/pool/Makefile

> diff --git a/platform/linux-generic/test/Makefile.am

> b/platform/linux-generic/test/Makefile.am

> index e629872..aa246d2 100644

> --- a/platform/linux-generic/test/Makefile.am

> +++ b/platform/linux-generic/test/Makefile.am

> @@ -6,6 +6,8 @@ ODP_MODULES = pktio

>  if test_vald

>  TESTS = pktio/pktio_run \

>         pktio/pktio_run_tap \

> +       ${top_builddir}/test/validation/atomic/atomic_main$(EXEEXT) \

> +       ${top_builddir}/test/validation/barrier/barrier_main$(EXEEXT) \

>         ${top_builddir}/test/validation/buffer/buffer_main$(EXEEXT) \

>

> ${top_builddir}/test/validation/classification/classification_main$(EXEEXT)

> \

>         ${top_builddir}/test/validation/config/config_main$(EXEEXT) \

> @@ -16,6 +18,7 @@ TESTS = pktio/pktio_run \

>         ${top_builddir}/test/validation/init/init_main_ok$(EXEEXT) \

>         ${top_builddir}/test/validation/init/init_main_abort$(EXEEXT) \

>         ${top_builddir}/test/validation/init/init_main_log$(EXEEXT) \

> +       ${top_builddir}/test/validation/lock/lock_main$(EXEEXT) \

>         ${top_builddir}/test/validation/packet/packet_main$(EXEEXT) \

>         ${top_builddir}/test/validation/pool/pool_main$(EXEEXT) \

>         ${top_builddir}/test/validation/queue/queue_main$(EXEEXT) \

> diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am

> index 1711b93..9a5bbff 100644

> --- a/test/validation/Makefile.am

> +++ b/test/validation/Makefile.am

> @@ -1,4 +1,6 @@

> -ODP_MODULES = buffer \

> +ODP_MODULES = atomic \

> +             barrier \

> +             buffer \

>               classification \

>               config \

>               cpumask \

> @@ -6,6 +8,7 @@ ODP_MODULES = buffer \

>               errno \

>               hash \

>               init \

> +             lock \

>               queue \

>               packet \

>               pktio \

> diff --git a/test/validation/atomic/.gitignore

> b/test/validation/atomic/.gitignore

> new file mode 100644

> index 0000000..610ffea

> --- /dev/null

> +++ b/test/validation/atomic/.gitignore

> @@ -0,0 +1 @@

> +atomic_main

> diff --git a/test/validation/atomic/Makefile.am

> b/test/validation/atomic/Makefile.am

> new file mode 100644

> index 0000000..9b6bd63

> --- /dev/null

> +++ b/test/validation/atomic/Makefile.am

> @@ -0,0 +1,10 @@

> +include ../Makefile.inc

> +

> +noinst_LTLIBRARIES = libtestatomic.la

> +libtestatomic_la_SOURCES = atomic.c

> +

> +test_PROGRAMS = atomic_main$(EXEEXT)

> +dist_atomic_main_SOURCES = atomic_main.c

> +atomic_main_LDADD = libtestatomic.la $(LIBCUNIT_COMMON) $(LIBODP)

> +

> +EXTRA_DIST = atomic.h

> diff --git a/test/validation/atomic/atomic.c

> b/test/validation/atomic/atomic.c

> new file mode 100644

> index 0000000..633b465

> --- /dev/null

> +++ b/test/validation/atomic/atomic.c

> @@ -0,0 +1,441 @@

> +/* Copyright (c) 2014, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#include <malloc.h>

> +#include <odp.h>

> +#include <CUnit/Basic.h>

> +#include <odp_cunit_common.h>

> +#include <unistd.h>

> +#include "atomic.h"

> +

> +#define VERBOSE                        0

> +#define MAX_ITERATIONS         1000

> +

> +#define ADD_SUB_CNT            5

> +

> +#define CNT                    10

> +#define U32_INIT_VAL           (1UL << 10)

> +#define U64_INIT_VAL           (1ULL << 33)

> +

> +#define GLOBAL_SHM_NAME                "GlobalLockTest"

> +

> +#define UNUSED                 __attribute__((__unused__))

> +

> +static odp_atomic_u32_t a32u;

> +static odp_atomic_u64_t a64u;

> +

> +typedef __volatile uint32_t volatile_u32_t;

> +typedef __volatile uint64_t volatile_u64_t;

> +

> +typedef struct {

> +       /* Global variables */

> +       uint32_t g_num_threads;

> +       uint32_t g_iterations;

> +       uint32_t g_verbose;

> +       uint32_t g_max_num_cores;

> +

> +       volatile_u32_t global_lock_owner;

> +} global_shared_mem_t;

> +

> +/* Per-thread memory */

> +typedef struct {

> +       global_shared_mem_t *global_mem;

> +

> +       int thread_id;

> +       int thread_core;

> +

> +       volatile_u64_t delay_counter;

> +} per_thread_mem_t;

> +

> +static odp_shm_t global_shm;

> +static global_shared_mem_t *global_mem;

> +

> +/* Initialise per-thread memory */

> +static per_thread_mem_t *thread_init(void)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       odp_shm_t global_shm;

> +       uint32_t per_thread_mem_len;

> +

> +       per_thread_mem_len = sizeof(per_thread_mem_t);

> +       per_thread_mem = malloc(per_thread_mem_len);

> +       memset(per_thread_mem, 0, per_thread_mem_len);

> +

> +       per_thread_mem->delay_counter = 1;

> +

> +       per_thread_mem->thread_id = odp_thread_id();

> +       per_thread_mem->thread_core = odp_cpu_id();

> +

> +       global_shm = odp_shm_lookup(GLOBAL_SHM_NAME);

> +       global_mem = odp_shm_addr(global_shm);

> +       CU_ASSERT_PTR_NOT_NULL(global_mem);

> +

> +       per_thread_mem->global_mem = global_mem;

> +

> +       return per_thread_mem;

> +}

> +

> +static void thread_finalize(per_thread_mem_t *per_thread_mem)

> +{

> +       free(per_thread_mem);

> +}

> +

> +static void test_atomic_inc_32(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_inc_u32(&a32u);

> +}

> +

> +static void test_atomic_inc_64(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_inc_u64(&a64u);

> +}

> +

> +static void test_atomic_dec_32(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_dec_u32(&a32u);

> +}

> +

> +static void test_atomic_dec_64(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_dec_u64(&a64u);

> +}

> +

> +static void test_atomic_fetch_inc_32(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_fetch_inc_u32(&a32u);

> +}

> +

> +static void test_atomic_fetch_inc_64(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_fetch_inc_u64(&a64u);

> +}

> +

> +static void test_atomic_fetch_dec_32(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_fetch_dec_u32(&a32u);

> +}

> +

> +static void test_atomic_fetch_dec_64(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_fetch_dec_u64(&a64u);

> +}

> +

> +static void test_atomic_add_32(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_add_u32(&a32u, ADD_SUB_CNT);

> +}

> +

> +static void test_atomic_add_64(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_add_u64(&a64u, ADD_SUB_CNT);

> +}

> +

> +static void test_atomic_sub_32(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_sub_u32(&a32u, ADD_SUB_CNT);

> +}

> +

> +static void test_atomic_sub_64(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_sub_u64(&a64u, ADD_SUB_CNT);

> +}

> +

> +static void test_atomic_fetch_add_32(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_fetch_add_u32(&a32u, ADD_SUB_CNT);

> +}

> +

> +static void test_atomic_fetch_add_64(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_fetch_add_u64(&a64u, ADD_SUB_CNT);

> +}

> +

> +static void test_atomic_fetch_sub_32(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_fetch_sub_u32(&a32u, ADD_SUB_CNT);

> +}

> +

> +static void test_atomic_fetch_sub_64(void)

> +{

> +       int i;

> +

> +       for (i = 0; i < CNT; i++)

> +               odp_atomic_fetch_sub_u64(&a64u, ADD_SUB_CNT);

> +}

> +

> +static void test_atomic_inc_dec_32(void)

> +{

> +       test_atomic_inc_32();

> +       test_atomic_dec_32();

> +}

> +

> +static void test_atomic_inc_dec_64(void)

> +{

> +       test_atomic_inc_64();

> +       test_atomic_dec_64();

> +}

> +

> +static void test_atomic_fetch_inc_dec_32(void)

> +{

> +       test_atomic_fetch_inc_32();

> +       test_atomic_fetch_dec_32();

> +}

> +

> +static void test_atomic_fetch_inc_dec_64(void)

> +{

> +       test_atomic_fetch_inc_64();

> +       test_atomic_fetch_dec_64();

> +}

> +

> +static void test_atomic_add_sub_32(void)

> +{

> +       test_atomic_add_32();

> +       test_atomic_sub_32();

> +}

> +

> +static void test_atomic_add_sub_64(void)

> +{

> +       test_atomic_add_64();

> +       test_atomic_sub_64();

> +}

> +

> +static void test_atomic_fetch_add_sub_32(void)

> +{

> +       test_atomic_fetch_add_32();

> +       test_atomic_fetch_sub_32();

> +}

> +

> +static void test_atomic_fetch_add_sub_64(void)

> +{

> +       test_atomic_fetch_add_64();

> +       test_atomic_fetch_sub_64();

> +}

> +

> +static void test_atomic_init(void)

> +{

> +       odp_atomic_init_u32(&a32u, 0);

> +       odp_atomic_init_u64(&a64u, 0);

> +}

> +

> +static void test_atomic_store(void)

> +{

> +       odp_atomic_store_u32(&a32u, U32_INIT_VAL);

> +       odp_atomic_store_u64(&a64u, U64_INIT_VAL);

> +}

> +

> +static void test_atomic_validate(void)

> +{

> +       CU_ASSERT(U32_INIT_VAL == odp_atomic_load_u32(&a32u));

> +       CU_ASSERT(U64_INIT_VAL == odp_atomic_load_u64(&a64u));

> +}

> +

> +int atomic_init(void)

> +{

> +       uint32_t workers_count, max_threads;

> +       int ret = 0;

> +       odp_cpumask_t mask;

> +

> +       if (0 != odp_init_global(NULL, NULL)) {

> +               fprintf(stderr, "error: odp_init_global() failed.\n");

> +               return -1;

> +       }

> +       if (0 != odp_init_local(ODP_THREAD_CONTROL)) {

> +               fprintf(stderr, "error: odp_init_local() failed.\n");

> +               return -1;

> +       }

> +

> +       global_shm = odp_shm_reserve(GLOBAL_SHM_NAME,

> +                                    sizeof(global_shared_mem_t), 64,

> +                                    ODP_SHM_SW_ONLY);

> +       if (ODP_SHM_INVALID == global_shm) {

> +               fprintf(stderr, "Unable reserve memory for global_shm\n");

> +               return -1;

> +       }

> +

> +       global_mem = odp_shm_addr(global_shm);

> +       memset(global_mem, 0, sizeof(global_shared_mem_t));

> +

> +       global_mem->g_num_threads = MAX_WORKERS;

> +       global_mem->g_iterations = MAX_ITERATIONS;

> +       global_mem->g_verbose = VERBOSE;

> +

> +       workers_count = odp_cpumask_default_worker(&mask, 0);

> +

> +       max_threads = (workers_count >= MAX_WORKERS) ?

> +                       MAX_WORKERS : workers_count;

> +

> +       if (max_threads < global_mem->g_num_threads) {

> +               printf("Requested num of threads is too large\n");

> +               printf("reducing from %" PRIu32 " to %" PRIu32 "\n",

> +                      global_mem->g_num_threads,

> +                      max_threads);

> +               global_mem->g_num_threads = max_threads;

> +       }

> +

> +       printf("Num of threads used = %" PRIu32 "\n",

> +              global_mem->g_num_threads);

> +

> +       return ret;

> +}

> +

> +/* Atomic tests */

> +static void *test_atomic_inc_dec_thread(void *arg UNUSED)

> +{

> +       per_thread_mem_t *per_thread_mem;

> +

> +       per_thread_mem = thread_init();

> +       test_atomic_inc_dec_32();

> +       test_atomic_inc_dec_64();

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void *test_atomic_add_sub_thread(void *arg UNUSED)

> +{

> +       per_thread_mem_t *per_thread_mem;

> +

> +       per_thread_mem = thread_init();

> +       test_atomic_add_sub_32();

> +       test_atomic_add_sub_64();

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void *test_atomic_fetch_inc_dec_thread(void *arg UNUSED)

> +{

> +       per_thread_mem_t *per_thread_mem;

> +

> +       per_thread_mem = thread_init();

> +       test_atomic_fetch_inc_dec_32();

> +       test_atomic_fetch_inc_dec_64();

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void *test_atomic_fetch_add_sub_thread(void *arg UNUSED)

> +{

> +       per_thread_mem_t *per_thread_mem;

> +

> +       per_thread_mem = thread_init();

> +       test_atomic_fetch_add_sub_32();

> +       test_atomic_fetch_add_sub_64();

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void test_atomic_functional(void *func_ptr(void *))

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +       test_atomic_init();

> +       test_atomic_store();

> +       odp_cunit_thread_create(func_ptr, &arg);

> +       odp_cunit_thread_exit(&arg);

> +       test_atomic_validate();

> +}

> +

> +void atomic_test_atomic_inc_dec(void)

> +{

> +       test_atomic_functional(test_atomic_inc_dec_thread);

> +}

> +

> +void atomic_test_atomic_add_sub(void)

> +{

> +       test_atomic_functional(test_atomic_add_sub_thread);

> +}

> +

> +void atomic_test_atomic_fetch_inc_dec(void)

> +{

> +       test_atomic_functional(test_atomic_fetch_inc_dec_thread);

> +}

> +

> +void atomic_test_atomic_fetch_add_sub(void)

> +{

> +       test_atomic_functional(test_atomic_fetch_add_sub_thread);

> +}

> +

> +odp_testinfo_t atomic_suite_atomic[] = {

> +       ODP_TEST_INFO(atomic_test_atomic_inc_dec),

> +       ODP_TEST_INFO(atomic_test_atomic_add_sub),

> +       ODP_TEST_INFO(atomic_test_atomic_fetch_inc_dec),

> +       ODP_TEST_INFO(atomic_test_atomic_fetch_add_sub),

> +       ODP_TEST_INFO_NULL,

> +};

> +

> +odp_suiteinfo_t atomic_suites[] = {

> +       {"atomic", NULL, NULL,

> +               atomic_suite_atomic},

> +       ODP_SUITE_INFO_NULL

> +};

> +

> +int atomic_main(void)

> +{

> +       int ret;

> +

> +       odp_cunit_register_global_init(atomic_init);

> +

> +       ret = odp_cunit_register(atomic_suites);

> +

> +       if (ret == 0)

> +               ret = odp_cunit_run();

> +

> +       return ret;

> +}

> diff --git a/test/validation/atomic/atomic.h

> b/test/validation/atomic/atomic.h

> new file mode 100644

> index 0000000..3516c67

> --- /dev/null

> +++ b/test/validation/atomic/atomic.h

> @@ -0,0 +1,33 @@

> +/* Copyright (c) 2015, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#ifndef _ODP_TEST_SYNCHRONIZERS_H_

> +#define _ODP_TEST_SYNCHRONIZERS_H_

> +

> +#include <odp_cunit_common.h>

> +

> +/* test functions: */

> +void atomic_test_atomic_inc_dec(void);

> +void atomic_test_atomic_add_sub(void);

> +void atomic_test_atomic_fetch_inc_dec(void);

> +void atomic_test_atomic_fetch_add_sub(void);

> +

> +/* test arrays: */

> +extern odp_testinfo_t atomic_suite_atomic[];

> +

> +/* test array init/term functions: */

> +int atomic_suite_init(void);

> +

> +/* test registry: */

> +extern odp_suiteinfo_t atomic_suites[];

> +

> +/* executable init/term functions: */

> +int atomic_init(void);

> +

> +/* main test program: */

> +int atomic_main(void);

> +

> +#endif

> diff --git a/test/validation/atomic/atomic_main.c

> b/test/validation/atomic/atomic_main.c

> new file mode 100644

> index 0000000..377bdd5

> --- /dev/null

> +++ b/test/validation/atomic/atomic_main.c

> @@ -0,0 +1,12 @@

> +/* Copyright (c) 2015, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#include "atomic.h"

> +

> +int main(void)

> +{

> +       return atomic_main();

> +}

> diff --git a/test/validation/barrier/.gitignore

> b/test/validation/barrier/.gitignore

> new file mode 100644

> index 0000000..2e0ee7a

> --- /dev/null

> +++ b/test/validation/barrier/.gitignore

> @@ -0,0 +1 @@

> +barrier_main

> diff --git a/test/validation/barrier/Makefile.am

> b/test/validation/barrier/Makefile.am

> new file mode 100644

> index 0000000..8fc632c

> --- /dev/null

> +++ b/test/validation/barrier/Makefile.am

> @@ -0,0 +1,10 @@

> +include ../Makefile.inc

> +

> +noinst_LTLIBRARIES = libtestbarrier.la

> +libtestbarrier_la_SOURCES = barrier.c

> +

> +test_PROGRAMS = barrier_main$(EXEEXT)

> +dist_barrier_main_SOURCES = barrier_main.c

> +barrier_main_LDADD = libtestbarrier.la $(LIBCUNIT_COMMON) $(LIBODP)

> +

> +EXTRA_DIST = barrier.h

> diff --git a/test/validation/barrier/barrier.c

> b/test/validation/barrier/barrier.c

> new file mode 100644

> index 0000000..ab7fcf4

> --- /dev/null

> +++ b/test/validation/barrier/barrier.c

> @@ -0,0 +1,370 @@

> +/* Copyright (c) 2014, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#include <malloc.h>

> +#include <odp.h>

> +#include <CUnit/Basic.h>

> +#include <odp_cunit_common.h>

> +#include <unistd.h>

> +#include "barrier.h"

> +

> +#define VERBOSE                        0

> +#define MAX_ITERATIONS         1000

> +#define BARRIER_ITERATIONS     64

> +

> +#define SLOW_BARRIER_DELAY     400

> +#define BASE_DELAY             6

> +

> +#define NUM_TEST_BARRIERS      BARRIER_ITERATIONS

> +#define NUM_RESYNC_BARRIERS    100

> +

> +#define BARRIER_DELAY          10

> +

> +#define GLOBAL_SHM_NAME                "GlobalLockTest"

> +

> +#define UNUSED                 __attribute__((__unused__))

> +

> +typedef __volatile uint32_t volatile_u32_t;

> +typedef __volatile uint64_t volatile_u64_t;

> +

> +typedef struct {

> +       odp_atomic_u32_t wait_cnt;

> +} custom_barrier_t;

> +

> +typedef struct {

> +       /* Global variables */

> +       uint32_t g_num_threads;

> +       uint32_t g_iterations;

> +       uint32_t g_verbose;

> +       uint32_t g_max_num_cores;

> +

> +       odp_barrier_t test_barriers[NUM_TEST_BARRIERS];

> +       custom_barrier_t custom_barrier1[NUM_TEST_BARRIERS];

> +       custom_barrier_t custom_barrier2[NUM_TEST_BARRIERS];

> +       volatile_u32_t slow_thread_num;

> +       volatile_u32_t barrier_cnt1;

> +       volatile_u32_t barrier_cnt2;

> +       odp_barrier_t global_barrier;

> +

> +} global_shared_mem_t;

> +

> +/* Per-thread memory */

> +typedef struct {

> +       global_shared_mem_t *global_mem;

> +

> +       int thread_id;

> +       int thread_core;

> +

> +       volatile_u64_t delay_counter;

> +} per_thread_mem_t;

> +

> +static odp_shm_t global_shm;

> +static global_shared_mem_t *global_mem;

> +

> +/*

> +* Delay a consistent amount of time.  Ideally the amount of CPU time taken

> +* is linearly proportional to "iterations".  The goal is to try to do some

> +* work that the compiler optimizer won't optimize away, and also to

> +* minimize loads and stores (at least to different memory addresses)

> +* so as to not affect or be affected by caching issues.  This does NOT

> have to

> +* correlate to a specific number of cpu cycles or be consistent across

> +* CPU architectures.

> +*/

> +static void thread_delay(per_thread_mem_t *per_thread_mem, uint32_t

> iterations)

> +{

> +       volatile_u64_t *counter_ptr;

> +       uint32_t cnt;

> +

> +       counter_ptr = &per_thread_mem->delay_counter;

> +

> +       for (cnt = 1; cnt <= iterations; cnt++)

> +               (*counter_ptr)++;

> +}

> +

> +/* Initialise per-thread memory */

> +static per_thread_mem_t *thread_init(void)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       odp_shm_t global_shm;

> +       uint32_t per_thread_mem_len;

> +

> +       per_thread_mem_len = sizeof(per_thread_mem_t);

> +       per_thread_mem = malloc(per_thread_mem_len);

> +       memset(per_thread_mem, 0, per_thread_mem_len);

> +

> +       per_thread_mem->delay_counter = 1;

> +

> +       per_thread_mem->thread_id = odp_thread_id();

> +       per_thread_mem->thread_core = odp_cpu_id();

> +

> +       global_shm = odp_shm_lookup(GLOBAL_SHM_NAME);

> +       global_mem = odp_shm_addr(global_shm);

> +       CU_ASSERT_PTR_NOT_NULL(global_mem);

> +

> +       per_thread_mem->global_mem = global_mem;

> +

> +       return per_thread_mem;

> +}

> +

> +static void thread_finalize(per_thread_mem_t *per_thread_mem)

> +{

> +       free(per_thread_mem);

> +}

> +

> +static void custom_barrier_init(custom_barrier_t *custom_barrier,

> +                               uint32_t num_threads)

> +{

> +       odp_atomic_init_u32(&custom_barrier->wait_cnt, num_threads);

> +}

> +

> +static void custom_barrier_wait(custom_barrier_t *custom_barrier)

> +{

> +       volatile_u64_t counter = 1;

> +       uint32_t delay_cnt, wait_cnt;

> +

> +       odp_atomic_sub_u32(&custom_barrier->wait_cnt, 1);

> +

> +       wait_cnt = 1;

> +       while (wait_cnt != 0) {

> +               for (delay_cnt = 1; delay_cnt <= BARRIER_DELAY;

> delay_cnt++)

> +                       counter++;

> +

> +               wait_cnt = odp_atomic_load_u32(&custom_barrier->wait_cnt);

> +       }

> +}

> +

> +static uint32_t barrier_test(per_thread_mem_t *per_thread_mem,

> +                            odp_bool_t no_barrier_test)

> +{

> +       global_shared_mem_t *global_mem;

> +       uint32_t barrier_errs, iterations, cnt, i_am_slow_thread;

> +       uint32_t thread_num, slow_thread_num, next_slow_thread,

> num_threads;

> +       uint32_t lock_owner_delay, barrier_cnt1, barrier_cnt2;

> +

> +       thread_num = odp_thread_id();

> +       global_mem = per_thread_mem->global_mem;

> +       num_threads = global_mem->g_num_threads;

> +       iterations = BARRIER_ITERATIONS;

> +

> +       barrier_errs = 0;

> +       lock_owner_delay = SLOW_BARRIER_DELAY;

> +

> +       for (cnt = 1; cnt < iterations; cnt++) {

> +               /* Wait here until all of the threads reach this point */

> +               custom_barrier_wait(&global_mem->custom_barrier1[cnt]);

> +

> +               barrier_cnt1 = global_mem->barrier_cnt1;

> +               barrier_cnt2 = global_mem->barrier_cnt2;

> +

> +               if ((barrier_cnt1 != cnt) || (barrier_cnt2 != cnt)) {

> +                       printf("thread_num=%" PRIu32 " barrier_cnts of %"

> PRIu32

> +                                  " %" PRIu32 " cnt=%" PRIu32 "\n",

> +                              thread_num, barrier_cnt1, barrier_cnt2,

> cnt);

> +                       barrier_errs++;

> +               }

> +

> +               /* Wait here until all of the threads reach this point */

> +               custom_barrier_wait(&global_mem->custom_barrier2[cnt]);

> +

> +               slow_thread_num = global_mem->slow_thread_num;

> +               i_am_slow_thread = thread_num == slow_thread_num;

> +               next_slow_thread = slow_thread_num + 1;

> +               if (num_threads < next_slow_thread)

> +                       next_slow_thread = 1;

> +

> +               /*

> +               * Now run the test, which involves having all but one

> thread

> +               * immediately calling odp_barrier_wait(), and one thread

> wait a

> +               * moderate amount of time and then calling

> odp_barrier_wait().

> +               * The test fails if any of the first group of threads

> +               * has not waited for the "slow" thread. The "slow" thread

> is

> +               * responsible for re-initializing the barrier for next

> trial.

> +               */

> +               if (i_am_slow_thread) {

> +                       thread_delay(per_thread_mem, lock_owner_delay);

> +                       lock_owner_delay += BASE_DELAY;

> +                       if ((global_mem->barrier_cnt1 != cnt) ||

> +                           (global_mem->barrier_cnt2 != cnt) ||

> +                           (global_mem->slow_thread_num

> +                                       != slow_thread_num))

> +                               barrier_errs++;

> +               }

> +

> +               if (no_barrier_test == 0)

> +                       odp_barrier_wait(&global_mem->test_barriers[cnt]);

> +

> +               global_mem->barrier_cnt1 = cnt + 1;

> +               odp_sync_stores();

> +

> +               if (i_am_slow_thread) {

> +                       global_mem->slow_thread_num = next_slow_thread;

> +                       global_mem->barrier_cnt2 = cnt + 1;

> +                       odp_sync_stores();

> +               } else {

> +                       while (global_mem->barrier_cnt2 != (cnt + 1))

> +                               thread_delay(per_thread_mem, BASE_DELAY);

> +               }

> +       }

> +

> +       if ((global_mem->g_verbose) && (barrier_errs != 0))

> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

> +                      " barrier_errs in %" PRIu32 " iterations\n",

> thread_num,

> +                      per_thread_mem->thread_id,

> +                      per_thread_mem->thread_core, barrier_errs,

> iterations);

> +

> +       return barrier_errs;

> +}

> +

> +static void *no_barrier_functional_test(void *arg UNUSED)

> +{

> +       per_thread_mem_t *per_thread_mem;

> +       uint32_t barrier_errs;

> +

> +       per_thread_mem = thread_init();

> +       barrier_errs = barrier_test(per_thread_mem, 1);

> +

> +       /*

> +       * Note that the following CU_ASSERT MAY appear incorrect, but for

> the

> +       * no_barrier test it should see barrier_errs or else there is

> something

> +       * wrong with the test methodology or the ODP thread implementation.

> +       * So this test PASSES only if it sees barrier_errs or a single

> +       * worker was used.

> +       */

> +       CU_ASSERT(barrier_errs != 0 || global_mem->g_num_threads == 1);

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void *barrier_functional_test(void *arg UNUSED)

> +{

> +       per_thread_mem_t *per_thread_mem;

> +       uint32_t barrier_errs;

> +

> +       per_thread_mem = thread_init();

> +       barrier_errs = barrier_test(per_thread_mem, 0);

> +

> +       CU_ASSERT(barrier_errs == 0);

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void barrier_test_init(void)

> +{

> +       uint32_t num_threads, idx;

> +

> +       num_threads = global_mem->g_num_threads;

> +

> +       for (idx = 0; idx < NUM_TEST_BARRIERS; idx++) {

> +               odp_barrier_init(&global_mem->test_barriers[idx],

> num_threads);

> +               custom_barrier_init(&global_mem->custom_barrier1[idx],

> +                                   num_threads);

> +               custom_barrier_init(&global_mem->custom_barrier2[idx],

> +                                   num_threads);

> +       }

> +

> +       global_mem->slow_thread_num = 1;

> +       global_mem->barrier_cnt1 = 1;

> +       global_mem->barrier_cnt2 = 1;

> +}

> +

> +/* Barrier tests */

> +void barrier_test_no_barrier_functional(void)

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +       barrier_test_init();

> +       odp_cunit_thread_create(no_barrier_functional_test, &arg);

> +       odp_cunit_thread_exit(&arg);

> +}

> +

> +void barrier_test_barrier_functional(void)

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +       barrier_test_init();

> +       odp_cunit_thread_create(barrier_functional_test, &arg);

> +       odp_cunit_thread_exit(&arg);

> +}

> +

> +odp_testinfo_t barrier_suite_barrier[] = {

> +       ODP_TEST_INFO(barrier_test_no_barrier_functional),

> +       ODP_TEST_INFO(barrier_test_barrier_functional),

> +       ODP_TEST_INFO_NULL

> +};

> +

> +int barrier_init(void)

> +{

> +       uint32_t workers_count, max_threads;

> +       int ret = 0;

> +       odp_cpumask_t mask;

> +

> +       if (0 != odp_init_global(NULL, NULL)) {

> +               fprintf(stderr, "error: odp_init_global() failed.\n");

> +               return -1;

> +       }

> +       if (0 != odp_init_local(ODP_THREAD_CONTROL)) {

> +               fprintf(stderr, "error: odp_init_local() failed.\n");

> +               return -1;

> +       }

> +

> +       global_shm = odp_shm_reserve(GLOBAL_SHM_NAME,

> +                                    sizeof(global_shared_mem_t), 64,

> +                                    ODP_SHM_SW_ONLY);

> +       if (ODP_SHM_INVALID == global_shm) {

> +               fprintf(stderr, "Unable reserve memory for global_shm\n");

> +               return -1;

> +       }

> +

> +       global_mem = odp_shm_addr(global_shm);

> +       memset(global_mem, 0, sizeof(global_shared_mem_t));

> +

> +       global_mem->g_num_threads = MAX_WORKERS;

> +       global_mem->g_iterations = MAX_ITERATIONS;

> +       global_mem->g_verbose = VERBOSE;

> +

> +       workers_count = odp_cpumask_default_worker(&mask, 0);

> +

> +       max_threads = (workers_count >= MAX_WORKERS) ?

> +                       MAX_WORKERS : workers_count;

> +

> +       if (max_threads < global_mem->g_num_threads) {

> +               printf("Requested num of threads is too large\n");

> +               printf("reducing from %" PRIu32 " to %" PRIu32 "\n",

> +                      global_mem->g_num_threads,

> +                      max_threads);

> +               global_mem->g_num_threads = max_threads;

> +       }

> +

> +       printf("Num of threads used = %" PRIu32 "\n",

> +              global_mem->g_num_threads);

> +

> +       return ret;

> +}

> +

> +odp_suiteinfo_t barrier_suites[] = {

> +       {"barrier", NULL, NULL,

> +               barrier_suite_barrier},

> +       ODP_SUITE_INFO_NULL

> +};

> +

> +int barrier_main(void)

> +{

> +       int ret;

> +

> +       odp_cunit_register_global_init(barrier_init);

> +

> +       ret = odp_cunit_register(barrier_suites);

> +

> +       if (ret == 0)

> +               ret = odp_cunit_run();

> +

> +       return ret;

> +}

> diff --git a/test/validation/barrier/barrier.h

> b/test/validation/barrier/barrier.h

> new file mode 100644

> index 0000000..a6310d0

> --- /dev/null

> +++ b/test/validation/barrier/barrier.h

> @@ -0,0 +1,28 @@

> +/* Copyright (c) 2015, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#ifndef _ODP_TEST_SYNCHRONIZERS_H_

> +#define _ODP_TEST_SYNCHRONIZERS_H_

> +

> +#include <odp_cunit_common.h>

> +

> +/* test functions: */

> +void barrier_test_no_barrier_functional(void);

> +void barrier_test_barrier_functional(void);

> +

> +/* test arrays: */

> +extern odp_testinfo_t barrier_suite_barrier[];

> +

> +/* test registry: */

> +extern odp_suiteinfo_t barrier_suites[];

> +

> +/* executable init/term functions: */

> +int barrier_init(void);

> +

> +/* main test program: */

> +int barrier_main(void);

> +

> +#endif

> diff --git a/test/validation/barrier/barrier_main.c

> b/test/validation/barrier/barrier_main.c

> new file mode 100644

> index 0000000..88c9b3e

> --- /dev/null

> +++ b/test/validation/barrier/barrier_main.c

> @@ -0,0 +1,12 @@

> +/* Copyright (c) 2015, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#include "barrier.h"

> +

> +int main(void)

> +{

> +       return barrier_main();

> +}

> diff --git a/test/validation/lock/.gitignore

> b/test/validation/lock/.gitignore

> new file mode 100644

> index 0000000..ff16646

> --- /dev/null

> +++ b/test/validation/lock/.gitignore

> @@ -0,0 +1 @@

> +lock_main

> diff --git a/test/validation/lock/Makefile.am

> b/test/validation/lock/Makefile.am

> new file mode 100644

> index 0000000..29993df

> --- /dev/null

> +++ b/test/validation/lock/Makefile.am

> @@ -0,0 +1,10 @@

> +include ../Makefile.inc

> +

> +noinst_LTLIBRARIES = libtestlock.la

> +libtestlock_la_SOURCES = lock.c

> +

> +test_PROGRAMS = lock_main$(EXEEXT)

> +dist_lock_main_SOURCES = lock_main.c

> +lock_main_LDADD = libtestlock.la $(LIBCUNIT_COMMON) $(LIBODP)

> +

> +EXTRA_DIST = lock.h

> diff --git a/test/validation/lock/lock.c b/test/validation/lock/lock.c

> new file mode 100644

> index 0000000..76009f0

> --- /dev/null

> +++ b/test/validation/lock/lock.c

> @@ -0,0 +1,1135 @@

> +/* Copyright (c) 2014, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#include <malloc.h>

> +#include <odp.h>

> +#include <CUnit/Basic.h>

> +#include <odp_cunit_common.h>

> +#include <unistd.h>

> +#include "lock.h"

> +

> +#define VERBOSE                        0

> +#define MAX_ITERATIONS         1000

> +

> +#define SLOW_BARRIER_DELAY     400

> +#define BASE_DELAY             6

> +#define MIN_DELAY              1

> +

> +#define NUM_RESYNC_BARRIERS    100

> +

> +#define GLOBAL_SHM_NAME                "GlobalLockTest"

> +

> +#define UNUSED                 __attribute__((__unused__))

> +

> +typedef __volatile uint32_t volatile_u32_t;

> +typedef __volatile uint64_t volatile_u64_t;

> +

> +typedef struct {

> +       odp_atomic_u32_t wait_cnt;

> +} custom_barrier_t;

> +

> +typedef struct {

> +       /* Global variables */

> +       uint32_t g_num_threads;

> +       uint32_t g_iterations;

> +       uint32_t g_verbose;

> +       uint32_t g_max_num_cores;

> +

> +       volatile_u32_t slow_thread_num;

> +       volatile_u32_t barrier_cnt1;

> +       volatile_u32_t barrier_cnt2;

> +       odp_barrier_t global_barrier;

> +

> +       /* Used to periodically resync within the lock functional tests */

> +       odp_barrier_t barrier_array[NUM_RESYNC_BARRIERS];

> +

> +       /* Locks */

> +       odp_spinlock_t global_spinlock;

> +       odp_spinlock_recursive_t global_recursive_spinlock;

> +       odp_ticketlock_t global_ticketlock;

> +       odp_rwlock_t global_rwlock;

> +       odp_rwlock_recursive_t global_recursive_rwlock;

> +

> +       volatile_u32_t global_lock_owner;

> +} global_shared_mem_t;

> +

> +/* Per-thread memory */

> +typedef struct {

> +       global_shared_mem_t *global_mem;

> +

> +       int thread_id;

> +       int thread_core;

> +

> +       odp_spinlock_t per_thread_spinlock;

> +       odp_spinlock_recursive_t per_thread_recursive_spinlock;

> +       odp_ticketlock_t per_thread_ticketlock;

> +       odp_rwlock_t per_thread_rwlock;

> +       odp_rwlock_recursive_t per_thread_recursive_rwlock;

> +

> +       volatile_u64_t delay_counter;

> +} per_thread_mem_t;

> +

> +static odp_shm_t global_shm;

> +static global_shared_mem_t *global_mem;

> +

> +/*

> +* Delay a consistent amount of time.  Ideally the amount of CPU time taken

> +* is linearly proportional to "iterations".  The goal is to try to do some

> +* work that the compiler optimizer won't optimize away, and also to

> +* minimize loads and stores (at least to different memory addresses)

> +* so as to not affect or be affected by caching issues.  This does NOT

> have to

> +* correlate to a specific number of cpu cycles or be consistent across

> +* CPU architectures.

> +*/

> +static void thread_delay(per_thread_mem_t *per_thread_mem, uint32_t

> iterations)

> +{

> +       volatile_u64_t *counter_ptr;

> +       uint32_t cnt;

> +

> +       counter_ptr = &per_thread_mem->delay_counter;

> +

> +       for (cnt = 1; cnt <= iterations; cnt++)

> +               (*counter_ptr)++;

> +}

> +

> +/* Initialise per-thread memory */

> +static per_thread_mem_t *thread_init(void)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       odp_shm_t global_shm;

> +       uint32_t per_thread_mem_len;

> +

> +       per_thread_mem_len = sizeof(per_thread_mem_t);

> +       per_thread_mem = malloc(per_thread_mem_len);

> +       memset(per_thread_mem, 0, per_thread_mem_len);

> +

> +       per_thread_mem->delay_counter = 1;

> +

> +       per_thread_mem->thread_id = odp_thread_id();

> +       per_thread_mem->thread_core = odp_cpu_id();

> +

> +       global_shm = odp_shm_lookup(GLOBAL_SHM_NAME);

> +       global_mem = odp_shm_addr(global_shm);

> +       CU_ASSERT_PTR_NOT_NULL(global_mem);

> +

> +       per_thread_mem->global_mem = global_mem;

> +

> +       return per_thread_mem;

> +}

> +

> +static void thread_finalize(per_thread_mem_t *per_thread_mem)

> +{

> +       free(per_thread_mem);

> +}

> +

> +static void spinlock_api_test(odp_spinlock_t *spinlock)

> +{

> +       odp_spinlock_init(spinlock);

> +       CU_ASSERT(odp_spinlock_is_locked(spinlock) == 0);

> +

> +       odp_spinlock_lock(spinlock);

> +       CU_ASSERT(odp_spinlock_is_locked(spinlock) == 1);

> +

> +       odp_spinlock_unlock(spinlock);

> +       CU_ASSERT(odp_spinlock_is_locked(spinlock) == 0);

> +

> +       CU_ASSERT(odp_spinlock_trylock(spinlock) == 1);

> +

> +       CU_ASSERT(odp_spinlock_is_locked(spinlock) == 1);

> +

> +       odp_spinlock_unlock(spinlock);

> +       CU_ASSERT(odp_spinlock_is_locked(spinlock) == 0);

> +}

> +

> +static void *spinlock_api_tests(void *arg UNUSED)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       odp_spinlock_t local_spin_lock;

> +

> +       per_thread_mem = thread_init();

> +       global_mem = per_thread_mem->global_mem;

> +

> +       odp_barrier_wait(&global_mem->global_barrier);

> +

> +       spinlock_api_test(&local_spin_lock);

> +       spinlock_api_test(&per_thread_mem->per_thread_spinlock);

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void spinlock_recursive_api_test(odp_spinlock_recursive_t

> *spinlock)

> +{

> +       odp_spinlock_recursive_init(spinlock);

> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 0);

> +

> +       odp_spinlock_recursive_lock(spinlock);

> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);

> +

> +       odp_spinlock_recursive_lock(spinlock);

> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);

> +

> +       odp_spinlock_recursive_unlock(spinlock);

> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);

> +

> +       odp_spinlock_recursive_unlock(spinlock);

> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 0);

> +

> +       CU_ASSERT(odp_spinlock_recursive_trylock(spinlock) == 1);

> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);

> +

> +       CU_ASSERT(odp_spinlock_recursive_trylock(spinlock) == 1);

> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);

> +

> +       odp_spinlock_recursive_unlock(spinlock);

> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);

> +

> +       odp_spinlock_recursive_unlock(spinlock);

> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 0);

> +}

> +

> +static void *spinlock_recursive_api_tests(void *arg UNUSED)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       odp_spinlock_recursive_t local_recursive_spin_lock;

> +

> +       per_thread_mem = thread_init();

> +       global_mem = per_thread_mem->global_mem;

> +

> +       odp_barrier_wait(&global_mem->global_barrier);

> +

> +       spinlock_recursive_api_test(&local_recursive_spin_lock);

> +       spinlock_recursive_api_test(

> +               &per_thread_mem->per_thread_recursive_spinlock);

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void ticketlock_api_test(odp_ticketlock_t *ticketlock)

> +{

> +       odp_ticketlock_init(ticketlock);

> +       CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 0);

> +

> +       odp_ticketlock_lock(ticketlock);

> +       CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 1);

> +

> +       odp_ticketlock_unlock(ticketlock);

> +       CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 0);

> +

> +       CU_ASSERT(odp_ticketlock_trylock(ticketlock) == 1);

> +       CU_ASSERT(odp_ticketlock_trylock(ticketlock) == 0);

> +       CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 1);

> +

> +       odp_ticketlock_unlock(ticketlock);

> +       CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 0);

> +}

> +

> +static void *ticketlock_api_tests(void *arg UNUSED)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       odp_ticketlock_t local_ticket_lock;

> +

> +       per_thread_mem = thread_init();

> +       global_mem = per_thread_mem->global_mem;

> +

> +       odp_barrier_wait(&global_mem->global_barrier);

> +

> +       ticketlock_api_test(&local_ticket_lock);

> +       ticketlock_api_test(&per_thread_mem->per_thread_ticketlock);

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void rwlock_api_test(odp_rwlock_t *rw_lock)

> +{

> +       odp_rwlock_init(rw_lock);

> +       /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */

> +

> +       odp_rwlock_read_lock(rw_lock);

> +       odp_rwlock_read_unlock(rw_lock);

> +

> +       odp_rwlock_write_lock(rw_lock);

> +       /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 1); */

> +

> +       odp_rwlock_write_unlock(rw_lock);

> +       /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */

> +}

> +

> +static void *rwlock_api_tests(void *arg UNUSED)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       odp_rwlock_t local_rwlock;

> +

> +       per_thread_mem = thread_init();

> +       global_mem = per_thread_mem->global_mem;

> +

> +       odp_barrier_wait(&global_mem->global_barrier);

> +

> +       rwlock_api_test(&local_rwlock);

> +       rwlock_api_test(&per_thread_mem->per_thread_rwlock);

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void rwlock_recursive_api_test(odp_rwlock_recursive_t *rw_lock)

> +{

> +       odp_rwlock_recursive_init(rw_lock);

> +       /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */

> +

> +       odp_rwlock_recursive_read_lock(rw_lock);

> +       odp_rwlock_recursive_read_lock(rw_lock);

> +

> +       odp_rwlock_recursive_read_unlock(rw_lock);

> +       odp_rwlock_recursive_read_unlock(rw_lock);

> +

> +       odp_rwlock_recursive_write_lock(rw_lock);

> +       odp_rwlock_recursive_write_lock(rw_lock);

> +       /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 1); */

> +

> +       odp_rwlock_recursive_write_unlock(rw_lock);

> +       odp_rwlock_recursive_write_unlock(rw_lock);

> +       /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */

> +}

> +

> +static void *rwlock_recursive_api_tests(void *arg UNUSED)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       odp_rwlock_recursive_t local_recursive_rwlock;

> +

> +       per_thread_mem = thread_init();

> +       global_mem = per_thread_mem->global_mem;

> +

> +       odp_barrier_wait(&global_mem->global_barrier);

> +

> +       rwlock_recursive_api_test(&local_recursive_rwlock);

> +

>  rwlock_recursive_api_test(&per_thread_mem->per_thread_recursive_rwlock);

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void *no_lock_functional_test(void *arg UNUSED)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;

> +       uint32_t sync_failures, current_errs, lock_owner_delay;

> +

> +       thread_num = odp_cpu_id() + 1;

> +       per_thread_mem = thread_init();

> +       global_mem = per_thread_mem->global_mem;

> +       iterations = global_mem->g_iterations;

> +

> +       odp_barrier_wait(&global_mem->global_barrier);

> +

> +       sync_failures = 0;

> +       current_errs = 0;

> +       rs_idx = 0;

> +       resync_cnt = iterations / NUM_RESYNC_BARRIERS;

> +       lock_owner_delay = BASE_DELAY;

> +

> +       for (cnt = 1; cnt <= iterations; cnt++) {

> +               global_mem->global_lock_owner = thread_num;

> +               odp_sync_stores();

> +               thread_delay(per_thread_mem, lock_owner_delay);

> +

> +               if (global_mem->global_lock_owner != thread_num) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               global_mem->global_lock_owner = 0;

> +               odp_sync_stores();

> +               thread_delay(per_thread_mem, MIN_DELAY);

> +

> +               if (global_mem->global_lock_owner == thread_num) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               if (current_errs == 0)

> +                       lock_owner_delay++;

> +

> +               /* Wait a small amount of time and rerun the test */

> +               thread_delay(per_thread_mem, BASE_DELAY);

> +

> +               /* Try to resync all of the threads to increase contention

> */

> +               if ((rs_idx < NUM_RESYNC_BARRIERS) &&

> +                   ((cnt % resync_cnt) == (resync_cnt - 1)))

> +

>  odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);

> +       }

> +

> +       if (global_mem->g_verbose)

> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

> +                      " sync_failures in %" PRIu32 " iterations\n",

> +                      thread_num,

> +                      per_thread_mem->thread_id,

> +                      per_thread_mem->thread_core,

> +                      sync_failures, iterations);

> +

> +       /* Note that the following CU_ASSERT MAY appear incorrect, but for

> the

> +       * no_lock test it should see sync_failures or else there is

> something

> +       * wrong with the test methodology or the ODP thread implementation.

> +       * So this test PASSES only if it sees sync_failures or a single

> +       * worker was used.

> +       */

> +       CU_ASSERT(sync_failures != 0 || global_mem->g_num_threads == 1);

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void *spinlock_functional_test(void *arg UNUSED)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;

> +       uint32_t sync_failures, is_locked_errs, current_errs;

> +       uint32_t lock_owner_delay;

> +

> +       thread_num = odp_cpu_id() + 1;

> +       per_thread_mem = thread_init();

> +       global_mem = per_thread_mem->global_mem;

> +       iterations = global_mem->g_iterations;

> +

> +       odp_barrier_wait(&global_mem->global_barrier);

> +

> +       sync_failures = 0;

> +       is_locked_errs = 0;

> +       current_errs = 0;

> +       rs_idx = 0;

> +       resync_cnt = iterations / NUM_RESYNC_BARRIERS;

> +       lock_owner_delay = BASE_DELAY;

> +

> +       for (cnt = 1; cnt <= iterations; cnt++) {

> +               /* Acquire the shared global lock */

> +               odp_spinlock_lock(&global_mem->global_spinlock);

> +

> +               /* Make sure we have the lock AND didn't previously own it

> */

> +               if (odp_spinlock_is_locked(&global_mem->global_spinlock)

> != 1)

> +                       is_locked_errs++;

> +

> +               if (global_mem->global_lock_owner != 0) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               /* Now set the global_lock_owner to be us, wait a while,

> and

> +               * then we see if anyone else has snuck in and changed the

> +               * global_lock_owner to be themselves

> +               */

> +               global_mem->global_lock_owner = thread_num;

> +               odp_sync_stores();

> +               thread_delay(per_thread_mem, lock_owner_delay);

> +               if (global_mem->global_lock_owner != thread_num) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               /* Release shared lock, and make sure we no longer have it

> */

> +               global_mem->global_lock_owner = 0;

> +               odp_sync_stores();

> +               odp_spinlock_unlock(&global_mem->global_spinlock);

> +               if (global_mem->global_lock_owner == thread_num) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               if (current_errs == 0)

> +                       lock_owner_delay++;

> +

> +               /* Wait a small amount of time and rerun the test */

> +               thread_delay(per_thread_mem, BASE_DELAY);

> +

> +               /* Try to resync all of the threads to increase contention

> */

> +               if ((rs_idx < NUM_RESYNC_BARRIERS) &&

> +                   ((cnt % resync_cnt) == (resync_cnt - 1)))

> +

>  odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);

> +       }

> +

> +       if ((global_mem->g_verbose) &&

> +           ((sync_failures != 0) || (is_locked_errs != 0)))

> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

> +                      " sync_failures and %" PRIu32

> +                      " is_locked_errs in %" PRIu32

> +                      " iterations\n", thread_num,

> +                      per_thread_mem->thread_id,

> per_thread_mem->thread_core,

> +                      sync_failures, is_locked_errs, iterations);

> +

> +       CU_ASSERT(sync_failures == 0);

> +       CU_ASSERT(is_locked_errs == 0);

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void *spinlock_recursive_functional_test(void *arg UNUSED)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;

> +       uint32_t sync_failures, recursive_errs, is_locked_errs,

> current_errs;

> +       uint32_t lock_owner_delay;

> +

> +       thread_num = odp_cpu_id() + 1;

> +       per_thread_mem = thread_init();

> +       global_mem = per_thread_mem->global_mem;

> +       iterations = global_mem->g_iterations;

> +

> +       odp_barrier_wait(&global_mem->global_barrier);

> +

> +       sync_failures = 0;

> +       recursive_errs = 0;

> +       is_locked_errs = 0;

> +       current_errs = 0;

> +       rs_idx = 0;

> +       resync_cnt = iterations / NUM_RESYNC_BARRIERS;

> +       lock_owner_delay = BASE_DELAY;

> +

> +       for (cnt = 1; cnt <= iterations; cnt++) {

> +               /* Acquire the shared global lock */

> +               odp_spinlock_recursive_lock(

> +                       &global_mem->global_recursive_spinlock);

> +

> +               /* Make sure we have the lock AND didn't previously own it

> */

> +               if (odp_spinlock_recursive_is_locked(

> +                           &global_mem->global_recursive_spinlock) != 1)

> +                       is_locked_errs++;

> +

> +               if (global_mem->global_lock_owner != 0) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +              /* Now set the global_lock_owner to be us, wait a while, and

> +               * then we see if anyone else has snuck in and changed the

> +               * global_lock_owner to be themselves

> +               */

> +               global_mem->global_lock_owner = thread_num;

> +               odp_sync_stores();

> +               thread_delay(per_thread_mem, lock_owner_delay);

> +               if (global_mem->global_lock_owner != thread_num) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               /* Verify that we can acquire the lock recursively */

> +               odp_spinlock_recursive_lock(

> +                       &global_mem->global_recursive_spinlock);

> +               if (global_mem->global_lock_owner != thread_num) {

> +                       current_errs++;

> +                       recursive_errs++;

> +               }

> +

> +               /* Release the lock and verify that we still have it*/

> +               odp_spinlock_recursive_unlock(

> +                       &global_mem->global_recursive_spinlock);

> +               thread_delay(per_thread_mem, lock_owner_delay);

> +               if (global_mem->global_lock_owner != thread_num) {

> +                       current_errs++;

> +                       recursive_errs++;

> +               }

> +

> +               /* Release shared lock, and make sure we no longer have it

> */

> +               global_mem->global_lock_owner = 0;

> +               odp_sync_stores();

> +               odp_spinlock_recursive_unlock(

> +                       &global_mem->global_recursive_spinlock);

> +               if (global_mem->global_lock_owner == thread_num) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               if (current_errs == 0)

> +                       lock_owner_delay++;

> +

> +               /* Wait a small amount of time and rerun the test */

> +               thread_delay(per_thread_mem, BASE_DELAY);

> +

> +               /* Try to resync all of the threads to increase contention

> */

> +               if ((rs_idx < NUM_RESYNC_BARRIERS) &&

> +                   ((cnt % resync_cnt) == (resync_cnt - 1)))

> +

>  odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);

> +       }

> +

> +       if ((global_mem->g_verbose) &&

> +           (sync_failures != 0 || recursive_errs != 0 || is_locked_errs

> != 0))

> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

> +                      " sync_failures and %" PRIu32

> +                      " recursive_errs and %" PRIu32

> +                      " is_locked_errs in %" PRIu32

> +                      " iterations\n", thread_num,

> +                      per_thread_mem->thread_id,

> per_thread_mem->thread_core,

> +                      sync_failures, recursive_errs, is_locked_errs,

> +                      iterations);

> +

> +       CU_ASSERT(sync_failures == 0);

> +       CU_ASSERT(recursive_errs == 0);

> +       CU_ASSERT(is_locked_errs == 0);

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void *ticketlock_functional_test(void *arg UNUSED)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;

> +       uint32_t sync_failures, is_locked_errs, current_errs;

> +       uint32_t lock_owner_delay;

> +

> +       thread_num = odp_cpu_id() + 1;

> +       per_thread_mem = thread_init();

> +       global_mem = per_thread_mem->global_mem;

> +       iterations = global_mem->g_iterations;

> +

> +       /* Wait here until all of the threads have also reached this point

> */

> +       odp_barrier_wait(&global_mem->global_barrier);

> +

> +       sync_failures = 0;

> +       is_locked_errs = 0;

> +       current_errs = 0;

> +       rs_idx = 0;

> +       resync_cnt = iterations / NUM_RESYNC_BARRIERS;

> +       lock_owner_delay = BASE_DELAY;

> +

> +       for (cnt = 1; cnt <= iterations; cnt++) {

> +               /* Acquire the shared global lock */

> +               odp_ticketlock_lock(&global_mem->global_ticketlock);

> +

> +               /* Make sure we have the lock AND didn't previously own it

> */

> +               if

> (odp_ticketlock_is_locked(&global_mem->global_ticketlock)

> +                               != 1)

> +                       is_locked_errs++;

> +

> +               if (global_mem->global_lock_owner != 0) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               /* Now set the global_lock_owner to be us, wait a while,

> and

> +               * then we see if anyone else has snuck in and changed the

> +               * global_lock_owner to be themselves

> +               */

> +               global_mem->global_lock_owner = thread_num;

> +               odp_sync_stores();

> +               thread_delay(per_thread_mem, lock_owner_delay);

> +               if (global_mem->global_lock_owner != thread_num) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               /* Release shared lock, and make sure we no longer have it

> */

> +               global_mem->global_lock_owner = 0;

> +               odp_sync_stores();

> +               odp_ticketlock_unlock(&global_mem->global_ticketlock);

> +               if (global_mem->global_lock_owner == thread_num) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               if (current_errs == 0)

> +                       lock_owner_delay++;

> +

> +               /* Wait a small amount of time and then rerun the test */

> +               thread_delay(per_thread_mem, BASE_DELAY);

> +

> +               /* Try to resync all of the threads to increase contention

> */

> +               if ((rs_idx < NUM_RESYNC_BARRIERS) &&

> +                   ((cnt % resync_cnt) == (resync_cnt - 1)))

> +

>  odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);

> +       }

> +

> +       if ((global_mem->g_verbose) &&

> +           ((sync_failures != 0) || (is_locked_errs != 0)))

> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

> +                      " sync_failures and %" PRIu32

> +                      " is_locked_errs in %" PRIu32 " iterations\n",

> +                      thread_num,

> +                      per_thread_mem->thread_id,

> per_thread_mem->thread_core,

> +                      sync_failures, is_locked_errs, iterations);

> +

> +       CU_ASSERT(sync_failures == 0);

> +       CU_ASSERT(is_locked_errs == 0);

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void *rwlock_functional_test(void *arg UNUSED)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;

> +       uint32_t sync_failures, current_errs, lock_owner_delay;

> +

> +       thread_num = odp_cpu_id() + 1;

> +       per_thread_mem = thread_init();

> +       global_mem = per_thread_mem->global_mem;

> +       iterations = global_mem->g_iterations;

> +

> +       /* Wait here until all of the threads have also reached this point

> */

> +       odp_barrier_wait(&global_mem->global_barrier);

> +

> +       sync_failures = 0;

> +       current_errs = 0;

> +       rs_idx = 0;

> +       resync_cnt = iterations / NUM_RESYNC_BARRIERS;

> +       lock_owner_delay = BASE_DELAY;

> +

> +       for (cnt = 1; cnt <= iterations; cnt++) {

> +               /* Verify that we can obtain a read lock */

> +               odp_rwlock_read_lock(&global_mem->global_rwlock);

> +

> +               /* Verify lock is unowned (no writer holds it) */

> +               thread_delay(per_thread_mem, lock_owner_delay);

> +               if (global_mem->global_lock_owner != 0) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               /* Release the read lock */

> +               odp_rwlock_read_unlock(&global_mem->global_rwlock);

> +

> +               /* Acquire the shared global lock */

> +               odp_rwlock_write_lock(&global_mem->global_rwlock);

> +

> +               /* Make sure we have lock now AND didn't previously own it

> */

> +               if (global_mem->global_lock_owner != 0) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               /* Now set the global_lock_owner to be us, wait a while,

> and

> +               * then we see if anyone else has snuck in and changed the

> +               * global_lock_owner to be themselves

> +               */

> +               global_mem->global_lock_owner = thread_num;

> +               odp_sync_stores();

> +               thread_delay(per_thread_mem, lock_owner_delay);

> +               if (global_mem->global_lock_owner != thread_num) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               /* Release shared lock, and make sure we no longer have it

> */

> +               global_mem->global_lock_owner = 0;

> +               odp_sync_stores();

> +               odp_rwlock_write_unlock(&global_mem->global_rwlock);

> +               if (global_mem->global_lock_owner == thread_num) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               if (current_errs == 0)

> +                       lock_owner_delay++;

> +

> +               /* Wait a small amount of time and then rerun the test */

> +               thread_delay(per_thread_mem, BASE_DELAY);

> +

> +               /* Try to resync all of the threads to increase contention

> */

> +               if ((rs_idx < NUM_RESYNC_BARRIERS) &&

> +                   ((cnt % resync_cnt) == (resync_cnt - 1)))

> +

>  odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);

> +       }

> +

> +       if ((global_mem->g_verbose) && (sync_failures != 0))

> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

> +                      " sync_failures in %" PRIu32 " iterations\n",

> thread_num,

> +                      per_thread_mem->thread_id,

> +                      per_thread_mem->thread_core,

> +                      sync_failures, iterations);

> +

> +       CU_ASSERT(sync_failures == 0);

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +static void *rwlock_recursive_functional_test(void *arg UNUSED)

> +{

> +       global_shared_mem_t *global_mem;

> +       per_thread_mem_t *per_thread_mem;

> +       uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;

> +       uint32_t sync_failures, recursive_errs, current_errs,

> lock_owner_delay;

> +

> +       thread_num = odp_cpu_id() + 1;

> +       per_thread_mem = thread_init();

> +       global_mem = per_thread_mem->global_mem;

> +       iterations = global_mem->g_iterations;

> +

> +       /* Wait here until all of the threads have also reached this point

> */

> +       odp_barrier_wait(&global_mem->global_barrier);

> +

> +       sync_failures = 0;

> +       recursive_errs = 0;

> +       current_errs = 0;

> +       rs_idx = 0;

> +       resync_cnt = iterations / NUM_RESYNC_BARRIERS;

> +       lock_owner_delay = BASE_DELAY;

> +

> +       for (cnt = 1; cnt <= iterations; cnt++) {

> +               /* Verify that we can obtain a read lock */

> +               odp_rwlock_recursive_read_lock(

> +                       &global_mem->global_recursive_rwlock);

> +

> +               /* Verify lock is unowned (no writer holds it) */

> +               thread_delay(per_thread_mem, lock_owner_delay);

> +               if (global_mem->global_lock_owner != 0) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               /* Verify we can get read lock recursively */

> +               odp_rwlock_recursive_read_lock(

> +                       &global_mem->global_recursive_rwlock);

> +

> +               /* Verify lock is unowned (no writer holds it) */

> +               thread_delay(per_thread_mem, lock_owner_delay);

> +               if (global_mem->global_lock_owner != 0) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               /* Release the read lock */

> +               odp_rwlock_recursive_read_unlock(

> +                       &global_mem->global_recursive_rwlock);

> +               odp_rwlock_recursive_read_unlock(

> +                       &global_mem->global_recursive_rwlock);

> +

> +               /* Acquire the shared global lock */

> +               odp_rwlock_recursive_write_lock(

> +                       &global_mem->global_recursive_rwlock);

> +

> +               /* Make sure we have lock now AND didn't previously own it

> */

> +               if (global_mem->global_lock_owner != 0) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               /* Now set the global_lock_owner to be us, wait a while,

> and

> +               * then we see if anyone else has snuck in and changed the

> +               * global_lock_owner to be themselves

> +               */

> +               global_mem->global_lock_owner = thread_num;

> +               odp_sync_stores();

> +               thread_delay(per_thread_mem, lock_owner_delay);

> +               if (global_mem->global_lock_owner != thread_num) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               /* Acquire it again and verify we still own it */

> +               odp_rwlock_recursive_write_lock(

> +                       &global_mem->global_recursive_rwlock);

> +               thread_delay(per_thread_mem, lock_owner_delay);

> +               if (global_mem->global_lock_owner != thread_num) {

> +                       current_errs++;

> +                       recursive_errs++;

> +               }

> +

> +               /* Release the recursive lock and make sure we still own

> it */

> +               odp_rwlock_recursive_write_unlock(

> +                       &global_mem->global_recursive_rwlock);

> +               thread_delay(per_thread_mem, lock_owner_delay);

> +               if (global_mem->global_lock_owner != thread_num) {

> +                       current_errs++;

> +                       recursive_errs++;

> +               }

> +

> +               /* Release shared lock, and make sure we no longer have it

> */

> +               global_mem->global_lock_owner = 0;

> +               odp_sync_stores();

> +               odp_rwlock_recursive_write_unlock(

> +                       &global_mem->global_recursive_rwlock);

> +               if (global_mem->global_lock_owner == thread_num) {

> +                       current_errs++;

> +                       sync_failures++;

> +               }

> +

> +               if (current_errs == 0)

> +                       lock_owner_delay++;

> +

> +               /* Wait a small amount of time and then rerun the test */

> +               thread_delay(per_thread_mem, BASE_DELAY);

> +

> +               /* Try to resync all of the threads to increase contention

> */

> +               if ((rs_idx < NUM_RESYNC_BARRIERS) &&

> +                   ((cnt % resync_cnt) == (resync_cnt - 1)))

> +

>  odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);

> +       }

> +

> +       if ((global_mem->g_verbose) && (sync_failures != 0))

> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

> +                      " sync_failures and %" PRIu32

> +                      " recursive_errs in %" PRIu32

> +                      " iterations\n", thread_num,

> +                      per_thread_mem->thread_id,

> +                      per_thread_mem->thread_core,

> +                      sync_failures, recursive_errs, iterations);

> +

> +       CU_ASSERT(sync_failures == 0);

> +       CU_ASSERT(recursive_errs == 0);

> +

> +       thread_finalize(per_thread_mem);

> +

> +       return NULL;

> +}

> +

> +/* Thread-unsafe tests */

> +void lock_test_no_lock_functional(void)

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +       odp_cunit_thread_create(no_lock_functional_test, &arg);

> +       odp_cunit_thread_exit(&arg);

> +}

> +

> +odp_testinfo_t lock_suite_no_locking[] = {

> +       ODP_TEST_INFO(lock_test_no_lock_functional),

> +       ODP_TEST_INFO_NULL

> +};

> +

> +/* Spin lock tests */

> +void lock_test_spinlock_api(void)

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +       odp_cunit_thread_create(spinlock_api_tests, &arg);

> +       odp_cunit_thread_exit(&arg);

> +}

> +

> +void lock_test_spinlock_functional(void)

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +       odp_spinlock_init(&global_mem->global_spinlock);

> +       odp_cunit_thread_create(spinlock_functional_test, &arg);

> +       odp_cunit_thread_exit(&arg);

> +}

> +

> +void lock_test_spinlock_recursive_api(void)

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +       odp_cunit_thread_create(spinlock_recursive_api_tests, &arg);

> +       odp_cunit_thread_exit(&arg);

> +}

> +

> +void lock_test_spinlock_recursive_functional(void)

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +

>  odp_spinlock_recursive_init(&global_mem->global_recursive_spinlock);

> +       odp_cunit_thread_create(spinlock_recursive_functional_test, &arg);

> +       odp_cunit_thread_exit(&arg);

> +}

> +

> +odp_testinfo_t lock_suite_spinlock[] = {

> +       ODP_TEST_INFO(lock_test_spinlock_api),

> +       ODP_TEST_INFO(lock_test_spinlock_functional),

> +       ODP_TEST_INFO_NULL

> +};

> +

> +odp_testinfo_t lock_suite_spinlock_recursive[] = {

> +       ODP_TEST_INFO(lock_test_spinlock_recursive_api),

> +       ODP_TEST_INFO(lock_test_spinlock_recursive_functional),

> +       ODP_TEST_INFO_NULL

> +};

> +

> +/* Ticket lock tests */

> +void lock_test_ticketlock_api(void)

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +       odp_cunit_thread_create(ticketlock_api_tests, &arg);

> +       odp_cunit_thread_exit(&arg);

> +}

> +

> +void lock_test_ticketlock_functional(void)

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +       odp_ticketlock_init(&global_mem->global_ticketlock);

> +

> +       odp_cunit_thread_create(ticketlock_functional_test, &arg);

> +       odp_cunit_thread_exit(&arg);

> +}

> +

> +odp_testinfo_t lock_suite_ticketlock[] = {

> +       ODP_TEST_INFO(lock_test_ticketlock_api),

> +       ODP_TEST_INFO(lock_test_ticketlock_functional),

> +       ODP_TEST_INFO_NULL

> +};

> +

> +/* RW lock tests */

> +void lock_test_rwlock_api(void)

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +       odp_cunit_thread_create(rwlock_api_tests, &arg);

> +       odp_cunit_thread_exit(&arg);

> +}

> +

> +void lock_test_rwlock_functional(void)

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +       odp_rwlock_init(&global_mem->global_rwlock);

> +       odp_cunit_thread_create(rwlock_functional_test, &arg);

> +       odp_cunit_thread_exit(&arg);

> +}

> +

> +odp_testinfo_t lock_suite_rwlock[] = {

> +       ODP_TEST_INFO(lock_test_rwlock_api),

> +       ODP_TEST_INFO(lock_test_rwlock_functional),

> +       ODP_TEST_INFO_NULL

> +};

> +

> +void lock_test_rwlock_recursive_api(void)

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +       odp_cunit_thread_create(rwlock_recursive_api_tests, &arg);

> +       odp_cunit_thread_exit(&arg);

> +}

> +

> +void lock_test_rwlock_recursive_functional(void)

> +{

> +       pthrd_arg arg;

> +

> +       arg.numthrds = global_mem->g_num_threads;

> +       odp_rwlock_recursive_init(&global_mem->global_recursive_rwlock);

> +       odp_cunit_thread_create(rwlock_recursive_functional_test, &arg);

> +       odp_cunit_thread_exit(&arg);

> +}

> +

> +odp_testinfo_t lock_suite_rwlock_recursive[] = {

> +       ODP_TEST_INFO(lock_test_rwlock_recursive_api),

> +       ODP_TEST_INFO(lock_test_rwlock_recursive_functional),

> +       ODP_TEST_INFO_NULL

> +};

> +

> +int lock_suite_init(void)

> +{

> +       uint32_t num_threads, idx;

> +

> +       num_threads = global_mem->g_num_threads;

> +       odp_barrier_init(&global_mem->global_barrier, num_threads);

> +       for (idx = 0; idx < NUM_RESYNC_BARRIERS; idx++)

> +               odp_barrier_init(&global_mem->barrier_array[idx],

> num_threads);

> +

> +       return 0;

> +}

> +

> +int lock_init(void)

> +{

> +       uint32_t workers_count, max_threads;

> +       int ret = 0;

> +       odp_cpumask_t mask;

> +

> +       if (0 != odp_init_global(NULL, NULL)) {

> +               fprintf(stderr, "error: odp_init_global() failed.\n");

> +               return -1;

> +       }

> +       if (0 != odp_init_local(ODP_THREAD_CONTROL)) {

> +               fprintf(stderr, "error: odp_init_local() failed.\n");

> +               return -1;

> +       }

> +

> +       global_shm = odp_shm_reserve(GLOBAL_SHM_NAME,

> +                                    sizeof(global_shared_mem_t), 64,

> +                                    ODP_SHM_SW_ONLY);

> +       if (ODP_SHM_INVALID == global_shm) {

> +               fprintf(stderr, "Unable reserve memory for global_shm\n");

> +               return -1;

> +       }

> +

> +       global_mem = odp_shm_addr(global_shm);

> +       memset(global_mem, 0, sizeof(global_shared_mem_t));

> +

> +       global_mem->g_num_threads = MAX_WORKERS;

> +       global_mem->g_iterations = MAX_ITERATIONS;

> +       global_mem->g_verbose = VERBOSE;

> +

> +       workers_count = odp_cpumask_default_worker(&mask, 0);

> +

> +       max_threads = (workers_count >= MAX_WORKERS) ?

> +                       MAX_WORKERS : workers_count;

> +

> +       if (max_threads < global_mem->g_num_threads) {

> +               printf("Requested num of threads is too large\n");

> +               printf("reducing from %" PRIu32 " to %" PRIu32 "\n",

> +                      global_mem->g_num_threads,

> +                      max_threads);

> +               global_mem->g_num_threads = max_threads;

> +       }

> +

> +       printf("Num of threads used = %" PRIu32 "\n",

> +              global_mem->g_num_threads);

> +

> +       return ret;

> +}

> +

> +odp_suiteinfo_t lock_suites[] = {

> +       {"nolocking", lock_suite_init, NULL,

> +               lock_suite_no_locking},

> +       {"spinlock", lock_suite_init, NULL,

> +               lock_suite_spinlock},

> +       {"spinlock_recursive", lock_suite_init, NULL,

> +               lock_suite_spinlock_recursive},

> +       {"ticketlock", lock_suite_init, NULL,

> +               lock_suite_ticketlock},

> +       {"rwlock", lock_suite_init, NULL,

> +               lock_suite_rwlock},

> +       {"rwlock_recursive", lock_suite_init, NULL,

> +               lock_suite_rwlock_recursive},

> +       ODP_SUITE_INFO_NULL

> +};

> +

> +int lock_main(void)

> +{

> +       int ret;

> +

> +       odp_cunit_register_global_init(lock_init);

> +

> +       ret = odp_cunit_register(lock_suites);

> +

> +       if (ret == 0)

> +               ret = odp_cunit_run();

> +

> +       return ret;

> +}

> diff --git a/test/validation/lock/lock.h b/test/validation/lock/lock.h

> new file mode 100644

> index 0000000..d41123f

> --- /dev/null

> +++ b/test/validation/lock/lock.h

> @@ -0,0 +1,45 @@

> +/* Copyright (c) 2015, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#ifndef _ODP_TEST_SYNCHRONIZERS_H_

> +#define _ODP_TEST_SYNCHRONIZERS_H_

> +

> +#include <odp_cunit_common.h>

> +

> +/* test functions: */

> +void lock_test_no_lock_functional(void);

> +void lock_test_spinlock_api(void);

> +void lock_test_spinlock_functional(void);

> +void lock_test_spinlock_recursive_api(void);

> +void lock_test_spinlock_recursive_functional(void);

> +void lock_test_ticketlock_api(void);

> +void lock_test_ticketlock_functional(void);

> +void lock_test_rwlock_api(void);

> +void lock_test_rwlock_functional(void);

> +void lock_test_rwlock_recursive_api(void);

> +void lock_test_rwlock_recursive_functional(void);

> +

> +/* test arrays: */

> +extern odp_testinfo_t lock_suite_no_locking[];

> +extern odp_testinfo_t lock_suite_spinlock[];

> +extern odp_testinfo_t lock_suite_spinlock_recursive[];

> +extern odp_testinfo_t lock_suite_ticketlock[];

> +extern odp_testinfo_t lock_suite_rwlock[];

> +extern odp_testinfo_t lock_suite_rwlock_recursive[];

> +

> +/* test array init/term functions: */

> +int lock_suite_init(void);

> +

> +/* test registry: */

> +extern odp_suiteinfo_t lock_suites[];

> +

> +/* executable init/term functions: */

> +int lock_init(void);

> +

> +/* main test program: */

> +int lock_main(void);

> +

> +#endif

> diff --git a/test/validation/lock/lock_main.c

> b/test/validation/lock/lock_main.c

> new file mode 100644

> index 0000000..c12c2b5

> --- /dev/null

> +++ b/test/validation/lock/lock_main.c

> @@ -0,0 +1,12 @@

> +/* Copyright (c) 2015, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#include "lock.h"

> +

> +int main(void)

> +{

> +       return lock_main();

> +}

> --

> 2.1.4

>

> _______________________________________________

> lng-odp mailing list

> lng-odp@lists.linaro.org

> https://lists.linaro.org/mailman/listinfo/lng-odp

>
Christophe Milard Dec. 17, 2015, 12:08 p.m. UTC | #2
This should say [API-NEXT PATCH] and now seems to need rebasing.
I'll send a new one on the proper branch.
Christophe.

On 17 December 2015 at 01:02, Bill Fischofer <bill.fischofer@linaro.org>
wrote:

> Patch fails to apply.  Needs a rebase?

>

> bill@Ubuntu15:~/linaro/christophe$ git am --reject

> ~/Mail/Incoming/Christophe/1

> Applying: validation: synchro tests split into 3 groups

> Checking patch configure.ac...

> Hunk #1 succeeded at 348 (offset -1 lines).

> error: while searching for:

> test/validation/errno/Makefile

> test/validation/hash/Makefile

> test/validation/init/Makefile

> test/validation/packet/Makefile

> test/validation/pktio/Makefile

> test/validation/pool/Makefile

>

> error: patch failed: configure.ac:358

> Checking patch platform/linux-generic/test/Makefile.am...

> Hunk #2 succeeded at 17 (offset -1 lines).

> Checking patch test/validation/Makefile.am...

> error: while searching for:

>      errno \

>      hash \

>      init \

>      queue \

>      packet \

>      pktio \

>

> error: patch failed: test/validation/Makefile.am:6

> Checking patch test/validation/atomic/.gitignore...

> Checking patch test/validation/atomic/Makefile.am...

> Checking patch test/validation/atomic/atomic.c...

> Checking patch test/validation/atomic/atomic.h...

> Checking patch test/validation/atomic/atomic_main.c...

> Checking patch test/validation/barrier/.gitignore...

> Checking patch test/validation/barrier/Makefile.am...

> Checking patch test/validation/barrier/barrier.c...

> Checking patch test/validation/barrier/barrier.h...

> Checking patch test/validation/barrier/barrier_main.c...

> Checking patch test/validation/lock/.gitignore...

> Checking patch test/validation/lock/Makefile.am...

> Checking patch test/validation/lock/lock.c...

> Checking patch test/validation/lock/lock.h...

> Checking patch test/validation/lock/lock_main.c...

> Applying patch configure.ac with 1 reject...

> Hunk #1 applied cleanly.

> Rejected hunk #2.

> Applied patch platform/linux-generic/test/Makefile.am cleanly.

> Applying patch test/validation/Makefile.am with 1 reject...

> Hunk #1 applied cleanly.

> Rejected hunk #2.

> Applied patch test/validation/atomic/.gitignore cleanly.

> Applied patch test/validation/atomic/Makefile.am cleanly.

> Applied patch test/validation/atomic/atomic.c cleanly.

> Applied patch test/validation/atomic/atomic.h cleanly.

> Applied patch test/validation/atomic/atomic_main.c cleanly.

> Applied patch test/validation/barrier/.gitignore cleanly.

> Applied patch test/validation/barrier/Makefile.am cleanly.

> Applied patch test/validation/barrier/barrier.c cleanly.

> Applied patch test/validation/barrier/barrier.h cleanly.

> Applied patch test/validation/barrier/barrier_main.c cleanly.

> Applied patch test/validation/lock/.gitignore cleanly.

> Applied patch test/validation/lock/Makefile.am cleanly.

> Applied patch test/validation/lock/lock.c cleanly.

> Applied patch test/validation/lock/lock.h cleanly.

> Applied patch test/validation/lock/lock_main.c cleanly.

> Patch failed at 0001 validation: synchro tests split into 3 groups

>

>

> On Mon, Dec 14, 2015 at 9:46 AM, Christophe Milard <

> christophe.milard@linaro.org> wrote:

>

>> No functionnal changes: just code reordering to match the ODP modules.

>>

>> Signed-off-by: Christophe Milard <christophe.milard@linaro.org>

>> ---

>>  configure.ac                            |    3 +

>>  platform/linux-generic/test/Makefile.am |    3 +

>>  test/validation/Makefile.am             |    5 +-

>>  test/validation/atomic/.gitignore       |    1 +

>>  test/validation/atomic/Makefile.am      |   10 +

>>  test/validation/atomic/atomic.c         |  441 ++++++++++++

>>  test/validation/atomic/atomic.h         |   33 +

>>  test/validation/atomic/atomic_main.c    |   12 +

>>  test/validation/barrier/.gitignore      |    1 +

>>  test/validation/barrier/Makefile.am     |   10 +

>>  test/validation/barrier/barrier.c       |  370 ++++++++++

>>  test/validation/barrier/barrier.h       |   28 +

>>  test/validation/barrier/barrier_main.c  |   12 +

>>  test/validation/lock/.gitignore         |    1 +

>>  test/validation/lock/Makefile.am        |   10 +

>>  test/validation/lock/lock.c             | 1135

>> +++++++++++++++++++++++++++++++

>>  test/validation/lock/lock.h             |   45 ++

>>  test/validation/lock/lock_main.c        |   12 +

>>  18 files changed, 2131 insertions(+), 1 deletion(-)

>>  create mode 100644 test/validation/atomic/.gitignore

>>  create mode 100644 test/validation/atomic/Makefile.am

>>  create mode 100644 test/validation/atomic/atomic.c

>>  create mode 100644 test/validation/atomic/atomic.h

>>  create mode 100644 test/validation/atomic/atomic_main.c

>>  create mode 100644 test/validation/barrier/.gitignore

>>  create mode 100644 test/validation/barrier/Makefile.am

>>  create mode 100644 test/validation/barrier/barrier.c

>>  create mode 100644 test/validation/barrier/barrier.h

>>  create mode 100644 test/validation/barrier/barrier_main.c

>>  create mode 100644 test/validation/lock/.gitignore

>>  create mode 100644 test/validation/lock/Makefile.am

>>  create mode 100644 test/validation/lock/lock.c

>>  create mode 100644 test/validation/lock/lock.h

>>  create mode 100644 test/validation/lock/lock_main.c

>>

>> diff --git a/configure.ac b/configure.ac

>> index 4f89f03..7a05574 100644

>> --- a/configure.ac

>> +++ b/configure.ac

>> @@ -349,6 +349,8 @@ AC_CONFIG_FILES([Makefile

>>                  test/api_test/Makefile

>>                  test/performance/Makefile

>>                  test/validation/Makefile

>> +                test/validation/atomic/Makefile

>> +                test/validation/barrier/Makefile

>>                  test/validation/buffer/Makefile

>>                  test/validation/classification/Makefile

>>                  test/validation/config/Makefile

>> @@ -358,6 +360,7 @@ AC_CONFIG_FILES([Makefile

>>                  test/validation/errno/Makefile

>>                  test/validation/hash/Makefile

>>                  test/validation/init/Makefile

>> +                test/validation/lock/Makefile

>>                  test/validation/packet/Makefile

>>                  test/validation/pktio/Makefile

>>                  test/validation/pool/Makefile

>> diff --git a/platform/linux-generic/test/Makefile.am

>> b/platform/linux-generic/test/Makefile.am

>> index e629872..aa246d2 100644

>> --- a/platform/linux-generic/test/Makefile.am

>> +++ b/platform/linux-generic/test/Makefile.am

>> @@ -6,6 +6,8 @@ ODP_MODULES = pktio

>>  if test_vald

>>  TESTS = pktio/pktio_run \

>>         pktio/pktio_run_tap \

>> +       ${top_builddir}/test/validation/atomic/atomic_main$(EXEEXT) \

>> +       ${top_builddir}/test/validation/barrier/barrier_main$(EXEEXT) \

>>         ${top_builddir}/test/validation/buffer/buffer_main$(EXEEXT) \

>>

>> ${top_builddir}/test/validation/classification/classification_main$(EXEEXT)

>> \

>>         ${top_builddir}/test/validation/config/config_main$(EXEEXT) \

>> @@ -16,6 +18,7 @@ TESTS = pktio/pktio_run \

>>         ${top_builddir}/test/validation/init/init_main_ok$(EXEEXT) \

>>         ${top_builddir}/test/validation/init/init_main_abort$(EXEEXT) \

>>         ${top_builddir}/test/validation/init/init_main_log$(EXEEXT) \

>> +       ${top_builddir}/test/validation/lock/lock_main$(EXEEXT) \

>>         ${top_builddir}/test/validation/packet/packet_main$(EXEEXT) \

>>         ${top_builddir}/test/validation/pool/pool_main$(EXEEXT) \

>>         ${top_builddir}/test/validation/queue/queue_main$(EXEEXT) \

>> diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am

>> index 1711b93..9a5bbff 100644

>> --- a/test/validation/Makefile.am

>> +++ b/test/validation/Makefile.am

>> @@ -1,4 +1,6 @@

>> -ODP_MODULES = buffer \

>> +ODP_MODULES = atomic \

>> +             barrier \

>> +             buffer \

>>               classification \

>>               config \

>>               cpumask \

>> @@ -6,6 +8,7 @@ ODP_MODULES = buffer \

>>               errno \

>>               hash \

>>               init \

>> +             lock \

>>               queue \

>>               packet \

>>               pktio \

>> diff --git a/test/validation/atomic/.gitignore

>> b/test/validation/atomic/.gitignore

>> new file mode 100644

>> index 0000000..610ffea

>> --- /dev/null

>> +++ b/test/validation/atomic/.gitignore

>> @@ -0,0 +1 @@

>> +atomic_main

>> diff --git a/test/validation/atomic/Makefile.am

>> b/test/validation/atomic/Makefile.am

>> new file mode 100644

>> index 0000000..9b6bd63

>> --- /dev/null

>> +++ b/test/validation/atomic/Makefile.am

>> @@ -0,0 +1,10 @@

>> +include ../Makefile.inc

>> +

>> +noinst_LTLIBRARIES = libtestatomic.la

>> +libtestatomic_la_SOURCES = atomic.c

>> +

>> +test_PROGRAMS = atomic_main$(EXEEXT)

>> +dist_atomic_main_SOURCES = atomic_main.c

>> +atomic_main_LDADD = libtestatomic.la $(LIBCUNIT_COMMON) $(LIBODP)

>> +

>> +EXTRA_DIST = atomic.h

>> diff --git a/test/validation/atomic/atomic.c

>> b/test/validation/atomic/atomic.c

>> new file mode 100644

>> index 0000000..633b465

>> --- /dev/null

>> +++ b/test/validation/atomic/atomic.c

>> @@ -0,0 +1,441 @@

>> +/* Copyright (c) 2014, Linaro Limited

>> + * All rights reserved.

>> + *

>> + * SPDX-License-Identifier:     BSD-3-Clause

>> + */

>> +

>> +#include <malloc.h>

>> +#include <odp.h>

>> +#include <CUnit/Basic.h>

>> +#include <odp_cunit_common.h>

>> +#include <unistd.h>

>> +#include "atomic.h"

>> +

>> +#define VERBOSE                        0

>> +#define MAX_ITERATIONS         1000

>> +

>> +#define ADD_SUB_CNT            5

>> +

>> +#define CNT                    10

>> +#define U32_INIT_VAL           (1UL << 10)

>> +#define U64_INIT_VAL           (1ULL << 33)

>> +

>> +#define GLOBAL_SHM_NAME                "GlobalLockTest"

>> +

>> +#define UNUSED                 __attribute__((__unused__))

>> +

>> +static odp_atomic_u32_t a32u;

>> +static odp_atomic_u64_t a64u;

>> +

>> +typedef __volatile uint32_t volatile_u32_t;

>> +typedef __volatile uint64_t volatile_u64_t;

>> +

>> +typedef struct {

>> +       /* Global variables */

>> +       uint32_t g_num_threads;

>> +       uint32_t g_iterations;

>> +       uint32_t g_verbose;

>> +       uint32_t g_max_num_cores;

>> +

>> +       volatile_u32_t global_lock_owner;

>> +} global_shared_mem_t;

>> +

>> +/* Per-thread memory */

>> +typedef struct {

>> +       global_shared_mem_t *global_mem;

>> +

>> +       int thread_id;

>> +       int thread_core;

>> +

>> +       volatile_u64_t delay_counter;

>> +} per_thread_mem_t;

>> +

>> +static odp_shm_t global_shm;

>> +static global_shared_mem_t *global_mem;

>> +

>> +/* Initialise per-thread memory */

>> +static per_thread_mem_t *thread_init(void)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       odp_shm_t global_shm;

>> +       uint32_t per_thread_mem_len;

>> +

>> +       per_thread_mem_len = sizeof(per_thread_mem_t);

>> +       per_thread_mem = malloc(per_thread_mem_len);

>> +       memset(per_thread_mem, 0, per_thread_mem_len);

>> +

>> +       per_thread_mem->delay_counter = 1;

>> +

>> +       per_thread_mem->thread_id = odp_thread_id();

>> +       per_thread_mem->thread_core = odp_cpu_id();

>> +

>> +       global_shm = odp_shm_lookup(GLOBAL_SHM_NAME);

>> +       global_mem = odp_shm_addr(global_shm);

>> +       CU_ASSERT_PTR_NOT_NULL(global_mem);

>> +

>> +       per_thread_mem->global_mem = global_mem;

>> +

>> +       return per_thread_mem;

>> +}

>> +

>> +static void thread_finalize(per_thread_mem_t *per_thread_mem)

>> +{

>> +       free(per_thread_mem);

>> +}

>> +

>> +static void test_atomic_inc_32(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_inc_u32(&a32u);

>> +}

>> +

>> +static void test_atomic_inc_64(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_inc_u64(&a64u);

>> +}

>> +

>> +static void test_atomic_dec_32(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_dec_u32(&a32u);

>> +}

>> +

>> +static void test_atomic_dec_64(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_dec_u64(&a64u);

>> +}

>> +

>> +static void test_atomic_fetch_inc_32(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_fetch_inc_u32(&a32u);

>> +}

>> +

>> +static void test_atomic_fetch_inc_64(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_fetch_inc_u64(&a64u);

>> +}

>> +

>> +static void test_atomic_fetch_dec_32(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_fetch_dec_u32(&a32u);

>> +}

>> +

>> +static void test_atomic_fetch_dec_64(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_fetch_dec_u64(&a64u);

>> +}

>> +

>> +static void test_atomic_add_32(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_add_u32(&a32u, ADD_SUB_CNT);

>> +}

>> +

>> +static void test_atomic_add_64(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_add_u64(&a64u, ADD_SUB_CNT);

>> +}

>> +

>> +static void test_atomic_sub_32(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_sub_u32(&a32u, ADD_SUB_CNT);

>> +}

>> +

>> +static void test_atomic_sub_64(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_sub_u64(&a64u, ADD_SUB_CNT);

>> +}

>> +

>> +static void test_atomic_fetch_add_32(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_fetch_add_u32(&a32u, ADD_SUB_CNT);

>> +}

>> +

>> +static void test_atomic_fetch_add_64(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_fetch_add_u64(&a64u, ADD_SUB_CNT);

>> +}

>> +

>> +static void test_atomic_fetch_sub_32(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_fetch_sub_u32(&a32u, ADD_SUB_CNT);

>> +}

>> +

>> +static void test_atomic_fetch_sub_64(void)

>> +{

>> +       int i;

>> +

>> +       for (i = 0; i < CNT; i++)

>> +               odp_atomic_fetch_sub_u64(&a64u, ADD_SUB_CNT);

>> +}

>> +

>> +static void test_atomic_inc_dec_32(void)

>> +{

>> +       test_atomic_inc_32();

>> +       test_atomic_dec_32();

>> +}

>> +

>> +static void test_atomic_inc_dec_64(void)

>> +{

>> +       test_atomic_inc_64();

>> +       test_atomic_dec_64();

>> +}

>> +

>> +static void test_atomic_fetch_inc_dec_32(void)

>> +{

>> +       test_atomic_fetch_inc_32();

>> +       test_atomic_fetch_dec_32();

>> +}

>> +

>> +static void test_atomic_fetch_inc_dec_64(void)

>> +{

>> +       test_atomic_fetch_inc_64();

>> +       test_atomic_fetch_dec_64();

>> +}

>> +

>> +static void test_atomic_add_sub_32(void)

>> +{

>> +       test_atomic_add_32();

>> +       test_atomic_sub_32();

>> +}

>> +

>> +static void test_atomic_add_sub_64(void)

>> +{

>> +       test_atomic_add_64();

>> +       test_atomic_sub_64();

>> +}

>> +

>> +static void test_atomic_fetch_add_sub_32(void)

>> +{

>> +       test_atomic_fetch_add_32();

>> +       test_atomic_fetch_sub_32();

>> +}

>> +

>> +static void test_atomic_fetch_add_sub_64(void)

>> +{

>> +       test_atomic_fetch_add_64();

>> +       test_atomic_fetch_sub_64();

>> +}

>> +

>> +static void test_atomic_init(void)

>> +{

>> +       odp_atomic_init_u32(&a32u, 0);

>> +       odp_atomic_init_u64(&a64u, 0);

>> +}

>> +

>> +static void test_atomic_store(void)

>> +{

>> +       odp_atomic_store_u32(&a32u, U32_INIT_VAL);

>> +       odp_atomic_store_u64(&a64u, U64_INIT_VAL);

>> +}

>> +

>> +static void test_atomic_validate(void)

>> +{

>> +       CU_ASSERT(U32_INIT_VAL == odp_atomic_load_u32(&a32u));

>> +       CU_ASSERT(U64_INIT_VAL == odp_atomic_load_u64(&a64u));

>> +}

>> +

>> +int atomic_init(void)

>> +{

>> +       uint32_t workers_count, max_threads;

>> +       int ret = 0;

>> +       odp_cpumask_t mask;

>> +

>> +       if (0 != odp_init_global(NULL, NULL)) {

>> +               fprintf(stderr, "error: odp_init_global() failed.\n");

>> +               return -1;

>> +       }

>> +       if (0 != odp_init_local(ODP_THREAD_CONTROL)) {

>> +               fprintf(stderr, "error: odp_init_local() failed.\n");

>> +               return -1;

>> +       }

>> +

>> +       global_shm = odp_shm_reserve(GLOBAL_SHM_NAME,

>> +                                    sizeof(global_shared_mem_t), 64,

>> +                                    ODP_SHM_SW_ONLY);

>> +       if (ODP_SHM_INVALID == global_shm) {

>> +               fprintf(stderr, "Unable reserve memory for global_shm\n");

>> +               return -1;

>> +       }

>> +

>> +       global_mem = odp_shm_addr(global_shm);

>> +       memset(global_mem, 0, sizeof(global_shared_mem_t));

>> +

>> +       global_mem->g_num_threads = MAX_WORKERS;

>> +       global_mem->g_iterations = MAX_ITERATIONS;

>> +       global_mem->g_verbose = VERBOSE;

>> +

>> +       workers_count = odp_cpumask_default_worker(&mask, 0);

>> +

>> +       max_threads = (workers_count >= MAX_WORKERS) ?

>> +                       MAX_WORKERS : workers_count;

>> +

>> +       if (max_threads < global_mem->g_num_threads) {

>> +               printf("Requested num of threads is too large\n");

>> +               printf("reducing from %" PRIu32 " to %" PRIu32 "\n",

>> +                      global_mem->g_num_threads,

>> +                      max_threads);

>> +               global_mem->g_num_threads = max_threads;

>> +       }

>> +

>> +       printf("Num of threads used = %" PRIu32 "\n",

>> +              global_mem->g_num_threads);

>> +

>> +       return ret;

>> +}

>> +

>> +/* Atomic tests */

>> +static void *test_atomic_inc_dec_thread(void *arg UNUSED)

>> +{

>> +       per_thread_mem_t *per_thread_mem;

>> +

>> +       per_thread_mem = thread_init();

>> +       test_atomic_inc_dec_32();

>> +       test_atomic_inc_dec_64();

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void *test_atomic_add_sub_thread(void *arg UNUSED)

>> +{

>> +       per_thread_mem_t *per_thread_mem;

>> +

>> +       per_thread_mem = thread_init();

>> +       test_atomic_add_sub_32();

>> +       test_atomic_add_sub_64();

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void *test_atomic_fetch_inc_dec_thread(void *arg UNUSED)

>> +{

>> +       per_thread_mem_t *per_thread_mem;

>> +

>> +       per_thread_mem = thread_init();

>> +       test_atomic_fetch_inc_dec_32();

>> +       test_atomic_fetch_inc_dec_64();

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void *test_atomic_fetch_add_sub_thread(void *arg UNUSED)

>> +{

>> +       per_thread_mem_t *per_thread_mem;

>> +

>> +       per_thread_mem = thread_init();

>> +       test_atomic_fetch_add_sub_32();

>> +       test_atomic_fetch_add_sub_64();

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void test_atomic_functional(void *func_ptr(void *))

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +       test_atomic_init();

>> +       test_atomic_store();

>> +       odp_cunit_thread_create(func_ptr, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +       test_atomic_validate();

>> +}

>> +

>> +void atomic_test_atomic_inc_dec(void)

>> +{

>> +       test_atomic_functional(test_atomic_inc_dec_thread);

>> +}

>> +

>> +void atomic_test_atomic_add_sub(void)

>> +{

>> +       test_atomic_functional(test_atomic_add_sub_thread);

>> +}

>> +

>> +void atomic_test_atomic_fetch_inc_dec(void)

>> +{

>> +       test_atomic_functional(test_atomic_fetch_inc_dec_thread);

>> +}

>> +

>> +void atomic_test_atomic_fetch_add_sub(void)

>> +{

>> +       test_atomic_functional(test_atomic_fetch_add_sub_thread);

>> +}

>> +

>> +odp_testinfo_t atomic_suite_atomic[] = {

>> +       ODP_TEST_INFO(atomic_test_atomic_inc_dec),

>> +       ODP_TEST_INFO(atomic_test_atomic_add_sub),

>> +       ODP_TEST_INFO(atomic_test_atomic_fetch_inc_dec),

>> +       ODP_TEST_INFO(atomic_test_atomic_fetch_add_sub),

>> +       ODP_TEST_INFO_NULL,

>> +};

>> +

>> +odp_suiteinfo_t atomic_suites[] = {

>> +       {"atomic", NULL, NULL,

>> +               atomic_suite_atomic},

>> +       ODP_SUITE_INFO_NULL

>> +};

>> +

>> +int atomic_main(void)

>> +{

>> +       int ret;

>> +

>> +       odp_cunit_register_global_init(atomic_init);

>> +

>> +       ret = odp_cunit_register(atomic_suites);

>> +

>> +       if (ret == 0)

>> +               ret = odp_cunit_run();

>> +

>> +       return ret;

>> +}

>> diff --git a/test/validation/atomic/atomic.h

>> b/test/validation/atomic/atomic.h

>> new file mode 100644

>> index 0000000..3516c67

>> --- /dev/null

>> +++ b/test/validation/atomic/atomic.h

>> @@ -0,0 +1,33 @@

>> +/* Copyright (c) 2015, Linaro Limited

>> + * All rights reserved.

>> + *

>> + * SPDX-License-Identifier:     BSD-3-Clause

>> + */

>> +

>> +#ifndef _ODP_TEST_SYNCHRONIZERS_H_

>> +#define _ODP_TEST_SYNCHRONIZERS_H_

>> +

>> +#include <odp_cunit_common.h>

>> +

>> +/* test functions: */

>> +void atomic_test_atomic_inc_dec(void);

>> +void atomic_test_atomic_add_sub(void);

>> +void atomic_test_atomic_fetch_inc_dec(void);

>> +void atomic_test_atomic_fetch_add_sub(void);

>> +

>> +/* test arrays: */

>> +extern odp_testinfo_t atomic_suite_atomic[];

>> +

>> +/* test array init/term functions: */

>> +int atomic_suite_init(void);

>> +

>> +/* test registry: */

>> +extern odp_suiteinfo_t atomic_suites[];

>> +

>> +/* executable init/term functions: */

>> +int atomic_init(void);

>> +

>> +/* main test program: */

>> +int atomic_main(void);

>> +

>> +#endif

>> diff --git a/test/validation/atomic/atomic_main.c

>> b/test/validation/atomic/atomic_main.c

>> new file mode 100644

>> index 0000000..377bdd5

>> --- /dev/null

>> +++ b/test/validation/atomic/atomic_main.c

>> @@ -0,0 +1,12 @@

>> +/* Copyright (c) 2015, Linaro Limited

>> + * All rights reserved.

>> + *

>> + * SPDX-License-Identifier:     BSD-3-Clause

>> + */

>> +

>> +#include "atomic.h"

>> +

>> +int main(void)

>> +{

>> +       return atomic_main();

>> +}

>> diff --git a/test/validation/barrier/.gitignore

>> b/test/validation/barrier/.gitignore

>> new file mode 100644

>> index 0000000..2e0ee7a

>> --- /dev/null

>> +++ b/test/validation/barrier/.gitignore

>> @@ -0,0 +1 @@

>> +barrier_main

>> diff --git a/test/validation/barrier/Makefile.am

>> b/test/validation/barrier/Makefile.am

>> new file mode 100644

>> index 0000000..8fc632c

>> --- /dev/null

>> +++ b/test/validation/barrier/Makefile.am

>> @@ -0,0 +1,10 @@

>> +include ../Makefile.inc

>> +

>> +noinst_LTLIBRARIES = libtestbarrier.la

>> +libtestbarrier_la_SOURCES = barrier.c

>> +

>> +test_PROGRAMS = barrier_main$(EXEEXT)

>> +dist_barrier_main_SOURCES = barrier_main.c

>> +barrier_main_LDADD = libtestbarrier.la $(LIBCUNIT_COMMON) $(LIBODP)

>> +

>> +EXTRA_DIST = barrier.h

>> diff --git a/test/validation/barrier/barrier.c

>> b/test/validation/barrier/barrier.c

>> new file mode 100644

>> index 0000000..ab7fcf4

>> --- /dev/null

>> +++ b/test/validation/barrier/barrier.c

>> @@ -0,0 +1,370 @@

>> +/* Copyright (c) 2014, Linaro Limited

>> + * All rights reserved.

>> + *

>> + * SPDX-License-Identifier:     BSD-3-Clause

>> + */

>> +

>> +#include <malloc.h>

>> +#include <odp.h>

>> +#include <CUnit/Basic.h>

>> +#include <odp_cunit_common.h>

>> +#include <unistd.h>

>> +#include "barrier.h"

>> +

>> +#define VERBOSE                        0

>> +#define MAX_ITERATIONS         1000

>> +#define BARRIER_ITERATIONS     64

>> +

>> +#define SLOW_BARRIER_DELAY     400

>> +#define BASE_DELAY             6

>> +

>> +#define NUM_TEST_BARRIERS      BARRIER_ITERATIONS

>> +#define NUM_RESYNC_BARRIERS    100

>> +

>> +#define BARRIER_DELAY          10

>> +

>> +#define GLOBAL_SHM_NAME                "GlobalLockTest"

>> +

>> +#define UNUSED                 __attribute__((__unused__))

>> +

>> +typedef __volatile uint32_t volatile_u32_t;

>> +typedef __volatile uint64_t volatile_u64_t;

>> +

>> +typedef struct {

>> +       odp_atomic_u32_t wait_cnt;

>> +} custom_barrier_t;

>> +

>> +typedef struct {

>> +       /* Global variables */

>> +       uint32_t g_num_threads;

>> +       uint32_t g_iterations;

>> +       uint32_t g_verbose;

>> +       uint32_t g_max_num_cores;

>> +

>> +       odp_barrier_t test_barriers[NUM_TEST_BARRIERS];

>> +       custom_barrier_t custom_barrier1[NUM_TEST_BARRIERS];

>> +       custom_barrier_t custom_barrier2[NUM_TEST_BARRIERS];

>> +       volatile_u32_t slow_thread_num;

>> +       volatile_u32_t barrier_cnt1;

>> +       volatile_u32_t barrier_cnt2;

>> +       odp_barrier_t global_barrier;

>> +

>> +} global_shared_mem_t;

>> +

>> +/* Per-thread memory */

>> +typedef struct {

>> +       global_shared_mem_t *global_mem;

>> +

>> +       int thread_id;

>> +       int thread_core;

>> +

>> +       volatile_u64_t delay_counter;

>> +} per_thread_mem_t;

>> +

>> +static odp_shm_t global_shm;

>> +static global_shared_mem_t *global_mem;

>> +

>> +/*

>> +* Delay a consistent amount of time.  Ideally the amount of CPU time

>> taken

>> +* is linearly proportional to "iterations".  The goal is to try to do

>> some

>> +* work that the compiler optimizer won't optimize away, and also to

>> +* minimize loads and stores (at least to different memory addresses)

>> +* so as to not affect or be affected by caching issues.  This does NOT

>> have to

>> +* correlate to a specific number of cpu cycles or be consistent across

>> +* CPU architectures.

>> +*/

>> +static void thread_delay(per_thread_mem_t *per_thread_mem, uint32_t

>> iterations)

>> +{

>> +       volatile_u64_t *counter_ptr;

>> +       uint32_t cnt;

>> +

>> +       counter_ptr = &per_thread_mem->delay_counter;

>> +

>> +       for (cnt = 1; cnt <= iterations; cnt++)

>> +               (*counter_ptr)++;

>> +}

>> +

>> +/* Initialise per-thread memory */

>> +static per_thread_mem_t *thread_init(void)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       odp_shm_t global_shm;

>> +       uint32_t per_thread_mem_len;

>> +

>> +       per_thread_mem_len = sizeof(per_thread_mem_t);

>> +       per_thread_mem = malloc(per_thread_mem_len);

>> +       memset(per_thread_mem, 0, per_thread_mem_len);

>> +

>> +       per_thread_mem->delay_counter = 1;

>> +

>> +       per_thread_mem->thread_id = odp_thread_id();

>> +       per_thread_mem->thread_core = odp_cpu_id();

>> +

>> +       global_shm = odp_shm_lookup(GLOBAL_SHM_NAME);

>> +       global_mem = odp_shm_addr(global_shm);

>> +       CU_ASSERT_PTR_NOT_NULL(global_mem);

>> +

>> +       per_thread_mem->global_mem = global_mem;

>> +

>> +       return per_thread_mem;

>> +}

>> +

>> +static void thread_finalize(per_thread_mem_t *per_thread_mem)

>> +{

>> +       free(per_thread_mem);

>> +}

>> +

>> +static void custom_barrier_init(custom_barrier_t *custom_barrier,

>> +                               uint32_t num_threads)

>> +{

>> +       odp_atomic_init_u32(&custom_barrier->wait_cnt, num_threads);

>> +}

>> +

>> +static void custom_barrier_wait(custom_barrier_t *custom_barrier)

>> +{

>> +       volatile_u64_t counter = 1;

>> +       uint32_t delay_cnt, wait_cnt;

>> +

>> +       odp_atomic_sub_u32(&custom_barrier->wait_cnt, 1);

>> +

>> +       wait_cnt = 1;

>> +       while (wait_cnt != 0) {

>> +               for (delay_cnt = 1; delay_cnt <= BARRIER_DELAY;

>> delay_cnt++)

>> +                       counter++;

>> +

>> +               wait_cnt = odp_atomic_load_u32(&custom_barrier->wait_cnt);

>> +       }

>> +}

>> +

>> +static uint32_t barrier_test(per_thread_mem_t *per_thread_mem,

>> +                            odp_bool_t no_barrier_test)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       uint32_t barrier_errs, iterations, cnt, i_am_slow_thread;

>> +       uint32_t thread_num, slow_thread_num, next_slow_thread,

>> num_threads;

>> +       uint32_t lock_owner_delay, barrier_cnt1, barrier_cnt2;

>> +

>> +       thread_num = odp_thread_id();

>> +       global_mem = per_thread_mem->global_mem;

>> +       num_threads = global_mem->g_num_threads;

>> +       iterations = BARRIER_ITERATIONS;

>> +

>> +       barrier_errs = 0;

>> +       lock_owner_delay = SLOW_BARRIER_DELAY;

>> +

>> +       for (cnt = 1; cnt < iterations; cnt++) {

>> +               /* Wait here until all of the threads reach this point */

>> +               custom_barrier_wait(&global_mem->custom_barrier1[cnt]);

>> +

>> +               barrier_cnt1 = global_mem->barrier_cnt1;

>> +               barrier_cnt2 = global_mem->barrier_cnt2;

>> +

>> +               if ((barrier_cnt1 != cnt) || (barrier_cnt2 != cnt)) {

>> +                       printf("thread_num=%" PRIu32 " barrier_cnts of %"

>> PRIu32

>> +                                  " %" PRIu32 " cnt=%" PRIu32 "\n",

>> +                              thread_num, barrier_cnt1, barrier_cnt2,

>> cnt);

>> +                       barrier_errs++;

>> +               }

>> +

>> +               /* Wait here until all of the threads reach this point */

>> +               custom_barrier_wait(&global_mem->custom_barrier2[cnt]);

>> +

>> +               slow_thread_num = global_mem->slow_thread_num;

>> +               i_am_slow_thread = thread_num == slow_thread_num;

>> +               next_slow_thread = slow_thread_num + 1;

>> +               if (num_threads < next_slow_thread)

>> +                       next_slow_thread = 1;

>> +

>> +               /*

>> +               * Now run the test, which involves having all but one

>> thread

>> +               * immediately calling odp_barrier_wait(), and one thread

>> wait a

>> +               * moderate amount of time and then calling

>> odp_barrier_wait().

>> +               * The test fails if any of the first group of threads

>> +               * has not waited for the "slow" thread. The "slow" thread

>> is

>> +               * responsible for re-initializing the barrier for next

>> trial.

>> +               */

>> +               if (i_am_slow_thread) {

>> +                       thread_delay(per_thread_mem, lock_owner_delay);

>> +                       lock_owner_delay += BASE_DELAY;

>> +                       if ((global_mem->barrier_cnt1 != cnt) ||

>> +                           (global_mem->barrier_cnt2 != cnt) ||

>> +                           (global_mem->slow_thread_num

>> +                                       != slow_thread_num))

>> +                               barrier_errs++;

>> +               }

>> +

>> +               if (no_barrier_test == 0)

>> +                       odp_barrier_wait(&global_mem->test_barriers[cnt]);

>> +

>> +               global_mem->barrier_cnt1 = cnt + 1;

>> +               odp_sync_stores();

>> +

>> +               if (i_am_slow_thread) {

>> +                       global_mem->slow_thread_num = next_slow_thread;

>> +                       global_mem->barrier_cnt2 = cnt + 1;

>> +                       odp_sync_stores();

>> +               } else {

>> +                       while (global_mem->barrier_cnt2 != (cnt + 1))

>> +                               thread_delay(per_thread_mem, BASE_DELAY);

>> +               }

>> +       }

>> +

>> +       if ((global_mem->g_verbose) && (barrier_errs != 0))

>> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

>> +                      " barrier_errs in %" PRIu32 " iterations\n",

>> thread_num,

>> +                      per_thread_mem->thread_id,

>> +                      per_thread_mem->thread_core, barrier_errs,

>> iterations);

>> +

>> +       return barrier_errs;

>> +}

>> +

>> +static void *no_barrier_functional_test(void *arg UNUSED)

>> +{

>> +       per_thread_mem_t *per_thread_mem;

>> +       uint32_t barrier_errs;

>> +

>> +       per_thread_mem = thread_init();

>> +       barrier_errs = barrier_test(per_thread_mem, 1);

>> +

>> +       /*

>> +       * Note that the following CU_ASSERT MAY appear incorrect, but for

>> the

>> +       * no_barrier test it should see barrier_errs or else there is

>> something

>> +       * wrong with the test methodology or the ODP thread

>> implementation.

>> +       * So this test PASSES only if it sees barrier_errs or a single

>> +       * worker was used.

>> +       */

>> +       CU_ASSERT(barrier_errs != 0 || global_mem->g_num_threads == 1);

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void *barrier_functional_test(void *arg UNUSED)

>> +{

>> +       per_thread_mem_t *per_thread_mem;

>> +       uint32_t barrier_errs;

>> +

>> +       per_thread_mem = thread_init();

>> +       barrier_errs = barrier_test(per_thread_mem, 0);

>> +

>> +       CU_ASSERT(barrier_errs == 0);

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void barrier_test_init(void)

>> +{

>> +       uint32_t num_threads, idx;

>> +

>> +       num_threads = global_mem->g_num_threads;

>> +

>> +       for (idx = 0; idx < NUM_TEST_BARRIERS; idx++) {

>> +               odp_barrier_init(&global_mem->test_barriers[idx],

>> num_threads);

>> +               custom_barrier_init(&global_mem->custom_barrier1[idx],

>> +                                   num_threads);

>> +               custom_barrier_init(&global_mem->custom_barrier2[idx],

>> +                                   num_threads);

>> +       }

>> +

>> +       global_mem->slow_thread_num = 1;

>> +       global_mem->barrier_cnt1 = 1;

>> +       global_mem->barrier_cnt2 = 1;

>> +}

>> +

>> +/* Barrier tests */

>> +void barrier_test_no_barrier_functional(void)

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +       barrier_test_init();

>> +       odp_cunit_thread_create(no_barrier_functional_test, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +}

>> +

>> +void barrier_test_barrier_functional(void)

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +       barrier_test_init();

>> +       odp_cunit_thread_create(barrier_functional_test, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +}

>> +

>> +odp_testinfo_t barrier_suite_barrier[] = {

>> +       ODP_TEST_INFO(barrier_test_no_barrier_functional),

>> +       ODP_TEST_INFO(barrier_test_barrier_functional),

>> +       ODP_TEST_INFO_NULL

>> +};

>> +

>> +int barrier_init(void)

>> +{

>> +       uint32_t workers_count, max_threads;

>> +       int ret = 0;

>> +       odp_cpumask_t mask;

>> +

>> +       if (0 != odp_init_global(NULL, NULL)) {

>> +               fprintf(stderr, "error: odp_init_global() failed.\n");

>> +               return -1;

>> +       }

>> +       if (0 != odp_init_local(ODP_THREAD_CONTROL)) {

>> +               fprintf(stderr, "error: odp_init_local() failed.\n");

>> +               return -1;

>> +       }

>> +

>> +       global_shm = odp_shm_reserve(GLOBAL_SHM_NAME,

>> +                                    sizeof(global_shared_mem_t), 64,

>> +                                    ODP_SHM_SW_ONLY);

>> +       if (ODP_SHM_INVALID == global_shm) {

>> +               fprintf(stderr, "Unable reserve memory for global_shm\n");

>> +               return -1;

>> +       }

>> +

>> +       global_mem = odp_shm_addr(global_shm);

>> +       memset(global_mem, 0, sizeof(global_shared_mem_t));

>> +

>> +       global_mem->g_num_threads = MAX_WORKERS;

>> +       global_mem->g_iterations = MAX_ITERATIONS;

>> +       global_mem->g_verbose = VERBOSE;

>> +

>> +       workers_count = odp_cpumask_default_worker(&mask, 0);

>> +

>> +       max_threads = (workers_count >= MAX_WORKERS) ?

>> +                       MAX_WORKERS : workers_count;

>> +

>> +       if (max_threads < global_mem->g_num_threads) {

>> +               printf("Requested num of threads is too large\n");

>> +               printf("reducing from %" PRIu32 " to %" PRIu32 "\n",

>> +                      global_mem->g_num_threads,

>> +                      max_threads);

>> +               global_mem->g_num_threads = max_threads;

>> +       }

>> +

>> +       printf("Num of threads used = %" PRIu32 "\n",

>> +              global_mem->g_num_threads);

>> +

>> +       return ret;

>> +}

>> +

>> +odp_suiteinfo_t barrier_suites[] = {

>> +       {"barrier", NULL, NULL,

>> +               barrier_suite_barrier},

>> +       ODP_SUITE_INFO_NULL

>> +};

>> +

>> +int barrier_main(void)

>> +{

>> +       int ret;

>> +

>> +       odp_cunit_register_global_init(barrier_init);

>> +

>> +       ret = odp_cunit_register(barrier_suites);

>> +

>> +       if (ret == 0)

>> +               ret = odp_cunit_run();

>> +

>> +       return ret;

>> +}

>> diff --git a/test/validation/barrier/barrier.h

>> b/test/validation/barrier/barrier.h

>> new file mode 100644

>> index 0000000..a6310d0

>> --- /dev/null

>> +++ b/test/validation/barrier/barrier.h

>> @@ -0,0 +1,28 @@

>> +/* Copyright (c) 2015, Linaro Limited

>> + * All rights reserved.

>> + *

>> + * SPDX-License-Identifier:     BSD-3-Clause

>> + */

>> +

>> +#ifndef _ODP_TEST_SYNCHRONIZERS_H_

>> +#define _ODP_TEST_SYNCHRONIZERS_H_

>> +

>> +#include <odp_cunit_common.h>

>> +

>> +/* test functions: */

>> +void barrier_test_no_barrier_functional(void);

>> +void barrier_test_barrier_functional(void);

>> +

>> +/* test arrays: */

>> +extern odp_testinfo_t barrier_suite_barrier[];

>> +

>> +/* test registry: */

>> +extern odp_suiteinfo_t barrier_suites[];

>> +

>> +/* executable init/term functions: */

>> +int barrier_init(void);

>> +

>> +/* main test program: */

>> +int barrier_main(void);

>> +

>> +#endif

>> diff --git a/test/validation/barrier/barrier_main.c

>> b/test/validation/barrier/barrier_main.c

>> new file mode 100644

>> index 0000000..88c9b3e

>> --- /dev/null

>> +++ b/test/validation/barrier/barrier_main.c

>> @@ -0,0 +1,12 @@

>> +/* Copyright (c) 2015, Linaro Limited

>> + * All rights reserved.

>> + *

>> + * SPDX-License-Identifier:     BSD-3-Clause

>> + */

>> +

>> +#include "barrier.h"

>> +

>> +int main(void)

>> +{

>> +       return barrier_main();

>> +}

>> diff --git a/test/validation/lock/.gitignore

>> b/test/validation/lock/.gitignore

>> new file mode 100644

>> index 0000000..ff16646

>> --- /dev/null

>> +++ b/test/validation/lock/.gitignore

>> @@ -0,0 +1 @@

>> +lock_main

>> diff --git a/test/validation/lock/Makefile.am

>> b/test/validation/lock/Makefile.am

>> new file mode 100644

>> index 0000000..29993df

>> --- /dev/null

>> +++ b/test/validation/lock/Makefile.am

>> @@ -0,0 +1,10 @@

>> +include ../Makefile.inc

>> +

>> +noinst_LTLIBRARIES = libtestlock.la

>> +libtestlock_la_SOURCES = lock.c

>> +

>> +test_PROGRAMS = lock_main$(EXEEXT)

>> +dist_lock_main_SOURCES = lock_main.c

>> +lock_main_LDADD = libtestlock.la $(LIBCUNIT_COMMON) $(LIBODP)

>> +

>> +EXTRA_DIST = lock.h

>> diff --git a/test/validation/lock/lock.c b/test/validation/lock/lock.c

>> new file mode 100644

>> index 0000000..76009f0

>> --- /dev/null

>> +++ b/test/validation/lock/lock.c

>> @@ -0,0 +1,1135 @@

>> +/* Copyright (c) 2014, Linaro Limited

>> + * All rights reserved.

>> + *

>> + * SPDX-License-Identifier:     BSD-3-Clause

>> + */

>> +

>> +#include <malloc.h>

>> +#include <odp.h>

>> +#include <CUnit/Basic.h>

>> +#include <odp_cunit_common.h>

>> +#include <unistd.h>

>> +#include "lock.h"

>> +

>> +#define VERBOSE                        0

>> +#define MAX_ITERATIONS         1000

>> +

>> +#define SLOW_BARRIER_DELAY     400

>> +#define BASE_DELAY             6

>> +#define MIN_DELAY              1

>> +

>> +#define NUM_RESYNC_BARRIERS    100

>> +

>> +#define GLOBAL_SHM_NAME                "GlobalLockTest"

>> +

>> +#define UNUSED                 __attribute__((__unused__))

>> +

>> +typedef __volatile uint32_t volatile_u32_t;

>> +typedef __volatile uint64_t volatile_u64_t;

>> +

>> +typedef struct {

>> +       odp_atomic_u32_t wait_cnt;

>> +} custom_barrier_t;

>> +

>> +typedef struct {

>> +       /* Global variables */

>> +       uint32_t g_num_threads;

>> +       uint32_t g_iterations;

>> +       uint32_t g_verbose;

>> +       uint32_t g_max_num_cores;

>> +

>> +       volatile_u32_t slow_thread_num;

>> +       volatile_u32_t barrier_cnt1;

>> +       volatile_u32_t barrier_cnt2;

>> +       odp_barrier_t global_barrier;

>> +

>> +       /* Used to periodically resync within the lock functional tests */

>> +       odp_barrier_t barrier_array[NUM_RESYNC_BARRIERS];

>> +

>> +       /* Locks */

>> +       odp_spinlock_t global_spinlock;

>> +       odp_spinlock_recursive_t global_recursive_spinlock;

>> +       odp_ticketlock_t global_ticketlock;

>> +       odp_rwlock_t global_rwlock;

>> +       odp_rwlock_recursive_t global_recursive_rwlock;

>> +

>> +       volatile_u32_t global_lock_owner;

>> +} global_shared_mem_t;

>> +

>> +/* Per-thread memory */

>> +typedef struct {

>> +       global_shared_mem_t *global_mem;

>> +

>> +       int thread_id;

>> +       int thread_core;

>> +

>> +       odp_spinlock_t per_thread_spinlock;

>> +       odp_spinlock_recursive_t per_thread_recursive_spinlock;

>> +       odp_ticketlock_t per_thread_ticketlock;

>> +       odp_rwlock_t per_thread_rwlock;

>> +       odp_rwlock_recursive_t per_thread_recursive_rwlock;

>> +

>> +       volatile_u64_t delay_counter;

>> +} per_thread_mem_t;

>> +

>> +static odp_shm_t global_shm;

>> +static global_shared_mem_t *global_mem;

>> +

>> +/*

>> +* Delay a consistent amount of time.  Ideally the amount of CPU time

>> taken

>> +* is linearly proportional to "iterations".  The goal is to try to do

>> some

>> +* work that the compiler optimizer won't optimize away, and also to

>> +* minimize loads and stores (at least to different memory addresses)

>> +* so as to not affect or be affected by caching issues.  This does NOT

>> have to

>> +* correlate to a specific number of cpu cycles or be consistent across

>> +* CPU architectures.

>> +*/

>> +static void thread_delay(per_thread_mem_t *per_thread_mem, uint32_t

>> iterations)

>> +{

>> +       volatile_u64_t *counter_ptr;

>> +       uint32_t cnt;

>> +

>> +       counter_ptr = &per_thread_mem->delay_counter;

>> +

>> +       for (cnt = 1; cnt <= iterations; cnt++)

>> +               (*counter_ptr)++;

>> +}

>> +

>> +/* Initialise per-thread memory */

>> +static per_thread_mem_t *thread_init(void)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       odp_shm_t global_shm;

>> +       uint32_t per_thread_mem_len;

>> +

>> +       per_thread_mem_len = sizeof(per_thread_mem_t);

>> +       per_thread_mem = malloc(per_thread_mem_len);

>> +       memset(per_thread_mem, 0, per_thread_mem_len);

>> +

>> +       per_thread_mem->delay_counter = 1;

>> +

>> +       per_thread_mem->thread_id = odp_thread_id();

>> +       per_thread_mem->thread_core = odp_cpu_id();

>> +

>> +       global_shm = odp_shm_lookup(GLOBAL_SHM_NAME);

>> +       global_mem = odp_shm_addr(global_shm);

>> +       CU_ASSERT_PTR_NOT_NULL(global_mem);

>> +

>> +       per_thread_mem->global_mem = global_mem;

>> +

>> +       return per_thread_mem;

>> +}

>> +

>> +static void thread_finalize(per_thread_mem_t *per_thread_mem)

>> +{

>> +       free(per_thread_mem);

>> +}

>> +

>> +static void spinlock_api_test(odp_spinlock_t *spinlock)

>> +{

>> +       odp_spinlock_init(spinlock);

>> +       CU_ASSERT(odp_spinlock_is_locked(spinlock) == 0);

>> +

>> +       odp_spinlock_lock(spinlock);

>> +       CU_ASSERT(odp_spinlock_is_locked(spinlock) == 1);

>> +

>> +       odp_spinlock_unlock(spinlock);

>> +       CU_ASSERT(odp_spinlock_is_locked(spinlock) == 0);

>> +

>> +       CU_ASSERT(odp_spinlock_trylock(spinlock) == 1);

>> +

>> +       CU_ASSERT(odp_spinlock_is_locked(spinlock) == 1);

>> +

>> +       odp_spinlock_unlock(spinlock);

>> +       CU_ASSERT(odp_spinlock_is_locked(spinlock) == 0);

>> +}

>> +

>> +static void *spinlock_api_tests(void *arg UNUSED)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       odp_spinlock_t local_spin_lock;

>> +

>> +       per_thread_mem = thread_init();

>> +       global_mem = per_thread_mem->global_mem;

>> +

>> +       odp_barrier_wait(&global_mem->global_barrier);

>> +

>> +       spinlock_api_test(&local_spin_lock);

>> +       spinlock_api_test(&per_thread_mem->per_thread_spinlock);

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void spinlock_recursive_api_test(odp_spinlock_recursive_t

>> *spinlock)

>> +{

>> +       odp_spinlock_recursive_init(spinlock);

>> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 0);

>> +

>> +       odp_spinlock_recursive_lock(spinlock);

>> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);

>> +

>> +       odp_spinlock_recursive_lock(spinlock);

>> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);

>> +

>> +       odp_spinlock_recursive_unlock(spinlock);

>> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);

>> +

>> +       odp_spinlock_recursive_unlock(spinlock);

>> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 0);

>> +

>> +       CU_ASSERT(odp_spinlock_recursive_trylock(spinlock) == 1);

>> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);

>> +

>> +       CU_ASSERT(odp_spinlock_recursive_trylock(spinlock) == 1);

>> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);

>> +

>> +       odp_spinlock_recursive_unlock(spinlock);

>> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);

>> +

>> +       odp_spinlock_recursive_unlock(spinlock);

>> +       CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 0);

>> +}

>> +

>> +static void *spinlock_recursive_api_tests(void *arg UNUSED)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       odp_spinlock_recursive_t local_recursive_spin_lock;

>> +

>> +       per_thread_mem = thread_init();

>> +       global_mem = per_thread_mem->global_mem;

>> +

>> +       odp_barrier_wait(&global_mem->global_barrier);

>> +

>> +       spinlock_recursive_api_test(&local_recursive_spin_lock);

>> +       spinlock_recursive_api_test(

>> +               &per_thread_mem->per_thread_recursive_spinlock);

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void ticketlock_api_test(odp_ticketlock_t *ticketlock)

>> +{

>> +       odp_ticketlock_init(ticketlock);

>> +       CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 0);

>> +

>> +       odp_ticketlock_lock(ticketlock);

>> +       CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 1);

>> +

>> +       odp_ticketlock_unlock(ticketlock);

>> +       CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 0);

>> +

>> +       CU_ASSERT(odp_ticketlock_trylock(ticketlock) == 1);

>> +       CU_ASSERT(odp_ticketlock_trylock(ticketlock) == 0);

>> +       CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 1);

>> +

>> +       odp_ticketlock_unlock(ticketlock);

>> +       CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 0);

>> +}

>> +

>> +static void *ticketlock_api_tests(void *arg UNUSED)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       odp_ticketlock_t local_ticket_lock;

>> +

>> +       per_thread_mem = thread_init();

>> +       global_mem = per_thread_mem->global_mem;

>> +

>> +       odp_barrier_wait(&global_mem->global_barrier);

>> +

>> +       ticketlock_api_test(&local_ticket_lock);

>> +       ticketlock_api_test(&per_thread_mem->per_thread_ticketlock);

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void rwlock_api_test(odp_rwlock_t *rw_lock)

>> +{

>> +       odp_rwlock_init(rw_lock);

>> +       /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */

>> +

>> +       odp_rwlock_read_lock(rw_lock);

>> +       odp_rwlock_read_unlock(rw_lock);

>> +

>> +       odp_rwlock_write_lock(rw_lock);

>> +       /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 1); */

>> +

>> +       odp_rwlock_write_unlock(rw_lock);

>> +       /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */

>> +}

>> +

>> +static void *rwlock_api_tests(void *arg UNUSED)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       odp_rwlock_t local_rwlock;

>> +

>> +       per_thread_mem = thread_init();

>> +       global_mem = per_thread_mem->global_mem;

>> +

>> +       odp_barrier_wait(&global_mem->global_barrier);

>> +

>> +       rwlock_api_test(&local_rwlock);

>> +       rwlock_api_test(&per_thread_mem->per_thread_rwlock);

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void rwlock_recursive_api_test(odp_rwlock_recursive_t *rw_lock)

>> +{

>> +       odp_rwlock_recursive_init(rw_lock);

>> +       /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */

>> +

>> +       odp_rwlock_recursive_read_lock(rw_lock);

>> +       odp_rwlock_recursive_read_lock(rw_lock);

>> +

>> +       odp_rwlock_recursive_read_unlock(rw_lock);

>> +       odp_rwlock_recursive_read_unlock(rw_lock);

>> +

>> +       odp_rwlock_recursive_write_lock(rw_lock);

>> +       odp_rwlock_recursive_write_lock(rw_lock);

>> +       /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 1); */

>> +

>> +       odp_rwlock_recursive_write_unlock(rw_lock);

>> +       odp_rwlock_recursive_write_unlock(rw_lock);

>> +       /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */

>> +}

>> +

>> +static void *rwlock_recursive_api_tests(void *arg UNUSED)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       odp_rwlock_recursive_t local_recursive_rwlock;

>> +

>> +       per_thread_mem = thread_init();

>> +       global_mem = per_thread_mem->global_mem;

>> +

>> +       odp_barrier_wait(&global_mem->global_barrier);

>> +

>> +       rwlock_recursive_api_test(&local_recursive_rwlock);

>> +

>>  rwlock_recursive_api_test(&per_thread_mem->per_thread_recursive_rwlock);

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void *no_lock_functional_test(void *arg UNUSED)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;

>> +       uint32_t sync_failures, current_errs, lock_owner_delay;

>> +

>> +       thread_num = odp_cpu_id() + 1;

>> +       per_thread_mem = thread_init();

>> +       global_mem = per_thread_mem->global_mem;

>> +       iterations = global_mem->g_iterations;

>> +

>> +       odp_barrier_wait(&global_mem->global_barrier);

>> +

>> +       sync_failures = 0;

>> +       current_errs = 0;

>> +       rs_idx = 0;

>> +       resync_cnt = iterations / NUM_RESYNC_BARRIERS;

>> +       lock_owner_delay = BASE_DELAY;

>> +

>> +       for (cnt = 1; cnt <= iterations; cnt++) {

>> +               global_mem->global_lock_owner = thread_num;

>> +               odp_sync_stores();

>> +               thread_delay(per_thread_mem, lock_owner_delay);

>> +

>> +               if (global_mem->global_lock_owner != thread_num) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               global_mem->global_lock_owner = 0;

>> +               odp_sync_stores();

>> +               thread_delay(per_thread_mem, MIN_DELAY);

>> +

>> +               if (global_mem->global_lock_owner == thread_num) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               if (current_errs == 0)

>> +                       lock_owner_delay++;

>> +

>> +               /* Wait a small amount of time and rerun the test */

>> +               thread_delay(per_thread_mem, BASE_DELAY);

>> +

>> +               /* Try to resync all of the threads to increase

>> contention */

>> +               if ((rs_idx < NUM_RESYNC_BARRIERS) &&

>> +                   ((cnt % resync_cnt) == (resync_cnt - 1)))

>> +

>>  odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);

>> +       }

>> +

>> +       if (global_mem->g_verbose)

>> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

>> +                      " sync_failures in %" PRIu32 " iterations\n",

>> +                      thread_num,

>> +                      per_thread_mem->thread_id,

>> +                      per_thread_mem->thread_core,

>> +                      sync_failures, iterations);

>> +

>> +       /* Note that the following CU_ASSERT MAY appear incorrect, but

>> for the

>> +       * no_lock test it should see sync_failures or else there is

>> something

>> +       * wrong with the test methodology or the ODP thread

>> implementation.

>> +       * So this test PASSES only if it sees sync_failures or a single

>> +       * worker was used.

>> +       */

>> +       CU_ASSERT(sync_failures != 0 || global_mem->g_num_threads == 1);

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void *spinlock_functional_test(void *arg UNUSED)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;

>> +       uint32_t sync_failures, is_locked_errs, current_errs;

>> +       uint32_t lock_owner_delay;

>> +

>> +       thread_num = odp_cpu_id() + 1;

>> +       per_thread_mem = thread_init();

>> +       global_mem = per_thread_mem->global_mem;

>> +       iterations = global_mem->g_iterations;

>> +

>> +       odp_barrier_wait(&global_mem->global_barrier);

>> +

>> +       sync_failures = 0;

>> +       is_locked_errs = 0;

>> +       current_errs = 0;

>> +       rs_idx = 0;

>> +       resync_cnt = iterations / NUM_RESYNC_BARRIERS;

>> +       lock_owner_delay = BASE_DELAY;

>> +

>> +       for (cnt = 1; cnt <= iterations; cnt++) {

>> +               /* Acquire the shared global lock */

>> +               odp_spinlock_lock(&global_mem->global_spinlock);

>> +

>> +               /* Make sure we have the lock AND didn't previously own

>> it */

>> +               if (odp_spinlock_is_locked(&global_mem->global_spinlock)

>> != 1)

>> +                       is_locked_errs++;

>> +

>> +               if (global_mem->global_lock_owner != 0) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               /* Now set the global_lock_owner to be us, wait a while,

>> and

>> +               * then we see if anyone else has snuck in and changed the

>> +               * global_lock_owner to be themselves

>> +               */

>> +               global_mem->global_lock_owner = thread_num;

>> +               odp_sync_stores();

>> +               thread_delay(per_thread_mem, lock_owner_delay);

>> +               if (global_mem->global_lock_owner != thread_num) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               /* Release shared lock, and make sure we no longer have

>> it */

>> +               global_mem->global_lock_owner = 0;

>> +               odp_sync_stores();

>> +               odp_spinlock_unlock(&global_mem->global_spinlock);

>> +               if (global_mem->global_lock_owner == thread_num) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               if (current_errs == 0)

>> +                       lock_owner_delay++;

>> +

>> +               /* Wait a small amount of time and rerun the test */

>> +               thread_delay(per_thread_mem, BASE_DELAY);

>> +

>> +               /* Try to resync all of the threads to increase

>> contention */

>> +               if ((rs_idx < NUM_RESYNC_BARRIERS) &&

>> +                   ((cnt % resync_cnt) == (resync_cnt - 1)))

>> +

>>  odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);

>> +       }

>> +

>> +       if ((global_mem->g_verbose) &&

>> +           ((sync_failures != 0) || (is_locked_errs != 0)))

>> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

>> +                      " sync_failures and %" PRIu32

>> +                      " is_locked_errs in %" PRIu32

>> +                      " iterations\n", thread_num,

>> +                      per_thread_mem->thread_id,

>> per_thread_mem->thread_core,

>> +                      sync_failures, is_locked_errs, iterations);

>> +

>> +       CU_ASSERT(sync_failures == 0);

>> +       CU_ASSERT(is_locked_errs == 0);

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void *spinlock_recursive_functional_test(void *arg UNUSED)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;

>> +       uint32_t sync_failures, recursive_errs, is_locked_errs,

>> current_errs;

>> +       uint32_t lock_owner_delay;

>> +

>> +       thread_num = odp_cpu_id() + 1;

>> +       per_thread_mem = thread_init();

>> +       global_mem = per_thread_mem->global_mem;

>> +       iterations = global_mem->g_iterations;

>> +

>> +       odp_barrier_wait(&global_mem->global_barrier);

>> +

>> +       sync_failures = 0;

>> +       recursive_errs = 0;

>> +       is_locked_errs = 0;

>> +       current_errs = 0;

>> +       rs_idx = 0;

>> +       resync_cnt = iterations / NUM_RESYNC_BARRIERS;

>> +       lock_owner_delay = BASE_DELAY;

>> +

>> +       for (cnt = 1; cnt <= iterations; cnt++) {

>> +               /* Acquire the shared global lock */

>> +               odp_spinlock_recursive_lock(

>> +                       &global_mem->global_recursive_spinlock);

>> +

>> +               /* Make sure we have the lock AND didn't previously own

>> it */

>> +               if (odp_spinlock_recursive_is_locked(

>> +                           &global_mem->global_recursive_spinlock) != 1)

>> +                       is_locked_errs++;

>> +

>> +               if (global_mem->global_lock_owner != 0) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +              /* Now set the global_lock_owner to be us, wait a while,

>> and

>> +               * then we see if anyone else has snuck in and changed the

>> +               * global_lock_owner to be themselves

>> +               */

>> +               global_mem->global_lock_owner = thread_num;

>> +               odp_sync_stores();

>> +               thread_delay(per_thread_mem, lock_owner_delay);

>> +               if (global_mem->global_lock_owner != thread_num) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               /* Verify that we can acquire the lock recursively */

>> +               odp_spinlock_recursive_lock(

>> +                       &global_mem->global_recursive_spinlock);

>> +               if (global_mem->global_lock_owner != thread_num) {

>> +                       current_errs++;

>> +                       recursive_errs++;

>> +               }

>> +

>> +               /* Release the lock and verify that we still have it*/

>> +               odp_spinlock_recursive_unlock(

>> +                       &global_mem->global_recursive_spinlock);

>> +               thread_delay(per_thread_mem, lock_owner_delay);

>> +               if (global_mem->global_lock_owner != thread_num) {

>> +                       current_errs++;

>> +                       recursive_errs++;

>> +               }

>> +

>> +               /* Release shared lock, and make sure we no longer have

>> it */

>> +               global_mem->global_lock_owner = 0;

>> +               odp_sync_stores();

>> +               odp_spinlock_recursive_unlock(

>> +                       &global_mem->global_recursive_spinlock);

>> +               if (global_mem->global_lock_owner == thread_num) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               if (current_errs == 0)

>> +                       lock_owner_delay++;

>> +

>> +               /* Wait a small amount of time and rerun the test */

>> +               thread_delay(per_thread_mem, BASE_DELAY);

>> +

>> +               /* Try to resync all of the threads to increase

>> contention */

>> +               if ((rs_idx < NUM_RESYNC_BARRIERS) &&

>> +                   ((cnt % resync_cnt) == (resync_cnt - 1)))

>> +

>>  odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);

>> +       }

>> +

>> +       if ((global_mem->g_verbose) &&

>> +           (sync_failures != 0 || recursive_errs != 0 || is_locked_errs

>> != 0))

>> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

>> +                      " sync_failures and %" PRIu32

>> +                      " recursive_errs and %" PRIu32

>> +                      " is_locked_errs in %" PRIu32

>> +                      " iterations\n", thread_num,

>> +                      per_thread_mem->thread_id,

>> per_thread_mem->thread_core,

>> +                      sync_failures, recursive_errs, is_locked_errs,

>> +                      iterations);

>> +

>> +       CU_ASSERT(sync_failures == 0);

>> +       CU_ASSERT(recursive_errs == 0);

>> +       CU_ASSERT(is_locked_errs == 0);

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void *ticketlock_functional_test(void *arg UNUSED)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;

>> +       uint32_t sync_failures, is_locked_errs, current_errs;

>> +       uint32_t lock_owner_delay;

>> +

>> +       thread_num = odp_cpu_id() + 1;

>> +       per_thread_mem = thread_init();

>> +       global_mem = per_thread_mem->global_mem;

>> +       iterations = global_mem->g_iterations;

>> +

>> +       /* Wait here until all of the threads have also reached this

>> point */

>> +       odp_barrier_wait(&global_mem->global_barrier);

>> +

>> +       sync_failures = 0;

>> +       is_locked_errs = 0;

>> +       current_errs = 0;

>> +       rs_idx = 0;

>> +       resync_cnt = iterations / NUM_RESYNC_BARRIERS;

>> +       lock_owner_delay = BASE_DELAY;

>> +

>> +       for (cnt = 1; cnt <= iterations; cnt++) {

>> +               /* Acquire the shared global lock */

>> +               odp_ticketlock_lock(&global_mem->global_ticketlock);

>> +

>> +               /* Make sure we have the lock AND didn't previously own

>> it */

>> +               if

>> (odp_ticketlock_is_locked(&global_mem->global_ticketlock)

>> +                               != 1)

>> +                       is_locked_errs++;

>> +

>> +               if (global_mem->global_lock_owner != 0) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               /* Now set the global_lock_owner to be us, wait a while,

>> and

>> +               * then we see if anyone else has snuck in and changed the

>> +               * global_lock_owner to be themselves

>> +               */

>> +               global_mem->global_lock_owner = thread_num;

>> +               odp_sync_stores();

>> +               thread_delay(per_thread_mem, lock_owner_delay);

>> +               if (global_mem->global_lock_owner != thread_num) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               /* Release shared lock, and make sure we no longer have

>> it */

>> +               global_mem->global_lock_owner = 0;

>> +               odp_sync_stores();

>> +               odp_ticketlock_unlock(&global_mem->global_ticketlock);

>> +               if (global_mem->global_lock_owner == thread_num) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               if (current_errs == 0)

>> +                       lock_owner_delay++;

>> +

>> +               /* Wait a small amount of time and then rerun the test */

>> +               thread_delay(per_thread_mem, BASE_DELAY);

>> +

>> +               /* Try to resync all of the threads to increase

>> contention */

>> +               if ((rs_idx < NUM_RESYNC_BARRIERS) &&

>> +                   ((cnt % resync_cnt) == (resync_cnt - 1)))

>> +

>>  odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);

>> +       }

>> +

>> +       if ((global_mem->g_verbose) &&

>> +           ((sync_failures != 0) || (is_locked_errs != 0)))

>> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

>> +                      " sync_failures and %" PRIu32

>> +                      " is_locked_errs in %" PRIu32 " iterations\n",

>> +                      thread_num,

>> +                      per_thread_mem->thread_id,

>> per_thread_mem->thread_core,

>> +                      sync_failures, is_locked_errs, iterations);

>> +

>> +       CU_ASSERT(sync_failures == 0);

>> +       CU_ASSERT(is_locked_errs == 0);

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void *rwlock_functional_test(void *arg UNUSED)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;

>> +       uint32_t sync_failures, current_errs, lock_owner_delay;

>> +

>> +       thread_num = odp_cpu_id() + 1;

>> +       per_thread_mem = thread_init();

>> +       global_mem = per_thread_mem->global_mem;

>> +       iterations = global_mem->g_iterations;

>> +

>> +       /* Wait here until all of the threads have also reached this

>> point */

>> +       odp_barrier_wait(&global_mem->global_barrier);

>> +

>> +       sync_failures = 0;

>> +       current_errs = 0;

>> +       rs_idx = 0;

>> +       resync_cnt = iterations / NUM_RESYNC_BARRIERS;

>> +       lock_owner_delay = BASE_DELAY;

>> +

>> +       for (cnt = 1; cnt <= iterations; cnt++) {

>> +               /* Verify that we can obtain a read lock */

>> +               odp_rwlock_read_lock(&global_mem->global_rwlock);

>> +

>> +               /* Verify lock is unowned (no writer holds it) */

>> +               thread_delay(per_thread_mem, lock_owner_delay);

>> +               if (global_mem->global_lock_owner != 0) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               /* Release the read lock */

>> +               odp_rwlock_read_unlock(&global_mem->global_rwlock);

>> +

>> +               /* Acquire the shared global lock */

>> +               odp_rwlock_write_lock(&global_mem->global_rwlock);

>> +

>> +               /* Make sure we have lock now AND didn't previously own

>> it */

>> +               if (global_mem->global_lock_owner != 0) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               /* Now set the global_lock_owner to be us, wait a while,

>> and

>> +               * then we see if anyone else has snuck in and changed the

>> +               * global_lock_owner to be themselves

>> +               */

>> +               global_mem->global_lock_owner = thread_num;

>> +               odp_sync_stores();

>> +               thread_delay(per_thread_mem, lock_owner_delay);

>> +               if (global_mem->global_lock_owner != thread_num) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               /* Release shared lock, and make sure we no longer have

>> it */

>> +               global_mem->global_lock_owner = 0;

>> +               odp_sync_stores();

>> +               odp_rwlock_write_unlock(&global_mem->global_rwlock);

>> +               if (global_mem->global_lock_owner == thread_num) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               if (current_errs == 0)

>> +                       lock_owner_delay++;

>> +

>> +               /* Wait a small amount of time and then rerun the test */

>> +               thread_delay(per_thread_mem, BASE_DELAY);

>> +

>> +               /* Try to resync all of the threads to increase

>> contention */

>> +               if ((rs_idx < NUM_RESYNC_BARRIERS) &&

>> +                   ((cnt % resync_cnt) == (resync_cnt - 1)))

>> +

>>  odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);

>> +       }

>> +

>> +       if ((global_mem->g_verbose) && (sync_failures != 0))

>> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

>> +                      " sync_failures in %" PRIu32 " iterations\n",

>> thread_num,

>> +                      per_thread_mem->thread_id,

>> +                      per_thread_mem->thread_core,

>> +                      sync_failures, iterations);

>> +

>> +       CU_ASSERT(sync_failures == 0);

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +static void *rwlock_recursive_functional_test(void *arg UNUSED)

>> +{

>> +       global_shared_mem_t *global_mem;

>> +       per_thread_mem_t *per_thread_mem;

>> +       uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;

>> +       uint32_t sync_failures, recursive_errs, current_errs,

>> lock_owner_delay;

>> +

>> +       thread_num = odp_cpu_id() + 1;

>> +       per_thread_mem = thread_init();

>> +       global_mem = per_thread_mem->global_mem;

>> +       iterations = global_mem->g_iterations;

>> +

>> +       /* Wait here until all of the threads have also reached this

>> point */

>> +       odp_barrier_wait(&global_mem->global_barrier);

>> +

>> +       sync_failures = 0;

>> +       recursive_errs = 0;

>> +       current_errs = 0;

>> +       rs_idx = 0;

>> +       resync_cnt = iterations / NUM_RESYNC_BARRIERS;

>> +       lock_owner_delay = BASE_DELAY;

>> +

>> +       for (cnt = 1; cnt <= iterations; cnt++) {

>> +               /* Verify that we can obtain a read lock */

>> +               odp_rwlock_recursive_read_lock(

>> +                       &global_mem->global_recursive_rwlock);

>> +

>> +               /* Verify lock is unowned (no writer holds it) */

>> +               thread_delay(per_thread_mem, lock_owner_delay);

>> +               if (global_mem->global_lock_owner != 0) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               /* Verify we can get read lock recursively */

>> +               odp_rwlock_recursive_read_lock(

>> +                       &global_mem->global_recursive_rwlock);

>> +

>> +               /* Verify lock is unowned (no writer holds it) */

>> +               thread_delay(per_thread_mem, lock_owner_delay);

>> +               if (global_mem->global_lock_owner != 0) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               /* Release the read lock */

>> +               odp_rwlock_recursive_read_unlock(

>> +                       &global_mem->global_recursive_rwlock);

>> +               odp_rwlock_recursive_read_unlock(

>> +                       &global_mem->global_recursive_rwlock);

>> +

>> +               /* Acquire the shared global lock */

>> +               odp_rwlock_recursive_write_lock(

>> +                       &global_mem->global_recursive_rwlock);

>> +

>> +               /* Make sure we have lock now AND didn't previously own

>> it */

>> +               if (global_mem->global_lock_owner != 0) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               /* Now set the global_lock_owner to be us, wait a while,

>> and

>> +               * then we see if anyone else has snuck in and changed the

>> +               * global_lock_owner to be themselves

>> +               */

>> +               global_mem->global_lock_owner = thread_num;

>> +               odp_sync_stores();

>> +               thread_delay(per_thread_mem, lock_owner_delay);

>> +               if (global_mem->global_lock_owner != thread_num) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               /* Acquire it again and verify we still own it */

>> +               odp_rwlock_recursive_write_lock(

>> +                       &global_mem->global_recursive_rwlock);

>> +               thread_delay(per_thread_mem, lock_owner_delay);

>> +               if (global_mem->global_lock_owner != thread_num) {

>> +                       current_errs++;

>> +                       recursive_errs++;

>> +               }

>> +

>> +               /* Release the recursive lock and make sure we still own

>> it */

>> +               odp_rwlock_recursive_write_unlock(

>> +                       &global_mem->global_recursive_rwlock);

>> +               thread_delay(per_thread_mem, lock_owner_delay);

>> +               if (global_mem->global_lock_owner != thread_num) {

>> +                       current_errs++;

>> +                       recursive_errs++;

>> +               }

>> +

>> +               /* Release shared lock, and make sure we no longer have

>> it */

>> +               global_mem->global_lock_owner = 0;

>> +               odp_sync_stores();

>> +               odp_rwlock_recursive_write_unlock(

>> +                       &global_mem->global_recursive_rwlock);

>> +               if (global_mem->global_lock_owner == thread_num) {

>> +                       current_errs++;

>> +                       sync_failures++;

>> +               }

>> +

>> +               if (current_errs == 0)

>> +                       lock_owner_delay++;

>> +

>> +               /* Wait a small amount of time and then rerun the test */

>> +               thread_delay(per_thread_mem, BASE_DELAY);

>> +

>> +               /* Try to resync all of the threads to increase

>> contention */

>> +               if ((rs_idx < NUM_RESYNC_BARRIERS) &&

>> +                   ((cnt % resync_cnt) == (resync_cnt - 1)))

>> +

>>  odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);

>> +       }

>> +

>> +       if ((global_mem->g_verbose) && (sync_failures != 0))

>> +               printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32

>> +                      " sync_failures and %" PRIu32

>> +                      " recursive_errs in %" PRIu32

>> +                      " iterations\n", thread_num,

>> +                      per_thread_mem->thread_id,

>> +                      per_thread_mem->thread_core,

>> +                      sync_failures, recursive_errs, iterations);

>> +

>> +       CU_ASSERT(sync_failures == 0);

>> +       CU_ASSERT(recursive_errs == 0);

>> +

>> +       thread_finalize(per_thread_mem);

>> +

>> +       return NULL;

>> +}

>> +

>> +/* Thread-unsafe tests */

>> +void lock_test_no_lock_functional(void)

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +       odp_cunit_thread_create(no_lock_functional_test, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +}

>> +

>> +odp_testinfo_t lock_suite_no_locking[] = {

>> +       ODP_TEST_INFO(lock_test_no_lock_functional),

>> +       ODP_TEST_INFO_NULL

>> +};

>> +

>> +/* Spin lock tests */

>> +void lock_test_spinlock_api(void)

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +       odp_cunit_thread_create(spinlock_api_tests, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +}

>> +

>> +void lock_test_spinlock_functional(void)

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +       odp_spinlock_init(&global_mem->global_spinlock);

>> +       odp_cunit_thread_create(spinlock_functional_test, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +}

>> +

>> +void lock_test_spinlock_recursive_api(void)

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +       odp_cunit_thread_create(spinlock_recursive_api_tests, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +}

>> +

>> +void lock_test_spinlock_recursive_functional(void)

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +

>>  odp_spinlock_recursive_init(&global_mem->global_recursive_spinlock);

>> +       odp_cunit_thread_create(spinlock_recursive_functional_test, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +}

>> +

>> +odp_testinfo_t lock_suite_spinlock[] = {

>> +       ODP_TEST_INFO(lock_test_spinlock_api),

>> +       ODP_TEST_INFO(lock_test_spinlock_functional),

>> +       ODP_TEST_INFO_NULL

>> +};

>> +

>> +odp_testinfo_t lock_suite_spinlock_recursive[] = {

>> +       ODP_TEST_INFO(lock_test_spinlock_recursive_api),

>> +       ODP_TEST_INFO(lock_test_spinlock_recursive_functional),

>> +       ODP_TEST_INFO_NULL

>> +};

>> +

>> +/* Ticket lock tests */

>> +void lock_test_ticketlock_api(void)

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +       odp_cunit_thread_create(ticketlock_api_tests, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +}

>> +

>> +void lock_test_ticketlock_functional(void)

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +       odp_ticketlock_init(&global_mem->global_ticketlock);

>> +

>> +       odp_cunit_thread_create(ticketlock_functional_test, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +}

>> +

>> +odp_testinfo_t lock_suite_ticketlock[] = {

>> +       ODP_TEST_INFO(lock_test_ticketlock_api),

>> +       ODP_TEST_INFO(lock_test_ticketlock_functional),

>> +       ODP_TEST_INFO_NULL

>> +};

>> +

>> +/* RW lock tests */

>> +void lock_test_rwlock_api(void)

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +       odp_cunit_thread_create(rwlock_api_tests, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +}

>> +

>> +void lock_test_rwlock_functional(void)

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +       odp_rwlock_init(&global_mem->global_rwlock);

>> +       odp_cunit_thread_create(rwlock_functional_test, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +}

>> +

>> +odp_testinfo_t lock_suite_rwlock[] = {

>> +       ODP_TEST_INFO(lock_test_rwlock_api),

>> +       ODP_TEST_INFO(lock_test_rwlock_functional),

>> +       ODP_TEST_INFO_NULL

>> +};

>> +

>> +void lock_test_rwlock_recursive_api(void)

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +       odp_cunit_thread_create(rwlock_recursive_api_tests, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +}

>> +

>> +void lock_test_rwlock_recursive_functional(void)

>> +{

>> +       pthrd_arg arg;

>> +

>> +       arg.numthrds = global_mem->g_num_threads;

>> +       odp_rwlock_recursive_init(&global_mem->global_recursive_rwlock);

>> +       odp_cunit_thread_create(rwlock_recursive_functional_test, &arg);

>> +       odp_cunit_thread_exit(&arg);

>> +}

>> +

>> +odp_testinfo_t lock_suite_rwlock_recursive[] = {

>> +       ODP_TEST_INFO(lock_test_rwlock_recursive_api),

>> +       ODP_TEST_INFO(lock_test_rwlock_recursive_functional),

>> +       ODP_TEST_INFO_NULL

>> +};

>> +

>> +int lock_suite_init(void)

>> +{

>> +       uint32_t num_threads, idx;

>> +

>> +       num_threads = global_mem->g_num_threads;

>> +       odp_barrier_init(&global_mem->global_barrier, num_threads);

>> +       for (idx = 0; idx < NUM_RESYNC_BARRIERS; idx++)

>> +               odp_barrier_init(&global_mem->barrier_array[idx],

>> num_threads);

>> +

>> +       return 0;

>> +}

>> +

>> +int lock_init(void)

>> +{

>> +       uint32_t workers_count, max_threads;

>> +       int ret = 0;

>> +       odp_cpumask_t mask;

>> +

>> +       if (0 != odp_init_global(NULL, NULL)) {

>> +               fprintf(stderr, "error: odp_init_global() failed.\n");

>> +               return -1;

>> +       }

>> +       if (0 != odp_init_local(ODP_THREAD_CONTROL)) {

>> +               fprintf(stderr, "error: odp_init_local() failed.\n");

>> +               return -1;

>> +       }

>> +

>> +       global_shm = odp_shm_reserve(GLOBAL_SHM_NAME,

>> +                                    sizeof(global_shared_mem_t), 64,

>> +                                    ODP_SHM_SW_ONLY);

>> +       if (ODP_SHM_INVALID == global_shm) {

>> +               fprintf(stderr, "Unable reserve memory for global_shm\n");

>> +               return -1;

>> +       }

>> +

>> +       global_mem = odp_shm_addr(global_shm);

>> +       memset(global_mem, 0, sizeof(global_shared_mem_t));

>> +

>> +       global_mem->g_num_threads = MAX_WORKERS;

>> +       global_mem->g_iterations = MAX_ITERATIONS;

>> +       global_mem->g_verbose = VERBOSE;

>> +

>> +       workers_count = odp_cpumask_default_worker(&mask, 0);

>> +

>> +       max_threads = (workers_count >= MAX_WORKERS) ?

>> +                       MAX_WORKERS : workers_count;

>> +

>> +       if (max_threads < global_mem->g_num_threads) {

>> +               printf("Requested num of threads is too large\n");

>> +               printf("reducing from %" PRIu32 " to %" PRIu32 "\n",

>> +                      global_mem->g_num_threads,

>> +                      max_threads);

>> +               global_mem->g_num_threads = max_threads;

>> +       }

>> +

>> +       printf("Num of threads used = %" PRIu32 "\n",

>> +              global_mem->g_num_threads);

>> +

>> +       return ret;

>> +}

>> +

>> +odp_suiteinfo_t lock_suites[] = {

>> +       {"nolocking", lock_suite_init, NULL,

>> +               lock_suite_no_locking},

>> +       {"spinlock", lock_suite_init, NULL,

>> +               lock_suite_spinlock},

>> +       {"spinlock_recursive", lock_suite_init, NULL,

>> +               lock_suite_spinlock_recursive},

>> +       {"ticketlock", lock_suite_init, NULL,

>> +               lock_suite_ticketlock},

>> +       {"rwlock", lock_suite_init, NULL,

>> +               lock_suite_rwlock},

>> +       {"rwlock_recursive", lock_suite_init, NULL,

>> +               lock_suite_rwlock_recursive},

>> +       ODP_SUITE_INFO_NULL

>> +};

>> +

>> +int lock_main(void)

>> +{

>> +       int ret;

>> +

>> +       odp_cunit_register_global_init(lock_init);

>> +

>> +       ret = odp_cunit_register(lock_suites);

>> +

>> +       if (ret == 0)

>> +               ret = odp_cunit_run();

>> +

>> +       return ret;

>> +}

>> diff --git a/test/validation/lock/lock.h b/test/validation/lock/lock.h

>> new file mode 100644

>> index 0000000..d41123f

>> --- /dev/null

>> +++ b/test/validation/lock/lock.h

>> @@ -0,0 +1,45 @@

>> +/* Copyright (c) 2015, Linaro Limited

>> + * All rights reserved.

>> + *

>> + * SPDX-License-Identifier:     BSD-3-Clause

>> + */

>> +

>> +#ifndef _ODP_TEST_SYNCHRONIZERS_H_

>> +#define _ODP_TEST_SYNCHRONIZERS_H_

>> +

>> +#include <odp_cunit_common.h>

>> +

>> +/* test functions: */

>> +void lock_test_no_lock_functional(void);

>> +void lock_test_spinlock_api(void);

>> +void lock_test_spinlock_functional(void);

>> +void lock_test_spinlock_recursive_api(void);

>> +void lock_test_spinlock_recursive_functional(void);

>> +void lock_test_ticketlock_api(void);

>> +void lock_test_ticketlock_functional(void);

>> +void lock_test_rwlock_api(void);

>> +void lock_test_rwlock_functional(void);

>> +void lock_test_rwlock_recursive_api(void);

>> +void lock_test_rwlock_recursive_functional(void);

>> +

>> +/* test arrays: */

>> +extern odp_testinfo_t lock_suite_no_locking[];

>> +extern odp_testinfo_t lock_suite_spinlock[];

>> +extern odp_testinfo_t lock_suite_spinlock_recursive[];

>> +extern odp_testinfo_t lock_suite_ticketlock[];

>> +extern odp_testinfo_t lock_suite_rwlock[];

>> +extern odp_testinfo_t lock_suite_rwlock_recursive[];

>> +

>> +/* test array init/term functions: */

>> +int lock_suite_init(void);

>> +

>> +/* test registry: */

>> +extern odp_suiteinfo_t lock_suites[];

>> +

>> +/* executable init/term functions: */

>> +int lock_init(void);

>> +

>> +/* main test program: */

>> +int lock_main(void);

>> +

>> +#endif

>> diff --git a/test/validation/lock/lock_main.c

>> b/test/validation/lock/lock_main.c

>> new file mode 100644

>> index 0000000..c12c2b5

>> --- /dev/null

>> +++ b/test/validation/lock/lock_main.c

>> @@ -0,0 +1,12 @@

>> +/* Copyright (c) 2015, Linaro Limited

>> + * All rights reserved.

>> + *

>> + * SPDX-License-Identifier:     BSD-3-Clause

>> + */

>> +

>> +#include "lock.h"

>> +

>> +int main(void)

>> +{

>> +       return lock_main();

>> +}

>> --

>> 2.1.4

>>

>> _______________________________________________

>> lng-odp mailing list

>> lng-odp@lists.linaro.org

>> https://lists.linaro.org/mailman/listinfo/lng-odp

>>

>

>
diff mbox

Patch

diff --git a/configure.ac b/configure.ac
index 4f89f03..7a05574 100644
--- a/configure.ac
+++ b/configure.ac
@@ -349,6 +349,8 @@  AC_CONFIG_FILES([Makefile
 		 test/api_test/Makefile
 		 test/performance/Makefile
 		 test/validation/Makefile
+		 test/validation/atomic/Makefile
+		 test/validation/barrier/Makefile
 		 test/validation/buffer/Makefile
 		 test/validation/classification/Makefile
 		 test/validation/config/Makefile
@@ -358,6 +360,7 @@  AC_CONFIG_FILES([Makefile
 		 test/validation/errno/Makefile
 		 test/validation/hash/Makefile
 		 test/validation/init/Makefile
+		 test/validation/lock/Makefile
 		 test/validation/packet/Makefile
 		 test/validation/pktio/Makefile
 		 test/validation/pool/Makefile
diff --git a/platform/linux-generic/test/Makefile.am b/platform/linux-generic/test/Makefile.am
index e629872..aa246d2 100644
--- a/platform/linux-generic/test/Makefile.am
+++ b/platform/linux-generic/test/Makefile.am
@@ -6,6 +6,8 @@  ODP_MODULES = pktio
 if test_vald
 TESTS = pktio/pktio_run \
 	pktio/pktio_run_tap \
+	${top_builddir}/test/validation/atomic/atomic_main$(EXEEXT) \
+	${top_builddir}/test/validation/barrier/barrier_main$(EXEEXT) \
 	${top_builddir}/test/validation/buffer/buffer_main$(EXEEXT) \
 	${top_builddir}/test/validation/classification/classification_main$(EXEEXT) \
 	${top_builddir}/test/validation/config/config_main$(EXEEXT) \
@@ -16,6 +18,7 @@  TESTS = pktio/pktio_run \
 	${top_builddir}/test/validation/init/init_main_ok$(EXEEXT) \
 	${top_builddir}/test/validation/init/init_main_abort$(EXEEXT) \
 	${top_builddir}/test/validation/init/init_main_log$(EXEEXT) \
+	${top_builddir}/test/validation/lock/lock_main$(EXEEXT) \
 	${top_builddir}/test/validation/packet/packet_main$(EXEEXT) \
 	${top_builddir}/test/validation/pool/pool_main$(EXEEXT) \
 	${top_builddir}/test/validation/queue/queue_main$(EXEEXT) \
diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am
index 1711b93..9a5bbff 100644
--- a/test/validation/Makefile.am
+++ b/test/validation/Makefile.am
@@ -1,4 +1,6 @@ 
-ODP_MODULES = buffer \
+ODP_MODULES = atomic \
+	      barrier \
+	      buffer \
 	      classification \
 	      config \
 	      cpumask \
@@ -6,6 +8,7 @@  ODP_MODULES = buffer \
 	      errno \
 	      hash \
 	      init \
+	      lock \
 	      queue \
 	      packet \
 	      pktio \
diff --git a/test/validation/atomic/.gitignore b/test/validation/atomic/.gitignore
new file mode 100644
index 0000000..610ffea
--- /dev/null
+++ b/test/validation/atomic/.gitignore
@@ -0,0 +1 @@ 
+atomic_main
diff --git a/test/validation/atomic/Makefile.am b/test/validation/atomic/Makefile.am
new file mode 100644
index 0000000..9b6bd63
--- /dev/null
+++ b/test/validation/atomic/Makefile.am
@@ -0,0 +1,10 @@ 
+include ../Makefile.inc
+
+noinst_LTLIBRARIES = libtestatomic.la
+libtestatomic_la_SOURCES = atomic.c
+
+test_PROGRAMS = atomic_main$(EXEEXT)
+dist_atomic_main_SOURCES = atomic_main.c
+atomic_main_LDADD = libtestatomic.la $(LIBCUNIT_COMMON) $(LIBODP)
+
+EXTRA_DIST = atomic.h
diff --git a/test/validation/atomic/atomic.c b/test/validation/atomic/atomic.c
new file mode 100644
index 0000000..633b465
--- /dev/null
+++ b/test/validation/atomic/atomic.c
@@ -0,0 +1,441 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:	 BSD-3-Clause
+ */
+
+#include <malloc.h>
+#include <odp.h>
+#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
+#include <unistd.h>
+#include "atomic.h"
+
+#define VERBOSE			0
+#define MAX_ITERATIONS		1000
+
+#define ADD_SUB_CNT		5
+
+#define CNT			10
+#define U32_INIT_VAL		(1UL << 10)
+#define U64_INIT_VAL		(1ULL << 33)
+
+#define GLOBAL_SHM_NAME		"GlobalLockTest"
+
+#define UNUSED			__attribute__((__unused__))
+
+static odp_atomic_u32_t a32u;
+static odp_atomic_u64_t a64u;
+
+typedef __volatile uint32_t volatile_u32_t;
+typedef __volatile uint64_t volatile_u64_t;
+
+typedef struct {
+	/* Global variables */
+	uint32_t g_num_threads;
+	uint32_t g_iterations;
+	uint32_t g_verbose;
+	uint32_t g_max_num_cores;
+
+	volatile_u32_t global_lock_owner;
+} global_shared_mem_t;
+
+/* Per-thread memory */
+typedef struct {
+	global_shared_mem_t *global_mem;
+
+	int thread_id;
+	int thread_core;
+
+	volatile_u64_t delay_counter;
+} per_thread_mem_t;
+
+static odp_shm_t global_shm;
+static global_shared_mem_t *global_mem;
+
+/* Initialise per-thread memory */
+static per_thread_mem_t *thread_init(void)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	odp_shm_t global_shm;
+	uint32_t per_thread_mem_len;
+
+	per_thread_mem_len = sizeof(per_thread_mem_t);
+	per_thread_mem = malloc(per_thread_mem_len);
+	memset(per_thread_mem, 0, per_thread_mem_len);
+
+	per_thread_mem->delay_counter = 1;
+
+	per_thread_mem->thread_id = odp_thread_id();
+	per_thread_mem->thread_core = odp_cpu_id();
+
+	global_shm = odp_shm_lookup(GLOBAL_SHM_NAME);
+	global_mem = odp_shm_addr(global_shm);
+	CU_ASSERT_PTR_NOT_NULL(global_mem);
+
+	per_thread_mem->global_mem = global_mem;
+
+	return per_thread_mem;
+}
+
+static void thread_finalize(per_thread_mem_t *per_thread_mem)
+{
+	free(per_thread_mem);
+}
+
+static void test_atomic_inc_32(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_inc_u32(&a32u);
+}
+
+static void test_atomic_inc_64(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_inc_u64(&a64u);
+}
+
+static void test_atomic_dec_32(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_dec_u32(&a32u);
+}
+
+static void test_atomic_dec_64(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_dec_u64(&a64u);
+}
+
+static void test_atomic_fetch_inc_32(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_fetch_inc_u32(&a32u);
+}
+
+static void test_atomic_fetch_inc_64(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_fetch_inc_u64(&a64u);
+}
+
+static void test_atomic_fetch_dec_32(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_fetch_dec_u32(&a32u);
+}
+
+static void test_atomic_fetch_dec_64(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_fetch_dec_u64(&a64u);
+}
+
+static void test_atomic_add_32(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_add_u32(&a32u, ADD_SUB_CNT);
+}
+
+static void test_atomic_add_64(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_add_u64(&a64u, ADD_SUB_CNT);
+}
+
+static void test_atomic_sub_32(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_sub_u32(&a32u, ADD_SUB_CNT);
+}
+
+static void test_atomic_sub_64(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_sub_u64(&a64u, ADD_SUB_CNT);
+}
+
+static void test_atomic_fetch_add_32(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_fetch_add_u32(&a32u, ADD_SUB_CNT);
+}
+
+static void test_atomic_fetch_add_64(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_fetch_add_u64(&a64u, ADD_SUB_CNT);
+}
+
+static void test_atomic_fetch_sub_32(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_fetch_sub_u32(&a32u, ADD_SUB_CNT);
+}
+
+static void test_atomic_fetch_sub_64(void)
+{
+	int i;
+
+	for (i = 0; i < CNT; i++)
+		odp_atomic_fetch_sub_u64(&a64u, ADD_SUB_CNT);
+}
+
+static void test_atomic_inc_dec_32(void)
+{
+	test_atomic_inc_32();
+	test_atomic_dec_32();
+}
+
+static void test_atomic_inc_dec_64(void)
+{
+	test_atomic_inc_64();
+	test_atomic_dec_64();
+}
+
+static void test_atomic_fetch_inc_dec_32(void)
+{
+	test_atomic_fetch_inc_32();
+	test_atomic_fetch_dec_32();
+}
+
+static void test_atomic_fetch_inc_dec_64(void)
+{
+	test_atomic_fetch_inc_64();
+	test_atomic_fetch_dec_64();
+}
+
+static void test_atomic_add_sub_32(void)
+{
+	test_atomic_add_32();
+	test_atomic_sub_32();
+}
+
+static void test_atomic_add_sub_64(void)
+{
+	test_atomic_add_64();
+	test_atomic_sub_64();
+}
+
+static void test_atomic_fetch_add_sub_32(void)
+{
+	test_atomic_fetch_add_32();
+	test_atomic_fetch_sub_32();
+}
+
+static void test_atomic_fetch_add_sub_64(void)
+{
+	test_atomic_fetch_add_64();
+	test_atomic_fetch_sub_64();
+}
+
+static void test_atomic_init(void)
+{
+	odp_atomic_init_u32(&a32u, 0);
+	odp_atomic_init_u64(&a64u, 0);
+}
+
+static void test_atomic_store(void)
+{
+	odp_atomic_store_u32(&a32u, U32_INIT_VAL);
+	odp_atomic_store_u64(&a64u, U64_INIT_VAL);
+}
+
+static void test_atomic_validate(void)
+{
+	CU_ASSERT(U32_INIT_VAL == odp_atomic_load_u32(&a32u));
+	CU_ASSERT(U64_INIT_VAL == odp_atomic_load_u64(&a64u));
+}
+
+int atomic_init(void)
+{
+	uint32_t workers_count, max_threads;
+	int ret = 0;
+	odp_cpumask_t mask;
+
+	if (0 != odp_init_global(NULL, NULL)) {
+		fprintf(stderr, "error: odp_init_global() failed.\n");
+		return -1;
+	}
+	if (0 != odp_init_local(ODP_THREAD_CONTROL)) {
+		fprintf(stderr, "error: odp_init_local() failed.\n");
+		return -1;
+	}
+
+	global_shm = odp_shm_reserve(GLOBAL_SHM_NAME,
+				     sizeof(global_shared_mem_t), 64,
+				     ODP_SHM_SW_ONLY);
+	if (ODP_SHM_INVALID == global_shm) {
+		fprintf(stderr, "Unable reserve memory for global_shm\n");
+		return -1;
+	}
+
+	global_mem = odp_shm_addr(global_shm);
+	memset(global_mem, 0, sizeof(global_shared_mem_t));
+
+	global_mem->g_num_threads = MAX_WORKERS;
+	global_mem->g_iterations = MAX_ITERATIONS;
+	global_mem->g_verbose = VERBOSE;
+
+	workers_count = odp_cpumask_default_worker(&mask, 0);
+
+	max_threads = (workers_count >= MAX_WORKERS) ?
+			MAX_WORKERS : workers_count;
+
+	if (max_threads < global_mem->g_num_threads) {
+		printf("Requested num of threads is too large\n");
+		printf("reducing from %" PRIu32 " to %" PRIu32 "\n",
+		       global_mem->g_num_threads,
+		       max_threads);
+		global_mem->g_num_threads = max_threads;
+	}
+
+	printf("Num of threads used = %" PRIu32 "\n",
+	       global_mem->g_num_threads);
+
+	return ret;
+}
+
+/* Atomic tests */
+static void *test_atomic_inc_dec_thread(void *arg UNUSED)
+{
+	per_thread_mem_t *per_thread_mem;
+
+	per_thread_mem = thread_init();
+	test_atomic_inc_dec_32();
+	test_atomic_inc_dec_64();
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void *test_atomic_add_sub_thread(void *arg UNUSED)
+{
+	per_thread_mem_t *per_thread_mem;
+
+	per_thread_mem = thread_init();
+	test_atomic_add_sub_32();
+	test_atomic_add_sub_64();
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void *test_atomic_fetch_inc_dec_thread(void *arg UNUSED)
+{
+	per_thread_mem_t *per_thread_mem;
+
+	per_thread_mem = thread_init();
+	test_atomic_fetch_inc_dec_32();
+	test_atomic_fetch_inc_dec_64();
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void *test_atomic_fetch_add_sub_thread(void *arg UNUSED)
+{
+	per_thread_mem_t *per_thread_mem;
+
+	per_thread_mem = thread_init();
+	test_atomic_fetch_add_sub_32();
+	test_atomic_fetch_add_sub_64();
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void test_atomic_functional(void *func_ptr(void *))
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	test_atomic_init();
+	test_atomic_store();
+	odp_cunit_thread_create(func_ptr, &arg);
+	odp_cunit_thread_exit(&arg);
+	test_atomic_validate();
+}
+
+void atomic_test_atomic_inc_dec(void)
+{
+	test_atomic_functional(test_atomic_inc_dec_thread);
+}
+
+void atomic_test_atomic_add_sub(void)
+{
+	test_atomic_functional(test_atomic_add_sub_thread);
+}
+
+void atomic_test_atomic_fetch_inc_dec(void)
+{
+	test_atomic_functional(test_atomic_fetch_inc_dec_thread);
+}
+
+void atomic_test_atomic_fetch_add_sub(void)
+{
+	test_atomic_functional(test_atomic_fetch_add_sub_thread);
+}
+
+odp_testinfo_t atomic_suite_atomic[] = {
+	ODP_TEST_INFO(atomic_test_atomic_inc_dec),
+	ODP_TEST_INFO(atomic_test_atomic_add_sub),
+	ODP_TEST_INFO(atomic_test_atomic_fetch_inc_dec),
+	ODP_TEST_INFO(atomic_test_atomic_fetch_add_sub),
+	ODP_TEST_INFO_NULL,
+};
+
+odp_suiteinfo_t atomic_suites[] = {
+	{"atomic", NULL, NULL,
+		atomic_suite_atomic},
+	ODP_SUITE_INFO_NULL
+};
+
+int atomic_main(void)
+{
+	int ret;
+
+	odp_cunit_register_global_init(atomic_init);
+
+	ret = odp_cunit_register(atomic_suites);
+
+	if (ret == 0)
+		ret = odp_cunit_run();
+
+	return ret;
+}
diff --git a/test/validation/atomic/atomic.h b/test/validation/atomic/atomic.h
new file mode 100644
index 0000000..3516c67
--- /dev/null
+++ b/test/validation/atomic/atomic.h
@@ -0,0 +1,33 @@ 
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef _ODP_TEST_SYNCHRONIZERS_H_
+#define _ODP_TEST_SYNCHRONIZERS_H_
+
+#include <odp_cunit_common.h>
+
+/* test functions: */
+void atomic_test_atomic_inc_dec(void);
+void atomic_test_atomic_add_sub(void);
+void atomic_test_atomic_fetch_inc_dec(void);
+void atomic_test_atomic_fetch_add_sub(void);
+
+/* test arrays: */
+extern odp_testinfo_t atomic_suite_atomic[];
+
+/* test array init/term functions: */
+int atomic_suite_init(void);
+
+/* test registry: */
+extern odp_suiteinfo_t atomic_suites[];
+
+/* executable init/term functions: */
+int atomic_init(void);
+
+/* main test program: */
+int atomic_main(void);
+
+#endif
diff --git a/test/validation/atomic/atomic_main.c b/test/validation/atomic/atomic_main.c
new file mode 100644
index 0000000..377bdd5
--- /dev/null
+++ b/test/validation/atomic/atomic_main.c
@@ -0,0 +1,12 @@ 
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include "atomic.h"
+
+int main(void)
+{
+	return atomic_main();
+}
diff --git a/test/validation/barrier/.gitignore b/test/validation/barrier/.gitignore
new file mode 100644
index 0000000..2e0ee7a
--- /dev/null
+++ b/test/validation/barrier/.gitignore
@@ -0,0 +1 @@ 
+barrier_main
diff --git a/test/validation/barrier/Makefile.am b/test/validation/barrier/Makefile.am
new file mode 100644
index 0000000..8fc632c
--- /dev/null
+++ b/test/validation/barrier/Makefile.am
@@ -0,0 +1,10 @@ 
+include ../Makefile.inc
+
+noinst_LTLIBRARIES = libtestbarrier.la
+libtestbarrier_la_SOURCES = barrier.c
+
+test_PROGRAMS = barrier_main$(EXEEXT)
+dist_barrier_main_SOURCES = barrier_main.c
+barrier_main_LDADD = libtestbarrier.la $(LIBCUNIT_COMMON) $(LIBODP)
+
+EXTRA_DIST = barrier.h
diff --git a/test/validation/barrier/barrier.c b/test/validation/barrier/barrier.c
new file mode 100644
index 0000000..ab7fcf4
--- /dev/null
+++ b/test/validation/barrier/barrier.c
@@ -0,0 +1,370 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:	 BSD-3-Clause
+ */
+
+#include <malloc.h>
+#include <odp.h>
+#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
+#include <unistd.h>
+#include "barrier.h"
+
+#define VERBOSE			0
+#define MAX_ITERATIONS		1000
+#define BARRIER_ITERATIONS	64
+
+#define SLOW_BARRIER_DELAY	400
+#define BASE_DELAY		6
+
+#define NUM_TEST_BARRIERS	BARRIER_ITERATIONS
+#define NUM_RESYNC_BARRIERS	100
+
+#define BARRIER_DELAY		10
+
+#define GLOBAL_SHM_NAME		"GlobalLockTest"
+
+#define UNUSED			__attribute__((__unused__))
+
+typedef __volatile uint32_t volatile_u32_t;
+typedef __volatile uint64_t volatile_u64_t;
+
+typedef struct {
+	odp_atomic_u32_t wait_cnt;
+} custom_barrier_t;
+
+typedef struct {
+	/* Global variables */
+	uint32_t g_num_threads;
+	uint32_t g_iterations;
+	uint32_t g_verbose;
+	uint32_t g_max_num_cores;
+
+	odp_barrier_t test_barriers[NUM_TEST_BARRIERS];
+	custom_barrier_t custom_barrier1[NUM_TEST_BARRIERS];
+	custom_barrier_t custom_barrier2[NUM_TEST_BARRIERS];
+	volatile_u32_t slow_thread_num;
+	volatile_u32_t barrier_cnt1;
+	volatile_u32_t barrier_cnt2;
+	odp_barrier_t global_barrier;
+
+} global_shared_mem_t;
+
+/* Per-thread memory */
+typedef struct {
+	global_shared_mem_t *global_mem;
+
+	int thread_id;
+	int thread_core;
+
+	volatile_u64_t delay_counter;
+} per_thread_mem_t;
+
+static odp_shm_t global_shm;
+static global_shared_mem_t *global_mem;
+
+/*
+* Delay a consistent amount of time.  Ideally the amount of CPU time taken
+* is linearly proportional to "iterations".  The goal is to try to do some
+* work that the compiler optimizer won't optimize away, and also to
+* minimize loads and stores (at least to different memory addresses)
+* so as to not affect or be affected by caching issues.  This does NOT have to
+* correlate to a specific number of cpu cycles or be consistent across
+* CPU architectures.
+*/
+static void thread_delay(per_thread_mem_t *per_thread_mem, uint32_t iterations)
+{
+	volatile_u64_t *counter_ptr;
+	uint32_t cnt;
+
+	counter_ptr = &per_thread_mem->delay_counter;
+
+	for (cnt = 1; cnt <= iterations; cnt++)
+		(*counter_ptr)++;
+}
+
+/* Initialise per-thread memory */
+static per_thread_mem_t *thread_init(void)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	odp_shm_t global_shm;
+	uint32_t per_thread_mem_len;
+
+	per_thread_mem_len = sizeof(per_thread_mem_t);
+	per_thread_mem = malloc(per_thread_mem_len);
+	memset(per_thread_mem, 0, per_thread_mem_len);
+
+	per_thread_mem->delay_counter = 1;
+
+	per_thread_mem->thread_id = odp_thread_id();
+	per_thread_mem->thread_core = odp_cpu_id();
+
+	global_shm = odp_shm_lookup(GLOBAL_SHM_NAME);
+	global_mem = odp_shm_addr(global_shm);
+	CU_ASSERT_PTR_NOT_NULL(global_mem);
+
+	per_thread_mem->global_mem = global_mem;
+
+	return per_thread_mem;
+}
+
+static void thread_finalize(per_thread_mem_t *per_thread_mem)
+{
+	free(per_thread_mem);
+}
+
+static void custom_barrier_init(custom_barrier_t *custom_barrier,
+				uint32_t num_threads)
+{
+	odp_atomic_init_u32(&custom_barrier->wait_cnt, num_threads);
+}
+
+static void custom_barrier_wait(custom_barrier_t *custom_barrier)
+{
+	volatile_u64_t counter = 1;
+	uint32_t delay_cnt, wait_cnt;
+
+	odp_atomic_sub_u32(&custom_barrier->wait_cnt, 1);
+
+	wait_cnt = 1;
+	while (wait_cnt != 0) {
+		for (delay_cnt = 1; delay_cnt <= BARRIER_DELAY; delay_cnt++)
+			counter++;
+
+		wait_cnt = odp_atomic_load_u32(&custom_barrier->wait_cnt);
+	}
+}
+
+static uint32_t barrier_test(per_thread_mem_t *per_thread_mem,
+			     odp_bool_t no_barrier_test)
+{
+	global_shared_mem_t *global_mem;
+	uint32_t barrier_errs, iterations, cnt, i_am_slow_thread;
+	uint32_t thread_num, slow_thread_num, next_slow_thread, num_threads;
+	uint32_t lock_owner_delay, barrier_cnt1, barrier_cnt2;
+
+	thread_num = odp_thread_id();
+	global_mem = per_thread_mem->global_mem;
+	num_threads = global_mem->g_num_threads;
+	iterations = BARRIER_ITERATIONS;
+
+	barrier_errs = 0;
+	lock_owner_delay = SLOW_BARRIER_DELAY;
+
+	for (cnt = 1; cnt < iterations; cnt++) {
+		/* Wait here until all of the threads reach this point */
+		custom_barrier_wait(&global_mem->custom_barrier1[cnt]);
+
+		barrier_cnt1 = global_mem->barrier_cnt1;
+		barrier_cnt2 = global_mem->barrier_cnt2;
+
+		if ((barrier_cnt1 != cnt) || (barrier_cnt2 != cnt)) {
+			printf("thread_num=%" PRIu32 " barrier_cnts of %" PRIu32
+				   " %" PRIu32 " cnt=%" PRIu32 "\n",
+			       thread_num, barrier_cnt1, barrier_cnt2, cnt);
+			barrier_errs++;
+		}
+
+		/* Wait here until all of the threads reach this point */
+		custom_barrier_wait(&global_mem->custom_barrier2[cnt]);
+
+		slow_thread_num = global_mem->slow_thread_num;
+		i_am_slow_thread = thread_num == slow_thread_num;
+		next_slow_thread = slow_thread_num + 1;
+		if (num_threads < next_slow_thread)
+			next_slow_thread = 1;
+
+		/*
+		* Now run the test, which involves having all but one thread
+		* immediately calling odp_barrier_wait(), and one thread wait a
+		* moderate amount of time and then calling odp_barrier_wait().
+		* The test fails if any of the first group of threads
+		* has not waited for the "slow" thread. The "slow" thread is
+		* responsible for re-initializing the barrier for next trial.
+		*/
+		if (i_am_slow_thread) {
+			thread_delay(per_thread_mem, lock_owner_delay);
+			lock_owner_delay += BASE_DELAY;
+			if ((global_mem->barrier_cnt1 != cnt) ||
+			    (global_mem->barrier_cnt2 != cnt) ||
+			    (global_mem->slow_thread_num
+					!= slow_thread_num))
+				barrier_errs++;
+		}
+
+		if (no_barrier_test == 0)
+			odp_barrier_wait(&global_mem->test_barriers[cnt]);
+
+		global_mem->barrier_cnt1 = cnt + 1;
+		odp_sync_stores();
+
+		if (i_am_slow_thread) {
+			global_mem->slow_thread_num = next_slow_thread;
+			global_mem->barrier_cnt2 = cnt + 1;
+			odp_sync_stores();
+		} else {
+			while (global_mem->barrier_cnt2 != (cnt + 1))
+				thread_delay(per_thread_mem, BASE_DELAY);
+		}
+	}
+
+	if ((global_mem->g_verbose) && (barrier_errs != 0))
+		printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32
+		       " barrier_errs in %" PRIu32 " iterations\n", thread_num,
+		       per_thread_mem->thread_id,
+		       per_thread_mem->thread_core, barrier_errs, iterations);
+
+	return barrier_errs;
+}
+
+static void *no_barrier_functional_test(void *arg UNUSED)
+{
+	per_thread_mem_t *per_thread_mem;
+	uint32_t barrier_errs;
+
+	per_thread_mem = thread_init();
+	barrier_errs = barrier_test(per_thread_mem, 1);
+
+	/*
+	* Note that the following CU_ASSERT MAY appear incorrect, but for the
+	* no_barrier test it should see barrier_errs or else there is something
+	* wrong with the test methodology or the ODP thread implementation.
+	* So this test PASSES only if it sees barrier_errs or a single
+	* worker was used.
+	*/
+	CU_ASSERT(barrier_errs != 0 || global_mem->g_num_threads == 1);
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void *barrier_functional_test(void *arg UNUSED)
+{
+	per_thread_mem_t *per_thread_mem;
+	uint32_t barrier_errs;
+
+	per_thread_mem = thread_init();
+	barrier_errs = barrier_test(per_thread_mem, 0);
+
+	CU_ASSERT(barrier_errs == 0);
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void barrier_test_init(void)
+{
+	uint32_t num_threads, idx;
+
+	num_threads = global_mem->g_num_threads;
+
+	for (idx = 0; idx < NUM_TEST_BARRIERS; idx++) {
+		odp_barrier_init(&global_mem->test_barriers[idx], num_threads);
+		custom_barrier_init(&global_mem->custom_barrier1[idx],
+				    num_threads);
+		custom_barrier_init(&global_mem->custom_barrier2[idx],
+				    num_threads);
+	}
+
+	global_mem->slow_thread_num = 1;
+	global_mem->barrier_cnt1 = 1;
+	global_mem->barrier_cnt2 = 1;
+}
+
+/* Barrier tests */
+void barrier_test_no_barrier_functional(void)
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	barrier_test_init();
+	odp_cunit_thread_create(no_barrier_functional_test, &arg);
+	odp_cunit_thread_exit(&arg);
+}
+
+void barrier_test_barrier_functional(void)
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	barrier_test_init();
+	odp_cunit_thread_create(barrier_functional_test, &arg);
+	odp_cunit_thread_exit(&arg);
+}
+
+odp_testinfo_t barrier_suite_barrier[] = {
+	ODP_TEST_INFO(barrier_test_no_barrier_functional),
+	ODP_TEST_INFO(barrier_test_barrier_functional),
+	ODP_TEST_INFO_NULL
+};
+
+int barrier_init(void)
+{
+	uint32_t workers_count, max_threads;
+	int ret = 0;
+	odp_cpumask_t mask;
+
+	if (0 != odp_init_global(NULL, NULL)) {
+		fprintf(stderr, "error: odp_init_global() failed.\n");
+		return -1;
+	}
+	if (0 != odp_init_local(ODP_THREAD_CONTROL)) {
+		fprintf(stderr, "error: odp_init_local() failed.\n");
+		return -1;
+	}
+
+	global_shm = odp_shm_reserve(GLOBAL_SHM_NAME,
+				     sizeof(global_shared_mem_t), 64,
+				     ODP_SHM_SW_ONLY);
+	if (ODP_SHM_INVALID == global_shm) {
+		fprintf(stderr, "Unable reserve memory for global_shm\n");
+		return -1;
+	}
+
+	global_mem = odp_shm_addr(global_shm);
+	memset(global_mem, 0, sizeof(global_shared_mem_t));
+
+	global_mem->g_num_threads = MAX_WORKERS;
+	global_mem->g_iterations = MAX_ITERATIONS;
+	global_mem->g_verbose = VERBOSE;
+
+	workers_count = odp_cpumask_default_worker(&mask, 0);
+
+	max_threads = (workers_count >= MAX_WORKERS) ?
+			MAX_WORKERS : workers_count;
+
+	if (max_threads < global_mem->g_num_threads) {
+		printf("Requested num of threads is too large\n");
+		printf("reducing from %" PRIu32 " to %" PRIu32 "\n",
+		       global_mem->g_num_threads,
+		       max_threads);
+		global_mem->g_num_threads = max_threads;
+	}
+
+	printf("Num of threads used = %" PRIu32 "\n",
+	       global_mem->g_num_threads);
+
+	return ret;
+}
+
+odp_suiteinfo_t barrier_suites[] = {
+	{"barrier", NULL, NULL,
+		barrier_suite_barrier},
+	ODP_SUITE_INFO_NULL
+};
+
+int barrier_main(void)
+{
+	int ret;
+
+	odp_cunit_register_global_init(barrier_init);
+
+	ret = odp_cunit_register(barrier_suites);
+
+	if (ret == 0)
+		ret = odp_cunit_run();
+
+	return ret;
+}
diff --git a/test/validation/barrier/barrier.h b/test/validation/barrier/barrier.h
new file mode 100644
index 0000000..a6310d0
--- /dev/null
+++ b/test/validation/barrier/barrier.h
@@ -0,0 +1,28 @@ 
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef _ODP_TEST_SYNCHRONIZERS_H_
+#define _ODP_TEST_SYNCHRONIZERS_H_
+
+#include <odp_cunit_common.h>
+
+/* test functions: */
+void barrier_test_no_barrier_functional(void);
+void barrier_test_barrier_functional(void);
+
+/* test arrays: */
+extern odp_testinfo_t barrier_suite_barrier[];
+
+/* test registry: */
+extern odp_suiteinfo_t barrier_suites[];
+
+/* executable init/term functions: */
+int barrier_init(void);
+
+/* main test program: */
+int barrier_main(void);
+
+#endif
diff --git a/test/validation/barrier/barrier_main.c b/test/validation/barrier/barrier_main.c
new file mode 100644
index 0000000..88c9b3e
--- /dev/null
+++ b/test/validation/barrier/barrier_main.c
@@ -0,0 +1,12 @@ 
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include "barrier.h"
+
+int main(void)
+{
+	return barrier_main();
+}
diff --git a/test/validation/lock/.gitignore b/test/validation/lock/.gitignore
new file mode 100644
index 0000000..ff16646
--- /dev/null
+++ b/test/validation/lock/.gitignore
@@ -0,0 +1 @@ 
+lock_main
diff --git a/test/validation/lock/Makefile.am b/test/validation/lock/Makefile.am
new file mode 100644
index 0000000..29993df
--- /dev/null
+++ b/test/validation/lock/Makefile.am
@@ -0,0 +1,10 @@ 
+include ../Makefile.inc
+
+noinst_LTLIBRARIES = libtestlock.la
+libtestlock_la_SOURCES = lock.c
+
+test_PROGRAMS = lock_main$(EXEEXT)
+dist_lock_main_SOURCES = lock_main.c
+lock_main_LDADD = libtestlock.la $(LIBCUNIT_COMMON) $(LIBODP)
+
+EXTRA_DIST = lock.h
diff --git a/test/validation/lock/lock.c b/test/validation/lock/lock.c
new file mode 100644
index 0000000..76009f0
--- /dev/null
+++ b/test/validation/lock/lock.c
@@ -0,0 +1,1135 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:	 BSD-3-Clause
+ */
+
+#include <malloc.h>
+#include <odp.h>
+#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
+#include <unistd.h>
+#include "lock.h"
+
+#define VERBOSE			0
+#define MAX_ITERATIONS		1000
+
+#define SLOW_BARRIER_DELAY	400
+#define BASE_DELAY		6
+#define MIN_DELAY		1
+
+#define NUM_RESYNC_BARRIERS	100
+
+#define GLOBAL_SHM_NAME		"GlobalLockTest"
+
+#define UNUSED			__attribute__((__unused__))
+
+typedef __volatile uint32_t volatile_u32_t;
+typedef __volatile uint64_t volatile_u64_t;
+
+typedef struct {
+	odp_atomic_u32_t wait_cnt;
+} custom_barrier_t;
+
+typedef struct {
+	/* Global variables */
+	uint32_t g_num_threads;
+	uint32_t g_iterations;
+	uint32_t g_verbose;
+	uint32_t g_max_num_cores;
+
+	volatile_u32_t slow_thread_num;
+	volatile_u32_t barrier_cnt1;
+	volatile_u32_t barrier_cnt2;
+	odp_barrier_t global_barrier;
+
+	/* Used to periodically resync within the lock functional tests */
+	odp_barrier_t barrier_array[NUM_RESYNC_BARRIERS];
+
+	/* Locks */
+	odp_spinlock_t global_spinlock;
+	odp_spinlock_recursive_t global_recursive_spinlock;
+	odp_ticketlock_t global_ticketlock;
+	odp_rwlock_t global_rwlock;
+	odp_rwlock_recursive_t global_recursive_rwlock;
+
+	volatile_u32_t global_lock_owner;
+} global_shared_mem_t;
+
+/* Per-thread memory */
+typedef struct {
+	global_shared_mem_t *global_mem;
+
+	int thread_id;
+	int thread_core;
+
+	odp_spinlock_t per_thread_spinlock;
+	odp_spinlock_recursive_t per_thread_recursive_spinlock;
+	odp_ticketlock_t per_thread_ticketlock;
+	odp_rwlock_t per_thread_rwlock;
+	odp_rwlock_recursive_t per_thread_recursive_rwlock;
+
+	volatile_u64_t delay_counter;
+} per_thread_mem_t;
+
+static odp_shm_t global_shm;
+static global_shared_mem_t *global_mem;
+
+/*
+* Delay a consistent amount of time.  Ideally the amount of CPU time taken
+* is linearly proportional to "iterations".  The goal is to try to do some
+* work that the compiler optimizer won't optimize away, and also to
+* minimize loads and stores (at least to different memory addresses)
+* so as to not affect or be affected by caching issues.  This does NOT have to
+* correlate to a specific number of cpu cycles or be consistent across
+* CPU architectures.
+*/
+static void thread_delay(per_thread_mem_t *per_thread_mem, uint32_t iterations)
+{
+	volatile_u64_t *counter_ptr;
+	uint32_t cnt;
+
+	counter_ptr = &per_thread_mem->delay_counter;
+
+	for (cnt = 1; cnt <= iterations; cnt++)
+		(*counter_ptr)++;
+}
+
+/* Initialise per-thread memory */
+static per_thread_mem_t *thread_init(void)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	odp_shm_t global_shm;
+	uint32_t per_thread_mem_len;
+
+	per_thread_mem_len = sizeof(per_thread_mem_t);
+	per_thread_mem = malloc(per_thread_mem_len);
+	memset(per_thread_mem, 0, per_thread_mem_len);
+
+	per_thread_mem->delay_counter = 1;
+
+	per_thread_mem->thread_id = odp_thread_id();
+	per_thread_mem->thread_core = odp_cpu_id();
+
+	global_shm = odp_shm_lookup(GLOBAL_SHM_NAME);
+	global_mem = odp_shm_addr(global_shm);
+	CU_ASSERT_PTR_NOT_NULL(global_mem);
+
+	per_thread_mem->global_mem = global_mem;
+
+	return per_thread_mem;
+}
+
+static void thread_finalize(per_thread_mem_t *per_thread_mem)
+{
+	free(per_thread_mem);
+}
+
+static void spinlock_api_test(odp_spinlock_t *spinlock)
+{
+	odp_spinlock_init(spinlock);
+	CU_ASSERT(odp_spinlock_is_locked(spinlock) == 0);
+
+	odp_spinlock_lock(spinlock);
+	CU_ASSERT(odp_spinlock_is_locked(spinlock) == 1);
+
+	odp_spinlock_unlock(spinlock);
+	CU_ASSERT(odp_spinlock_is_locked(spinlock) == 0);
+
+	CU_ASSERT(odp_spinlock_trylock(spinlock) == 1);
+
+	CU_ASSERT(odp_spinlock_is_locked(spinlock) == 1);
+
+	odp_spinlock_unlock(spinlock);
+	CU_ASSERT(odp_spinlock_is_locked(spinlock) == 0);
+}
+
+static void *spinlock_api_tests(void *arg UNUSED)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	odp_spinlock_t local_spin_lock;
+
+	per_thread_mem = thread_init();
+	global_mem = per_thread_mem->global_mem;
+
+	odp_barrier_wait(&global_mem->global_barrier);
+
+	spinlock_api_test(&local_spin_lock);
+	spinlock_api_test(&per_thread_mem->per_thread_spinlock);
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void spinlock_recursive_api_test(odp_spinlock_recursive_t *spinlock)
+{
+	odp_spinlock_recursive_init(spinlock);
+	CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 0);
+
+	odp_spinlock_recursive_lock(spinlock);
+	CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);
+
+	odp_spinlock_recursive_lock(spinlock);
+	CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);
+
+	odp_spinlock_recursive_unlock(spinlock);
+	CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);
+
+	odp_spinlock_recursive_unlock(spinlock);
+	CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 0);
+
+	CU_ASSERT(odp_spinlock_recursive_trylock(spinlock) == 1);
+	CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);
+
+	CU_ASSERT(odp_spinlock_recursive_trylock(spinlock) == 1);
+	CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);
+
+	odp_spinlock_recursive_unlock(spinlock);
+	CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);
+
+	odp_spinlock_recursive_unlock(spinlock);
+	CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 0);
+}
+
+static void *spinlock_recursive_api_tests(void *arg UNUSED)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	odp_spinlock_recursive_t local_recursive_spin_lock;
+
+	per_thread_mem = thread_init();
+	global_mem = per_thread_mem->global_mem;
+
+	odp_barrier_wait(&global_mem->global_barrier);
+
+	spinlock_recursive_api_test(&local_recursive_spin_lock);
+	spinlock_recursive_api_test(
+		&per_thread_mem->per_thread_recursive_spinlock);
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void ticketlock_api_test(odp_ticketlock_t *ticketlock)
+{
+	odp_ticketlock_init(ticketlock);
+	CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 0);
+
+	odp_ticketlock_lock(ticketlock);
+	CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 1);
+
+	odp_ticketlock_unlock(ticketlock);
+	CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 0);
+
+	CU_ASSERT(odp_ticketlock_trylock(ticketlock) == 1);
+	CU_ASSERT(odp_ticketlock_trylock(ticketlock) == 0);
+	CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 1);
+
+	odp_ticketlock_unlock(ticketlock);
+	CU_ASSERT(odp_ticketlock_is_locked(ticketlock) == 0);
+}
+
+static void *ticketlock_api_tests(void *arg UNUSED)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	odp_ticketlock_t local_ticket_lock;
+
+	per_thread_mem = thread_init();
+	global_mem = per_thread_mem->global_mem;
+
+	odp_barrier_wait(&global_mem->global_barrier);
+
+	ticketlock_api_test(&local_ticket_lock);
+	ticketlock_api_test(&per_thread_mem->per_thread_ticketlock);
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void rwlock_api_test(odp_rwlock_t *rw_lock)
+{
+	odp_rwlock_init(rw_lock);
+	/* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */
+
+	odp_rwlock_read_lock(rw_lock);
+	odp_rwlock_read_unlock(rw_lock);
+
+	odp_rwlock_write_lock(rw_lock);
+	/* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 1); */
+
+	odp_rwlock_write_unlock(rw_lock);
+	/* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */
+}
+
+static void *rwlock_api_tests(void *arg UNUSED)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	odp_rwlock_t local_rwlock;
+
+	per_thread_mem = thread_init();
+	global_mem = per_thread_mem->global_mem;
+
+	odp_barrier_wait(&global_mem->global_barrier);
+
+	rwlock_api_test(&local_rwlock);
+	rwlock_api_test(&per_thread_mem->per_thread_rwlock);
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void rwlock_recursive_api_test(odp_rwlock_recursive_t *rw_lock)
+{
+	odp_rwlock_recursive_init(rw_lock);
+	/* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */
+
+	odp_rwlock_recursive_read_lock(rw_lock);
+	odp_rwlock_recursive_read_lock(rw_lock);
+
+	odp_rwlock_recursive_read_unlock(rw_lock);
+	odp_rwlock_recursive_read_unlock(rw_lock);
+
+	odp_rwlock_recursive_write_lock(rw_lock);
+	odp_rwlock_recursive_write_lock(rw_lock);
+	/* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 1); */
+
+	odp_rwlock_recursive_write_unlock(rw_lock);
+	odp_rwlock_recursive_write_unlock(rw_lock);
+	/* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */
+}
+
+static void *rwlock_recursive_api_tests(void *arg UNUSED)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	odp_rwlock_recursive_t local_recursive_rwlock;
+
+	per_thread_mem = thread_init();
+	global_mem = per_thread_mem->global_mem;
+
+	odp_barrier_wait(&global_mem->global_barrier);
+
+	rwlock_recursive_api_test(&local_recursive_rwlock);
+	rwlock_recursive_api_test(&per_thread_mem->per_thread_recursive_rwlock);
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void *no_lock_functional_test(void *arg UNUSED)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;
+	uint32_t sync_failures, current_errs, lock_owner_delay;
+
+	thread_num = odp_cpu_id() + 1;
+	per_thread_mem = thread_init();
+	global_mem = per_thread_mem->global_mem;
+	iterations = global_mem->g_iterations;
+
+	odp_barrier_wait(&global_mem->global_barrier);
+
+	sync_failures = 0;
+	current_errs = 0;
+	rs_idx = 0;
+	resync_cnt = iterations / NUM_RESYNC_BARRIERS;
+	lock_owner_delay = BASE_DELAY;
+
+	for (cnt = 1; cnt <= iterations; cnt++) {
+		global_mem->global_lock_owner = thread_num;
+		odp_sync_stores();
+		thread_delay(per_thread_mem, lock_owner_delay);
+
+		if (global_mem->global_lock_owner != thread_num) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		global_mem->global_lock_owner = 0;
+		odp_sync_stores();
+		thread_delay(per_thread_mem, MIN_DELAY);
+
+		if (global_mem->global_lock_owner == thread_num) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		if (current_errs == 0)
+			lock_owner_delay++;
+
+		/* Wait a small amount of time and rerun the test */
+		thread_delay(per_thread_mem, BASE_DELAY);
+
+		/* Try to resync all of the threads to increase contention */
+		if ((rs_idx < NUM_RESYNC_BARRIERS) &&
+		    ((cnt % resync_cnt) == (resync_cnt - 1)))
+			odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);
+	}
+
+	if (global_mem->g_verbose)
+		printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32
+		       " sync_failures in %" PRIu32 " iterations\n",
+		       thread_num,
+		       per_thread_mem->thread_id,
+		       per_thread_mem->thread_core,
+		       sync_failures, iterations);
+
+	/* Note that the following CU_ASSERT MAY appear incorrect, but for the
+	* no_lock test it should see sync_failures or else there is something
+	* wrong with the test methodology or the ODP thread implementation.
+	* So this test PASSES only if it sees sync_failures or a single
+	* worker was used.
+	*/
+	CU_ASSERT(sync_failures != 0 || global_mem->g_num_threads == 1);
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void *spinlock_functional_test(void *arg UNUSED)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;
+	uint32_t sync_failures, is_locked_errs, current_errs;
+	uint32_t lock_owner_delay;
+
+	thread_num = odp_cpu_id() + 1;
+	per_thread_mem = thread_init();
+	global_mem = per_thread_mem->global_mem;
+	iterations = global_mem->g_iterations;
+
+	odp_barrier_wait(&global_mem->global_barrier);
+
+	sync_failures = 0;
+	is_locked_errs = 0;
+	current_errs = 0;
+	rs_idx = 0;
+	resync_cnt = iterations / NUM_RESYNC_BARRIERS;
+	lock_owner_delay = BASE_DELAY;
+
+	for (cnt = 1; cnt <= iterations; cnt++) {
+		/* Acquire the shared global lock */
+		odp_spinlock_lock(&global_mem->global_spinlock);
+
+		/* Make sure we have the lock AND didn't previously own it */
+		if (odp_spinlock_is_locked(&global_mem->global_spinlock) != 1)
+			is_locked_errs++;
+
+		if (global_mem->global_lock_owner != 0) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		/* Now set the global_lock_owner to be us, wait a while, and
+		* then we see if anyone else has snuck in and changed the
+		* global_lock_owner to be themselves
+		*/
+		global_mem->global_lock_owner = thread_num;
+		odp_sync_stores();
+		thread_delay(per_thread_mem, lock_owner_delay);
+		if (global_mem->global_lock_owner != thread_num) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		/* Release shared lock, and make sure we no longer have it */
+		global_mem->global_lock_owner = 0;
+		odp_sync_stores();
+		odp_spinlock_unlock(&global_mem->global_spinlock);
+		if (global_mem->global_lock_owner == thread_num) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		if (current_errs == 0)
+			lock_owner_delay++;
+
+		/* Wait a small amount of time and rerun the test */
+		thread_delay(per_thread_mem, BASE_DELAY);
+
+		/* Try to resync all of the threads to increase contention */
+		if ((rs_idx < NUM_RESYNC_BARRIERS) &&
+		    ((cnt % resync_cnt) == (resync_cnt - 1)))
+			odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);
+	}
+
+	if ((global_mem->g_verbose) &&
+	    ((sync_failures != 0) || (is_locked_errs != 0)))
+		printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32
+		       " sync_failures and %" PRIu32
+		       " is_locked_errs in %" PRIu32
+		       " iterations\n", thread_num,
+		       per_thread_mem->thread_id, per_thread_mem->thread_core,
+		       sync_failures, is_locked_errs, iterations);
+
+	CU_ASSERT(sync_failures == 0);
+	CU_ASSERT(is_locked_errs == 0);
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void *spinlock_recursive_functional_test(void *arg UNUSED)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;
+	uint32_t sync_failures, recursive_errs, is_locked_errs, current_errs;
+	uint32_t lock_owner_delay;
+
+	thread_num = odp_cpu_id() + 1;
+	per_thread_mem = thread_init();
+	global_mem = per_thread_mem->global_mem;
+	iterations = global_mem->g_iterations;
+
+	odp_barrier_wait(&global_mem->global_barrier);
+
+	sync_failures = 0;
+	recursive_errs = 0;
+	is_locked_errs = 0;
+	current_errs = 0;
+	rs_idx = 0;
+	resync_cnt = iterations / NUM_RESYNC_BARRIERS;
+	lock_owner_delay = BASE_DELAY;
+
+	for (cnt = 1; cnt <= iterations; cnt++) {
+		/* Acquire the shared global lock */
+		odp_spinlock_recursive_lock(
+			&global_mem->global_recursive_spinlock);
+
+		/* Make sure we have the lock AND didn't previously own it */
+		if (odp_spinlock_recursive_is_locked(
+			    &global_mem->global_recursive_spinlock) != 1)
+			is_locked_errs++;
+
+		if (global_mem->global_lock_owner != 0) {
+			current_errs++;
+			sync_failures++;
+		}
+
+	       /* Now set the global_lock_owner to be us, wait a while, and
+		* then we see if anyone else has snuck in and changed the
+		* global_lock_owner to be themselves
+		*/
+		global_mem->global_lock_owner = thread_num;
+		odp_sync_stores();
+		thread_delay(per_thread_mem, lock_owner_delay);
+		if (global_mem->global_lock_owner != thread_num) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		/* Verify that we can acquire the lock recursively */
+		odp_spinlock_recursive_lock(
+			&global_mem->global_recursive_spinlock);
+		if (global_mem->global_lock_owner != thread_num) {
+			current_errs++;
+			recursive_errs++;
+		}
+
+		/* Release the lock and verify that we still have it*/
+		odp_spinlock_recursive_unlock(
+			&global_mem->global_recursive_spinlock);
+		thread_delay(per_thread_mem, lock_owner_delay);
+		if (global_mem->global_lock_owner != thread_num) {
+			current_errs++;
+			recursive_errs++;
+		}
+
+		/* Release shared lock, and make sure we no longer have it */
+		global_mem->global_lock_owner = 0;
+		odp_sync_stores();
+		odp_spinlock_recursive_unlock(
+			&global_mem->global_recursive_spinlock);
+		if (global_mem->global_lock_owner == thread_num) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		if (current_errs == 0)
+			lock_owner_delay++;
+
+		/* Wait a small amount of time and rerun the test */
+		thread_delay(per_thread_mem, BASE_DELAY);
+
+		/* Try to resync all of the threads to increase contention */
+		if ((rs_idx < NUM_RESYNC_BARRIERS) &&
+		    ((cnt % resync_cnt) == (resync_cnt - 1)))
+			odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);
+	}
+
+	if ((global_mem->g_verbose) &&
+	    (sync_failures != 0 || recursive_errs != 0 || is_locked_errs != 0))
+		printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32
+		       " sync_failures and %" PRIu32
+		       " recursive_errs and %" PRIu32
+		       " is_locked_errs in %" PRIu32
+		       " iterations\n", thread_num,
+		       per_thread_mem->thread_id, per_thread_mem->thread_core,
+		       sync_failures, recursive_errs, is_locked_errs,
+		       iterations);
+
+	CU_ASSERT(sync_failures == 0);
+	CU_ASSERT(recursive_errs == 0);
+	CU_ASSERT(is_locked_errs == 0);
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void *ticketlock_functional_test(void *arg UNUSED)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;
+	uint32_t sync_failures, is_locked_errs, current_errs;
+	uint32_t lock_owner_delay;
+
+	thread_num = odp_cpu_id() + 1;
+	per_thread_mem = thread_init();
+	global_mem = per_thread_mem->global_mem;
+	iterations = global_mem->g_iterations;
+
+	/* Wait here until all of the threads have also reached this point */
+	odp_barrier_wait(&global_mem->global_barrier);
+
+	sync_failures = 0;
+	is_locked_errs = 0;
+	current_errs = 0;
+	rs_idx = 0;
+	resync_cnt = iterations / NUM_RESYNC_BARRIERS;
+	lock_owner_delay = BASE_DELAY;
+
+	for (cnt = 1; cnt <= iterations; cnt++) {
+		/* Acquire the shared global lock */
+		odp_ticketlock_lock(&global_mem->global_ticketlock);
+
+		/* Make sure we have the lock AND didn't previously own it */
+		if (odp_ticketlock_is_locked(&global_mem->global_ticketlock)
+				!= 1)
+			is_locked_errs++;
+
+		if (global_mem->global_lock_owner != 0) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		/* Now set the global_lock_owner to be us, wait a while, and
+		* then we see if anyone else has snuck in and changed the
+		* global_lock_owner to be themselves
+		*/
+		global_mem->global_lock_owner = thread_num;
+		odp_sync_stores();
+		thread_delay(per_thread_mem, lock_owner_delay);
+		if (global_mem->global_lock_owner != thread_num) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		/* Release shared lock, and make sure we no longer have it */
+		global_mem->global_lock_owner = 0;
+		odp_sync_stores();
+		odp_ticketlock_unlock(&global_mem->global_ticketlock);
+		if (global_mem->global_lock_owner == thread_num) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		if (current_errs == 0)
+			lock_owner_delay++;
+
+		/* Wait a small amount of time and then rerun the test */
+		thread_delay(per_thread_mem, BASE_DELAY);
+
+		/* Try to resync all of the threads to increase contention */
+		if ((rs_idx < NUM_RESYNC_BARRIERS) &&
+		    ((cnt % resync_cnt) == (resync_cnt - 1)))
+			odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);
+	}
+
+	if ((global_mem->g_verbose) &&
+	    ((sync_failures != 0) || (is_locked_errs != 0)))
+		printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32
+		       " sync_failures and %" PRIu32
+		       " is_locked_errs in %" PRIu32 " iterations\n",
+		       thread_num,
+		       per_thread_mem->thread_id, per_thread_mem->thread_core,
+		       sync_failures, is_locked_errs, iterations);
+
+	CU_ASSERT(sync_failures == 0);
+	CU_ASSERT(is_locked_errs == 0);
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void *rwlock_functional_test(void *arg UNUSED)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;
+	uint32_t sync_failures, current_errs, lock_owner_delay;
+
+	thread_num = odp_cpu_id() + 1;
+	per_thread_mem = thread_init();
+	global_mem = per_thread_mem->global_mem;
+	iterations = global_mem->g_iterations;
+
+	/* Wait here until all of the threads have also reached this point */
+	odp_barrier_wait(&global_mem->global_barrier);
+
+	sync_failures = 0;
+	current_errs = 0;
+	rs_idx = 0;
+	resync_cnt = iterations / NUM_RESYNC_BARRIERS;
+	lock_owner_delay = BASE_DELAY;
+
+	for (cnt = 1; cnt <= iterations; cnt++) {
+		/* Verify that we can obtain a read lock */
+		odp_rwlock_read_lock(&global_mem->global_rwlock);
+
+		/* Verify lock is unowned (no writer holds it) */
+		thread_delay(per_thread_mem, lock_owner_delay);
+		if (global_mem->global_lock_owner != 0) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		/* Release the read lock */
+		odp_rwlock_read_unlock(&global_mem->global_rwlock);
+
+		/* Acquire the shared global lock */
+		odp_rwlock_write_lock(&global_mem->global_rwlock);
+
+		/* Make sure we have lock now AND didn't previously own it */
+		if (global_mem->global_lock_owner != 0) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		/* Now set the global_lock_owner to be us, wait a while, and
+		* then we see if anyone else has snuck in and changed the
+		* global_lock_owner to be themselves
+		*/
+		global_mem->global_lock_owner = thread_num;
+		odp_sync_stores();
+		thread_delay(per_thread_mem, lock_owner_delay);
+		if (global_mem->global_lock_owner != thread_num) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		/* Release shared lock, and make sure we no longer have it */
+		global_mem->global_lock_owner = 0;
+		odp_sync_stores();
+		odp_rwlock_write_unlock(&global_mem->global_rwlock);
+		if (global_mem->global_lock_owner == thread_num) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		if (current_errs == 0)
+			lock_owner_delay++;
+
+		/* Wait a small amount of time and then rerun the test */
+		thread_delay(per_thread_mem, BASE_DELAY);
+
+		/* Try to resync all of the threads to increase contention */
+		if ((rs_idx < NUM_RESYNC_BARRIERS) &&
+		    ((cnt % resync_cnt) == (resync_cnt - 1)))
+			odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);
+	}
+
+	if ((global_mem->g_verbose) && (sync_failures != 0))
+		printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32
+		       " sync_failures in %" PRIu32 " iterations\n", thread_num,
+		       per_thread_mem->thread_id,
+		       per_thread_mem->thread_core,
+		       sync_failures, iterations);
+
+	CU_ASSERT(sync_failures == 0);
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+static void *rwlock_recursive_functional_test(void *arg UNUSED)
+{
+	global_shared_mem_t *global_mem;
+	per_thread_mem_t *per_thread_mem;
+	uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;
+	uint32_t sync_failures, recursive_errs, current_errs, lock_owner_delay;
+
+	thread_num = odp_cpu_id() + 1;
+	per_thread_mem = thread_init();
+	global_mem = per_thread_mem->global_mem;
+	iterations = global_mem->g_iterations;
+
+	/* Wait here until all of the threads have also reached this point */
+	odp_barrier_wait(&global_mem->global_barrier);
+
+	sync_failures = 0;
+	recursive_errs = 0;
+	current_errs = 0;
+	rs_idx = 0;
+	resync_cnt = iterations / NUM_RESYNC_BARRIERS;
+	lock_owner_delay = BASE_DELAY;
+
+	for (cnt = 1; cnt <= iterations; cnt++) {
+		/* Verify that we can obtain a read lock */
+		odp_rwlock_recursive_read_lock(
+			&global_mem->global_recursive_rwlock);
+
+		/* Verify lock is unowned (no writer holds it) */
+		thread_delay(per_thread_mem, lock_owner_delay);
+		if (global_mem->global_lock_owner != 0) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		/* Verify we can get read lock recursively */
+		odp_rwlock_recursive_read_lock(
+			&global_mem->global_recursive_rwlock);
+
+		/* Verify lock is unowned (no writer holds it) */
+		thread_delay(per_thread_mem, lock_owner_delay);
+		if (global_mem->global_lock_owner != 0) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		/* Release the read lock */
+		odp_rwlock_recursive_read_unlock(
+			&global_mem->global_recursive_rwlock);
+		odp_rwlock_recursive_read_unlock(
+			&global_mem->global_recursive_rwlock);
+
+		/* Acquire the shared global lock */
+		odp_rwlock_recursive_write_lock(
+			&global_mem->global_recursive_rwlock);
+
+		/* Make sure we have lock now AND didn't previously own it */
+		if (global_mem->global_lock_owner != 0) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		/* Now set the global_lock_owner to be us, wait a while, and
+		* then we see if anyone else has snuck in and changed the
+		* global_lock_owner to be themselves
+		*/
+		global_mem->global_lock_owner = thread_num;
+		odp_sync_stores();
+		thread_delay(per_thread_mem, lock_owner_delay);
+		if (global_mem->global_lock_owner != thread_num) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		/* Acquire it again and verify we still own it */
+		odp_rwlock_recursive_write_lock(
+			&global_mem->global_recursive_rwlock);
+		thread_delay(per_thread_mem, lock_owner_delay);
+		if (global_mem->global_lock_owner != thread_num) {
+			current_errs++;
+			recursive_errs++;
+		}
+
+		/* Release the recursive lock and make sure we still own it */
+		odp_rwlock_recursive_write_unlock(
+			&global_mem->global_recursive_rwlock);
+		thread_delay(per_thread_mem, lock_owner_delay);
+		if (global_mem->global_lock_owner != thread_num) {
+			current_errs++;
+			recursive_errs++;
+		}
+
+		/* Release shared lock, and make sure we no longer have it */
+		global_mem->global_lock_owner = 0;
+		odp_sync_stores();
+		odp_rwlock_recursive_write_unlock(
+			&global_mem->global_recursive_rwlock);
+		if (global_mem->global_lock_owner == thread_num) {
+			current_errs++;
+			sync_failures++;
+		}
+
+		if (current_errs == 0)
+			lock_owner_delay++;
+
+		/* Wait a small amount of time and then rerun the test */
+		thread_delay(per_thread_mem, BASE_DELAY);
+
+		/* Try to resync all of the threads to increase contention */
+		if ((rs_idx < NUM_RESYNC_BARRIERS) &&
+		    ((cnt % resync_cnt) == (resync_cnt - 1)))
+			odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);
+	}
+
+	if ((global_mem->g_verbose) && (sync_failures != 0))
+		printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32
+		       " sync_failures and %" PRIu32
+		       " recursive_errs in %" PRIu32
+		       " iterations\n", thread_num,
+		       per_thread_mem->thread_id,
+		       per_thread_mem->thread_core,
+		       sync_failures, recursive_errs, iterations);
+
+	CU_ASSERT(sync_failures == 0);
+	CU_ASSERT(recursive_errs == 0);
+
+	thread_finalize(per_thread_mem);
+
+	return NULL;
+}
+
+/* Thread-unsafe tests */
+void lock_test_no_lock_functional(void)
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	odp_cunit_thread_create(no_lock_functional_test, &arg);
+	odp_cunit_thread_exit(&arg);
+}
+
+odp_testinfo_t lock_suite_no_locking[] = {
+	ODP_TEST_INFO(lock_test_no_lock_functional),
+	ODP_TEST_INFO_NULL
+};
+
+/* Spin lock tests */
+void lock_test_spinlock_api(void)
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	odp_cunit_thread_create(spinlock_api_tests, &arg);
+	odp_cunit_thread_exit(&arg);
+}
+
+void lock_test_spinlock_functional(void)
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	odp_spinlock_init(&global_mem->global_spinlock);
+	odp_cunit_thread_create(spinlock_functional_test, &arg);
+	odp_cunit_thread_exit(&arg);
+}
+
+void lock_test_spinlock_recursive_api(void)
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	odp_cunit_thread_create(spinlock_recursive_api_tests, &arg);
+	odp_cunit_thread_exit(&arg);
+}
+
+void lock_test_spinlock_recursive_functional(void)
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	odp_spinlock_recursive_init(&global_mem->global_recursive_spinlock);
+	odp_cunit_thread_create(spinlock_recursive_functional_test, &arg);
+	odp_cunit_thread_exit(&arg);
+}
+
+odp_testinfo_t lock_suite_spinlock[] = {
+	ODP_TEST_INFO(lock_test_spinlock_api),
+	ODP_TEST_INFO(lock_test_spinlock_functional),
+	ODP_TEST_INFO_NULL
+};
+
+odp_testinfo_t lock_suite_spinlock_recursive[] = {
+	ODP_TEST_INFO(lock_test_spinlock_recursive_api),
+	ODP_TEST_INFO(lock_test_spinlock_recursive_functional),
+	ODP_TEST_INFO_NULL
+};
+
+/* Ticket lock tests */
+void lock_test_ticketlock_api(void)
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	odp_cunit_thread_create(ticketlock_api_tests, &arg);
+	odp_cunit_thread_exit(&arg);
+}
+
+void lock_test_ticketlock_functional(void)
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	odp_ticketlock_init(&global_mem->global_ticketlock);
+
+	odp_cunit_thread_create(ticketlock_functional_test, &arg);
+	odp_cunit_thread_exit(&arg);
+}
+
+odp_testinfo_t lock_suite_ticketlock[] = {
+	ODP_TEST_INFO(lock_test_ticketlock_api),
+	ODP_TEST_INFO(lock_test_ticketlock_functional),
+	ODP_TEST_INFO_NULL
+};
+
+/* RW lock tests */
+void lock_test_rwlock_api(void)
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	odp_cunit_thread_create(rwlock_api_tests, &arg);
+	odp_cunit_thread_exit(&arg);
+}
+
+void lock_test_rwlock_functional(void)
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	odp_rwlock_init(&global_mem->global_rwlock);
+	odp_cunit_thread_create(rwlock_functional_test, &arg);
+	odp_cunit_thread_exit(&arg);
+}
+
+odp_testinfo_t lock_suite_rwlock[] = {
+	ODP_TEST_INFO(lock_test_rwlock_api),
+	ODP_TEST_INFO(lock_test_rwlock_functional),
+	ODP_TEST_INFO_NULL
+};
+
+void lock_test_rwlock_recursive_api(void)
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	odp_cunit_thread_create(rwlock_recursive_api_tests, &arg);
+	odp_cunit_thread_exit(&arg);
+}
+
+void lock_test_rwlock_recursive_functional(void)
+{
+	pthrd_arg arg;
+
+	arg.numthrds = global_mem->g_num_threads;
+	odp_rwlock_recursive_init(&global_mem->global_recursive_rwlock);
+	odp_cunit_thread_create(rwlock_recursive_functional_test, &arg);
+	odp_cunit_thread_exit(&arg);
+}
+
+odp_testinfo_t lock_suite_rwlock_recursive[] = {
+	ODP_TEST_INFO(lock_test_rwlock_recursive_api),
+	ODP_TEST_INFO(lock_test_rwlock_recursive_functional),
+	ODP_TEST_INFO_NULL
+};
+
+int lock_suite_init(void)
+{
+	uint32_t num_threads, idx;
+
+	num_threads = global_mem->g_num_threads;
+	odp_barrier_init(&global_mem->global_barrier, num_threads);
+	for (idx = 0; idx < NUM_RESYNC_BARRIERS; idx++)
+		odp_barrier_init(&global_mem->barrier_array[idx], num_threads);
+
+	return 0;
+}
+
+int lock_init(void)
+{
+	uint32_t workers_count, max_threads;
+	int ret = 0;
+	odp_cpumask_t mask;
+
+	if (0 != odp_init_global(NULL, NULL)) {
+		fprintf(stderr, "error: odp_init_global() failed.\n");
+		return -1;
+	}
+	if (0 != odp_init_local(ODP_THREAD_CONTROL)) {
+		fprintf(stderr, "error: odp_init_local() failed.\n");
+		return -1;
+	}
+
+	global_shm = odp_shm_reserve(GLOBAL_SHM_NAME,
+				     sizeof(global_shared_mem_t), 64,
+				     ODP_SHM_SW_ONLY);
+	if (ODP_SHM_INVALID == global_shm) {
+		fprintf(stderr, "Unable reserve memory for global_shm\n");
+		return -1;
+	}
+
+	global_mem = odp_shm_addr(global_shm);
+	memset(global_mem, 0, sizeof(global_shared_mem_t));
+
+	global_mem->g_num_threads = MAX_WORKERS;
+	global_mem->g_iterations = MAX_ITERATIONS;
+	global_mem->g_verbose = VERBOSE;
+
+	workers_count = odp_cpumask_default_worker(&mask, 0);
+
+	max_threads = (workers_count >= MAX_WORKERS) ?
+			MAX_WORKERS : workers_count;
+
+	if (max_threads < global_mem->g_num_threads) {
+		printf("Requested num of threads is too large\n");
+		printf("reducing from %" PRIu32 " to %" PRIu32 "\n",
+		       global_mem->g_num_threads,
+		       max_threads);
+		global_mem->g_num_threads = max_threads;
+	}
+
+	printf("Num of threads used = %" PRIu32 "\n",
+	       global_mem->g_num_threads);
+
+	return ret;
+}
+
+odp_suiteinfo_t lock_suites[] = {
+	{"nolocking", lock_suite_init, NULL,
+		lock_suite_no_locking},
+	{"spinlock", lock_suite_init, NULL,
+		lock_suite_spinlock},
+	{"spinlock_recursive", lock_suite_init, NULL,
+		lock_suite_spinlock_recursive},
+	{"ticketlock", lock_suite_init, NULL,
+		lock_suite_ticketlock},
+	{"rwlock", lock_suite_init, NULL,
+		lock_suite_rwlock},
+	{"rwlock_recursive", lock_suite_init, NULL,
+		lock_suite_rwlock_recursive},
+	ODP_SUITE_INFO_NULL
+};
+
+int lock_main(void)
+{
+	int ret;
+
+	odp_cunit_register_global_init(lock_init);
+
+	ret = odp_cunit_register(lock_suites);
+
+	if (ret == 0)
+		ret = odp_cunit_run();
+
+	return ret;
+}
diff --git a/test/validation/lock/lock.h b/test/validation/lock/lock.h
new file mode 100644
index 0000000..d41123f
--- /dev/null
+++ b/test/validation/lock/lock.h
@@ -0,0 +1,45 @@ 
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef _ODP_TEST_SYNCHRONIZERS_H_
+#define _ODP_TEST_SYNCHRONIZERS_H_
+
+#include <odp_cunit_common.h>
+
+/* test functions: */
+void lock_test_no_lock_functional(void);
+void lock_test_spinlock_api(void);
+void lock_test_spinlock_functional(void);
+void lock_test_spinlock_recursive_api(void);
+void lock_test_spinlock_recursive_functional(void);
+void lock_test_ticketlock_api(void);
+void lock_test_ticketlock_functional(void);
+void lock_test_rwlock_api(void);
+void lock_test_rwlock_functional(void);
+void lock_test_rwlock_recursive_api(void);
+void lock_test_rwlock_recursive_functional(void);
+
+/* test arrays: */
+extern odp_testinfo_t lock_suite_no_locking[];
+extern odp_testinfo_t lock_suite_spinlock[];
+extern odp_testinfo_t lock_suite_spinlock_recursive[];
+extern odp_testinfo_t lock_suite_ticketlock[];
+extern odp_testinfo_t lock_suite_rwlock[];
+extern odp_testinfo_t lock_suite_rwlock_recursive[];
+
+/* test array init/term functions: */
+int lock_suite_init(void);
+
+/* test registry: */
+extern odp_suiteinfo_t lock_suites[];
+
+/* executable init/term functions: */
+int lock_init(void);
+
+/* main test program: */
+int lock_main(void);
+
+#endif
diff --git a/test/validation/lock/lock_main.c b/test/validation/lock/lock_main.c
new file mode 100644
index 0000000..c12c2b5
--- /dev/null
+++ b/test/validation/lock/lock_main.c
@@ -0,0 +1,12 @@ 
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include "lock.h"
+
+int main(void)
+{
+	return lock_main();
+}