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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36076>
(cherry picked from commit 841080ed42)
This commit is contained in:
Mike Blumenkrantz 2025-07-11 11:57:46 -04:00 committed by Eric Engestrom
parent 824a06fd6b
commit 03a57620a9
2 changed files with 5 additions and 2 deletions

View file

@ -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

View file

@ -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);
}
}