From 7eaceb03921eb0d12d1e92bc8a655ad23b253b17 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Fri, 9 Feb 2024 13:11:47 -0600 Subject: [PATCH] vulkan/wsi/wayland: Adjust presentation id locking If we want to use the new wl_display_dispatch_queue_timeout function in libwayland we lose the ability to drop the lock while we poll and pick it up again to dispatch. That would cause other waiters to potentially block past their timeouts while waiting for the dispatching thread's timeout. Prepare for this change now by dropping the lock for the entire dispatch, and reacquiring the lock in the functions being dispatched. Signed-off-by: Derek Foreman Part-of: --- src/vulkan/wsi/wsi_common_wayland.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c index b9298d4903b..65469e6109b 100644 --- a/src/vulkan/wsi/wsi_common_wayland.c +++ b/src/vulkan/wsi/wsi_common_wayland.c @@ -1762,6 +1762,7 @@ wsi_wl_swapchain_wait_for_present(struct wsi_swapchain *wsi_chain, assert(!chain->present_ids.dispatch_in_progress); chain->present_ids.dispatch_in_progress = true; + pthread_mutex_unlock(&chain->present_ids.lock); /* Whether or not we were dispatching the events before, we are now: pull * all the new events from our event queue, post them, and wake up everyone @@ -1777,7 +1778,9 @@ wsi_wl_swapchain_wait_for_present(struct wsi_swapchain *wsi_chain, if (ret > 0) { /* Completed our own present; stop our own dispatching and let * someone else pick it up. */ + pthread_mutex_lock(&chain->present_ids.lock); if (chain->present_ids.max_completed >= present_id) { + pthread_mutex_unlock(&chain->present_ids.lock); ret = VK_SUCCESS; goto relinquish_dispatch; } @@ -1785,6 +1788,7 @@ wsi_wl_swapchain_wait_for_present(struct wsi_swapchain *wsi_chain, /* Wake up other waiters who may have been unblocked by the events * we just read. */ pthread_cond_broadcast(&chain->present_ids.list_advanced); + pthread_mutex_unlock(&chain->present_ids.lock); } /* Check for timeout, and relinquish the dispatch to another thread @@ -1810,9 +1814,6 @@ wsi_wl_swapchain_wait_for_present(struct wsi_swapchain *wsi_chain, goto relinquish_dispatch; } - /* Drop the lock around poll, so people can wait whilst we sleep. */ - pthread_mutex_unlock(&chain->present_ids.lock); - struct pollfd pollfd = { .fd = wl_fd, .events = POLLIN @@ -1822,11 +1823,6 @@ wsi_wl_swapchain_wait_for_present(struct wsi_swapchain *wsi_chain, timespec_sub(&rel_timeout, &end_time, ¤t_time); ret = ppoll(&pollfd, 1, &rel_timeout, NULL); - /* Re-lock after poll; either we're dispatching events under the lock or - * bouncing out from an error also under the lock. We can't use timedlock - * here because we need to acquire to clear dispatch_in_progress. */ - pthread_mutex_lock(&chain->present_ids.lock); - if (ret <= 0) { int lerrno = errno; wl_display_cancel_read(wl_display); @@ -1849,6 +1845,7 @@ wsi_wl_swapchain_wait_for_present(struct wsi_swapchain *wsi_chain, } relinquish_dispatch: + pthread_mutex_lock(&chain->present_ids.lock); assert(chain->present_ids.dispatch_in_progress); chain->present_ids.dispatch_in_progress = false; pthread_cond_broadcast(&chain->present_ids.list_advanced); @@ -1909,12 +1906,13 @@ presentation_handle_sync_output(void *data, static void wsi_wl_presentation_update_present_id(struct wsi_wl_present_id *id) { - /* present_ids.lock already held around dispatch */ + pthread_mutex_lock(&id->chain->present_ids.lock); if (id->present_id > id->chain->present_ids.max_completed) id->chain->present_ids.max_completed = id->present_id; wl_list_remove(&id->link); vk_free(id->alloc, id); + pthread_mutex_unlock(&id->chain->present_ids.lock); } static void