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 @@
#define TLS_OUT_OF_INDEXES (pthread_key_t)(~0)
#endif
#include <stdlib.h>
namespace sw
{
class Event;
......@@ -52,8 +54,9 @@ namespace sw
static LocalStorageKey allocateLocalStorageKey();
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 freeLocalStorage(LocalStorageKey key);
private:
struct Entry
......@@ -135,7 +138,7 @@ namespace sw
return TlsAlloc();
#else
LocalStorageKey key;
pthread_key_create(&key, NULL);
pthread_key_create(&key, free);
return key;
#endif
}
......@@ -149,16 +152,24 @@ namespace sw
#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)
TlsSetValue(key, value);
TlsSetValue(key, storage);
#else
if(key != TLS_OUT_OF_INDEXES) // Avoid undefined behavior.
{
pthread_setspecific(key, value);
}
pthread_setspecific(key, storage);
#endif
return storage;
}
inline void *Thread::getLocalStorage(LocalStorageKey key)
......@@ -175,6 +186,17 @@ namespace sw
#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()
{
#if defined(_WIN32)
......
......@@ -48,14 +48,7 @@ Current *attachThread()
currentTLS = sw::Thread::allocateLocalStorageKey();
}
Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);
if(!current)
{
current = new Current;
sw::Thread::setLocalStorage(currentTLS, current);
}
Current *current = (Current*)sw::Thread::allocateLocalStorage(currentTLS, sizeof(Current));
current->error = EGL_SUCCESS;
current->API = EGL_OPENGL_ES_API;
......@@ -72,8 +65,7 @@ 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);
sw::Thread::freeLocalStorage(currentTLS);
}
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