blob: 947ae520c19880b4af9ab42229ec6cb6715687c9 [file] [log] [blame]
Jim Stichnotha5fe17a2015-01-26 11:10:03 -08001//===- subzero/src/IceTLS.h - thread_local workaround -----------*- C++ -*-===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Defines macros for working around the lack of support for
12/// thread_local in MacOS 10.6.
13///
14/// This assumes std::thread is written in terms of pthread. Define
15/// ICE_THREAD_LOCAL_HACK to enable the pthread workarounds.
Andrew Scull9612d322015-07-06 14:53:25 -070016///
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080017//===----------------------------------------------------------------------===//
18
19#ifndef SUBZERO_SRC_ICETLS_H
20#define SUBZERO_SRC_ICETLS_H
21
Reed Kotleraf5d44c2015-11-09 16:52:56 -080022///
23/// @defgroup /IceTLS Defines 5 macros for unifying thread_local and pthread:
24/// @{
25///
26/// \def ICE_TLS_DECLARE_FIELD(Type, FieldName)
27/// Declare a static thread_local field inside the current class definition.
28/// "Type" needs to be a pointer type, such as int* or class Foo*.
29///
30/// \def ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName)
31/// Define a static thread_local field outside of its class definition. The
32/// field will ultimately be initialized to nullptr.
33///
34/// \def ICE_TLS_INIT_FIELD(FieldName)
35/// Ensure the thread_local field is properly initialized. This is intended
36/// to be called from within a static method of the field's class after main()
37/// starts (to ensure that the pthread library is fully initialized) but before
38/// any uses of ICE_TLS_GET_FIELD or ICE_TLS_SET_FIELD.
39///
40/// \def ICE_TLS_GET_FIELD(Type, FieldName)
41/// Read the value of the static thread_local field. Must be done within the
42/// context of its class.
43///
44/// \def ICE_TLS_SET_FIELD(FieldName, Value)
45/// Write a value into the static thread_local field. Must be done within the
46/// context of its class.
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080047
Jim Stichnothd880f0e2015-12-07 08:37:25 -080048/// TODO(stichnot): Limit this define to only the platforms that absolutely
49/// require it. And ideally, eventually remove this hack altogether.
Reed Kotleraf5d44c2015-11-09 16:52:56 -080050///
51
52///
53/// \def ICE_THREAD_LOCAL_HACK
54///
Nicolas Capensdbd600d2016-09-01 16:53:49 -040055#ifndef ICE_THREAD_LOCAL_HACK
56#define ICE_THREAD_LOCAL_HACK 1
57#endif
58
59#if ICE_THREAD_LOCAL_HACK
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080060
Andrew Scull57e12682015-09-16 11:30:19 -070061// For a static thread_local field F of a class C, instead of declaring and
62// defining C::F, we create two static fields:
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080063// static pthread_key_t F__key;
64// static int F__initStatus;
65//
66// The F__initStatus field is used to hold the result of the
Andrew Scull57e12682015-09-16 11:30:19 -070067// pthread_key_create() call, where a zero value indicates success, and a
68// nonzero value indicates failure or that ICE_TLS_INIT_FIELD() was never
69// called. The F__key field is used as the argument to pthread_getspecific()
70// and pthread_setspecific().
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080071
John Portoe82b5602016-02-24 15:58:55 -080072#include "llvm/Support/ErrorHandling.h"
73
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080074#include <pthread.h>
75
76#define ICE_TLS_DECLARE_FIELD(Type, FieldName) \
Andrew Scull8072bae2015-09-14 16:01:26 -070077 using FieldName##__type = Type; \
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080078 static pthread_key_t FieldName##__key; \
79 static int FieldName##__initStatus
80#define ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName) \
81 pthread_key_t ClassName::FieldName##__key; \
JF Bastien8427ea22015-01-27 12:56:49 -080082 int ClassName::FieldName##__initStatus = 1
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080083#define ICE_TLS_INIT_FIELD(FieldName) \
84 if (FieldName##__initStatus) { \
85 FieldName##__initStatus = pthread_key_create(&FieldName##__key, nullptr); \
86 if (FieldName##__initStatus) \
87 llvm::report_fatal_error("Failed to create pthread key"); \
88 }
89#define ICE_TLS_GET_FIELD(FieldName) \
90 (assert(FieldName##__initStatus == 0), \
91 static_cast<FieldName##__type>(pthread_getspecific(FieldName##__key)))
92#define ICE_TLS_SET_FIELD(FieldName, Value) \
93 (assert(FieldName##__initStatus == 0), \
94 pthread_setspecific(FieldName##__key, (Value)))
95
96#else // !ICE_THREAD_LOCAL_HACK
97
Reed Kotleraf5d44c2015-11-09 16:52:56 -080098#if defined(_MSC_VER)
99#define ICE_ATTRIBUTE_TLS __declspec(thread)
100#else // !_MSC_VER
101#define ICE_ATTRIBUTE_TLS thread_local
102#endif // !_MSC_VER
103
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800104#define ICE_TLS_DECLARE_FIELD(Type, FieldName) \
105 static ICE_ATTRIBUTE_TLS Type FieldName
106#define ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName) \
107 ICE_ATTRIBUTE_TLS Type ClassName::FieldName = nullptr
108#define ICE_TLS_INIT_FIELD(FieldName)
109#define ICE_TLS_GET_FIELD(FieldName) (FieldName)
110#define ICE_TLS_SET_FIELD(FieldName, Value) (FieldName = (Value))
111
112#endif // !ICE_THREAD_LOCAL_HACK
113
Reed Kotleraf5d44c2015-11-09 16:52:56 -0800114///
115/// @}
116///
117
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800118#endif // SUBZERO_SRC_ICETLS_H