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