blob: dabae0d2b3e18bc9e9e2335e67c837eaf466ffe3 [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
11/// This file defines macros for working around the lack of support for
Andrew Scull57e12682015-09-16 11:30:19 -070012/// thread_local in MacOS 10.6. It assumes std::thread is written in terms of
13/// pthread. Define ICE_THREAD_LOCAL_HACK to enable the pthread workarounds.
Andrew Scull9612d322015-07-06 14:53:25 -070014///
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080015//===----------------------------------------------------------------------===//
16
17#ifndef SUBZERO_SRC_ICETLS_H
18#define SUBZERO_SRC_ICETLS_H
19
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080020
Reed Kotleraf5d44c2015-11-09 16:52:56 -080021///
22/// @defgroup /IceTLS Defines 5 macros for unifying thread_local and pthread:
23/// @{
24///
25/// \def ICE_TLS_DECLARE_FIELD(Type, FieldName)
26/// Declare a static thread_local field inside the current class definition.
27/// "Type" needs to be a pointer type, such as int* or class Foo*.
28///
29/// \def ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName)
30/// Define a static thread_local field outside of its class definition. The
31/// field will ultimately be initialized to nullptr.
32///
33/// \def ICE_TLS_INIT_FIELD(FieldName)
34/// Ensure the thread_local field is properly initialized. This is intended
35/// to be called from within a static method of the field's class after main()
36/// starts (to ensure that the pthread library is fully initialized) but before
37/// any uses of ICE_TLS_GET_FIELD or ICE_TLS_SET_FIELD.
38///
39/// \def ICE_TLS_GET_FIELD(Type, FieldName)
40/// Read the value of the static thread_local field. Must be done within the
41/// context of its class.
42///
43/// \def ICE_TLS_SET_FIELD(FieldName, Value)
44/// Write a value into the static thread_local field. Must be done within the
45/// context of its class.
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080046
Reed Kotleraf5d44c2015-11-09 16:52:56 -080047/// \todo TODO(stichnot)
48/// Limit this define to only the platforms that absolutely require it. And
49/// ideally, eventually remove this hack altogether.
50///
51
52///
53/// \def ICE_THREAD_LOCAL_HACK
54///
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080055#define ICE_THREAD_LOCAL_HACK
56#ifdef ICE_THREAD_LOCAL_HACK
57
Andrew Scull57e12682015-09-16 11:30:19 -070058// For a static thread_local field F of a class C, instead of declaring and
59// defining C::F, we create two static fields:
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080060// static pthread_key_t F__key;
61// static int F__initStatus;
62//
63// The F__initStatus field is used to hold the result of the
Andrew Scull57e12682015-09-16 11:30:19 -070064// pthread_key_create() call, where a zero value indicates success, and a
65// nonzero value indicates failure or that ICE_TLS_INIT_FIELD() was never
66// called. The F__key field is used as the argument to pthread_getspecific()
67// and pthread_setspecific().
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080068
69#include <pthread.h>
70
71#define ICE_TLS_DECLARE_FIELD(Type, FieldName) \
Andrew Scull8072bae2015-09-14 16:01:26 -070072 using FieldName##__type = Type; \
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080073 static pthread_key_t FieldName##__key; \
74 static int FieldName##__initStatus
75#define ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName) \
76 pthread_key_t ClassName::FieldName##__key; \
JF Bastien8427ea22015-01-27 12:56:49 -080077 int ClassName::FieldName##__initStatus = 1
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080078#define ICE_TLS_INIT_FIELD(FieldName) \
79 if (FieldName##__initStatus) { \
80 FieldName##__initStatus = pthread_key_create(&FieldName##__key, nullptr); \
81 if (FieldName##__initStatus) \
82 llvm::report_fatal_error("Failed to create pthread key"); \
83 }
84#define ICE_TLS_GET_FIELD(FieldName) \
85 (assert(FieldName##__initStatus == 0), \
86 static_cast<FieldName##__type>(pthread_getspecific(FieldName##__key)))
87#define ICE_TLS_SET_FIELD(FieldName, Value) \
88 (assert(FieldName##__initStatus == 0), \
89 pthread_setspecific(FieldName##__key, (Value)))
90
91#else // !ICE_THREAD_LOCAL_HACK
92
Reed Kotleraf5d44c2015-11-09 16:52:56 -080093#if defined(_MSC_VER)
94#define ICE_ATTRIBUTE_TLS __declspec(thread)
95#else // !_MSC_VER
96#define ICE_ATTRIBUTE_TLS thread_local
97#endif // !_MSC_VER
98
99
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800100#define ICE_TLS_DECLARE_FIELD(Type, FieldName) \
101 static ICE_ATTRIBUTE_TLS Type FieldName
102#define ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName) \
103 ICE_ATTRIBUTE_TLS Type ClassName::FieldName = nullptr
104#define ICE_TLS_INIT_FIELD(FieldName)
105#define ICE_TLS_GET_FIELD(FieldName) (FieldName)
106#define ICE_TLS_SET_FIELD(FieldName, Value) (FieldName = (Value))
107
108#endif // !ICE_THREAD_LOCAL_HACK
109
Reed Kotleraf5d44c2015-11-09 16:52:56 -0800110///
111/// @}
112///
113
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800114#endif // SUBZERO_SRC_ICETLS_H