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