OSDN Git Service

Don't leave gralloc-only host connections hanging.
authorLingfeng Yang <lfy@google.com>
Mon, 13 Jun 2016 15:39:28 +0000 (08:39 -0700)
committerLingfeng Yang <lfy@google.com>
Fri, 17 Jun 2016 14:56:57 +0000 (14:56 +0000)
bug: 29318455

Memory leaks are becoming more of a problem, especially
with host machines that don't have much RAM and when
we use the emulator for long periods of time.

This CL fixes the problem detailed in the bug link,
which is that the number of render threads
(and thus thread-specific storage) skyrockets when
repeatedly pressing the Recents button while an app is active.

The thing is that there are lots of threads
that never use the EGL display, just gralloc, in order
to do gralloc things like update the screenshot display
of apps in recents.

These threads are not cleaned up because a thread pool
is often used to manage these sorts of tasks.
If a new or different thread suddenly wants to update
the recents screenshots through gralloc, a new connection
will be established.

This CL uses gralloc_unregister_buffer as a signal
for when a thread might be done with gralloc in general,
exiting the host connection immediately.

Of course, there may be other things that the thread wants
to do, but then it can just go ahead and create a new connection.

We also use the heuristic that we do not exit on gralloc_unregister_buffer
when the thread seems to be a bona fide rendering thread
(eglInitialize has been called).

There are still more leaks going on, this fixes just
one source of them.

After this CL, the render thread count should be held constant
when repeatedly starting apps and going to recents.

Change-Id: I5f57539429f149e3a938467e3b82fa911ab118c3

system/OpenglSystemCommon/HostConnection.cpp
system/OpenglSystemCommon/HostConnection.h
system/egl/eglDisplay.cpp
system/gralloc/gralloc.cpp

index 54b28e7..6a4a24e 100644 (file)
@@ -33,7 +33,8 @@ HostConnection::HostConnection() :
     m_glEnc(NULL),
     m_gl2Enc(NULL),
     m_rcEnc(NULL),
-    m_checksumHelper()
+    m_checksumHelper(),
+    m_grallocOnly(true)
 {
 }
 
@@ -45,8 +46,8 @@ HostConnection::~HostConnection()
     delete m_rcEnc;
 }
 
-HostConnection *HostConnection::get()
-{
+HostConnection *HostConnection::get() {
+
     /* TODO: Make this configurable with a system property */
     const int useQemuPipe = USE_QEMU_PIPE;
 
@@ -108,6 +109,20 @@ HostConnection *HostConnection::get()
     return tinfo->hostConn;
 }
 
+void HostConnection::exit() {
+    EGLThreadInfo *tinfo = getEGLThreadInfo();
+    if (!tinfo) {
+        return;
+    }
+
+    if (tinfo->hostConn) {
+        delete tinfo->hostConn;
+        tinfo->hostConn = NULL;
+    }
+}
+
+
+
 GLEncoder *HostConnection::glEncoder()
 {
     if (!m_glEnc) {
index 3896288..70b757c 100644 (file)
@@ -31,6 +31,7 @@ class HostConnection
 {
 public:
     static HostConnection *get();
+    static void exit();
     ~HostConnection();
 
     GLEncoder *glEncoder();
@@ -44,6 +45,12 @@ public:
         }
     }
 
+    void setGrallocOnly(bool gralloc_only) {
+        m_grallocOnly = gralloc_only;
+    }
+
+    bool isGrallocOnly() const { return m_grallocOnly; }
+
 private:
     HostConnection();
     static gl_client_context_t  *s_getGLContext();
@@ -60,6 +67,7 @@ private:
     GL2Encoder  *m_gl2Enc;
     renderControl_encoder_context_t *m_rcEnc;
     ChecksumCalculator m_checksumHelper;
+    bool m_grallocOnly;
 };
 
 #endif
index 9340482..051368a 100644 (file)
@@ -116,6 +116,7 @@ bool eglDisplay::initialize(EGLClient_eglInterface *eglIface)
             ALOGE("Failed to establish connection with the host\n");
             return false;
         }
+        hcon->setGrallocOnly(false);
 
         //
         // get renderControl encoder instance
index e89fa0f..f598766 100644 (file)
@@ -106,6 +106,14 @@ static int map_buffer(cb_handle_t *cb, void **vaddr)
     HostConnection *hostCon = HostConnection::get(); \
     renderControl_encoder_context_t *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
 
+#define EXIT_GRALLOCONLY_HOST_CONNECTION \
+    HostConnection *hostCon = HostConnection::get(); \
+    if (hostCon && hostCon->isGrallocOnly()) { \
+        ALOGD("%s: exiting HostConnection (is buffer-handling thread)", \
+              __FUNCTION__); \
+        HostConnection::exit(); \
+    }
+
 #define DEFINE_AND_VALIDATE_HOST_CONNECTION \
     HostConnection *hostCon = HostConnection::get(); \
     if (!hostCon) { \
@@ -595,6 +603,7 @@ static int gralloc_unregister_buffer(gralloc_module_t const* module,
 
     D("gralloc_unregister_buffer(%p) done\n", cb);
 
+    EXIT_GRALLOCONLY_HOST_CONNECTION;
     return 0;
 }