summaryrefslogtreecommitdiff
path: root/lib/ovs-thread.h
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2013-08-06 14:40:25 -0700
committerBen Pfaff <blp@nicira.com>2013-08-08 13:18:10 -0700
commit2ba4f163d9ea84aa8b8e9d8678371a70af766b5e (patch)
tree5a68d5749381779a32216618b2c8974b603c13f4 /lib/ovs-thread.h
parent9c4c45edc36b88bcb2956140965dbde9224ff967 (diff)
downloadopenvswitch-2ba4f163d9ea84aa8b8e9d8678371a70af766b5e.tar.gz
ovs-thread: Add support for globally visible per-thread data.
DEFINE_PER_THREAD_DATA always declared its data item as "static", meaning that it was only directly visible within a single translation unit. This commit adds additional forms of per-thread data that allow the data to be accessible from multiple translation units. Signed-off-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'lib/ovs-thread.h')
-rw-r--r--lib/ovs-thread.h94
1 files changed, 78 insertions, 16 deletions
diff --git a/lib/ovs-thread.h b/lib/ovs-thread.h
index 0d54a43fb..abe479ae6 100644
--- a/lib/ovs-thread.h
+++ b/lib/ovs-thread.h
@@ -193,7 +193,15 @@ void xpthread_create(pthread_t *, pthread_attr_t *, void *(*)(void *), void *);
* cross-thread access? yes no yes
*/
-/* DEFINE_PER_THREAD_DATA(TYPE, NAME, INITIALIZER).
+/* For static data, use this macro in a source file:
+ *
+ * DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, INITIALIZER).
+ *
+ * For global data, "declare" the data in the header and "define" it in
+ * the source file, with:
+ *
+ * DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME).
+ * DEFINE_EXTERN_PER_THREAD_DATA(NAME, INITIALIZER).
*
* One should prefer to use POSIX per-thread data, via pthread_key_t, when its
* performance is acceptable, because of its portability (see the table above).
@@ -231,23 +239,40 @@ void xpthread_create(pthread_t *, pthread_attr_t *, void *(*)(void *), void *);
#error
#endif
-#define DEFINE_PER_THREAD_DATA(TYPE, NAME, ...) \
- typedef TYPE NAME##_type; \
- static thread_local NAME##_type NAME##_var = __VA_ARGS__; \
- \
- static NAME##_type * \
- NAME##_get_unsafe(void) \
- { \
- return &NAME##_var; \
- } \
- \
- static NAME##_type * \
- NAME##_get(void) \
- { \
- return NAME##_get_unsafe(); \
+#define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...) \
+ typedef TYPE NAME##_type; \
+ \
+ static NAME##_type * \
+ NAME##_get_unsafe(void) \
+ { \
+ static thread_local NAME##_type var = __VA_ARGS__; \
+ return &var; \
+ } \
+ \
+ static NAME##_type * \
+ NAME##_get(void) \
+ { \
+ return NAME##_get_unsafe(); \
}
+#define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME) \
+ typedef TYPE NAME##_type; \
+ extern thread_local NAME##_type NAME##_var; \
+ \
+ static inline NAME##_type * \
+ NAME##_get_unsafe(void) \
+ { \
+ return &NAME##_var; \
+ } \
+ \
+ static inline NAME##_type * \
+ NAME##_get(void) \
+ { \
+ return NAME##_get_unsafe(); \
+ }
+#define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...) \
+ thread_local NAME##_type NAME##_var = __VA_ARGS__;
#else /* no C implementation support for thread-local storage */
-#define DEFINE_PER_THREAD_DATA(TYPE, NAME, ...) \
+#define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...) \
typedef TYPE NAME##_type; \
static pthread_key_t NAME##_key; \
\
@@ -282,6 +307,43 @@ void xpthread_create(pthread_t *, pthread_attr_t *, void *(*)(void *), void *);
} \
return value; \
}
+#define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME) \
+ typedef TYPE NAME##_type; \
+ static pthread_key_t NAME##_key; \
+ \
+ static inline NAME##_type * \
+ NAME##_get_unsafe(void) \
+ { \
+ return pthread_getspecific(NAME##_key); \
+ } \
+ \
+ NAME##_type *NAME##_get(void);
+#define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...) \
+ static void \
+ NAME##_once_init(void) \
+ { \
+ if (pthread_key_create(&NAME##_key, free)) { \
+ abort(); \
+ } \
+ } \
+ \
+ NAME##_type * \
+ NAME##_get(void) \
+ { \
+ static pthread_once_t once = PTHREAD_ONCE_INIT; \
+ NAME##_type *value; \
+ \
+ pthread_once(&once, NAME##_once_init); \
+ value = NAME##_get_unsafe(); \
+ if (!value) { \
+ static const NAME##_type initial_value = __VA_ARGS__; \
+ \
+ value = xmalloc(sizeof *value); \
+ *value = initial_value; \
+ xpthread_setspecific(NAME##_key, value); \
+ } \
+ return value; \
+ }
#endif
/* DEFINE_PER_THREAD_MALLOCED_DATA(TYPE, NAME).