summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/common/tls.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/common/tls.cpp')
-rwxr-xr-xgfx/angle/src/common/tls.cpp156
1 files changed, 156 insertions, 0 deletions
diff --git a/gfx/angle/src/common/tls.cpp b/gfx/angle/src/common/tls.cpp
new file mode 100755
index 000000000..cb1b32d32
--- /dev/null
+++ b/gfx/angle/src/common/tls.cpp
@@ -0,0 +1,156 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// tls.cpp: Simple cross-platform interface for thread local storage.
+
+#include "common/tls.h"
+
+#include <assert.h>
+
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+#include <vector>
+#include <set>
+#include <map>
+#include <mutex>
+
+#include <wrl/client.h>
+#include <wrl/async.h>
+#include <Windows.System.Threading.h>
+
+using namespace std;
+using namespace Windows::Foundation;
+using namespace ABI::Windows::System::Threading;
+
+// Thread local storage for Windows Store support
+typedef vector<void*> ThreadLocalData;
+
+static __declspec(thread) ThreadLocalData* currentThreadData = nullptr;
+static set<ThreadLocalData*> allThreadData;
+static DWORD nextTlsIndex = 0;
+static vector<DWORD> freeTlsIndices;
+
+#endif
+
+TLSIndex CreateTLSIndex()
+{
+ TLSIndex index;
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+ if (!freeTlsIndices.empty())
+ {
+ DWORD result = freeTlsIndices.back();
+ freeTlsIndices.pop_back();
+ index = result;
+ }
+ else
+ {
+ index = nextTlsIndex++;
+ }
+#else
+ index = TlsAlloc();
+#endif
+
+#elif defined(ANGLE_PLATFORM_POSIX)
+ // Create global pool key
+ if ((pthread_key_create(&index, NULL)) != 0)
+ {
+ index = TLS_INVALID_INDEX;
+ }
+#endif
+
+ assert(index != TLS_INVALID_INDEX && "CreateTLSIndex(): Unable to allocate Thread Local Storage");
+ return index;
+}
+
+bool DestroyTLSIndex(TLSIndex index)
+{
+ assert(index != TLS_INVALID_INDEX && "DestroyTLSIndex(): Invalid TLS Index");
+ if (index == TLS_INVALID_INDEX)
+ {
+ return false;
+ }
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+ assert(index < nextTlsIndex);
+ assert(find(freeTlsIndices.begin(), freeTlsIndices.end(), index) == freeTlsIndices.end());
+
+ freeTlsIndices.push_back(index);
+ for (auto threadData : allThreadData)
+ {
+ if (threadData->size() > index)
+ {
+ threadData->at(index) = nullptr;
+ }
+ }
+ return true;
+#else
+ return (TlsFree(index) == TRUE);
+#endif
+#elif defined(ANGLE_PLATFORM_POSIX)
+ return (pthread_key_delete(index) == 0);
+#endif
+}
+
+bool SetTLSValue(TLSIndex index, void *value)
+{
+ assert(index != TLS_INVALID_INDEX && "SetTLSValue(): Invalid TLS Index");
+ if (index == TLS_INVALID_INDEX)
+ {
+ return false;
+ }
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+ ThreadLocalData* threadData = currentThreadData;
+ if (!threadData)
+ {
+ threadData = new ThreadLocalData(index + 1, nullptr);
+ allThreadData.insert(threadData);
+ currentThreadData = threadData;
+ }
+ else if (threadData->size() <= index)
+ {
+ threadData->resize(index + 1, nullptr);
+ }
+
+ threadData->at(index) = value;
+ return true;
+#else
+ return (TlsSetValue(index, value) == TRUE);
+#endif
+#elif defined(ANGLE_PLATFORM_POSIX)
+ return (pthread_setspecific(index, value) == 0);
+#endif
+}
+
+void *GetTLSValue(TLSIndex index)
+{
+ assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index");
+ if (index == TLS_INVALID_INDEX)
+ {
+ return NULL;
+ }
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+ ThreadLocalData* threadData = currentThreadData;
+ if (threadData && threadData->size() > index)
+ {
+ return threadData->at(index);
+ }
+ else
+ {
+ return nullptr;
+ }
+#else
+ return TlsGetValue(index);
+#endif
+#elif defined(ANGLE_PLATFORM_POSIX)
+ return pthread_getspecific(index);
+#endif
+}