Commit 420b64d2 by Nicolas Capens

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/10451Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com> Tested-by: 's avatarNicolas Capens <capn@google.com>
parent a781af7d
...@@ -135,7 +135,7 @@ namespace sw ...@@ -135,7 +135,7 @@ namespace sw
return TlsAlloc(); return TlsAlloc();
#else #else
LocalStorageKey key; LocalStorageKey key;
pthread_key_create(&key, 0); pthread_key_create(&key, NULL);
return key; return key;
#endif #endif
} }
...@@ -145,7 +145,7 @@ namespace sw ...@@ -145,7 +145,7 @@ namespace sw
#if defined(_WIN32) #if defined(_WIN32)
TlsFree(key); TlsFree(key);
#else #else
pthread_key_delete(key); pthread_key_delete(key); // Using an invalid key is an error but not undefined behavior.
#endif #endif
} }
...@@ -154,7 +154,10 @@ namespace sw ...@@ -154,7 +154,10 @@ namespace sw
#if defined(_WIN32) #if defined(_WIN32)
TlsSetValue(key, value); TlsSetValue(key, value);
#else #else
pthread_setspecific(key, value); if(key != TLS_OUT_OF_INDEXES) // Avoid undefined behavior.
{
pthread_setspecific(key, value);
}
#endif #endif
} }
...@@ -163,6 +166,11 @@ namespace sw ...@@ -163,6 +166,11 @@ namespace sw
#if defined(_WIN32) #if defined(_WIN32)
return TlsGetValue(key); return TlsGetValue(key);
#else #else
if(key == TLS_OUT_OF_INDEXES) // Avoid undefined behavior.
{
return nullptr;
}
return pthread_getspecific(key); return pthread_getspecific(key);
#endif #endif
} }
......
...@@ -39,22 +39,31 @@ static sw::Thread::LocalStorageKey currentTLS = TLS_OUT_OF_INDEXES; ...@@ -39,22 +39,31 @@ static sw::Thread::LocalStorageKey currentTLS = TLS_OUT_OF_INDEXES;
namespace egl namespace egl
{ {
void attachThread() Current *attachThread()
{ {
TRACE("()"); 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 = new Current;
current->error = EGL_SUCCESS; sw::Thread::setLocalStorage(currentTLS, current);
current->API = EGL_OPENGL_ES_API;
current->context = nullptr;
current->drawSurface = nullptr;
current->readSurface = nullptr;
} }
current->error = EGL_SUCCESS;
current->API = EGL_OPENGL_ES_API;
current->context = nullptr;
current->drawSurface = nullptr;
current->readSurface = nullptr;
return current;
} }
void detachThread() void detachThread()
...@@ -82,13 +91,6 @@ CONSTRUCTOR void attachProcess() ...@@ -82,13 +91,6 @@ CONSTRUCTOR void attachProcess()
} }
#endif #endif
currentTLS = sw::Thread::allocateLocalStorageKey();
if(currentTLS == TLS_OUT_OF_INDEXES)
{
return;
}
attachThread(); attachThread();
} }
...@@ -176,10 +178,10 @@ static Current *getCurrent(void) ...@@ -176,10 +178,10 @@ static Current *getCurrent(void)
if(!current) if(!current)
{ {
attachThread(); current = attachThread();
} }
return (Current*)sw::Thread::getLocalStorage(currentTLS); return current;
} }
void setCurrentError(EGLint error) void setCurrentError(EGLint error)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment