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
This commit is contained in:
Mathias Agopian 2013-05-30 16:07:36 -07:00
parent 9e3cb55b8f
commit 4e620ddce3
4 changed files with 25 additions and 20 deletions

View File

@ -1177,6 +1177,11 @@ EGLBoolean eglReleaseThread(void)
{ {
clearError(); clearError();
#if EGL_TRACE
if (getEGLDebugLevel() > 0)
GLTrace_eglReleaseThread();
#endif
// If there is context bound to the thread, release it // If there is context bound to the thread, release it
egl_display_t::loseCurrent(get_context(getContext())); egl_display_t::loseCurrent(get_context(getContext()));
@ -1184,12 +1189,7 @@ EGLBoolean eglReleaseThread(void)
if (cnx->dso && cnx->egl.eglReleaseThread) { if (cnx->dso && cnx->egl.eglReleaseThread) {
cnx->egl.eglReleaseThread(); cnx->egl.eglReleaseThread();
} }
egl_tls_t::clearTLS(); egl_tls_t::clearTLS();
#if EGL_TRACE
if (getEGLDebugLevel() > 0)
GLTrace_eglReleaseThread();
#endif
return EGL_TRUE; return EGL_TRUE;
} }

View File

@ -29,8 +29,8 @@
namespace android { namespace android {
pthread_key_t egl_tls_t::sKey = -1; pthread_key_t egl_tls_t::sKey = TLS_KEY_NOT_INITIALIZED;
pthread_mutex_t egl_tls_t::sLockKey = PTHREAD_MUTEX_INITIALIZER; pthread_once_t egl_tls_t::sOnceKey = PTHREAD_ONCE_INIT;
egl_tls_t::egl_tls_t() egl_tls_t::egl_tls_t()
: error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { : 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() void egl_tls_t::validateTLSKey()
{ {
if (sKey == -1) { struct TlsKeyInitializer {
pthread_mutex_lock(&sLockKey); static void create() {
if (sKey == -1) pthread_key_create(&sKey, (void (*)(void*))&eglReleaseThread);
pthread_key_create(&sKey, NULL); }
pthread_mutex_unlock(&sLockKey); };
} pthread_once(&sOnceKey, TlsKeyInitializer::create);
} }
void egl_tls_t::setErrorEtcImpl( void egl_tls_t::setErrorEtcImpl(
@ -104,11 +104,11 @@ egl_tls_t* egl_tls_t::getTLS() {
} }
void egl_tls_t::clearTLS() { void egl_tls_t::clearTLS() {
if (sKey != -1) { if (sKey != TLS_KEY_NOT_INITIALIZED) {
egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey); egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
if (tls) { if (tls) {
delete tls;
pthread_setspecific(sKey, 0); pthread_setspecific(sKey, 0);
delete tls;
} }
} }
} }
@ -120,10 +120,13 @@ void egl_tls_t::clearError() {
} }
EGLint egl_tls_t::getError() { EGLint egl_tls_t::getError() {
if (sKey == -1) if (sKey == TLS_KEY_NOT_INITIALIZED) {
return EGL_SUCCESS; return EGL_SUCCESS;
}
egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey); egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
if (!tls) return EGL_SUCCESS; if (!tls) {
return EGL_SUCCESS;
}
EGLint error = tls->error; EGLint error = tls->error;
tls->error = EGL_SUCCESS; tls->error = EGL_SUCCESS;
return error; return error;
@ -135,8 +138,9 @@ void egl_tls_t::setContext(EGLContext ctx) {
} }
EGLContext egl_tls_t::getContext() { EGLContext egl_tls_t::getContext() {
if (sKey == -1) if (sKey == TLS_KEY_NOT_INITIALIZED) {
return EGL_NO_CONTEXT; return EGL_NO_CONTEXT;
}
egl_tls_t* tls = (egl_tls_t *)pthread_getspecific(sKey); egl_tls_t* tls = (egl_tls_t *)pthread_getspecific(sKey);
if (!tls) return EGL_NO_CONTEXT; if (!tls) return EGL_NO_CONTEXT;
return tls->ctx; return tls->ctx;

View File

@ -30,8 +30,9 @@ namespace android {
class DbgContext; class DbgContext;
class egl_tls_t { class egl_tls_t {
enum { TLS_KEY_NOT_INITIALIZED = -1 };
static pthread_key_t sKey; static pthread_key_t sKey;
static pthread_mutex_t sLockKey; static pthread_once_t sOnceKey;
EGLint error; EGLint error;
EGLContext ctx; EGLContext ctx;

View File

@ -32,7 +32,7 @@ static pthread_key_t sTLSKey = -1;
static pthread_once_t sPthreadOnceKey = PTHREAD_ONCE_INIT; static pthread_once_t sPthreadOnceKey = PTHREAD_ONCE_INIT;
void createTLSKey() { void createTLSKey() {
pthread_key_create(&sTLSKey, NULL); pthread_key_create(&sTLSKey, (void (*)(void*))&releaseContext);
} }
GLTraceContext *getGLTraceContext() { GLTraceContext *getGLTraceContext() {