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:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user