vulkan/wsi/x11: Use mtx_t and u_cnd_monotonic

Reviewed-by: Derek Foreman <derek.foreman@collabora.com>
Reviewed-by: Tatsuyuki Ishi <ishitatsuyuki@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29924>
This commit is contained in:
Faith Ekstrand
2024-06-26 15:04:21 -05:00
committed by Marge Bot
parent 3ba664c640
commit 7aac3ea26a
+64 -63
View File
@@ -44,6 +44,7 @@
#include <fcntl.h>
#include <xf86drm.h>
#include "drm-uapi/drm_fourcc.h"
#include "util/cnd_monotonic.h"
#include "util/hash_table.h"
#include "util/mesa-blake3.h"
#include "util/os_file.h"
@@ -89,7 +90,7 @@ struct wsi_x11_connection {
struct wsi_x11 {
struct wsi_interface base;
pthread_mutex_t mutex;
mtx_t mutex;
/* Hash table of xcb_connection -> wsi_x11_connection mappings */
struct hash_table *connections;
};
@@ -415,21 +416,21 @@ wsi_x11_get_connection(struct wsi_device *wsi_dev,
struct wsi_x11 *wsi =
(struct wsi_x11 *)wsi_dev->wsi[VK_ICD_WSI_PLATFORM_XCB];
pthread_mutex_lock(&wsi->mutex);
mtx_lock(&wsi->mutex);
struct hash_entry *entry = _mesa_hash_table_search(wsi->connections, conn);
if (!entry) {
/* We're about to make a bunch of blocking calls. Let's drop the
* mutex for now so we don't block up too badly.
*/
pthread_mutex_unlock(&wsi->mutex);
mtx_unlock(&wsi->mutex);
struct wsi_x11_connection *wsi_conn =
wsi_x11_connection_create(wsi_dev, conn);
if (!wsi_conn)
return NULL;
pthread_mutex_lock(&wsi->mutex);
mtx_lock(&wsi->mutex);
entry = _mesa_hash_table_search(wsi->connections, conn);
if (entry) {
@@ -440,7 +441,7 @@ wsi_x11_get_connection(struct wsi_device *wsi_dev,
}
}
pthread_mutex_unlock(&wsi->mutex);
mtx_unlock(&wsi->mutex);
return entry->data;
}
@@ -1109,13 +1110,13 @@ struct x11_swapchain {
* Lock is also taken when reading and writing status.
* When reading status in application threads,
* x11_swapchain_read_status_atomic can be used as a wrapper function. */
pthread_mutex_t thread_state_lock;
pthread_cond_t thread_state_cond;
mtx_t thread_state_lock;
struct u_cnd_monotonic thread_state_cond;
/* Lock and condition variable for present wait.
* Signalled by event thread and waited on by callers to PresentWaitKHR. */
pthread_mutex_t present_progress_mutex;
pthread_cond_t present_progress_cond;
mtx_t present_progress_mutex;
struct u_cnd_monotonic present_progress_cond;
uint64_t present_id;
VkResult present_progress_error;
@@ -1129,12 +1130,12 @@ static void x11_present_complete(struct x11_swapchain *swapchain,
{
uint64_t signal_present_id = image->pending_completions[index].signal_present_id;
if (signal_present_id) {
pthread_mutex_lock(&swapchain->present_progress_mutex);
mtx_lock(&swapchain->present_progress_mutex);
if (signal_present_id > swapchain->present_id) {
swapchain->present_id = signal_present_id;
pthread_cond_broadcast(&swapchain->present_progress_cond);
u_cnd_monotonic_broadcast(&swapchain->present_progress_cond);
}
pthread_mutex_unlock(&swapchain->present_progress_mutex);
mtx_unlock(&swapchain->present_progress_mutex);
}
image->present_queued_count--;
@@ -1145,24 +1146,24 @@ static void x11_present_complete(struct x11_swapchain *swapchain,
sizeof(image->pending_completions[0]));
}
pthread_cond_signal(&swapchain->thread_state_cond);
u_cnd_monotonic_signal(&swapchain->thread_state_cond);
}
static void x11_notify_pending_present(struct x11_swapchain *swapchain,
struct x11_image *image)
{
pthread_cond_signal(&swapchain->thread_state_cond);
u_cnd_monotonic_signal(&swapchain->thread_state_cond);
}
/* It is assumed that thread_state_lock is taken when calling this function. */
static void x11_swapchain_notify_error(struct x11_swapchain *swapchain, VkResult result)
{
pthread_mutex_lock(&swapchain->present_progress_mutex);
mtx_lock(&swapchain->present_progress_mutex);
swapchain->present_id = UINT64_MAX;
swapchain->present_progress_error = result;
pthread_cond_broadcast(&swapchain->present_progress_cond);
pthread_mutex_unlock(&swapchain->present_progress_mutex);
pthread_cond_broadcast(&swapchain->thread_state_cond);
u_cnd_monotonic_broadcast(&swapchain->present_progress_cond);
mtx_unlock(&swapchain->present_progress_mutex);
u_cnd_monotonic_broadcast(&swapchain->thread_state_cond);
}
/**
@@ -1736,9 +1737,9 @@ x11_acquire_next_image(struct wsi_swapchain *anv_chain,
return info->timeout ? VK_TIMEOUT : VK_NOT_READY;
if (result < 0) {
pthread_mutex_lock(&chain->thread_state_lock);
mtx_lock(&chain->thread_state_lock);
result = x11_swapchain_result(chain, result);
pthread_mutex_unlock(&chain->thread_state_lock);
mtx_unlock(&chain->thread_state_lock);
} else {
result = x11_swapchain_read_status_atomic(chain);
}
@@ -1836,7 +1837,7 @@ x11_manage_event_queue(void *state)
* but we don't know which mode is being used. */
unsigned forward_progress_guaranteed_acquired_images = chain->base.image_count - 1;
pthread_mutex_lock(&chain->thread_state_lock);
mtx_lock(&chain->thread_state_lock);
while (chain->status >= 0) {
/* This thread should only go sleep waiting for X events when we know there are pending events.
@@ -1862,10 +1863,10 @@ x11_manage_event_queue(void *state)
if (assume_forward_progress) {
/* Only yield lock when blocking on X11 event. */
pthread_mutex_unlock(&chain->thread_state_lock);
mtx_unlock(&chain->thread_state_lock);
xcb_generic_event_t *event =
xcb_wait_for_special_event(chain->conn, chain->special_event);
pthread_mutex_lock(&chain->thread_state_lock);
mtx_lock(&chain->thread_state_lock);
/* Re-check status since we dropped the lock while waiting for X. */
VkResult result = chain->status;
@@ -1888,11 +1889,11 @@ x11_manage_event_queue(void *state)
free(event);
} else {
/* Nothing important to do, go to sleep until queue thread wakes us up. */
pthread_cond_wait(&chain->thread_state_cond, &chain->thread_state_lock);
u_cnd_monotonic_wait(&chain->thread_state_cond, &chain->thread_state_lock);
}
}
pthread_mutex_unlock(&chain->thread_state_lock);
mtx_unlock(&chain->thread_state_lock);
return 0;
}
@@ -1952,25 +1953,25 @@ x11_manage_present_queue(void *state)
}
}
pthread_mutex_lock(&chain->thread_state_lock);
mtx_lock(&chain->thread_state_lock);
/* In IMMEDIATE and MAILBOX modes, there is a risk that we have exhausted the presentation queue,
* since IDLE could return multiple times before observing a COMPLETE. */
while (chain->status >= 0 &&
chain->images[image_index].present_queued_count ==
ARRAY_SIZE(chain->images[image_index].pending_completions)) {
pthread_cond_wait(&chain->thread_state_cond, &chain->thread_state_lock);
u_cnd_monotonic_wait(&chain->thread_state_cond, &chain->thread_state_lock);
}
if (chain->status < 0) {
pthread_mutex_unlock(&chain->thread_state_lock);
mtx_unlock(&chain->thread_state_lock);
break;
}
result = x11_present_to_x11(chain, image_index, target_msc, present_mode);
if (result < 0) {
pthread_mutex_unlock(&chain->thread_state_lock);
mtx_unlock(&chain->thread_state_lock);
break;
}
@@ -1981,7 +1982,7 @@ x11_manage_present_queue(void *state)
while (chain->status >= 0 && chain->images[image_index].present_queued_count != 0) {
/* In FIFO mode, we need to make sure we observe a COMPLETE before queueing up
* another present. */
pthread_cond_wait(&chain->thread_state_cond, &chain->thread_state_lock);
u_cnd_monotonic_wait(&chain->thread_state_cond, &chain->thread_state_lock);
}
/* If next present is not FIFO, we still need to ensure we don't override that
@@ -1989,14 +1990,14 @@ x11_manage_present_queue(void *state)
target_msc = chain->last_present_msc + 1;
}
pthread_mutex_unlock(&chain->thread_state_lock);
mtx_unlock(&chain->thread_state_lock);
}
pthread_mutex_lock(&chain->thread_state_lock);
mtx_lock(&chain->thread_state_lock);
x11_swapchain_result(chain, result);
if (!chain->base.image_info.explicit_sync)
wsi_queue_push(&chain->acquire_queue, UINT32_MAX);
pthread_mutex_unlock(&chain->thread_state_lock);
mtx_unlock(&chain->thread_state_lock);
return 0;
}
@@ -2363,10 +2364,10 @@ x11_swapchain_destroy(struct wsi_swapchain *anv_chain,
struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain;
xcb_void_cookie_t cookie;
pthread_mutex_lock(&chain->thread_state_lock);
mtx_lock(&chain->thread_state_lock);
chain->status = VK_ERROR_OUT_OF_DATE_KHR;
pthread_cond_broadcast(&chain->thread_state_cond);
pthread_mutex_unlock(&chain->thread_state_lock);
u_cnd_monotonic_broadcast(&chain->thread_state_cond);
mtx_unlock(&chain->thread_state_lock);
/* Push a UINT32_MAX to wake up the manager */
wsi_queue_push(&chain->present_queue, UINT32_MAX);
@@ -2386,10 +2387,10 @@ x11_swapchain_destroy(struct wsi_swapchain *anv_chain,
XCB_PRESENT_EVENT_MASK_NO_EVENT);
xcb_discard_reply(chain->conn, cookie.sequence);
pthread_mutex_destroy(&chain->present_progress_mutex);
pthread_cond_destroy(&chain->present_progress_cond);
pthread_mutex_destroy(&chain->thread_state_lock);
pthread_cond_destroy(&chain->thread_state_cond);
mtx_destroy(&chain->present_progress_mutex);
u_cnd_monotonic_destroy(&chain->present_progress_cond);
mtx_destroy(&chain->thread_state_lock);
u_cnd_monotonic_destroy(&chain->thread_state_cond);
wsi_swapchain_finish(&chain->base);
@@ -2443,11 +2444,11 @@ static VkResult x11_wait_for_present(struct wsi_swapchain *wsi_chain,
timespec_from_nsec(&abs_timespec, abs_timeout);
pthread_mutex_lock(&chain->present_progress_mutex);
mtx_lock(&chain->present_progress_mutex);
while (chain->present_id < waitValue) {
int ret = pthread_cond_timedwait(&chain->present_progress_cond,
&chain->present_progress_mutex,
&abs_timespec);
int ret = u_cnd_monotonic_timedwait(&chain->present_progress_cond,
&chain->present_progress_mutex,
&abs_timespec);
if (ret == ETIMEDOUT) {
result = VK_TIMEOUT;
break;
@@ -2459,7 +2460,7 @@ static VkResult x11_wait_for_present(struct wsi_swapchain *wsi_chain,
}
if (result == VK_SUCCESS && chain->present_progress_error)
result = chain->present_progress_error;
pthread_mutex_unlock(&chain->present_progress_mutex);
mtx_unlock(&chain->present_progress_mutex);
return result;
}
@@ -2542,32 +2543,32 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
if (chain == NULL)
return VK_ERROR_OUT_OF_HOST_MEMORY;
int ret = pthread_mutex_init(&chain->present_progress_mutex, NULL);
if (ret != 0) {
int ret = mtx_init(&chain->present_progress_mutex, mtx_plain);
if (ret != thrd_success) {
vk_free(pAllocator, chain);
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
ret = pthread_mutex_init(&chain->thread_state_lock, NULL);
if (ret != 0) {
pthread_mutex_destroy(&chain->present_progress_mutex);
ret = mtx_init(&chain->thread_state_lock, mtx_plain);
if (ret != thrd_success) {
mtx_destroy(&chain->present_progress_mutex);
vk_free(pAllocator, chain);
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
ret = pthread_cond_init(&chain->thread_state_cond, NULL);
if (ret != 0) {
pthread_mutex_destroy(&chain->present_progress_mutex);
pthread_mutex_destroy(&chain->thread_state_lock);
ret = u_cnd_monotonic_init(&chain->thread_state_cond);
if (ret != thrd_success) {
mtx_destroy(&chain->present_progress_mutex);
mtx_destroy(&chain->thread_state_lock);
vk_free(pAllocator, chain);
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
bool bret = wsi_init_pthread_cond_monotonic(&chain->present_progress_cond);
if (!bret) {
pthread_mutex_destroy(&chain->present_progress_mutex);
pthread_mutex_destroy(&chain->thread_state_lock);
pthread_cond_destroy(&chain->thread_state_cond);
ret = u_cnd_monotonic_init(&chain->present_progress_cond);
if (ret != thrd_success) {
mtx_destroy(&chain->present_progress_mutex);
mtx_destroy(&chain->thread_state_lock);
u_cnd_monotonic_destroy(&chain->thread_state_cond);
vk_free(pAllocator, chain);
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
@@ -2802,8 +2803,8 @@ wsi_x11_init_wsi(struct wsi_device *wsi_device,
goto fail;
}
int ret = pthread_mutex_init(&wsi->mutex, NULL);
if (ret != 0) {
int ret = mtx_init(&wsi->mutex, mtx_plain);
if (ret != thrd_success) {
if (ret == ENOMEM) {
result = VK_ERROR_OUT_OF_HOST_MEMORY;
} else {
@@ -2860,7 +2861,7 @@ wsi_x11_init_wsi(struct wsi_device *wsi_device,
return VK_SUCCESS;
fail_mutex:
pthread_mutex_destroy(&wsi->mutex);
mtx_destroy(&wsi->mutex);
fail_alloc:
vk_free(alloc, wsi);
fail:
@@ -2883,7 +2884,7 @@ wsi_x11_finish_wsi(struct wsi_device *wsi_device,
_mesa_hash_table_destroy(wsi->connections, NULL);
pthread_mutex_destroy(&wsi->mutex);
mtx_destroy(&wsi->mutex);
vk_free(alloc, wsi);
}