xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceTLS.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceTLS.h - thread_local workaround -----------*- C++ -*-===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker //                        The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Defines macros for working around the lack of support for
12*03ce13f7SAndroid Build Coastguard Worker /// thread_local in MacOS 10.6.
13*03ce13f7SAndroid Build Coastguard Worker ///
14*03ce13f7SAndroid Build Coastguard Worker /// This assumes std::thread is written in terms of pthread. Define
15*03ce13f7SAndroid Build Coastguard Worker /// ICE_THREAD_LOCAL_HACK to enable the pthread workarounds.
16*03ce13f7SAndroid Build Coastguard Worker ///
17*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
18*03ce13f7SAndroid Build Coastguard Worker 
19*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICETLS_H
20*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICETLS_H
21*03ce13f7SAndroid Build Coastguard Worker 
22*03ce13f7SAndroid Build Coastguard Worker ///
23*03ce13f7SAndroid Build Coastguard Worker /// @defgroup /IceTLS Defines 5 macros for unifying thread_local and pthread:
24*03ce13f7SAndroid Build Coastguard Worker /// @{
25*03ce13f7SAndroid Build Coastguard Worker ///
26*03ce13f7SAndroid Build Coastguard Worker /// \def ICE_TLS_DECLARE_FIELD(Type, FieldName)
27*03ce13f7SAndroid Build Coastguard Worker /// Declare a static thread_local field inside the current class definition.
28*03ce13f7SAndroid Build Coastguard Worker /// "Type" needs to be a pointer type, such as int* or class Foo*.
29*03ce13f7SAndroid Build Coastguard Worker ///
30*03ce13f7SAndroid Build Coastguard Worker /// \def ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName)
31*03ce13f7SAndroid Build Coastguard Worker /// Define a static thread_local field outside of its class definition. The
32*03ce13f7SAndroid Build Coastguard Worker /// field will ultimately be initialized to nullptr.
33*03ce13f7SAndroid Build Coastguard Worker ///
34*03ce13f7SAndroid Build Coastguard Worker /// \def ICE_TLS_INIT_FIELD(FieldName)
35*03ce13f7SAndroid Build Coastguard Worker /// Ensure the thread_local field is properly initialized. This is intended
36*03ce13f7SAndroid Build Coastguard Worker /// to be called from within a static method of the field's class after main()
37*03ce13f7SAndroid Build Coastguard Worker /// starts (to ensure that the pthread library is fully initialized) but before
38*03ce13f7SAndroid Build Coastguard Worker /// any uses of ICE_TLS_GET_FIELD or ICE_TLS_SET_FIELD.
39*03ce13f7SAndroid Build Coastguard Worker ///
40*03ce13f7SAndroid Build Coastguard Worker /// \def ICE_TLS_GET_FIELD(Type, FieldName)
41*03ce13f7SAndroid Build Coastguard Worker /// Read the value of the static thread_local field. Must be done within the
42*03ce13f7SAndroid Build Coastguard Worker /// context of its class.
43*03ce13f7SAndroid Build Coastguard Worker ///
44*03ce13f7SAndroid Build Coastguard Worker /// \def ICE_TLS_SET_FIELD(FieldName, Value)
45*03ce13f7SAndroid Build Coastguard Worker /// Write a value into the static thread_local field. Must be done within the
46*03ce13f7SAndroid Build Coastguard Worker /// context of its class.
47*03ce13f7SAndroid Build Coastguard Worker 
48*03ce13f7SAndroid Build Coastguard Worker /// TODO(stichnot): Limit this define to only the platforms that absolutely
49*03ce13f7SAndroid Build Coastguard Worker /// require it. And ideally, eventually remove this hack altogether.
50*03ce13f7SAndroid Build Coastguard Worker ///
51*03ce13f7SAndroid Build Coastguard Worker 
52*03ce13f7SAndroid Build Coastguard Worker ///
53*03ce13f7SAndroid Build Coastguard Worker /// \def ICE_THREAD_LOCAL_HACK
54*03ce13f7SAndroid Build Coastguard Worker ///
55*03ce13f7SAndroid Build Coastguard Worker #ifndef ICE_THREAD_LOCAL_HACK
56*03ce13f7SAndroid Build Coastguard Worker #define ICE_THREAD_LOCAL_HACK 1
57*03ce13f7SAndroid Build Coastguard Worker #endif
58*03ce13f7SAndroid Build Coastguard Worker 
59*03ce13f7SAndroid Build Coastguard Worker #if ICE_THREAD_LOCAL_HACK
60*03ce13f7SAndroid Build Coastguard Worker 
61*03ce13f7SAndroid Build Coastguard Worker // For a static thread_local field F of a class C, instead of declaring and
62*03ce13f7SAndroid Build Coastguard Worker // defining C::F, we create two static fields:
63*03ce13f7SAndroid Build Coastguard Worker //   static pthread_key_t F__key;
64*03ce13f7SAndroid Build Coastguard Worker //   static int F__initStatus;
65*03ce13f7SAndroid Build Coastguard Worker //
66*03ce13f7SAndroid Build Coastguard Worker // The F__initStatus field is used to hold the result of the
67*03ce13f7SAndroid Build Coastguard Worker // pthread_key_create() call, where a zero value indicates success, and a
68*03ce13f7SAndroid Build Coastguard Worker // nonzero value indicates failure or that ICE_TLS_INIT_FIELD() was never
69*03ce13f7SAndroid Build Coastguard Worker // called. The F__key field is used as the argument to pthread_getspecific()
70*03ce13f7SAndroid Build Coastguard Worker // and pthread_setspecific().
71*03ce13f7SAndroid Build Coastguard Worker 
72*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
73*03ce13f7SAndroid Build Coastguard Worker 
74*03ce13f7SAndroid Build Coastguard Worker #include <pthread.h>
75*03ce13f7SAndroid Build Coastguard Worker 
76*03ce13f7SAndroid Build Coastguard Worker #define ICE_TLS_DECLARE_FIELD(Type, FieldName)                                 \
77*03ce13f7SAndroid Build Coastguard Worker   using FieldName##__type = Type;                                              \
78*03ce13f7SAndroid Build Coastguard Worker   static pthread_key_t FieldName##__key;                                       \
79*03ce13f7SAndroid Build Coastguard Worker   static int FieldName##__initStatus
80*03ce13f7SAndroid Build Coastguard Worker #define ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName)                       \
81*03ce13f7SAndroid Build Coastguard Worker   pthread_key_t ClassName::FieldName##__key;                                   \
82*03ce13f7SAndroid Build Coastguard Worker   int ClassName::FieldName##__initStatus = 1
83*03ce13f7SAndroid Build Coastguard Worker #define ICE_TLS_INIT_FIELD(FieldName)                                          \
84*03ce13f7SAndroid Build Coastguard Worker   if (FieldName##__initStatus) {                                               \
85*03ce13f7SAndroid Build Coastguard Worker     FieldName##__initStatus = pthread_key_create(&FieldName##__key, nullptr);  \
86*03ce13f7SAndroid Build Coastguard Worker     if (FieldName##__initStatus)                                               \
87*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("Failed to create pthread key");                \
88*03ce13f7SAndroid Build Coastguard Worker   }
89*03ce13f7SAndroid Build Coastguard Worker #define ICE_TLS_GET_FIELD(FieldName)                                           \
90*03ce13f7SAndroid Build Coastguard Worker   (assert(FieldName##__initStatus == 0),                                       \
91*03ce13f7SAndroid Build Coastguard Worker    static_cast<FieldName##__type>(pthread_getspecific(FieldName##__key)))
92*03ce13f7SAndroid Build Coastguard Worker #define ICE_TLS_SET_FIELD(FieldName, Value)                                    \
93*03ce13f7SAndroid Build Coastguard Worker   (assert(FieldName##__initStatus == 0),                                       \
94*03ce13f7SAndroid Build Coastguard Worker    pthread_setspecific(FieldName##__key, (Value)))
95*03ce13f7SAndroid Build Coastguard Worker 
96*03ce13f7SAndroid Build Coastguard Worker #else // !ICE_THREAD_LOCAL_HACK
97*03ce13f7SAndroid Build Coastguard Worker 
98*03ce13f7SAndroid Build Coastguard Worker #if defined(_MSC_VER)
99*03ce13f7SAndroid Build Coastguard Worker #define ICE_ATTRIBUTE_TLS __declspec(thread)
100*03ce13f7SAndroid Build Coastguard Worker #else // !_MSC_VER
101*03ce13f7SAndroid Build Coastguard Worker #define ICE_ATTRIBUTE_TLS thread_local
102*03ce13f7SAndroid Build Coastguard Worker #endif // !_MSC_VER
103*03ce13f7SAndroid Build Coastguard Worker 
104*03ce13f7SAndroid Build Coastguard Worker #define ICE_TLS_DECLARE_FIELD(Type, FieldName)                                 \
105*03ce13f7SAndroid Build Coastguard Worker   static ICE_ATTRIBUTE_TLS Type FieldName
106*03ce13f7SAndroid Build Coastguard Worker #define ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName)                       \
107*03ce13f7SAndroid Build Coastguard Worker   ICE_ATTRIBUTE_TLS Type ClassName::FieldName = nullptr
108*03ce13f7SAndroid Build Coastguard Worker #define ICE_TLS_INIT_FIELD(FieldName)
109*03ce13f7SAndroid Build Coastguard Worker #define ICE_TLS_GET_FIELD(FieldName) (FieldName)
110*03ce13f7SAndroid Build Coastguard Worker #define ICE_TLS_SET_FIELD(FieldName, Value) (FieldName = (Value))
111*03ce13f7SAndroid Build Coastguard Worker 
112*03ce13f7SAndroid Build Coastguard Worker #endif // !ICE_THREAD_LOCAL_HACK
113*03ce13f7SAndroid Build Coastguard Worker 
114*03ce13f7SAndroid Build Coastguard Worker ///
115*03ce13f7SAndroid Build Coastguard Worker /// @}
116*03ce13f7SAndroid Build Coastguard Worker ///
117*03ce13f7SAndroid Build Coastguard Worker 
118*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICETLS_H
119