xref: /aosp_15_r20/external/angle/src/common/tls.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 Worker TLSIndex 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 Worker bool 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 Worker bool 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 Worker void *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