From 4e620ddce344e946ced992f61a69c367ff92fe24 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 30 May 2013 16:07:36 -0700 Subject: [PATCH] free EGL resources associated to a thread when it terminates destroyed but current-to-a-thread resources are only destroyed when they're made not-current; however, we were not destroying those when the thread itself terminated, causing these resources to be leaked forever. we now install a tls-key destructor that takes care of this by calling eglReleaseThread upon thread termination. Bug: 9209776 Change-Id: I88298a34e3a27488eb81eab76717715569c7d57c --- opengl/libs/EGL/eglApi.cpp | 10 +++---- opengl/libs/EGL/egl_tls.cpp | 30 +++++++++++-------- opengl/libs/EGL/egl_tls.h | 3 +- .../libs/GLES_trace/src/gltrace_context.cpp | 2 +- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index 74d397335..334e1648a 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -1177,6 +1177,11 @@ EGLBoolean eglReleaseThread(void) { clearError(); +#if EGL_TRACE + if (getEGLDebugLevel() > 0) + GLTrace_eglReleaseThread(); +#endif + // If there is context bound to the thread, release it egl_display_t::loseCurrent(get_context(getContext())); @@ -1184,12 +1189,7 @@ EGLBoolean eglReleaseThread(void) if (cnx->dso && cnx->egl.eglReleaseThread) { cnx->egl.eglReleaseThread(); } - egl_tls_t::clearTLS(); -#if EGL_TRACE - if (getEGLDebugLevel() > 0) - GLTrace_eglReleaseThread(); -#endif return EGL_TRUE; } diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp index 52312a2b7..f3739aafa 100644 --- a/opengl/libs/EGL/egl_tls.cpp +++ b/opengl/libs/EGL/egl_tls.cpp @@ -29,8 +29,8 @@ namespace android { -pthread_key_t egl_tls_t::sKey = -1; -pthread_mutex_t egl_tls_t::sLockKey = PTHREAD_MUTEX_INITIALIZER; +pthread_key_t egl_tls_t::sKey = TLS_KEY_NOT_INITIALIZED; +pthread_once_t egl_tls_t::sOnceKey = PTHREAD_ONCE_INIT; egl_tls_t::egl_tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { @@ -59,12 +59,12 @@ const char *egl_tls_t::egl_strerror(EGLint err) { void egl_tls_t::validateTLSKey() { - if (sKey == -1) { - pthread_mutex_lock(&sLockKey); - if (sKey == -1) - pthread_key_create(&sKey, NULL); - pthread_mutex_unlock(&sLockKey); - } + struct TlsKeyInitializer { + static void create() { + pthread_key_create(&sKey, (void (*)(void*))&eglReleaseThread); + } + }; + pthread_once(&sOnceKey, TlsKeyInitializer::create); } void egl_tls_t::setErrorEtcImpl( @@ -104,11 +104,11 @@ egl_tls_t* egl_tls_t::getTLS() { } void egl_tls_t::clearTLS() { - if (sKey != -1) { + if (sKey != TLS_KEY_NOT_INITIALIZED) { egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey); if (tls) { - delete tls; pthread_setspecific(sKey, 0); + delete tls; } } } @@ -120,10 +120,13 @@ void egl_tls_t::clearError() { } EGLint egl_tls_t::getError() { - if (sKey == -1) + if (sKey == TLS_KEY_NOT_INITIALIZED) { return EGL_SUCCESS; + } egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey); - if (!tls) return EGL_SUCCESS; + if (!tls) { + return EGL_SUCCESS; + } EGLint error = tls->error; tls->error = EGL_SUCCESS; return error; @@ -135,8 +138,9 @@ void egl_tls_t::setContext(EGLContext ctx) { } EGLContext egl_tls_t::getContext() { - if (sKey == -1) + if (sKey == TLS_KEY_NOT_INITIALIZED) { return EGL_NO_CONTEXT; + } egl_tls_t* tls = (egl_tls_t *)pthread_getspecific(sKey); if (!tls) return EGL_NO_CONTEXT; return tls->ctx; diff --git a/opengl/libs/EGL/egl_tls.h b/opengl/libs/EGL/egl_tls.h index 56c5dba37..5af4f5b3b 100644 --- a/opengl/libs/EGL/egl_tls.h +++ b/opengl/libs/EGL/egl_tls.h @@ -30,8 +30,9 @@ namespace android { class DbgContext; class egl_tls_t { + enum { TLS_KEY_NOT_INITIALIZED = -1 }; static pthread_key_t sKey; - static pthread_mutex_t sLockKey; + static pthread_once_t sOnceKey; EGLint error; EGLContext ctx; diff --git a/opengl/libs/GLES_trace/src/gltrace_context.cpp b/opengl/libs/GLES_trace/src/gltrace_context.cpp index 3a8deccd7..0323e8f46 100644 --- a/opengl/libs/GLES_trace/src/gltrace_context.cpp +++ b/opengl/libs/GLES_trace/src/gltrace_context.cpp @@ -32,7 +32,7 @@ static pthread_key_t sTLSKey = -1; static pthread_once_t sPthreadOnceKey = PTHREAD_ONCE_INIT; void createTLSKey() { - pthread_key_create(&sTLSKey, NULL); + pthread_key_create(&sTLSKey, (void (*)(void*))&releaseContext); } GLTraceContext *getGLTraceContext() {