Commit 4ad365b4 by Nicolas Capens Committed by Nicolas Capens

Free thread-local storage implicitly on thread termination.

Some applications may not call eglReleaseThread() before terminating a thread, which can cause a minor memory leak. pthread_key_create() supports specifying a destructor callback to implicitly free the thread-local storage on thread termination. On Windows we use the DLL_THREAD_DETACH signal to free it explicitly. This change also simplifies TLS management by removing the ability to set a new value. Bug swiftshader:80 Change-Id: I249ca519c1c9ab722e570516d0931cb17ea081bb Reviewed-on: https://swiftshader-review.googlesource.com/12068Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent a28d04b2
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#define TLS_OUT_OF_INDEXES (pthread_key_t)(~0) #define TLS_OUT_OF_INDEXES (pthread_key_t)(~0)
#endif #endif
#include <stdlib.h>
namespace sw namespace sw
{ {
class Event; class Event;
...@@ -52,8 +54,9 @@ namespace sw ...@@ -52,8 +54,9 @@ namespace sw
static LocalStorageKey allocateLocalStorageKey(); static LocalStorageKey allocateLocalStorageKey();
static void freeLocalStorageKey(LocalStorageKey key); static void freeLocalStorageKey(LocalStorageKey key);
static void setLocalStorage(LocalStorageKey key, void *value); static void *allocateLocalStorage(LocalStorageKey key, size_t size);
static void *getLocalStorage(LocalStorageKey key); static void *getLocalStorage(LocalStorageKey key);
static void freeLocalStorage(LocalStorageKey key);
private: private:
struct Entry struct Entry
...@@ -135,7 +138,7 @@ namespace sw ...@@ -135,7 +138,7 @@ namespace sw
return TlsAlloc(); return TlsAlloc();
#else #else
LocalStorageKey key; LocalStorageKey key;
pthread_key_create(&key, NULL); pthread_key_create(&key, free);
return key; return key;
#endif #endif
} }
...@@ -149,16 +152,24 @@ namespace sw ...@@ -149,16 +152,24 @@ namespace sw
#endif #endif
} }
inline void Thread::setLocalStorage(LocalStorageKey key, void *value) inline void *Thread::allocateLocalStorage(LocalStorageKey key, size_t size)
{ {
if(key == TLS_OUT_OF_INDEXES)
{
return nullptr;
}
freeLocalStorage(key);
void *storage = malloc(size);
#if defined(_WIN32) #if defined(_WIN32)
TlsSetValue(key, value); TlsSetValue(key, storage);
#else #else
if(key != TLS_OUT_OF_INDEXES) // Avoid undefined behavior. pthread_setspecific(key, storage);
{
pthread_setspecific(key, value);
}
#endif #endif
return storage;
} }
inline void *Thread::getLocalStorage(LocalStorageKey key) inline void *Thread::getLocalStorage(LocalStorageKey key)
...@@ -175,6 +186,17 @@ namespace sw ...@@ -175,6 +186,17 @@ namespace sw
#endif #endif
} }
inline void Thread::freeLocalStorage(LocalStorageKey key)
{
free(getLocalStorage(key));
#if defined(_WIN32)
TlsSetValue(key, nullptr);
#else
pthread_setspecific(key, nullptr);
#endif
}
inline void Event::signal() inline void Event::signal()
{ {
#if defined(_WIN32) #if defined(_WIN32)
......
...@@ -48,14 +48,7 @@ Current *attachThread() ...@@ -48,14 +48,7 @@ Current *attachThread()
currentTLS = sw::Thread::allocateLocalStorageKey(); currentTLS = sw::Thread::allocateLocalStorageKey();
} }
Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS); Current *current = (Current*)sw::Thread::allocateLocalStorage(currentTLS, sizeof(Current));
if(!current)
{
current = new Current;
sw::Thread::setLocalStorage(currentTLS, current);
}
current->error = EGL_SUCCESS; current->error = EGL_SUCCESS;
current->API = EGL_OPENGL_ES_API; current->API = EGL_OPENGL_ES_API;
...@@ -72,8 +65,7 @@ void detachThread() ...@@ -72,8 +65,7 @@ void detachThread()
eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
delete (Current*)sw::Thread::getLocalStorage(currentTLS); sw::Thread::freeLocalStorage(currentTLS);
sw::Thread::setLocalStorage(currentTLS, nullptr);
} }
CONSTRUCTOR void attachProcess() CONSTRUCTOR void attachProcess()
......
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