1 //===- 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 /// \file 11 /// \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. 16 /// 17 //===----------------------------------------------------------------------===// 18 19 #ifndef SUBZERO_SRC_ICETLS_H 20 #define SUBZERO_SRC_ICETLS_H 21 22 /// 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. 47 48 /// TODO(stichnot): Limit this define to only the platforms that absolutely 49 /// require it. And ideally, eventually remove this hack altogether. 50 /// 51 52 /// 53 /// \def ICE_THREAD_LOCAL_HACK 54 /// 55 #ifndef ICE_THREAD_LOCAL_HACK 56 #define ICE_THREAD_LOCAL_HACK 1 57 #endif 58 59 #if ICE_THREAD_LOCAL_HACK 60 61 // For a static thread_local field F of a class C, instead of declaring and 62 // defining C::F, we create two static fields: 63 // 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 67 // 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(). 71 72 #include "llvm/Support/ErrorHandling.h" 73 74 #include <pthread.h> 75 76 #define ICE_TLS_DECLARE_FIELD(Type, FieldName) \ 77 using FieldName##__type = Type; \ 78 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; \ 82 int ClassName::FieldName##__initStatus = 1 83 #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 98 #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 104 #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 114 /// 115 /// @} 116 /// 117 118 #endif // SUBZERO_SRC_ICETLS_H 119