From 09e3a1b1cb15b8a4e396542b4fcbb3ec6281a6ff Mon Sep 17 00:00:00 2001 From: Aizal Khan Date: Fri, 2 Oct 2026 00:08:14 +0530 Subject: [PATCH] take loader_lock in terminator_DestroySurfaceKHR --- loader/wsi.c | 5 +++++ tests/loader_threading_tests.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/loader/wsi.c b/loader/wsi.c index cbd866e3d..cf3f7c677 100644 --- a/loader/wsi.c +++ b/loader/wsi.c @@ -337,6 +337,10 @@ VKAPI_ATTR void VKAPI_CALL terminator_DestroySurfaceKHR(VkInstance instance, VkS return; } #endif // VK_USE_PLATFORM_MACOS_MVK + // Every surface creation terminator holds loader_lock while it reserves a slot in loader_inst->surfaces_list and + // grows each driver's surface_list, either of which can reallocate the list. vkDestroySurfaceKHR only requires + // the surface itself to be externally synchronized, so take the same lock before touching that shared state. + loader_platform_thread_lock_mutex(&loader_lock); for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { if (icd_term->enabled_instance_extensions.khr_surface && icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR && @@ -360,6 +364,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_DestroySurfaceKHR(VkInstance instance, VkS loader_instance_heap_free(loader_inst, icd_surface->create_info); } loader_release_object_from_list(&loader_inst->surfaces_list, icd_surface->surface_index); + loader_platform_thread_unlock_mutex(&loader_lock); // NOLINTNEXTLINE(performance-no-int-to-ptr) - decoding the loader-internal pointer out of the handle loader_instance_heap_free(loader_inst, (void *)(uintptr_t)surface); } diff --git a/tests/loader_threading_tests.cpp b/tests/loader_threading_tests.cpp index 4d4efa82f..499cfae55 100644 --- a/tests/loader_threading_tests.cpp +++ b/tests/loader_threading_tests.cpp @@ -172,3 +172,30 @@ TEST(Threading, SetDebugUtilsNameCreateDestroyLoop) { set_debug_name_threads[i].join(); } } + +void create_destroy_surface_loop(FrameworkEnvironment* env, uint32_t num_loops, InstWrapper* inst) { + for (uint32_t i = 0; i < num_loops; i++) { + VkSurfaceKHR surface{}; + ASSERT_EQ(VK_SUCCESS, create_surface(*inst, surface)); + env->vulkan_functions.vkDestroySurfaceKHR(inst->inst, surface, nullptr); + } +} + +TEST(Threading, SurfaceCreateDestroyLoop) { + const auto processor_count = std::thread::hardware_concurrency(); + uint32_t num_loops = 100; + FrameworkEnvironment env{FrameworkSettings{}.set_log_filter("")}; + env.add_icd(TEST_ICD_PATH_VERSION_2).setup_WSI().add_physical_device({}); + + InstWrapper inst{env.vulkan_functions}; + inst.create_info.setup_WSI(); + inst.CheckCreate(); + + std::vector surface_threads; + for (uint32_t i = 0; i < processor_count; i++) { + surface_threads.emplace_back(create_destroy_surface_loop, &env, num_loops, &inst); + } + for (uint32_t i = 0; i < processor_count; i++) { + surface_threads[i].join(); + } +}