From 9cfb950bc704d4f984f5a39838634c73a5765bac Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Jul 2022 10:34:04 +1000 Subject: [PATCH] kms/dri: add mutex lock around map/unmap this can get called from multiple threads with the recent llvmpipe overlapping rendering changes, so make sure to lock around the map/unmapping so they can't race. This should fixes some crashes seen with kwin. --- .../winsys/sw/kms-dri/kms_dri_sw_winsys.c | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c index a26ff0ffe35..aa1257acea9 100644 --- a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c +++ b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c @@ -55,6 +55,8 @@ #include "frontend/drm_driver.h" #include "kms_dri_sw_winsys.h" +#include "util/simple_mtx.h" + #ifdef DEBUG #define DEBUG_PRINT(msg, ...) fprintf(stderr, msg, __VA_ARGS__) #else @@ -86,6 +88,7 @@ struct kms_sw_displaytarget int map_count; struct list_head link; struct list_head planes; + mtx_t map_lock; }; struct kms_sw_winsys @@ -183,6 +186,8 @@ kms_sw_displaytarget_create(struct sw_winsys *ws, kms_sw_dt->format = format; + mtx_init(&kms_sw_dt->map_lock, mtx_plain); + memset(&create_req, 0, sizeof(create_req)); create_req.bpp = util_format_get_blocksizebits(format); create_req.width = width; @@ -239,6 +244,7 @@ kms_sw_displaytarget_destroy(struct sw_winsys *ws, list_del(&kms_sw_dt->link); + mtx_destroy(&kms_sw_dt->map_lock); DEBUG_PRINT("KMS-DEBUG: destroyed buffer %u\n", kms_sw_dt->handle); struct kms_sw_plane *tmp; @@ -260,11 +266,12 @@ kms_sw_displaytarget_map(struct sw_winsys *ws, struct drm_mode_map_dumb map_req; int prot, ret; + mtx_lock(&kms_sw_dt->map_lock); memset(&map_req, 0, sizeof map_req); map_req.handle = kms_sw_dt->handle; ret = drmIoctl(kms_sw->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_req); if (ret) - return NULL; + goto fail_locked; prot = (flags == PIPE_MAP_READ) ? PROT_READ : (PROT_READ | PROT_WRITE); void **ptr = (flags == PIPE_MAP_READ) ? &kms_sw_dt->ro_mapped : &kms_sw_dt->mapped; @@ -272,7 +279,7 @@ kms_sw_displaytarget_map(struct sw_winsys *ws, void *tmp = mmap(NULL, kms_sw_dt->size, prot, MAP_SHARED, kms_sw->fd, map_req.offset); if (tmp == MAP_FAILED) - return NULL; + goto fail_locked; *ptr = tmp; } @@ -281,7 +288,12 @@ kms_sw_displaytarget_map(struct sw_winsys *ws, kms_sw_dt->map_count++; + mtx_unlock(&kms_sw_dt->map_lock); + return *ptr + plane->offset; +fail_locked: + mtx_unlock(&kms_sw_dt->map_lock); + return NULL; } static struct kms_sw_displaytarget * @@ -363,13 +375,16 @@ kms_sw_displaytarget_unmap(struct sw_winsys *ws, struct kms_sw_plane *plane = kms_sw_plane(dt); struct kms_sw_displaytarget *kms_sw_dt = plane->dt; + mtx_lock(&kms_sw_dt->map_lock); if (!kms_sw_dt->map_count) { DEBUG_PRINT("KMS-DEBUG: ignore duplicated unmap %u", kms_sw_dt->handle); + mtx_unlock(&kms_sw_dt->map_lock); return; } kms_sw_dt->map_count--; if (kms_sw_dt->map_count) { DEBUG_PRINT("KMS-DEBUG: ignore unmap for busy buffer %u", kms_sw_dt->handle); + mtx_unlock(&kms_sw_dt->map_lock); return; } @@ -384,6 +399,7 @@ kms_sw_displaytarget_unmap(struct sw_winsys *ws, munmap(kms_sw_dt->ro_mapped, kms_sw_dt->size); kms_sw_dt->ro_mapped = MAP_FAILED; } + mtx_unlock(&kms_sw_dt->map_lock); } static struct sw_displaytarget * -- 2.37.0