aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Capens <capn@google.com>2017-07-07 17:01:16 -0400
committerNicolas Capens <capn@google.com>2017-08-16 14:45:56 -0400
commite6a6ee59ddb2a9b0c9547fba7f43047250124ce7 (patch)
tree9ff9b1e1de8d30ec85e40296e7b39257898e3dfe
parent4bb633a54d6d592bec4d3af3a723db6ffb78bfbf (diff)
downloadswiftshader-e6a6ee59ddb2a9b0c9547fba7f43047250124ce7.tar.gz
Fix TLS for platforms without library constructors.
Some platforms don't support constructors that get called when the shared library gets loaded. This results in the thread-local-storage key to never be allocated. Instead we can check if it was allocated on each use. Also prevent creating new 'current' state if it already exists, and avoid pthreads undefined behavior. Bug b/25629882 Change-Id: I5e2486f88185150b976d88d0144e4d13a349eb79 Reviewed-on: https://swiftshader-review.googlesource.com/11628 Reviewed-by: Nicolas Capens <nicolascapens@google.com> Tested-by: Nicolas Capens <nicolascapens@google.com>
-rw-r--r--src/Common/Thread.hpp14
-rw-r--r--src/OpenGL/libEGL/main.cpp48
2 files changed, 37 insertions, 25 deletions
diff --git a/src/Common/Thread.hpp b/src/Common/Thread.hpp
index 8f6443e03..f59a0d4f5 100644
--- a/src/Common/Thread.hpp
+++ b/src/Common/Thread.hpp
@@ -135,7 +135,7 @@ namespace sw
return TlsAlloc();
#else
LocalStorageKey key;
- pthread_key_create(&key, 0);
+ pthread_key_create(&key, NULL);
return key;
#endif
}
@@ -145,7 +145,7 @@ namespace sw
#if defined(_WIN32)
TlsFree(key);
#else
- pthread_key_delete(key);
+ pthread_key_delete(key); // Using an invalid key is an error but not undefined behavior.
#endif
}
@@ -154,7 +154,10 @@ namespace sw
#if defined(_WIN32)
TlsSetValue(key, value);
#else
- pthread_setspecific(key, value);
+ if(key != TLS_OUT_OF_INDEXES) // Avoid undefined behavior.
+ {
+ pthread_setspecific(key, value);
+ }
#endif
}
@@ -163,6 +166,11 @@ namespace sw
#if defined(_WIN32)
return TlsGetValue(key);
#else
+ if(key == TLS_OUT_OF_INDEXES) // Avoid undefined behavior.
+ {
+ return nullptr;
+ }
+
return pthread_getspecific(key);
#endif
}
diff --git a/src/OpenGL/libEGL/main.cpp b/src/OpenGL/libEGL/main.cpp
index 667d7f410..f34047580 100644
--- a/src/OpenGL/libEGL/main.cpp
+++ b/src/OpenGL/libEGL/main.cpp
@@ -27,11 +27,7 @@
#include <EGL/eglext.h>
-static sw::Thread::LocalStorageKey currentTLS() {
- static sw::Thread::LocalStorageKey rval =
- sw::Thread::allocateLocalStorageKey();
- return rval;
-}
+static sw::Thread::LocalStorageKey currentTLS = TLS_OUT_OF_INDEXES;
#if !defined(_MSC_VER)
#define CONSTRUCTOR __attribute__((constructor))
@@ -43,23 +39,31 @@ static sw::Thread::LocalStorageKey currentTLS() {
namespace egl
{
-void attachThread()
+Current *attachThread()
{
TRACE("()");
- Current *current = new Current;
+ if(currentTLS == TLS_OUT_OF_INDEXES)
+ {
+ currentTLS = sw::Thread::allocateLocalStorageKey();
+ }
+
+ Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);
- if(current)
+ if(!current)
{
- sw::Thread::setLocalStorage(currentTLS(), current);
-
- current->error = EGL_SUCCESS;
- current->API = EGL_OPENGL_ES_API;
- current->display = EGL_NO_DISPLAY;
- current->context = nullptr;
- current->drawSurface = nullptr;
- current->readSurface = nullptr;
+ current = new Current;
+
+ sw::Thread::setLocalStorage(currentTLS, current);
}
+
+ current->error = EGL_SUCCESS;
+ current->API = EGL_OPENGL_ES_API;
+ current->context = nullptr;
+ current->drawSurface = nullptr;
+ current->readSurface = nullptr;
+
+ return current;
}
void detachThread()
@@ -68,8 +72,8 @@ void detachThread()
eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
- delete (Current*)sw::Thread::getLocalStorage(currentTLS());
- sw::Thread::setLocalStorage(currentTLS(), nullptr);
+ delete (Current*)sw::Thread::getLocalStorage(currentTLS);
+ sw::Thread::setLocalStorage(currentTLS, nullptr);
}
CONSTRUCTOR void attachProcess()
@@ -95,7 +99,7 @@ DESTRUCTOR void detachProcess()
TRACE("()");
detachThread();
- sw::Thread::freeLocalStorageKey(currentTLS());
+ sw::Thread::freeLocalStorageKey(currentTLS);
}
}
@@ -170,14 +174,14 @@ namespace egl
{
static Current *getCurrent(void)
{
- Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS());
+ Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);
if(!current)
{
- attachThread();
+ current = attachThread();
}
- return (Current*)sw::Thread::getLocalStorage(currentTLS());
+ return current;
}
void setCurrentError(EGLint error)