diff mbox

[API-NEXT,1/2] validation: synchro tests split into 3 groups

Message ID 1450366632-5041-1-git-send-email-christophe.milard@linaro.org
State Accepted
Commit dbac88879e40ae5ce86b6adc50ace33c1032d2c5
Headers show

Commit Message

Christophe Milard Dec. 17, 2015, 3:37 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       |  393 +++++++++++
 test/validation/barrier/barrier.h       |   29 +
 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, 2155 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

Maxim Uvarov Jan. 14, 2016, 4:52 p.m. UTC | #1
ping.

On 12/17/2015 18:37, Christophe Milard 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       |  393 +++++++++++
>   test/validation/barrier/barrier.h       |   29 +
>   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, 2155 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..8f15cdf
> --- /dev/null
> +++ b/test/validation/barrier/barrier.c
> @@ -0,0 +1,393 @@
> +/* 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__))
> +
> +static volatile int temp_result;
> +
> +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_mb_full();
> +
> +		if (i_am_slow_thread) {
> +			global_mem->slow_thread_num = next_slow_thread;
> +			global_mem->barrier_cnt2 = cnt + 1;
> +			odp_mb_full();
> +		} 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_memory_barrier(void)
> +{
> +	volatile int a = 0;
> +	volatile int b = 0;
> +	volatile int c = 0;
> +	volatile int d = 0;
> +
> +	/* Call all memory barriers to verify that those are implemented */
> +	a = 1;
> +	odp_mb_release();
> +	b = 1;
> +	odp_mb_acquire();
> +	c = 1;
> +	odp_mb_full();
> +	d = 1;
> +
> +	/* Avoid "variable set but not used" warning */
> +	temp_result = a + b + c + d;
> +}
> +
> +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_memory_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..15fa7b2
> --- /dev/null
> +++ b/test/validation/barrier/barrier.h
> @@ -0,0 +1,29 @@
> +/* 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_memory_barrier(void);
> +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..0f4415d
> --- /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_mb_full();
> +		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_mb_full();
> +		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_mb_full();
> +		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_mb_full();
> +		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_mb_full();
> +		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_mb_full();
> +		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_mb_full();
> +		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_mb_full();
> +		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_mb_full();
> +		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_mb_full();
> +		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_mb_full();
> +		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_mb_full();
> +		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();
> +}
Bill Fischofer Jan. 15, 2016, 2:30 p.m. UTC | #2
As noted last month, this series looks good but needs a rebase to apply
properly to API-NEXT.

On Thu, Jan 14, 2016 at 10:52 AM, Maxim Uvarov <maxim.uvarov@linaro.org>
wrote:

> ping.

>

> On 12/17/2015 18:37, Christophe Milard 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       |  393 +++++++++++

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

>>   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, 2155 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..8f15cdf

>> --- /dev/null

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

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

>> +/* 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__))

>> +

>> +static volatile int temp_result;

>> +

>> +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_mb_full();

>> +

>> +               if (i_am_slow_thread) {

>> +                       global_mem->slow_thread_num = next_slow_thread;

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

>> +                       odp_mb_full();

>> +               } 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_memory_barrier(void)

>> +{

>> +       volatile int a = 0;

>> +       volatile int b = 0;

>> +       volatile int c = 0;

>> +       volatile int d = 0;

>> +

>> +       /* Call all memory barriers to verify that those are implemented

>> */

>> +       a = 1;

>> +       odp_mb_release();

>> +       b = 1;

>> +       odp_mb_acquire();

>> +       c = 1;

>> +       odp_mb_full();

>> +       d = 1;

>> +

>> +       /* Avoid "variable set but not used" warning */

>> +       temp_result = a + b + c + d;

>> +}

>> +

>> +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_memory_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..15fa7b2

>> --- /dev/null

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

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

>> +/* 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_memory_barrier(void);

>> +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..0f4415d

>> --- /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_mb_full();

>> +               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_mb_full();

>> +               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_mb_full();

>> +               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_mb_full();

>> +               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_mb_full();

>> +               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_mb_full();

>> +               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_mb_full();

>> +               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_mb_full();

>> +               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_mb_full();

>> +               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_mb_full();

>> +               odp_rwlock_write_unlock(&global_mem->global_rwlock);

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

>> +                       current_errs++;

>> +                       sync_failures++;

>

>
Christophe Milard Jan. 15, 2016, 5:37 p.m. UTC | #3
Sorry, I am probably missing something, but I did rebase it last month: It
does not say v2 because the original patch was sent on master, not on
api-next.
So this is really the first patch on api-next.
I can apply this:
linaro@perric:~/linaro/ODP/odp$ git co -B synchronizer_tests origin/api-next
Branch synchronizer_tests set up to track remote branch api-next from
origin.
Reset branch 'synchronizer_tests'
Your branch is up-to-date with 'origin/api-next'.
linaro@perric:~/linaro/ODP/odp$ git am ~/incoming/*
Applying: validation: synchro tests split into 3 groups
Applying: validation: removing synchronizers tests
linaro@perric:~/linaro/ODP/odp$

Thanks for looking at it. and sorry if I did something wrong. just tell me
then! - Thanks
Christophe

On 15 January 2016 at 15:30, Bill Fischofer <bill.fischofer@linaro.org>
wrote:

> As noted last month, this series looks good but needs a rebase to apply

> properly to API-NEXT.

>

> On Thu, Jan 14, 2016 at 10:52 AM, Maxim Uvarov <maxim.uvarov@linaro.org>

> wrote:

>

>> ping.

>>

>> On 12/17/2015 18:37, Christophe Milard 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       |  393 +++++++++++

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

>>>   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, 2155 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..8f15cdf

>>> --- /dev/null

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

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

>>> +/* 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__))

>>> +

>>> +static volatile int temp_result;

>>> +

>>> +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_mb_full();

>>> +

>>> +               if (i_am_slow_thread) {

>>> +                       global_mem->slow_thread_num = next_slow_thread;

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

>>> +                       odp_mb_full();

>>> +               } 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_memory_barrier(void)

>>> +{

>>> +       volatile int a = 0;

>>> +       volatile int b = 0;

>>> +       volatile int c = 0;

>>> +       volatile int d = 0;

>>> +

>>> +       /* Call all memory barriers to verify that those are implemented

>>> */

>>> +       a = 1;

>>> +       odp_mb_release();

>>> +       b = 1;

>>> +       odp_mb_acquire();

>>> +       c = 1;

>>> +       odp_mb_full();

>>> +       d = 1;

>>> +

>>> +       /* Avoid "variable set but not used" warning */

>>> +       temp_result = a + b + c + d;

>>> +}

>>> +

>>> +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_memory_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..15fa7b2

>>> --- /dev/null

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

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

>>> +/* 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_memory_barrier(void);

>>> +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..0f4415d

>>> --- /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_mb_full();

>>> +               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_mb_full();

>>> +               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_mb_full();

>>> +               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_mb_full();

>>> +               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_mb_full();

>>> +               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_mb_full();

>>> +               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_mb_full();

>>> +               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_mb_full();

>>> +               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_mb_full();

>>> +               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_mb_full();

>>> +               odp_rwlock_write_unlock(&global_mem->global_rwlock);

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

>>> +                       current_errs++;

>>> +                       sync_failures++;

>>

>>

>

> _______________________________________________

> lng-odp mailing list

> lng-odp@lists.linaro.org

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

>

>
Bill Fischofer Jan. 21, 2016, 5:01 p.m. UTC | #4
Sorry for the delay.  For this series:

Reviewed-and-tested-by: Bill Fischofer <bill.fischofer@linaro.org>

On Fri, Jan 15, 2016 at 11:37 AM, Christophe Milard <
christophe.milard@linaro.org> wrote:

> Sorry, I am probably missing something, but I did rebase it last month: It

> does not say v2 because the original patch was sent on master, not on

> api-next.

> So this is really the first patch on api-next.

> I can apply this:

> linaro@perric:~/linaro/ODP/odp$ git co -B synchronizer_tests

> origin/api-next

> Branch synchronizer_tests set up to track remote branch api-next from

> origin.

> Reset branch 'synchronizer_tests'

> Your branch is up-to-date with 'origin/api-next'.

> linaro@perric:~/linaro/ODP/odp$ git am ~/incoming/*

> Applying: validation: synchro tests split into 3 groups

> Applying: validation: removing synchronizers tests

> linaro@perric:~/linaro/ODP/odp$

>

> Thanks for looking at it. and sorry if I did something wrong. just tell me

> then! - Thanks

> Christophe

>

> On 15 January 2016 at 15:30, Bill Fischofer <bill.fischofer@linaro.org>

> wrote:

>

>> As noted last month, this series looks good but needs a rebase to apply

>> properly to API-NEXT.

>>

>> On Thu, Jan 14, 2016 at 10:52 AM, Maxim Uvarov <maxim.uvarov@linaro.org>

>> wrote:

>>

>>> ping.

>>>

>>> On 12/17/2015 18:37, Christophe Milard 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       |  393 +++++++++++

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

>>>>   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, 2155 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..8f15cdf

>>>> --- /dev/null

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

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

>>>> +/* 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__))

>>>> +

>>>> +static volatile int temp_result;

>>>> +

>>>> +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_mb_full();

>>>> +

>>>> +               if (i_am_slow_thread) {

>>>> +                       global_mem->slow_thread_num = next_slow_thread;

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

>>>> +                       odp_mb_full();

>>>> +               } 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_memory_barrier(void)

>>>> +{

>>>> +       volatile int a = 0;

>>>> +       volatile int b = 0;

>>>> +       volatile int c = 0;

>>>> +       volatile int d = 0;

>>>> +

>>>> +       /* Call all memory barriers to verify that those are

>>>> implemented */

>>>> +       a = 1;

>>>> +       odp_mb_release();

>>>> +       b = 1;

>>>> +       odp_mb_acquire();

>>>> +       c = 1;

>>>> +       odp_mb_full();

>>>> +       d = 1;

>>>> +

>>>> +       /* Avoid "variable set but not used" warning */

>>>> +       temp_result = a + b + c + d;

>>>> +}

>>>> +

>>>> +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_memory_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..15fa7b2

>>>> --- /dev/null

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

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

>>>> +/* 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_memory_barrier(void);

>>>> +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..0f4415d

>>>> --- /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_mb_full();

>>>> +               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_mb_full();

>>>> +               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_mb_full();

>>>> +               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_mb_full();

>>>> +               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_mb_full();

>>>> +               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_mb_full();

>>>> +               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_mb_full();

>>>> +               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_mb_full();

>>>> +               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_mb_full();

>>>> +               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_mb_full();

>>>> +               odp_rwlock_write_unlock(&global_mem->global_rwlock);

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

>>>> +                       current_errs++;

>>>> +                       sync_failures++;

>>>

>>>

>>

>> _______________________________________________

>> lng-odp mailing list

>> lng-odp@lists.linaro.org

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

>>

>>

>
Maxim Uvarov Jan. 22, 2016, 11:57 a.m. UTC | #5
Merged,
Maxim.

On 01/21/2016 20:01, Bill Fischofer wrote:
> Sorry for the delay.  For this series:
>
> Reviewed-and-tested-by: Bill Fischofer <bill.fischofer@linaro.org 
> <mailto:bill.fischofer@linaro.org>>
>
> On Fri, Jan 15, 2016 at 11:37 AM, Christophe Milard 
> <christophe.milard@linaro.org <mailto:christophe.milard@linaro.org>> 
> wrote:
>
>     Sorry, I am probably missing something, but I did rebase it last
>     month: It does not say v2 because the original patch was sent on
>     master, not on api-next.
>     So this is really the first patch on api-next.
>     I can apply this:
>     linaro@perric:~/linaro/ODP/odp$ git co -B synchronizer_tests
>     origin/api-next
>     Branch synchronizer_tests set up to track remote branch api-next
>     from origin.
>     Reset branch 'synchronizer_tests'
>     Your branch is up-to-date with 'origin/api-next'.
>     linaro@perric:~/linaro/ODP/odp$ git am ~/incoming/*
>     Applying: validation: synchro tests split into 3 groups
>     Applying: validation: removing synchronizers tests
>     linaro@perric:~/linaro/ODP/odp$
>
>     Thanks for looking at it. and sorry if I did something wrong. just
>     tell me then! - Thanks
>     Christophe
>
>     On 15 January 2016 at 15:30, Bill Fischofer
>     <bill.fischofer@linaro.org <mailto:bill.fischofer@linaro.org>> wrote:
>
>         As noted last month, this series looks good but needs a rebase
>         to apply properly to API-NEXT.
>
>         On Thu, Jan 14, 2016 at 10:52 AM, Maxim Uvarov
>         <maxim.uvarov@linaro.org <mailto:maxim.uvarov@linaro.org>> wrote:
>
>             ping.
>
>             On 12/17/2015 18:37, Christophe Milard wrote:
>
>                 No functionnal changes: just code reordering to match
>                 the ODP modules.
>
>                 Signed-off-by: Christophe Milard
>                 <christophe.milard@linaro.org
>                 <mailto:christophe.milard@linaro.org>>
>                 ---
>                 configure.ac <http://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    |  393 +++++++++++
>                   test/validation/barrier/barrier.h    |   29 +
>                 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, 2155 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 <http://configure.ac>
>                 b/configure.ac <http://configure.ac>
>                 index 4f89f03..7a05574 100644
>                 --- a/configure.ac <http://configure.ac>
>                 +++ b/configure.ac <http://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
>                 <http://libtestatomic.la>
>                 +libtestatomic_la_SOURCES = atomic.c
>                 +
>                 +test_PROGRAMS = atomic_main$(EXEEXT)
>                 +dist_atomic_main_SOURCES = atomic_main.c
>                 +atomic_main_LDADD = libtestatomic.la
>                 <http://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
>                 <http://libtestbarrier.la>
>                 +libtestbarrier_la_SOURCES = barrier.c
>                 +
>                 +test_PROGRAMS = barrier_main$(EXEEXT)
>                 +dist_barrier_main_SOURCES = barrier_main.c
>                 +barrier_main_LDADD = libtestbarrier.la
>                 <http://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..8f15cdf
>                 --- /dev/null
>                 +++ b/test/validation/barrier/barrier.c
>                 @@ -0,0 +1,393 @@
>                 +/* 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__))
>                 +
>                 +static volatile int temp_result;
>                 +
>                 +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_mb_full();
>                 +
>                 +               if (i_am_slow_thread) {
>                 +  global_mem->slow_thread_num = next_slow_thread;
>                 +  global_mem->barrier_cnt2 = cnt + 1;
>                 +                       odp_mb_full();
>                 +               } 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_memory_barrier(void)
>                 +{
>                 +       volatile int a = 0;
>                 +       volatile int b = 0;
>                 +       volatile int c = 0;
>                 +       volatile int d = 0;
>                 +
>                 +       /* Call all memory barriers to verify that
>                 those are implemented */
>                 +       a = 1;
>                 +       odp_mb_release();
>                 +       b = 1;
>                 +       odp_mb_acquire();
>                 +       c = 1;
>                 +       odp_mb_full();
>                 +       d = 1;
>                 +
>                 +       /* Avoid "variable set but not used" warning */
>                 +       temp_result = a + b + c + d;
>                 +}
>                 +
>                 +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_memory_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..15fa7b2
>                 --- /dev/null
>                 +++ b/test/validation/barrier/barrier.h
>                 @@ -0,0 +1,29 @@
>                 +/* 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_memory_barrier(void);
>                 +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
>                 <http://libtestlock.la>
>                 +libtestlock_la_SOURCES = lock.c
>                 +
>                 +test_PROGRAMS = lock_main$(EXEEXT)
>                 +dist_lock_main_SOURCES = lock_main.c
>                 +lock_main_LDADD = libtestlock.la
>                 <http://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..0f4415d
>                 --- /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_mb_full();
>                 +  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_mb_full();
>                 +  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_mb_full();
>                 +  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_mb_full();
>                 +  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_mb_full();
>                 +  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_mb_full();
>                 +  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_mb_full();
>                 +  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_mb_full();
>                 +  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_mb_full();
>                 +  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_mb_full();
>                 +  odp_rwlock_write_unlock(&global_mem->global_rwlock);
>                 +               if (global_mem->global_lock_owner ==
>                 thread_num) {
>                 +  current_errs++;
>                 +  sync_failures++;
>
>
>
>         _______________________________________________
>         lng-odp mailing list
>         lng-odp@lists.linaro.org <mailto: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..8f15cdf
--- /dev/null
+++ b/test/validation/barrier/barrier.c
@@ -0,0 +1,393 @@ 
+/* 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__))
+
+static volatile int temp_result;
+
+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_mb_full();
+
+		if (i_am_slow_thread) {
+			global_mem->slow_thread_num = next_slow_thread;
+			global_mem->barrier_cnt2 = cnt + 1;
+			odp_mb_full();
+		} 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_memory_barrier(void)
+{
+	volatile int a = 0;
+	volatile int b = 0;
+	volatile int c = 0;
+	volatile int d = 0;
+
+	/* Call all memory barriers to verify that those are implemented */
+	a = 1;
+	odp_mb_release();
+	b = 1;
+	odp_mb_acquire();
+	c = 1;
+	odp_mb_full();
+	d = 1;
+
+	/* Avoid "variable set but not used" warning */
+	temp_result = a + b + c + d;
+}
+
+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_memory_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..15fa7b2
--- /dev/null
+++ b/test/validation/barrier/barrier.h
@@ -0,0 +1,29 @@ 
+/* 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_memory_barrier(void);
+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..0f4415d
--- /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_mb_full();
+		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_mb_full();
+		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_mb_full();
+		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_mb_full();
+		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_mb_full();
+		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_mb_full();
+		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_mb_full();
+		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_mb_full();
+		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_mb_full();
+		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_mb_full();
+		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_mb_full();
+		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_mb_full();
+		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();
+}