| From fce1dd0a6a8f675285da3fd1866d9487912fed01 Mon Sep 17 00:00:00 2001 |
| From: Iosif Antochi <iosif.antochi@imgtec.com> |
| Date: Wed, 14 Jun 2017 14:49:55 +0100 |
| Subject: [PATCH 10/10] egl: automatically call eglReleaseThread on thread |
| termination |
| |
| EGL thread cleanup conformance tests could run out of memory as the contexts |
| were not freed even though the application requested to have them deleted. |
| This was caused by the fact that the contexts were still current on their |
| threads when delete was called and (in order not to block any potential |
| pending renders) they were just marked for delete. |
| |
| Fix this by calling eglReleaseThread on thread termination. This is safe to |
| do even if this was already called by the application since, according to the |
| EGL 1.5 spec, eglReleaseThread can be called multiple times without error. |
| |
| Fixes: |
| dEQP-EGL.functional.thread_cleanup.multi_context_* |
| dEQP-EGL.functional.robustness.create_context.query_robust_access |
| --- |
| src/egl/main/eglcurrent.c | 26 +++++++++++++++++++++++++- |
| 1 file changed, 25 insertions(+), 1 deletion(-) |
| |
| diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c |
| index 479f231fb8f..d20ec64e654 100644 |
| --- a/src/egl/main/eglcurrent.c |
| +++ b/src/egl/main/eglcurrent.c |
| @@ -137,13 +137,37 @@ _eglDestroyThreadInfo(_EGLThreadInfo *t) |
| } |
| |
| |
| +/** |
| + * Delete/free a _EGLThreadInfo object. |
| + */ |
| +static void |
| +_eglDestroyThreadInfoCallback(_EGLThreadInfo *t) |
| +{ |
| + /* If this callback is called on thread termination then try to also give a |
| + * chance to cleanup to the client drivers. If called for module termination |
| + * then just release the thread information as calling eglReleaseThread |
| + * would result in a deadlock. |
| + */ |
| + if (_egl_TSDInitialized) { |
| + /* The callback handler has replaced the TLS entry, which is passed in as |
| + * 't', with NULL. Restore it here so that the release thread finds it in |
| + * the TLS entry. |
| + */ |
| + _eglSetTSD(t); |
| + eglReleaseThread(); |
| + } else { |
| + _eglDestroyThreadInfo(t); |
| + } |
| +} |
| + |
| + |
| /** |
| * Make sure TSD is initialized and return current value. |
| */ |
| static inline _EGLThreadInfo * |
| _eglCheckedGetTSD(void) |
| { |
| - if (_eglInitTSD(&_eglDestroyThreadInfo) != EGL_TRUE) { |
| + if (_eglInitTSD(&_eglDestroyThreadInfoCallback) != EGL_TRUE) { |
| _eglLog(_EGL_FATAL, "failed to initialize \"current\" system"); |
| return NULL; |
| } |
| -- |
| 2.22.0 |
| |