blob: ee1fe24687162c28a7e7dbf72c1b40a0fabea2b5 [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//===----------------------------------------------------------------------===//
9//
10// This file defines macros for working around the lack of support for
11// thread_local in MacOS 10.6. It assumes std::thread is written in
12// terms of pthread. Define ICE_THREAD_LOCAL_HACK to enable the
13// pthread workarounds.
14//
15//===----------------------------------------------------------------------===//
16
17#ifndef SUBZERO_SRC_ICETLS_H
18#define SUBZERO_SRC_ICETLS_H
19
20#if defined(_MSC_VER)
21#define ICE_ATTRIBUTE_TLS __declspec(thread)
22#else // !_MSC_VER
23#define ICE_ATTRIBUTE_TLS thread_local
24#endif // !_MSC_VER
25
26// Defines 4 macros for unifying thread_local and pthread:
27//
28// ICE_TLS_DECLARE_FIELD(Type, FieldName): Declare a static
29// thread_local field inside the current class definition. "Type"
30// needs to be a pointer type, such as int* or class Foo*.
31//
32// ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName): Define a static
33// thread_local field outside of its class definition. The field will
34// ultimately be initialized to nullptr.
35//
36// ICE_TLS_INIT_FIELD(FieldName): Ensure the thread_local field is
37// properly initialized. This is intended to be called from within a
38// static method of the field's class after main() starts (to ensure
39// that the pthread library is fully initialized) but before any uses
40// of ICE_TLS_GET_FIELD or ICE_TLS_SET_FIELD.
41//
42// ICE_TLS_GET_FIELD(Type, FieldName): Read the value of the static
43// thread_local field. Must be done within the context of its class.
44//
45// ICE_TLS_SET_FIELD(FieldName, Value): Write a value into the static
46// thread_local field. Must be done within the context of its class.
47
48// TODO(stichnot): Limit this define to only the platforms that
49// absolutely require it. And ideally, eventually remove this hack
50// altogether.
51#define ICE_THREAD_LOCAL_HACK
52#ifdef ICE_THREAD_LOCAL_HACK
53
54// For a static thread_local field F of a class C, instead of
55// declaring and defining C::F, we create two static fields:
56// static pthread_key_t F__key;
57// static int F__initStatus;
58//
59// The F__initStatus field is used to hold the result of the
60// pthread_key_create() call, where a zero value indicates success,
61// and a nonzero value indicates failure or that ICE_TLS_INIT_FIELD()
62// was never called.
63// The F__key field is used as the argument to
64// pthread_getspecific() and pthread_setspecific().
65
66#include <pthread.h>
67
68#define ICE_TLS_DECLARE_FIELD(Type, FieldName) \
69 typedef Type FieldName##__type; \
70 static pthread_key_t FieldName##__key; \
71 static int FieldName##__initStatus
72#define ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName) \
73 pthread_key_t ClassName::FieldName##__key; \
JF Bastien8427ea22015-01-27 12:56:49 -080074 int ClassName::FieldName##__initStatus = 1
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080075#define ICE_TLS_INIT_FIELD(FieldName) \
76 if (FieldName##__initStatus) { \
77 FieldName##__initStatus = pthread_key_create(&FieldName##__key, nullptr); \
78 if (FieldName##__initStatus) \
79 llvm::report_fatal_error("Failed to create pthread key"); \
80 }
81#define ICE_TLS_GET_FIELD(FieldName) \
82 (assert(FieldName##__initStatus == 0), \
83 static_cast<FieldName##__type>(pthread_getspecific(FieldName##__key)))
84#define ICE_TLS_SET_FIELD(FieldName, Value) \
85 (assert(FieldName##__initStatus == 0), \
86 pthread_setspecific(FieldName##__key, (Value)))
87
88#else // !ICE_THREAD_LOCAL_HACK
89
90#define ICE_TLS_DECLARE_FIELD(Type, FieldName) \
91 static ICE_ATTRIBUTE_TLS Type FieldName
92#define ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName) \
93 ICE_ATTRIBUTE_TLS Type ClassName::FieldName = nullptr
94#define ICE_TLS_INIT_FIELD(FieldName)
95#define ICE_TLS_GET_FIELD(FieldName) (FieldName)
96#define ICE_TLS_SET_FIELD(FieldName, Value) (FieldName = (Value))
97
98#endif // !ICE_THREAD_LOCAL_HACK
99
100#endif // SUBZERO_SRC_ICETLS_H