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/12068
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Common/Thread.hpp b/src/Common/Thread.hpp
index 3b9e674..87b90d1 100644
--- a/src/Common/Thread.hpp
+++ b/src/Common/Thread.hpp
@@ -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 @@
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 @@
return TlsAlloc();
#else
LocalStorageKey key;
- pthread_key_create(&key, NULL);
+ pthread_key_create(&key, free);
return key;
#endif
}
@@ -149,16 +152,24 @@
#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 @@
#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)
diff --git a/src/OpenGL/libEGL/main.cpp b/src/OpenGL/libEGL/main.cpp
index 3a8d1ce..b953e4b 100644
--- a/src/OpenGL/libEGL/main.cpp
+++ b/src/OpenGL/libEGL/main.cpp
@@ -48,14 +48,7 @@
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 @@
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()