From 1fd3cf990eb610da300374687ef146f92f0ebef5 Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Wed, 11 Aug 2021 13:30:31 +0800 Subject: [PATCH] mesa: fix glthread deadlock when EGL multi thread shared context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes dEQP EGL tests when glthread is enabled: dEQP-EGL.functional.sharing.gles2.multithread.random.images.copyteximage2d.* dEQP-EGL.functional.sharing.gles2.multithread.random.images.texsubimage2d.* dEQP-EGL.functional.sharing.gles2.multithread.random_egl_server_sync.images.teximage2d.* dEQP-EGL.functional.sharing.gles2.multithread.random_egl_server_sync.images.texsubimage2d.* dEQP-EGL.functional.sharing.gles2.multithread.random_egl_sync.images.copyteximage2d.* dEQP-EGL.functional.sharing.gles2.multithread.random_egl_sync.images.texsubimage2d.* Deadlock happens when: Thread A: call EGL context functions which will involve _mesa_glthread_finish(), like eglMakeCurrent() and eglDestroyContext(). It will hold the EGLDisplay.Mutex and wait on glthread job queue empty (util_queue_fence_wait(&last->fence)). glthread job thread executes batch holding gl_context.Shared.TexMutex (glthread_unmarshal_batch()). Thread B: call EGLImage import functions like EGLImageTargetTexture2DOES() which will hold gl_context.Shared.TexMutex (egl_image_target_texture()) then validate EGLImage and hold EGLDisplay.Mutex (dri2_lookup_egl_image()). This fixes the deadlock by moving the EGLImage validation out of gl_context.Shared.TexMutex lock area. Reviewed-by: Marek Olšák Reviewed-by: Emil Velikov Signed-off-by: Qiang Yu Part-of: --- src/gallium/frontends/dri/dri_screen.c | 4 +++- src/mesa/main/fbobject.c | 7 +++++++ src/mesa/main/teximage.c | 3 ++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/gallium/frontends/dri/dri_screen.c b/src/gallium/frontends/dri/dri_screen.c index 7866ee0fdb3..be33a6b8a2b 100644 --- a/src/gallium/frontends/dri/dri_screen.c +++ b/src/gallium/frontends/dri/dri_screen.c @@ -435,7 +435,9 @@ dri_get_egl_image(struct st_manager *smapi, __DRIimage *img = NULL; const struct dri2_format_mapping *map; - if (screen->lookup_egl_image) { + if (screen->lookup_egl_image_validated) { + img = screen->lookup_egl_image_validated(screen, egl_image); + } else if (screen->lookup_egl_image) { img = screen->lookup_egl_image(screen, egl_image); } diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index f9797ba6fc4..a848c1df799 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -2749,6 +2749,13 @@ _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) return; } + if (!image || (ctx->Driver.ValidateEGLImage && + !ctx->Driver.ValidateEGLImage(ctx, image))) { + _mesa_error(ctx, GL_INVALID_VALUE, + "EGLImageTargetRenderbufferStorageOES"); + return; + } + FLUSH_VERTICES(ctx, _NEW_BUFFERS, 0); ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image); diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 71c5f2b299f..41714dc9b0d 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -3421,7 +3421,8 @@ egl_image_target_texture(struct gl_context *ctx, return; } - if (!image) { + if (!image || (ctx->Driver.ValidateEGLImage && + !ctx->Driver.ValidateEGLImage(ctx, image))) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(image=%p)", caller, image); return; }