Based on API interface files.

Signed-off-by: Christophe Milard <christophe.mil...@linaro.org>
---
 include/odp_drv.h                                  |  1 +
 platform/linux-generic/Makefile.am                 |  3 ++
 platform/linux-generic/drv_barrier.c               | 50 ++++++++++++++++++++++
 platform/linux-generic/include/odp/drv/barrier.h   | 30 +++++++++++++
 .../include/odp/drv/plat/barrier_types.h           | 38 ++++++++++++++++
 5 files changed, 122 insertions(+)
 create mode 100644 platform/linux-generic/drv_barrier.c
 create mode 100644 platform/linux-generic/include/odp/drv/barrier.h
 create mode 100644 platform/linux-generic/include/odp/drv/plat/barrier_types.h

diff --git a/include/odp_drv.h b/include/odp_drv.h
index 776cf12..31c620e 100644
--- a/include/odp_drv.h
+++ b/include/odp_drv.h
@@ -20,6 +20,7 @@ extern C {
 
 #include <odp/drv/align.h>
 #include <odp/drv/atomic.h>
+#include <odp/drv/barrier.h>
 #include <odp/drv/byteorder.h>
 #include <odp/drv/compiler.h>
 #include <odp/drv/spinlock.h>
diff --git a/platform/linux-generic/Makefile.am 
b/platform/linux-generic/Makefile.am
index 747e96f..42e9996 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -96,6 +96,7 @@ odpdrvincludedir = $(includedir)/odp/drv
 odpdrvinclude_HEADERS = \
                  $(srcdir)/include/odp/drv/align.h \
                  $(srcdir)/include/odp/drv/atomic.h \
+                 $(srcdir)/include/odp/drv/barrier.h \
                  $(srcdir)/include/odp/drv/byteorder.h \
                  $(srcdir)/include/odp/drv/compiler.h \
                  $(srcdir)/include/odp/drv/spinlock.h \
@@ -105,6 +106,7 @@ odpdrvinclude_HEADERS = \
 odpdrvplatincludedir = $(includedir)/odp/drv/plat
 odpdrvplatinclude_HEADERS = \
                  $(srcdir)/include/odp/drv/plat/atomic_types.h \
+                 $(srcdir)/include/odp/drv/plat/barrier_types.h \
                  $(srcdir)/include/odp/drv/plat/byteorder_types.h \
                  $(srcdir)/include/odp/drv/plat/spinlock_types.h
 
@@ -204,6 +206,7 @@ __LIB__libodp_linux_la_SOURCES = \
                           odp_version.c \
                           odp_weak.c \
                           drv_atomic.c \
+                          drv_barrier.c \
                           drv_spinlock.c \
                           arch/@ARCH_DIR@/odp_cpu_arch.c \
                           arch/@ARCH_DIR@/odp_sysinfo_parse.c
diff --git a/platform/linux-generic/drv_barrier.c 
b/platform/linux-generic/drv_barrier.c
new file mode 100644
index 0000000..7a83981
--- /dev/null
+++ b/platform/linux-generic/drv_barrier.c
@@ -0,0 +1,50 @@
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp/drv/barrier.h>
+#include <odp/drv/sync.h>
+#include <odp/api/cpu.h>
+#include <odp/drv/atomic.h>
+
+void odpdrv_barrier_init(odpdrv_barrier_t *barrier, int count)
+{
+       barrier->count = (uint32_t)count;
+       odpdrv_atomic_init_u32(&barrier->bar, 0);
+}
+
+/*
+ * Efficient barrier_sync -
+ *
+ *   Barriers are initialized with a count of the number of callers
+ *   that must sync on the barrier before any may proceed.
+ *
+ *   To avoid race conditions and to permit the barrier to be fully
+ *   reusable, the barrier value cycles between 0..2*count-1. When
+ *   synchronizing the wasless variable simply tracks which half of
+ *   the cycle the barrier was in upon entry.  Exit is when the
+ *   barrier crosses to the other half of the cycle.
+ */
+void odpdrv_barrier_wait(odpdrv_barrier_t *barrier)
+{
+       uint32_t count;
+       int wasless;
+
+       odpdrv_mb_full();
+
+       count   = odpdrv_atomic_fetch_inc_u32(&barrier->bar);
+       wasless = count < barrier->count;
+
+       if (count == 2 * barrier->count - 1) {
+               /* Wrap around *atomically* */
+               odpdrv_atomic_sub_u32(&barrier->bar, 2 * barrier->count);
+       } else {
+               while ((odpdrv_atomic_load_u32(&barrier->bar) < barrier->count)
+                               == wasless)
+                       odp_cpu_pause();
+       }
+
+       odpdrv_mb_full();
+}
diff --git a/platform/linux-generic/include/odp/drv/barrier.h 
b/platform/linux-generic/include/odp/drv/barrier.h
new file mode 100644
index 0000000..877cacf
--- /dev/null
+++ b/platform/linux-generic/include/odp/drv/barrier.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODPDRV execution barriers
+ */
+
+#ifndef ODPDRV_PLAT_BARRIER_H_
+#define ODPDRV_PLAT_BARRIER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/drv/std_types.h>
+#include <odp/drv/atomic.h>
+#include <odp/drv/plat/barrier_types.h>
+
+#include <odp/drv/spec/barrier.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/drv/plat/barrier_types.h 
b/platform/linux-generic/include/odp/drv/plat/barrier_types.h
new file mode 100644
index 0000000..32264a1
--- /dev/null
+++ b/platform/linux-generic/include/odp/drv/plat/barrier_types.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODPDRV barrier
+ */
+
+#ifndef ODPDRV_BARRIER_TYPES_H_
+#define ODPDRV_BARRIER_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/drv/std_types.h>
+#include <odp/drv/atomic.h>
+
+/**
+ * @internal
+ * ODPDRV thread synchronization barrier
+ */
+struct odpdrv_barrier_s {
+       uint32_t                count;  /**< Thread count */
+       odpdrv_atomic_u32_t     bar;    /**< Barrier counter */
+};
+
+typedef struct odpdrv_barrier_s odpdrv_barrier_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
-- 
2.7.4

Reply via email to