mesa: fix glthread deadlock when EGL multi thread shared context

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 <marek.olsak@amd.com>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
Signed-off-by: Qiang Yu <yuq825@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12336>
This commit is contained in:
Qiang Yu
2021-08-11 13:30:31 +08:00
committed by Marge Bot
parent be4f5f1c92
commit 1fd3cf990e
3 changed files with 12 additions and 2 deletions
+3 -1
View File
@@ -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);
}
+7
View File
@@ -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);
+2 -1
View File
@@ -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;
}