1*8975f5c5SAndroid Build Coastguard Worker // 2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2014 The ANGLE Project Authors. All rights reserved. 3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file. 5*8975f5c5SAndroid Build Coastguard Worker // 6*8975f5c5SAndroid Build Coastguard Worker 7*8975f5c5SAndroid Build Coastguard Worker // tls.cpp: Simple cross-platform interface for thread local storage. 8*8975f5c5SAndroid Build Coastguard Worker 9*8975f5c5SAndroid Build Coastguard Worker #include "common/tls.h" 10*8975f5c5SAndroid Build Coastguard Worker 11*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h" 12*8975f5c5SAndroid Build Coastguard Worker 13*8975f5c5SAndroid Build Coastguard Worker #ifdef ANGLE_ENABLE_WINDOWS_UWP 14*8975f5c5SAndroid Build Coastguard Worker # include <map> 15*8975f5c5SAndroid Build Coastguard Worker # include <mutex> 16*8975f5c5SAndroid Build Coastguard Worker # include <set> 17*8975f5c5SAndroid Build Coastguard Worker # include <vector> 18*8975f5c5SAndroid Build Coastguard Worker 19*8975f5c5SAndroid Build Coastguard Worker # include <Windows.System.Threading.h> 20*8975f5c5SAndroid Build Coastguard Worker # include <wrl/async.h> 21*8975f5c5SAndroid Build Coastguard Worker # include <wrl/client.h> 22*8975f5c5SAndroid Build Coastguard Worker 23*8975f5c5SAndroid Build Coastguard Worker using namespace std; 24*8975f5c5SAndroid Build Coastguard Worker using namespace Windows::Foundation; 25*8975f5c5SAndroid Build Coastguard Worker using namespace ABI::Windows::System::Threading; 26*8975f5c5SAndroid Build Coastguard Worker 27*8975f5c5SAndroid Build Coastguard Worker // Thread local storage for Windows Store support 28*8975f5c5SAndroid Build Coastguard Worker typedef vector<void *> ThreadLocalData; 29*8975f5c5SAndroid Build Coastguard Worker 30*8975f5c5SAndroid Build Coastguard Worker static __declspec(thread) ThreadLocalData *currentThreadData = nullptr; 31*8975f5c5SAndroid Build Coastguard Worker static set<ThreadLocalData *> allThreadData; 32*8975f5c5SAndroid Build Coastguard Worker static DWORD nextTlsIndex = 0; 33*8975f5c5SAndroid Build Coastguard Worker static vector<DWORD> freeTlsIndices; 34*8975f5c5SAndroid Build Coastguard Worker 35*8975f5c5SAndroid Build Coastguard Worker #endif 36*8975f5c5SAndroid Build Coastguard Worker 37*8975f5c5SAndroid Build Coastguard Worker namespace angle 38*8975f5c5SAndroid Build Coastguard Worker { 39*8975f5c5SAndroid Build Coastguard Worker CreateTLSIndex(PthreadKeyDestructor destructor)40*8975f5c5SAndroid Build Coastguard WorkerTLSIndex CreateTLSIndex(PthreadKeyDestructor destructor) 41*8975f5c5SAndroid Build Coastguard Worker { 42*8975f5c5SAndroid Build Coastguard Worker TLSIndex index; 43*8975f5c5SAndroid Build Coastguard Worker 44*8975f5c5SAndroid Build Coastguard Worker #ifdef ANGLE_PLATFORM_WINDOWS 45*8975f5c5SAndroid Build Coastguard Worker # ifdef ANGLE_ENABLE_WINDOWS_UWP 46*8975f5c5SAndroid Build Coastguard Worker if (!freeTlsIndices.empty()) 47*8975f5c5SAndroid Build Coastguard Worker { 48*8975f5c5SAndroid Build Coastguard Worker DWORD result = freeTlsIndices.back(); 49*8975f5c5SAndroid Build Coastguard Worker freeTlsIndices.pop_back(); 50*8975f5c5SAndroid Build Coastguard Worker index = result; 51*8975f5c5SAndroid Build Coastguard Worker } 52*8975f5c5SAndroid Build Coastguard Worker else 53*8975f5c5SAndroid Build Coastguard Worker { 54*8975f5c5SAndroid Build Coastguard Worker index = nextTlsIndex++; 55*8975f5c5SAndroid Build Coastguard Worker } 56*8975f5c5SAndroid Build Coastguard Worker # else 57*8975f5c5SAndroid Build Coastguard Worker index = TlsAlloc(); 58*8975f5c5SAndroid Build Coastguard Worker # endif 59*8975f5c5SAndroid Build Coastguard Worker 60*8975f5c5SAndroid Build Coastguard Worker #elif defined(ANGLE_PLATFORM_POSIX) 61*8975f5c5SAndroid Build Coastguard Worker // Create pthread key 62*8975f5c5SAndroid Build Coastguard Worker if ((pthread_key_create(&index, destructor)) != 0) 63*8975f5c5SAndroid Build Coastguard Worker { 64*8975f5c5SAndroid Build Coastguard Worker index = TLS_INVALID_INDEX; 65*8975f5c5SAndroid Build Coastguard Worker } 66*8975f5c5SAndroid Build Coastguard Worker #endif 67*8975f5c5SAndroid Build Coastguard Worker 68*8975f5c5SAndroid Build Coastguard Worker ASSERT(index != TLS_INVALID_INDEX && "CreateTLSIndex: Unable to allocate Thread Local Storage"); 69*8975f5c5SAndroid Build Coastguard Worker return index; 70*8975f5c5SAndroid Build Coastguard Worker } 71*8975f5c5SAndroid Build Coastguard Worker DestroyTLSIndex(TLSIndex index)72*8975f5c5SAndroid Build Coastguard Workerbool DestroyTLSIndex(TLSIndex index) 73*8975f5c5SAndroid Build Coastguard Worker { 74*8975f5c5SAndroid Build Coastguard Worker ASSERT(index != TLS_INVALID_INDEX && "DestroyTLSIndex(): Invalid TLS Index"); 75*8975f5c5SAndroid Build Coastguard Worker if (index == TLS_INVALID_INDEX) 76*8975f5c5SAndroid Build Coastguard Worker { 77*8975f5c5SAndroid Build Coastguard Worker return false; 78*8975f5c5SAndroid Build Coastguard Worker } 79*8975f5c5SAndroid Build Coastguard Worker 80*8975f5c5SAndroid Build Coastguard Worker #ifdef ANGLE_PLATFORM_WINDOWS 81*8975f5c5SAndroid Build Coastguard Worker # ifdef ANGLE_ENABLE_WINDOWS_UWP 82*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < nextTlsIndex); 83*8975f5c5SAndroid Build Coastguard Worker ASSERT(find(freeTlsIndices.begin(), freeTlsIndices.end(), index) == freeTlsIndices.end()); 84*8975f5c5SAndroid Build Coastguard Worker 85*8975f5c5SAndroid Build Coastguard Worker freeTlsIndices.push_back(index); 86*8975f5c5SAndroid Build Coastguard Worker for (auto threadData : allThreadData) 87*8975f5c5SAndroid Build Coastguard Worker { 88*8975f5c5SAndroid Build Coastguard Worker if (threadData->size() > index) 89*8975f5c5SAndroid Build Coastguard Worker { 90*8975f5c5SAndroid Build Coastguard Worker threadData->at(index) = nullptr; 91*8975f5c5SAndroid Build Coastguard Worker } 92*8975f5c5SAndroid Build Coastguard Worker } 93*8975f5c5SAndroid Build Coastguard Worker return true; 94*8975f5c5SAndroid Build Coastguard Worker # else 95*8975f5c5SAndroid Build Coastguard Worker return (TlsFree(index) == TRUE); 96*8975f5c5SAndroid Build Coastguard Worker # endif 97*8975f5c5SAndroid Build Coastguard Worker #elif defined(ANGLE_PLATFORM_POSIX) 98*8975f5c5SAndroid Build Coastguard Worker return (pthread_key_delete(index) == 0); 99*8975f5c5SAndroid Build Coastguard Worker #endif 100*8975f5c5SAndroid Build Coastguard Worker } 101*8975f5c5SAndroid Build Coastguard Worker SetTLSValue(TLSIndex index,void * value)102*8975f5c5SAndroid Build Coastguard Workerbool SetTLSValue(TLSIndex index, void *value) 103*8975f5c5SAndroid Build Coastguard Worker { 104*8975f5c5SAndroid Build Coastguard Worker ASSERT(index != TLS_INVALID_INDEX && "SetTLSValue(): Invalid TLS Index"); 105*8975f5c5SAndroid Build Coastguard Worker if (index == TLS_INVALID_INDEX) 106*8975f5c5SAndroid Build Coastguard Worker { 107*8975f5c5SAndroid Build Coastguard Worker return false; 108*8975f5c5SAndroid Build Coastguard Worker } 109*8975f5c5SAndroid Build Coastguard Worker 110*8975f5c5SAndroid Build Coastguard Worker #ifdef ANGLE_PLATFORM_WINDOWS 111*8975f5c5SAndroid Build Coastguard Worker # ifdef ANGLE_ENABLE_WINDOWS_UWP 112*8975f5c5SAndroid Build Coastguard Worker ThreadLocalData *threadData = currentThreadData; 113*8975f5c5SAndroid Build Coastguard Worker if (!threadData) 114*8975f5c5SAndroid Build Coastguard Worker { 115*8975f5c5SAndroid Build Coastguard Worker threadData = new ThreadLocalData(index + 1, nullptr); 116*8975f5c5SAndroid Build Coastguard Worker allThreadData.insert(threadData); 117*8975f5c5SAndroid Build Coastguard Worker currentThreadData = threadData; 118*8975f5c5SAndroid Build Coastguard Worker } 119*8975f5c5SAndroid Build Coastguard Worker else if (threadData->size() <= index) 120*8975f5c5SAndroid Build Coastguard Worker { 121*8975f5c5SAndroid Build Coastguard Worker threadData->resize(index + 1, nullptr); 122*8975f5c5SAndroid Build Coastguard Worker } 123*8975f5c5SAndroid Build Coastguard Worker 124*8975f5c5SAndroid Build Coastguard Worker threadData->at(index) = value; 125*8975f5c5SAndroid Build Coastguard Worker return true; 126*8975f5c5SAndroid Build Coastguard Worker # else 127*8975f5c5SAndroid Build Coastguard Worker return (TlsSetValue(index, value) == TRUE); 128*8975f5c5SAndroid Build Coastguard Worker # endif 129*8975f5c5SAndroid Build Coastguard Worker #elif defined(ANGLE_PLATFORM_POSIX) 130*8975f5c5SAndroid Build Coastguard Worker return (pthread_setspecific(index, value) == 0); 131*8975f5c5SAndroid Build Coastguard Worker #endif 132*8975f5c5SAndroid Build Coastguard Worker } 133*8975f5c5SAndroid Build Coastguard Worker GetTLSValue(TLSIndex index)134*8975f5c5SAndroid Build Coastguard Workervoid *GetTLSValue(TLSIndex index) 135*8975f5c5SAndroid Build Coastguard Worker { 136*8975f5c5SAndroid Build Coastguard Worker ASSERT(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index"); 137*8975f5c5SAndroid Build Coastguard Worker if (index == TLS_INVALID_INDEX) 138*8975f5c5SAndroid Build Coastguard Worker { 139*8975f5c5SAndroid Build Coastguard Worker return nullptr; 140*8975f5c5SAndroid Build Coastguard Worker } 141*8975f5c5SAndroid Build Coastguard Worker 142*8975f5c5SAndroid Build Coastguard Worker #ifdef ANGLE_PLATFORM_WINDOWS 143*8975f5c5SAndroid Build Coastguard Worker # ifdef ANGLE_ENABLE_WINDOWS_UWP 144*8975f5c5SAndroid Build Coastguard Worker ThreadLocalData *threadData = currentThreadData; 145*8975f5c5SAndroid Build Coastguard Worker if (threadData && threadData->size() > index) 146*8975f5c5SAndroid Build Coastguard Worker { 147*8975f5c5SAndroid Build Coastguard Worker return threadData->at(index); 148*8975f5c5SAndroid Build Coastguard Worker } 149*8975f5c5SAndroid Build Coastguard Worker else 150*8975f5c5SAndroid Build Coastguard Worker { 151*8975f5c5SAndroid Build Coastguard Worker return nullptr; 152*8975f5c5SAndroid Build Coastguard Worker } 153*8975f5c5SAndroid Build Coastguard Worker # else 154*8975f5c5SAndroid Build Coastguard Worker return TlsGetValue(index); 155*8975f5c5SAndroid Build Coastguard Worker # endif 156*8975f5c5SAndroid Build Coastguard Worker #elif defined(ANGLE_PLATFORM_POSIX) 157*8975f5c5SAndroid Build Coastguard Worker return pthread_getspecific(index); 158*8975f5c5SAndroid Build Coastguard Worker #endif 159*8975f5c5SAndroid Build Coastguard Worker } 160*8975f5c5SAndroid Build Coastguard Worker 161*8975f5c5SAndroid Build Coastguard Worker } // namespace angle 162