diff mbox

linux-generic: configure: add conditional shared library support

Message ID 1472341786-14982-1-git-send-email-bill.fischofer@linaro.org
State Superseded
Headers show

Commit Message

Bill Fischofer Aug. 27, 2016, 11:49 p.m. UTC
Add support for the --enable-shared=[yes|no] configure options.
--enable-shared=yes is the default and results in suppressing the use
of inlines for ODP API functions to enhance ABI compatibility at
potentially some performance cost. When --enable-shared=no is specified,
inlines are allowed to boost performance at the possible loss of ABI
compatibility.

This patch addresses Bug https://bugs.linaro.org/show_bug.cgi?id=2490

Note: This patch is a port of the corresponding enhancements made to
odp-dpdk with a few changes, mainly that inlines are now part of the
odp/api/plat directory, and all ODP APIs are now treated uniformly with
regard to whether inlining is permitted.

Suggested-by: Zoltan Kiss <zoltan.kiss@linaro.org>
Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>

---
 .gitignore                                         |   1 +
 configure.ac                                       |   7 +
 example/Makefile.inc                               |   3 +-
 helper/Makefile.am                                 |   1 +
 platform/linux-generic/Makefile.am                 |   7 +
 platform/linux-generic/include/odp/api/atomic.h    | 384 +-------------------
 .../include/odp/api/plat/atomic_inlines.h          | 385 +++++++++++++++++++++
 .../include/odp/api/plat/inlines.h.in              |  33 ++
 .../include/odp/api/plat/std_clib_inlines.h        |  36 ++
 .../include/odp/api/plat/sync_inlines.h            |  47 +++
 platform/linux-generic/include/odp/api/std_clib.h  |  18 +-
 platform/linux-generic/include/odp/api/sync.h      |  18 +-
 platform/linux-generic/m4/configure.m4             |   3 +-
 platform/linux-generic/odp_atomic.c                |   3 +
 platform/linux-generic/odp_std_clib.c              |  11 +
 platform/linux-generic/odp_sync.c                  |  11 +
 16 files changed, 558 insertions(+), 410 deletions(-)
 create mode 100644 platform/linux-generic/include/odp/api/plat/atomic_inlines.h
 create mode 100644 platform/linux-generic/include/odp/api/plat/inlines.h.in
 create mode 100644 platform/linux-generic/include/odp/api/plat/std_clib_inlines.h
 create mode 100644 platform/linux-generic/include/odp/api/plat/sync_inlines.h
 create mode 100644 platform/linux-generic/odp_std_clib.c
 create mode 100644 platform/linux-generic/odp_sync.c

-- 
2.7.4
diff mbox

Patch

diff --git a/.gitignore b/.gitignore
index d4e7d02..c4bf291 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,5 +41,6 @@  ltmain.sh
 m4/*.m4
 missing
 pkgconfig/libodp*.pc
+platform/linux-generic/include/odp/api/plat/inlines.h
 tags
 test-driver
diff --git a/configure.ac b/configure.ac
index 6551287..982aff7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -176,6 +176,13 @@  AM_CONDITIONAL([test_example], [test x$test_example = xyes ])
 AM_CONDITIONAL([HAVE_DOXYGEN], [test "x${DOXYGEN}" = "xdoxygen"])
 AM_CONDITIONAL([user_guide], [test "x${user_guides}" = "xyes" ])
 AM_CONDITIONAL([HAVE_MSCGEN], [test "x${MSCGEN}" = "xmscgen"])
+if test x$enable_shared != xyes;
+then
+	_ODP_INLINES="_ODP_INLINES"
+else
+	_ODP_INLINES="_ODP_NO_INLINES"
+fi
+AC_SUBST(_ODP_INLINES)
 
 ##########################################################################
 # Setup doxygen documentation
diff --git a/example/Makefile.inc b/example/Makefile.inc
index 70ba2c0..9fb2f29 100644
--- a/example/Makefile.inc
+++ b/example/Makefile.inc
@@ -6,6 +6,7 @@  AM_CFLAGS += \
 	-I$(top_srcdir)/example \
 	-I$(top_srcdir)/platform/@with_platform@/include \
 	-I$(top_srcdir)/include/ \
-	-I$(top_srcdir)/helper/include
+	-I$(top_srcdir)/helper/include \
+	-I$(top_builddir)/platform/@with_platform@/include
 
 AM_LDFLAGS += -L$(LIB)
diff --git a/helper/Makefile.am b/helper/Makefile.am
index a82a11a..ee99f53 100644
--- a/helper/Makefile.am
+++ b/helper/Makefile.am
@@ -7,6 +7,7 @@  LIB   = $(top_builddir)/lib
 AM_CFLAGS  = -I$(srcdir)/include
 AM_CFLAGS += -I$(top_srcdir)/platform/@with_platform@/include
 AM_CFLAGS += -I$(top_srcdir)/include
+AM_CFLAGS += -I$(top_srcdir)/platform/@with_platform@/include
 
 AM_LDFLAGS += -version-number '$(ODPHELPER_LIBSO_VERSION)'
 
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index 0cfd0fe..6ac83b9 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -6,6 +6,7 @@  include $(top_srcdir)/platform/@with_platform@/Makefile.inc
 
 AM_CFLAGS +=  -I$(srcdir)/include
 AM_CFLAGS +=  -I$(top_srcdir)/include
+AM_CFLAGS +=  -Iinclude
 
 include_HEADERS = \
 		  $(top_srcdir)/include/odp.h \
@@ -60,6 +61,7 @@  odpapiinclude_HEADERS = \
 
 odpapiplatincludedir= $(includedir)/odp/api/plat
 odpapiplatinclude_HEADERS = \
+		  $(srcdir)/include/odp/api/plat/atomic_inlines.h \
 		  $(srcdir)/include/odp/api/plat/atomic_types.h \
 		  $(srcdir)/include/odp/api/plat/barrier_types.h \
 		  $(srcdir)/include/odp/api/plat/buffer_types.h \
@@ -69,6 +71,7 @@  odpapiplatinclude_HEADERS = \
 		  $(srcdir)/include/odp/api/plat/crypto_types.h \
 		  $(srcdir)/include/odp/api/plat/event_types.h \
 		  $(srcdir)/include/odp/api/plat/init_types.h \
+		  $(srcdir)/include/odp/api/plat/inlines.h \
 		  $(srcdir)/include/odp/api/plat/packet_types.h \
 		  $(srcdir)/include/odp/api/plat/packet_io_types.h \
 		  $(srcdir)/include/odp/api/plat/pool_types.h \
@@ -79,7 +82,9 @@  odpapiplatinclude_HEADERS = \
 		  $(srcdir)/include/odp/api/plat/shared_memory_types.h \
 		  $(srcdir)/include/odp/api/plat/spinlock_types.h \
 		  $(srcdir)/include/odp/api/plat/spinlock_recursive_types.h \
+		  $(srcdir)/include/odp/api/plat/std_clib_inlines.h \
 		  $(srcdir)/include/odp/api/plat/strong_types.h \
+		  $(srcdir)/include/odp/api/plat/sync_inlines.h \
 		  $(srcdir)/include/odp/api/plat/thread_types.h \
 		  $(srcdir)/include/odp/api/plat/thrmask_types.h \
 		  $(srcdir)/include/odp/api/plat/ticketlock_types.h \
@@ -173,6 +178,8 @@  __LIB__libodp_linux_la_SOURCES = \
 			   odp_sorted_list.c \
 			   odp_spinlock.c \
 			   odp_spinlock_recursive.c \
+			   odp_std_clib.c \
+			   odp_sync.c \
 			   odp_system_info.c \
 			   odp_thread.c \
 			   odp_thrmask.c \
diff --git a/platform/linux-generic/include/odp/api/atomic.h b/platform/linux-generic/include/odp/api/atomic.h
index b487383..c18e68b 100644
--- a/platform/linux-generic/include/odp/api/atomic.h
+++ b/platform/linux-generic/include/odp/api/atomic.h
@@ -24,388 +24,10 @@  extern "C" {
  *  @{
  */
 
-static inline void odp_atomic_init_u32(odp_atomic_u32_t *atom, uint32_t val)
-{
-	__atomic_store_n(&atom->v, val, __ATOMIC_RELAXED);
-}
-
-static inline uint32_t odp_atomic_load_u32(odp_atomic_u32_t *atom)
-{
-	return __atomic_load_n(&atom->v, __ATOMIC_RELAXED);
-}
-
-static inline void odp_atomic_store_u32(odp_atomic_u32_t *atom,
-					uint32_t val)
-{
-	__atomic_store_n(&atom->v, val, __ATOMIC_RELAXED);
-}
-
-static inline uint32_t odp_atomic_fetch_add_u32(odp_atomic_u32_t *atom,
-						uint32_t val)
-{
-	return __atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED);
-}
-
-static inline void odp_atomic_add_u32(odp_atomic_u32_t *atom,
-				      uint32_t val)
-{
-	(void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED);
-}
-
-static inline uint32_t odp_atomic_fetch_sub_u32(odp_atomic_u32_t *atom,
-						uint32_t val)
-{
-	return __atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED);
-}
-
-static inline void odp_atomic_sub_u32(odp_atomic_u32_t *atom,
-				      uint32_t val)
-{
-	(void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED);
-}
-
-static inline uint32_t odp_atomic_fetch_inc_u32(odp_atomic_u32_t *atom)
-{
-	return __atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED);
-}
-
-static inline void odp_atomic_inc_u32(odp_atomic_u32_t *atom)
-{
-	(void)__atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED);
-}
-
-static inline uint32_t odp_atomic_fetch_dec_u32(odp_atomic_u32_t *atom)
-{
-	return __atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED);
-}
-
-static inline void odp_atomic_dec_u32(odp_atomic_u32_t *atom)
-{
-	(void)__atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED);
-}
-
-static inline int odp_atomic_cas_u32(odp_atomic_u32_t *atom, uint32_t *old_val,
-				     uint32_t new_val)
-{
-	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
-					   0 /* strong */,
-					   __ATOMIC_RELAXED,
-					   __ATOMIC_RELAXED);
-}
-
-static inline uint32_t odp_atomic_xchg_u32(odp_atomic_u32_t *atom,
-					   uint32_t new_val)
-{
-	return __atomic_exchange_n(&atom->v, new_val, __ATOMIC_RELAXED);
-}
-
-static inline void odp_atomic_max_u32(odp_atomic_u32_t *atom, uint32_t new_max)
-{
-	uint32_t old_val;
-
-	old_val = odp_atomic_load_u32(atom);
-
-	while (new_max > old_val) {
-		if (odp_atomic_cas_u32(atom, &old_val, new_max))
-			break;
-	}
-}
-
-static inline void odp_atomic_min_u32(odp_atomic_u32_t *atom, uint32_t new_min)
-{
-	uint32_t old_val;
-
-	old_val = odp_atomic_load_u32(atom);
-
-	while (new_min < old_val) {
-		if (odp_atomic_cas_u32(atom, &old_val, new_min))
-			break;
-	}
-}
-
-static inline void odp_atomic_init_u64(odp_atomic_u64_t *atom, uint64_t val)
-{
-	atom->v = val;
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	__atomic_clear(&atom->lock, __ATOMIC_RELAXED);
-#endif
-}
-
-static inline uint64_t odp_atomic_load_u64(odp_atomic_u64_t *atom)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	return ATOMIC_OP(atom, (void)0);
-#else
-	return __atomic_load_n(&atom->v, __ATOMIC_RELAXED);
-#endif
-}
-
-static inline void odp_atomic_store_u64(odp_atomic_u64_t *atom,
-					uint64_t val)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	(void)ATOMIC_OP(atom, atom->v = val);
-#else
-	__atomic_store_n(&atom->v, val, __ATOMIC_RELAXED);
-#endif
-}
-
-static inline uint64_t odp_atomic_fetch_add_u64(odp_atomic_u64_t *atom,
-						uint64_t val)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	return ATOMIC_OP(atom, atom->v += val);
-#else
-	return __atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED);
-#endif
-}
-
-static inline void odp_atomic_add_u64(odp_atomic_u64_t *atom, uint64_t val)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	(void)ATOMIC_OP(atom, atom->v += val);
-#else
-	(void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED);
-#endif
-}
-
-static inline uint64_t odp_atomic_fetch_sub_u64(odp_atomic_u64_t *atom,
-						uint64_t val)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	return ATOMIC_OP(atom, atom->v -= val);
-#else
-	return __atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED);
-#endif
-}
-
-static inline void odp_atomic_sub_u64(odp_atomic_u64_t *atom, uint64_t val)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	(void)ATOMIC_OP(atom, atom->v -= val);
-#else
-	(void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED);
-#endif
-}
-
-static inline uint64_t odp_atomic_fetch_inc_u64(odp_atomic_u64_t *atom)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	return ATOMIC_OP(atom, atom->v++);
-#else
-	return __atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED);
-#endif
-}
-
-static inline void odp_atomic_inc_u64(odp_atomic_u64_t *atom)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	(void)ATOMIC_OP(atom, atom->v++);
-#else
-	(void)__atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED);
-#endif
-}
-
-static inline uint64_t odp_atomic_fetch_dec_u64(odp_atomic_u64_t *atom)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	return ATOMIC_OP(atom, atom->v--);
-#else
-	return __atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED);
+#include <odp/api/plat/inlines.h>
+#ifdef _ODP_INLINES
+#include <odp/api/plat/atomic_inlines.h>
 #endif
-}
-
-static inline void odp_atomic_dec_u64(odp_atomic_u64_t *atom)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	(void)ATOMIC_OP(atom, atom->v--);
-#else
-	(void)__atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED);
-#endif
-}
-
-static inline int odp_atomic_cas_u64(odp_atomic_u64_t *atom, uint64_t *old_val,
-				     uint64_t new_val)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	int ret;
-	*old_val = ATOMIC_OP(atom, ATOMIC_CAS_OP(&ret, *old_val, new_val));
-	return ret;
-#else
-	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
-					   0 /* strong */,
-					   __ATOMIC_RELAXED,
-					   __ATOMIC_RELAXED);
-#endif
-}
-
-static inline uint64_t odp_atomic_xchg_u64(odp_atomic_u64_t *atom,
-					   uint64_t new_val)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	return ATOMIC_OP(atom, atom->v = new_val);
-#else
-	return __atomic_exchange_n(&atom->v, new_val, __ATOMIC_RELAXED);
-#endif
-}
-
-static inline void odp_atomic_max_u64(odp_atomic_u64_t *atom, uint64_t new_max)
-{
-	uint64_t old_val;
-
-	old_val = odp_atomic_load_u64(atom);
-
-	while (new_max > old_val) {
-		if (odp_atomic_cas_u64(atom, &old_val, new_max))
-			break;
-	}
-}
-
-static inline void odp_atomic_min_u64(odp_atomic_u64_t *atom, uint64_t new_min)
-{
-	uint64_t old_val;
-
-	old_val = odp_atomic_load_u64(atom);
-
-	while (new_min < old_val) {
-		if (odp_atomic_cas_u64(atom, &old_val, new_min))
-			break;
-	}
-}
-
-static inline uint32_t odp_atomic_load_acq_u32(odp_atomic_u32_t *atom)
-{
-	return __atomic_load_n(&atom->v, __ATOMIC_ACQUIRE);
-}
-
-static inline void odp_atomic_store_rel_u32(odp_atomic_u32_t *atom,
-					    uint32_t val)
-{
-	__atomic_store_n(&atom->v, val, __ATOMIC_RELEASE);
-}
-
-static inline void odp_atomic_add_rel_u32(odp_atomic_u32_t *atom,
-					  uint32_t val)
-{
-	(void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELEASE);
-}
-
-static inline void odp_atomic_sub_rel_u32(odp_atomic_u32_t *atom,
-					  uint32_t val)
-{
-	(void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELEASE);
-}
-
-static inline int odp_atomic_cas_acq_u32(odp_atomic_u32_t *atom,
-					 uint32_t *old_val, uint32_t new_val)
-{
-	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
-					   0 /* strong */,
-					   __ATOMIC_ACQUIRE,
-					   __ATOMIC_RELAXED);
-}
-
-static inline int odp_atomic_cas_rel_u32(odp_atomic_u32_t *atom,
-					 uint32_t *old_val, uint32_t new_val)
-{
-	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
-					   0 /* strong */,
-					   __ATOMIC_RELEASE,
-					   __ATOMIC_RELAXED);
-}
-
-static inline int odp_atomic_cas_acq_rel_u32(odp_atomic_u32_t *atom,
-					     uint32_t *old_val,
-					     uint32_t new_val)
-{
-	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
-					   0 /* strong */,
-					   __ATOMIC_ACQ_REL,
-					   __ATOMIC_RELAXED);
-}
-
-static inline uint64_t odp_atomic_load_acq_u64(odp_atomic_u64_t *atom)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	return ATOMIC_OP(atom, (void)0);
-#else
-	return __atomic_load_n(&atom->v, __ATOMIC_ACQUIRE);
-#endif
-}
-
-static inline void odp_atomic_store_rel_u64(odp_atomic_u64_t *atom,
-					    uint64_t val)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	(void)ATOMIC_OP(atom, atom->v = val);
-#else
-	__atomic_store_n(&atom->v, val, __ATOMIC_RELEASE);
-#endif
-}
-
-static inline void odp_atomic_add_rel_u64(odp_atomic_u64_t *atom, uint64_t val)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	(void)ATOMIC_OP(atom, atom->v += val);
-#else
-	(void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELEASE);
-#endif
-}
-
-static inline void odp_atomic_sub_rel_u64(odp_atomic_u64_t *atom, uint64_t val)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	(void)ATOMIC_OP(atom, atom->v -= val);
-#else
-	(void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELEASE);
-#endif
-}
-
-static inline int odp_atomic_cas_acq_u64(odp_atomic_u64_t *atom,
-					 uint64_t *old_val, uint64_t new_val)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	int ret;
-	*old_val = ATOMIC_OP(atom, ATOMIC_CAS_OP(&ret, *old_val, new_val));
-	return ret;
-#else
-	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
-					   0 /* strong */,
-					   __ATOMIC_ACQUIRE,
-					   __ATOMIC_RELAXED);
-#endif
-}
-
-static inline int odp_atomic_cas_rel_u64(odp_atomic_u64_t *atom,
-					 uint64_t *old_val, uint64_t new_val)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	int ret;
-	*old_val = ATOMIC_OP(atom, ATOMIC_CAS_OP(&ret, *old_val, new_val));
-	return ret;
-#else
-	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
-					   0 /* strong */,
-					   __ATOMIC_RELEASE,
-					   __ATOMIC_RELAXED);
-#endif
-}
-
-static inline int odp_atomic_cas_acq_rel_u64(odp_atomic_u64_t *atom,
-					     uint64_t *old_val,
-					     uint64_t new_val)
-{
-#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
-	int ret;
-	*old_val = ATOMIC_OP(atom, ATOMIC_CAS_OP(&ret, *old_val, new_val));
-	return ret;
-#else
-	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
-					   0 /* strong */,
-					   __ATOMIC_ACQ_REL,
-					   __ATOMIC_RELAXED);
-#endif
-}
 
 /**
  * @}
diff --git a/platform/linux-generic/include/odp/api/plat/atomic_inlines.h b/platform/linux-generic/include/odp/api/plat/atomic_inlines.h
new file mode 100644
index 0000000..4471f2e
--- /dev/null
+++ b/platform/linux-generic/include/odp/api/plat/atomic_inlines.h
@@ -0,0 +1,385 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP Atomic inline functions
+ */
+
+#ifndef _ODP_PLAT_ATOMIC_INLINES_H_
+#define _ODP_PLAT_ATOMIC_INLINES_H_
+
+_STATIC void odp_atomic_init_u32(odp_atomic_u32_t *atom, uint32_t val)
+{
+	__atomic_store_n(&atom->v, val, __ATOMIC_RELAXED);
+}
+
+_STATIC uint32_t odp_atomic_load_u32(odp_atomic_u32_t *atom)
+{
+	return __atomic_load_n(&atom->v, __ATOMIC_RELAXED);
+}
+
+_STATIC void odp_atomic_store_u32(odp_atomic_u32_t *atom, uint32_t val)
+{
+	__atomic_store_n(&atom->v, val, __ATOMIC_RELAXED);
+}
+
+_STATIC uint32_t odp_atomic_fetch_add_u32(odp_atomic_u32_t *atom, uint32_t val)
+{
+	return __atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED);
+}
+
+_STATIC void odp_atomic_add_u32(odp_atomic_u32_t *atom, uint32_t val)
+{
+	(void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED);
+}
+
+_STATIC uint32_t odp_atomic_fetch_sub_u32(odp_atomic_u32_t *atom, uint32_t val)
+{
+	return __atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED);
+}
+
+_STATIC void odp_atomic_sub_u32(odp_atomic_u32_t *atom, uint32_t val)
+{
+	(void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED);
+}
+
+_STATIC uint32_t odp_atomic_fetch_inc_u32(odp_atomic_u32_t *atom)
+{
+	return __atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED);
+}
+
+_STATIC void odp_atomic_inc_u32(odp_atomic_u32_t *atom)
+{
+	(void)__atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED);
+}
+
+_STATIC uint32_t odp_atomic_fetch_dec_u32(odp_atomic_u32_t *atom)
+{
+	return __atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED);
+}
+
+_STATIC void odp_atomic_dec_u32(odp_atomic_u32_t *atom)
+{
+	(void)__atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED);
+}
+
+_STATIC int odp_atomic_cas_u32(odp_atomic_u32_t *atom, uint32_t *old_val,
+			       uint32_t new_val)
+{
+	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
+					   0 /* strong */,
+					   __ATOMIC_RELAXED,
+					   __ATOMIC_RELAXED);
+}
+
+_STATIC uint32_t odp_atomic_xchg_u32(odp_atomic_u32_t *atom, uint32_t new_val)
+{
+	return __atomic_exchange_n(&atom->v, new_val, __ATOMIC_RELAXED);
+}
+
+_STATIC void odp_atomic_max_u32(odp_atomic_u32_t *atom, uint32_t new_max)
+{
+	uint32_t old_val;
+
+	old_val = odp_atomic_load_u32(atom);
+
+	while (new_max > old_val) {
+		if (odp_atomic_cas_u32(atom, &old_val, new_max))
+			break;
+	}
+}
+
+_STATIC void odp_atomic_min_u32(odp_atomic_u32_t *atom, uint32_t new_min)
+{
+	uint32_t old_val;
+
+	old_val = odp_atomic_load_u32(atom);
+
+	while (new_min < old_val) {
+		if (odp_atomic_cas_u32(atom, &old_val, new_min))
+			break;
+	}
+}
+
+_STATIC void odp_atomic_init_u64(odp_atomic_u64_t *atom, uint64_t val)
+{
+	atom->v = val;
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	__atomic_clear(&atom->lock, __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC uint64_t odp_atomic_load_u64(odp_atomic_u64_t *atom)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	return ATOMIC_OP(atom, (void)0);
+#else
+	return __atomic_load_n(&atom->v, __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC void odp_atomic_store_u64(odp_atomic_u64_t *atom, uint64_t val)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	(void)ATOMIC_OP(atom, atom->v = val);
+#else
+	__atomic_store_n(&atom->v, val, __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC uint64_t odp_atomic_fetch_add_u64(odp_atomic_u64_t *atom, uint64_t val)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	return ATOMIC_OP(atom, atom->v += val);
+#else
+	return __atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC void odp_atomic_add_u64(odp_atomic_u64_t *atom, uint64_t val)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	(void)ATOMIC_OP(atom, atom->v += val);
+#else
+	(void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC uint64_t odp_atomic_fetch_sub_u64(odp_atomic_u64_t *atom, uint64_t val)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	return ATOMIC_OP(atom, atom->v -= val);
+#else
+	return __atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC void odp_atomic_sub_u64(odp_atomic_u64_t *atom, uint64_t val)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	(void)ATOMIC_OP(atom, atom->v -= val);
+#else
+	(void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC uint64_t odp_atomic_fetch_inc_u64(odp_atomic_u64_t *atom)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	return ATOMIC_OP(atom, atom->v++);
+#else
+	return __atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC void odp_atomic_inc_u64(odp_atomic_u64_t *atom)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	(void)ATOMIC_OP(atom, atom->v++);
+#else
+	(void)__atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC uint64_t odp_atomic_fetch_dec_u64(odp_atomic_u64_t *atom)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	return ATOMIC_OP(atom, atom->v--);
+#else
+	return __atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC void odp_atomic_dec_u64(odp_atomic_u64_t *atom)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	(void)ATOMIC_OP(atom, atom->v--);
+#else
+	(void)__atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC int odp_atomic_cas_u64(odp_atomic_u64_t *atom, uint64_t *old_val,
+			       uint64_t new_val)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	int ret;
+	*old_val = ATOMIC_OP(atom, ATOMIC_CAS_OP(&ret, *old_val, new_val));
+	return ret;
+#else
+	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
+					   0 /* strong */,
+					   __ATOMIC_RELAXED,
+					   __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC uint64_t odp_atomic_xchg_u64(odp_atomic_u64_t *atom, uint64_t new_val)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	return ATOMIC_OP(atom, atom->v = new_val);
+#else
+	return __atomic_exchange_n(&atom->v, new_val, __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC void odp_atomic_max_u64(odp_atomic_u64_t *atom, uint64_t new_max)
+{
+	uint64_t old_val;
+
+	old_val = odp_atomic_load_u64(atom);
+
+	while (new_max > old_val) {
+		if (odp_atomic_cas_u64(atom, &old_val, new_max))
+			break;
+	}
+}
+
+_STATIC void odp_atomic_min_u64(odp_atomic_u64_t *atom, uint64_t new_min)
+{
+	uint64_t old_val;
+
+	old_val = odp_atomic_load_u64(atom);
+
+	while (new_min < old_val) {
+		if (odp_atomic_cas_u64(atom, &old_val, new_min))
+			break;
+	}
+}
+
+_STATIC uint32_t odp_atomic_load_acq_u32(odp_atomic_u32_t *atom)
+{
+	return __atomic_load_n(&atom->v, __ATOMIC_ACQUIRE);
+}
+
+_STATIC void odp_atomic_store_rel_u32(odp_atomic_u32_t *atom, uint32_t val)
+{
+	__atomic_store_n(&atom->v, val, __ATOMIC_RELEASE);
+}
+
+_STATIC void odp_atomic_add_rel_u32(odp_atomic_u32_t *atom, uint32_t val)
+{
+	(void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELEASE);
+}
+
+_STATIC void odp_atomic_sub_rel_u32(odp_atomic_u32_t *atom, uint32_t val)
+{
+	(void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELEASE);
+}
+
+_STATIC int odp_atomic_cas_acq_u32(odp_atomic_u32_t *atom,
+				   uint32_t *old_val, uint32_t new_val)
+{
+	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
+					   0 /* strong */,
+					   __ATOMIC_ACQUIRE,
+					   __ATOMIC_RELAXED);
+}
+
+_STATIC int odp_atomic_cas_rel_u32(odp_atomic_u32_t *atom,
+				   uint32_t *old_val, uint32_t new_val)
+{
+	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
+					   0 /* strong */,
+					   __ATOMIC_RELEASE,
+					   __ATOMIC_RELAXED);
+}
+
+_STATIC int odp_atomic_cas_acq_rel_u32(odp_atomic_u32_t *atom,
+				       uint32_t *old_val,
+				       uint32_t new_val)
+{
+	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
+					   0 /* strong */,
+					   __ATOMIC_ACQ_REL,
+					   __ATOMIC_RELAXED);
+}
+
+_STATIC uint64_t odp_atomic_load_acq_u64(odp_atomic_u64_t *atom)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	return ATOMIC_OP(atom, (void)0);
+#else
+	return __atomic_load_n(&atom->v, __ATOMIC_ACQUIRE);
+#endif
+}
+
+_STATIC void odp_atomic_store_rel_u64(odp_atomic_u64_t *atom, uint64_t val)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	(void)ATOMIC_OP(atom, atom->v = val);
+#else
+	__atomic_store_n(&atom->v, val, __ATOMIC_RELEASE);
+#endif
+}
+
+_STATIC void odp_atomic_add_rel_u64(odp_atomic_u64_t *atom, uint64_t val)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	(void)ATOMIC_OP(atom, atom->v += val);
+#else
+	(void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELEASE);
+#endif
+}
+
+_STATIC void odp_atomic_sub_rel_u64(odp_atomic_u64_t *atom, uint64_t val)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	(void)ATOMIC_OP(atom, atom->v -= val);
+#else
+	(void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELEASE);
+#endif
+}
+
+_STATIC int odp_atomic_cas_acq_u64(odp_atomic_u64_t *atom,
+				   uint64_t *old_val, uint64_t new_val)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	int ret;
+	*old_val = ATOMIC_OP(atom, ATOMIC_CAS_OP(&ret, *old_val, new_val));
+	return ret;
+#else
+	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
+					   0 /* strong */,
+					   __ATOMIC_ACQUIRE,
+					   __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC int odp_atomic_cas_rel_u64(odp_atomic_u64_t *atom,
+				   uint64_t *old_val, uint64_t new_val)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	int ret;
+	*old_val = ATOMIC_OP(atom, ATOMIC_CAS_OP(&ret, *old_val, new_val));
+	return ret;
+#else
+	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
+					   0 /* strong */,
+					   __ATOMIC_RELEASE,
+					   __ATOMIC_RELAXED);
+#endif
+}
+
+_STATIC int odp_atomic_cas_acq_rel_u64(odp_atomic_u64_t *atom,
+				       uint64_t *old_val,
+				       uint64_t new_val)
+{
+#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
+	int ret;
+	*old_val = ATOMIC_OP(atom, ATOMIC_CAS_OP(&ret, *old_val, new_val));
+	return ret;
+#else
+	return __atomic_compare_exchange_n(&atom->v, old_val, new_val,
+					   0 /* strong */,
+					   __ATOMIC_ACQ_REL,
+					   __ATOMIC_RELAXED);
+#endif
+}
+
+#endif
diff --git a/platform/linux-generic/include/odp/api/plat/inlines.h.in b/platform/linux-generic/include/odp/api/plat/inlines.h.in
new file mode 100644
index 0000000..5d8c0dc
--- /dev/null
+++ b/platform/linux-generic/include/odp/api/plat/inlines.h.in
@@ -0,0 +1,33 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP platform inline functions
+ */
+
+#ifndef ODP_PLAT_INLINES_H_
+#define ODP_PLAT_INLINES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define @_ODP_INLINES@
+
+#ifdef _ODP_INLINES
+#define _STATIC static inline
+#else
+#define _STATIC
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* ODP_PLAT_INLINES_H_ */
diff --git a/platform/linux-generic/include/odp/api/plat/std_clib_inlines.h b/platform/linux-generic/include/odp/api/plat/std_clib_inlines.h
new file mode 100644
index 0000000..2e833e4
--- /dev/null
+++ b/platform/linux-generic/include/odp/api/plat/std_clib_inlines.h
@@ -0,0 +1,36 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef ODP_PLAT_STD_CLIB_INLINE_H_
+#define ODP_PLAT_STD_CLIB_INLINE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/api/spec/std_types.h>
+#include <string.h>
+
+_STATIC void *odp_memcpy(void *dst, const void *src, size_t num)
+{
+	return memcpy(dst, src, num);
+}
+
+_STATIC void *odp_memset(void *ptr, int value, size_t num)
+{
+	return memset(ptr, value, num);
+}
+
+_STATIC int odp_memcmp(const void *ptr1, const void *ptr2, size_t num)
+{
+	return memcmp(ptr1, ptr2, num);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/api/plat/sync_inlines.h b/platform/linux-generic/include/odp/api/plat/sync_inlines.h
new file mode 100644
index 0000000..245c750
--- /dev/null
+++ b/platform/linux-generic/include/odp/api/plat/sync_inlines.h
@@ -0,0 +1,47 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP synchronisation inlines
+ */
+
+#ifndef ODP_PLAT_SYNC_INLINE_H_
+#define ODP_PLAT_SYNC_INLINE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @ingroup odp_barrier
+ *  @{
+ */
+
+_STATIC void odp_mb_release(void)
+{
+	__atomic_thread_fence(__ATOMIC_RELEASE);
+}
+
+_STATIC void odp_mb_acquire(void)
+{
+	__atomic_thread_fence(__ATOMIC_ACQUIRE);
+}
+
+_STATIC void odp_mb_full(void)
+{
+	__atomic_thread_fence(__ATOMIC_SEQ_CST);
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/api/std_clib.h b/platform/linux-generic/include/odp/api/std_clib.h
index 40c0ea8..c498f68 100644
--- a/platform/linux-generic/include/odp/api/std_clib.h
+++ b/platform/linux-generic/include/odp/api/std_clib.h
@@ -14,20 +14,12 @@  extern "C" {
 #include <odp/api/spec/std_types.h>
 #include <string.h>
 
-static inline void *odp_memcpy(void *dst, const void *src, size_t num)
-{
-	return memcpy(dst, src, num);
-}
-
-static inline void *odp_memset(void *ptr, int value, size_t num)
-{
-	return memset(ptr, value, num);
-}
+#include <odp/api/plat/inlines.h>
+#ifdef _ODP_INLINES
+#include <odp/api/plat/std_clib_inlines.h>
+#endif
 
-static inline int odp_memcmp(const void *ptr1, const void *ptr2, size_t num)
-{
-	return memcmp(ptr1, ptr2, num);
-}
+#include <odp/api/spec/std_clib.h>
 
 #ifdef __cplusplus
 }
diff --git a/platform/linux-generic/include/odp/api/sync.h b/platform/linux-generic/include/odp/api/sync.h
index 45fe6bd..d2becb9 100644
--- a/platform/linux-generic/include/odp/api/sync.h
+++ b/platform/linux-generic/include/odp/api/sync.h
@@ -21,20 +21,10 @@  extern "C" {
  *  @{
  */
 
-static inline void odp_mb_release(void)
-{
-	__atomic_thread_fence(__ATOMIC_RELEASE);
-}
-
-static inline void odp_mb_acquire(void)
-{
-	__atomic_thread_fence(__ATOMIC_ACQUIRE);
-}
-
-static inline void odp_mb_full(void)
-{
-	__atomic_thread_fence(__ATOMIC_SEQ_CST);
-}
+#include <odp/api/plat/inlines.h>
+#ifdef _ODP_INLINES
+#include <odp/api/plat/sync_inlines.h>
+#endif
 
 /**
  * @}
diff --git a/platform/linux-generic/m4/configure.m4 b/platform/linux-generic/m4/configure.m4
index 1b1b883..6fb05c0 100644
--- a/platform/linux-generic/m4/configure.m4
+++ b/platform/linux-generic/m4/configure.m4
@@ -36,4 +36,5 @@  m4_include([platform/linux-generic/m4/odp_dpdk.m4])
 m4_include([platform/linux-generic/m4/odp_ipc.m4])
 m4_include([platform/linux-generic/m4/odp_schedule.m4])
 
-AC_CONFIG_FILES([platform/linux-generic/Makefile])
+AC_CONFIG_FILES([platform/linux-generic/Makefile
+		 platform/linux-generic/include/odp/api/plat/inlines.h])
diff --git a/platform/linux-generic/odp_atomic.c b/platform/linux-generic/odp_atomic.c
index 680e66d..e9a3ed0 100644
--- a/platform/linux-generic/odp_atomic.c
+++ b/platform/linux-generic/odp_atomic.c
@@ -5,6 +5,9 @@ 
  */
 
 #include <odp/api/atomic.h>
+#ifndef _ODP_INLINES
+#include <odp/api/plat/atomic_inlines.h>
+#endif
 
 int odp_atomic_lock_free_u64(odp_atomic_op_t *atomic_op)
 {
diff --git a/platform/linux-generic/odp_std_clib.c b/platform/linux-generic/odp_std_clib.c
new file mode 100644
index 0000000..7d360af
--- /dev/null
+++ b/platform/linux-generic/odp_std_clib.c
@@ -0,0 +1,11 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp/api/std_clib.h>
+#ifndef _ODP_INLINES
+#include <odp/api/plat/std_clib_inlines.h>
+#endif
+
diff --git a/platform/linux-generic/odp_sync.c b/platform/linux-generic/odp_sync.c
new file mode 100644
index 0000000..5b99d2d
--- /dev/null
+++ b/platform/linux-generic/odp_sync.c
@@ -0,0 +1,11 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp/api/sync.h>
+#ifndef _ODP_INLINES
+#include <odp/api/plat/sync_inlines.h>
+#endif
+