From 03a57620a91b8c3eba1b5b75eeb34d7d7863c1f7 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 11 Jul 2025 11:57:46 -0400 Subject: [PATCH] zink: lock harder around memory mappings this addresses an ancient race condition where unmapping memory in one thread at the same time memory is mapped in a different thread could proceed without synchronization and result in the second thread writing to unmapped memory this was the actual cause of #12533 cc: mesa-stable Part-of: (cherry picked from commit 841080ed42aadeaf2303e075ebdd272fc0761b69) --- .pick_status.json | 2 +- src/gallium/drivers/zink/zink_bo.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 2dd8e67244d..7d6fc934b40 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -3104,7 +3104,7 @@ "description": "zink: lock harder around memory mappings", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null, "notes": null diff --git a/src/gallium/drivers/zink/zink_bo.c b/src/gallium/drivers/zink/zink_bo.c index be67b2c1e3a..76b97565650 100644 --- a/src/gallium/drivers/zink/zink_bo.c +++ b/src/gallium/drivers/zink/zink_bo.c @@ -704,6 +704,7 @@ zink_bo_map(struct zink_screen *screen, struct zink_bo *bo) offset = bo->offset - real->offset; } + p_atomic_inc(&real->u.real.map_count); cpu = p_atomic_read(&real->u.real.cpu_ptr); if (!cpu) { simple_mtx_lock(&real->lock); @@ -715,6 +716,7 @@ zink_bo_map(struct zink_screen *screen, struct zink_bo *bo) if (result != VK_SUCCESS) { mesa_loge("ZINK: vkMapMemory failed (%s)", vk_Result_to_str(result)); simple_mtx_unlock(&real->lock); + p_atomic_dec(&real->u.real.map_count); return NULL; } if (unlikely(zink_debug & ZINK_DEBUG_MAP)) { @@ -725,7 +727,6 @@ zink_bo_map(struct zink_screen *screen, struct zink_bo *bo) } simple_mtx_unlock(&real->lock); } - p_atomic_inc(&real->u.real.map_count); return (uint8_t*)cpu + offset; } @@ -738,12 +739,14 @@ zink_bo_unmap(struct zink_screen *screen, struct zink_bo *bo) assert(real->u.real.map_count != 0 && "too many unmaps"); if (p_atomic_dec_zero(&real->u.real.map_count)) { + simple_mtx_lock(&real->lock); p_atomic_set(&real->u.real.cpu_ptr, NULL); if (unlikely(zink_debug & ZINK_DEBUG_MAP)) { p_atomic_add(&screen->mapped_vram, -real->base.base.size); mesa_loge("UNMAP(%"PRIu64") TOTAL(%"PRIu64")", real->base.base.size, screen->mapped_vram); } VKSCR(UnmapMemory)(screen->dev, real->mem); + simple_mtx_unlock(&real->lock); } }