diff --git a/include/Makefile.am b/include/Makefile.am
index c3452ef33..aa330b8d4 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -96,6 +96,7 @@ odpapispecinclude_HEADERS = \
 		  odp/api/spec/sync.h \
 		  odp/api/spec/system_info.h \
 		  odp/api/spec/thread.h \
+		  odp/api/spec/thread_types.h \
 		  odp/api/spec/threshold.h \
 		  odp/api/spec/thrmask.h \
 		  odp/api/spec/ticketlock.h \
diff --git a/include/odp/api/cpu.h b/include/odp/api/cpu.h
index 7229857a5..41c21b8a6 100644
--- a/include/odp/api/cpu.h
+++ b/include/odp/api/cpu.h
@@ -19,6 +19,8 @@ extern "C" {
 
 #include <odp/api/abi/cpu.h>
 
+/* Thread inline file implements cpu API function */
+#include <odp/api/thread.h>
 #include <odp/api/spec/cpu.h>
 
 #ifdef __cplusplus
diff --git a/include/odp/api/spec/thread.h b/include/odp/api/spec/thread.h
index 5fe74c69d..125e7a117 100644
--- a/include/odp/api/spec/thread.h
+++ b/include/odp/api/spec/thread.h
@@ -30,34 +30,6 @@ extern "C" {
  * which depend on system configuration and may be lower than this number.
  */
 
-/**
- * Thread type
- */
-typedef enum odp_thread_type_e {
-	/**
-	 * Worker thread
-	 *
-	 * Worker threads do most part of ODP application packet processing.
-	 * These threads provide high packet and data rates, with low and
-	 * predictable latency. Typically, worker threads are pinned to isolated
-	 * CPUs and packets are processed in a run-to-completion loop with very
-	 * low interference from the operating system.
-	 */
-	ODP_THREAD_WORKER = 0,
-
-	/**
-	 * Control thread
-	 *
-	 * Control threads do not participate the main packet flow through the
-	 * system, but e.g. control or monitor the worker threads, or handle
-	 * exceptions. These threads may perform general purpose processing,
-	 * use system calls, share the CPU with other threads and be interrupt
-	 * driven.
-	 */
-	ODP_THREAD_CONTROL
-} odp_thread_type_t;
-
-
 /**
  * Get thread identifier
  *
diff --git a/include/odp/api/spec/thread_types.h b/include/odp/api/spec/thread_types.h
new file mode 100644
index 000000000..a5ddb78ea
--- /dev/null
+++ b/include/odp/api/spec/thread_types.h
@@ -0,0 +1,59 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP thread API types
+ */
+
+#ifndef ODP_API_SPEC_THREAD_TYPES_H_
+#define ODP_API_SPEC_THREAD_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @ingroup odp_thread ODP THREAD
+ *  @{
+ */
+
+/**
+ * Thread type
+ */
+typedef enum odp_thread_type_e {
+	/**
+	 * Worker thread
+	 *
+	 * Worker threads do most part of ODP application packet processing.
+	 * These threads provide high packet and data rates, with low and
+	 * predictable latency. Typically, worker threads are pinned to isolated
+	 * CPUs and packets are processed in a run-to-completion loop with very
+	 * low interference from the operating system.
+	 */
+	ODP_THREAD_WORKER = 0,
+
+	/**
+	 * Control thread
+	 *
+	 * Control threads do not participate the main packet flow through the
+	 * system, but e.g. control or monitor the worker threads, or handle
+	 * exceptions. These threads may perform general purpose processing,
+	 * use system calls, share the CPU with other threads and be interrupt
+	 * driven.
+	 */
+	ODP_THREAD_CONTROL
+} odp_thread_type_t;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/odp/api/thread.h b/include/odp/api/thread.h
index 85af314be..d11c1671a 100644
--- a/include/odp/api/thread.h
+++ b/include/odp/api/thread.h
@@ -17,6 +17,8 @@
 extern "C" {
 #endif
 
+#include <odp/api/spec/thread_types.h>
+
 #include <odp/api/abi/thread.h>
 
 #include <odp/api/spec/thread.h>
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index da5540fed..a1cfc6976 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -34,6 +34,8 @@ odpapiplatinclude_HEADERS = \
 		  include/odp/api/plat/std_clib_inlines.h \
 		  include/odp/api/plat/strong_types.h \
 		  include/odp/api/plat/sync_inlines.h \
+		  include/odp/api/plat/thread_inlines.h \
+		  include/odp/api/plat/thread_inlines_api.h \
 		  include/odp/api/plat/ticketlock_inlines.h \
 		  include/odp/api/plat/ticketlock_inlines_api.h
 
@@ -206,6 +208,7 @@ __LIB__libodp_linux_la_SOURCES += \
 			   odp_packet_flags_api.c \
 			   odp_std_clib.c \
 			   odp_sync.c \
+			   odp_thread_api.c \
 			   odp_ticketlock.c
 endif
 
diff --git a/platform/linux-generic/include-abi/odp/api/abi/thread.h b/platform/linux-generic/include-abi/odp/api/abi/thread.h
index dc29a7dac..eb92d43c4 100644
--- a/platform/linux-generic/include-abi/odp/api/abi/thread.h
+++ b/platform/linux-generic/include-abi/odp/api/abi/thread.h
@@ -5,3 +5,7 @@
  */
 
 #include <odp/api/abi-default/thread.h>
+
+#define _ODP_INLINE static inline
+#include <odp/api/plat/thread_inlines.h>
+#include <odp/api/plat/thread_inlines_api.h>
diff --git a/platform/linux-generic/include/odp/api/plat/thread_inlines.h b/platform/linux-generic/include/odp/api/plat/thread_inlines.h
new file mode 100644
index 000000000..048df50bb
--- /dev/null
+++ b/platform/linux-generic/include/odp/api/plat/thread_inlines.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef ODP_PLAT_THREAD_INLINES_H_
+#define ODP_PLAT_THREAD_INLINES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond _ODP_HIDE_FROM_DOXYGEN_ */
+
+typedef struct {
+	int thr;
+	int cpu;
+	odp_thread_type_t type;
+
+} _odp_thread_state_t;
+
+extern __thread _odp_thread_state_t *_odp_this_thread;
+
+static inline int _odp_thread_id(void)
+{
+	return _odp_this_thread->thr;
+}
+
+static inline odp_thread_type_t _odp_thread_type(void)
+{
+	return _odp_this_thread->type;
+}
+
+static inline int _odp_cpu_id(void)
+{
+	return _odp_this_thread->cpu;
+}
+
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/api/plat/thread_inlines_api.h b/platform/linux-generic/include/odp/api/plat/thread_inlines_api.h
new file mode 100644
index 000000000..1c282a5cf
--- /dev/null
+++ b/platform/linux-generic/include/odp/api/plat/thread_inlines_api.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ */
+
+#ifndef ODP_PLAT_THREAD_INLINES_API_H_
+#define ODP_PLAT_THREAD_INLINES_API_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_ODP_INLINE int odp_thread_id(void)
+{
+	return _odp_thread_id();
+}
+
+_ODP_INLINE odp_thread_type_t odp_thread_type(void)
+{
+	return _odp_thread_type();
+}
+
+_ODP_INLINE int odp_cpu_id(void)
+{
+	return _odp_cpu_id();
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/odp_thread.c b/platform/linux-generic/odp_thread.c
index ffc247a4b..971837b00 100644
--- a/platform/linux-generic/odp_thread.c
+++ b/platform/linux-generic/odp_thread.c
@@ -19,20 +19,14 @@
 #include <odp/api/align.h>
 #include <odp/api/cpu.h>
 #include <odp_schedule_if.h>
+#include <odp/api/plat/thread_inlines.h>
 
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 typedef struct {
-	int thr;
-	int cpu;
-	odp_thread_type_t type;
-} thread_state_t;
-
-
-typedef struct {
-	thread_state_t thr[ODP_THREAD_COUNT_MAX];
+	_odp_thread_state_t thr[ODP_THREAD_COUNT_MAX];
 
 	struct {
 		odp_thrmask_t  all;
@@ -46,14 +40,15 @@ typedef struct {
 	odp_spinlock_t lock;
 } thread_globals_t;
 
-
 /* Globals */
 static thread_globals_t *thread_globals;
 
+#include <odp/visibility_begin.h>
 
 /* Thread local */
-static __thread thread_state_t *this_thread;
+__thread _odp_thread_state_t *_odp_this_thread;
 
+#include <odp/visibility_end.h>
 
 int odp_thread_init_global(void)
 {
@@ -162,7 +157,7 @@ int odp_thread_init_local(odp_thread_type_t type)
 	thread_globals->thr[id].cpu  = cpu;
 	thread_globals->thr[id].type = type;
 
-	this_thread = &thread_globals->thr[id];
+	_odp_this_thread = &thread_globals->thr[id];
 
 	sched_fn->thr_add(ODP_SCHED_GROUP_ALL, id);
 
@@ -177,8 +172,8 @@ int odp_thread_init_local(odp_thread_type_t type)
 int odp_thread_term_local(void)
 {
 	int num;
-	int id = this_thread->thr;
-	odp_thread_type_t type = this_thread->type;
+	int id = _odp_this_thread->thr;
+	odp_thread_type_t type = _odp_this_thread->type;
 
 	sched_fn->thr_rem(ODP_SCHED_GROUP_ALL, id);
 
@@ -199,11 +194,6 @@ int odp_thread_term_local(void)
 	return num; /* return a number of threads left */
 }
 
-int odp_thread_id(void)
-{
-	return this_thread->thr;
-}
-
 int odp_thread_count(void)
 {
 	return thread_globals->num;
@@ -214,16 +204,6 @@ int odp_thread_count_max(void)
 	return ODP_THREAD_COUNT_MAX;
 }
 
-odp_thread_type_t odp_thread_type(void)
-{
-	return this_thread->type;
-}
-
-int odp_cpu_id(void)
-{
-	return this_thread->cpu;
-}
-
 int odp_thrmask_worker(odp_thrmask_t *mask)
 {
 	odp_thrmask_copy(mask, &thread_globals->worker);
diff --git a/platform/linux-generic/odp_thread_api.c b/platform/linux-generic/odp_thread_api.c
new file mode 100644
index 000000000..ee5beb162
--- /dev/null
+++ b/platform/linux-generic/odp_thread_api.c
@@ -0,0 +1,15 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include "config.h"
+
+#include <odp/api/thread.h>
+#include <odp/api/cpu.h>
+#include <odp/api/plat/thread_inlines.h>
+
+/* Include non-inlined versions of API functions */
+#define _ODP_INLINE
+#include <odp/api/plat/thread_inlines_api.h>
