OSDN Git Service

free EGL resources associated to a thread when it terminates
authorMathias Agopian <mathias@google.com>
Thu, 30 May 2013 23:07:36 +0000 (16:07 -0700)
committerMathias Agopian <mathias@google.com>
Thu, 30 May 2013 23:07:36 +0000 (16:07 -0700)
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
opengl/libs/EGL/egl_tls.cpp
opengl/libs/EGL/egl_tls.h
opengl/libs/GLES_trace/src/gltrace_context.cpp

index 74d3973..334e164 100644 (file)
@@ -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;
 }
 
index 52312a2..f3739aa 100644 (file)
@@ -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;
index 56c5dba..5af4f5b 100644 (file)
@@ -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;
index 3a8decc..0323e8f 100644 (file)
@@ -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() {