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
m_glEnc(NULL),
m_gl2Enc(NULL),
m_rcEnc(NULL),
- m_checksumHelper()
+ m_checksumHelper(),
+ m_grallocOnly(true)
{
}
delete m_rcEnc;
}
-HostConnection *HostConnection::get()
-{
+HostConnection *HostConnection::get() {
+
/* TODO: Make this configurable with a system property */
const int useQemuPipe = USE_QEMU_PIPE;
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) {
{
public:
static HostConnection *get();
+ static void exit();
~HostConnection();
GLEncoder *glEncoder();
}
}
+ void setGrallocOnly(bool gralloc_only) {
+ m_grallocOnly = gralloc_only;
+ }
+
+ bool isGrallocOnly() const { return m_grallocOnly; }
+
private:
HostConnection();
static gl_client_context_t *s_getGLContext();
GL2Encoder *m_gl2Enc;
renderControl_encoder_context_t *m_rcEnc;
ChecksumCalculator m_checksumHelper;
+ bool m_grallocOnly;
};
#endif
ALOGE("Failed to establish connection with the host\n");
return false;
}
+ hcon->setGrallocOnly(false);
//
// get renderControl encoder instance
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) { \
D("gralloc_unregister_buffer(%p) done\n", cb);
+ EXIT_GRALLOCONLY_HOST_CONNECTION;
return 0;
}