Mesa (main): asahi: Fix hangs waiting on the notification queue
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Tue May 17 15:07:05 UTC 2022
Module: Mesa
Branch: main
Commit: 6b1e73c700f3ecb8115cbf8da7ebf9770772d1dc
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=6b1e73c700f3ecb8115cbf8da7ebf9770772d1dc
Author: Alyssa Rosenzweig <alyssa at rosenzweig.io>
Date: Sun May 15 12:57:31 2022 -0400
asahi: Fix hangs waiting on the notification queue
Dequeue and WaitForAvailableData can race. Restructure the loop to avoid
this. Fixes all timeouts in dEQP.
Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16518>
---
src/asahi/lib/agx_device.c | 44 ++++++++++++++++++++++++++++++--------------
1 file changed, 30 insertions(+), 14 deletions(-)
diff --git a/src/asahi/lib/agx_device.c b/src/asahi/lib/agx_device.c
index 30efa97a236..5fb8d9d1d43 100644
--- a/src/asahi/lib/agx_device.c
+++ b/src/asahi/lib/agx_device.c
@@ -465,23 +465,39 @@ agx_submit_cmdbuf(struct agx_device *dev, unsigned cmdbuf, unsigned mappings, ui
#endif
}
+/*
+ * Wait for a frame to finish rendering.
+ *
+ * The macOS kernel indicates that rendering has finished using a notification
+ * queue. The kernel will send two messages on the notification queue. The
+ * second message indicates that rendering has completed. This simple routine
+ * waits for both messages. It's important that IODataQueueDequeue is used in a
+ * loop to flush the entire queue before calling
+ * IODataQueueWaitForAvailableData. Otherwise, we can race and get stuck in
+ * WaitForAvailabaleData.
+ */
void
agx_wait_queue(struct agx_command_queue queue)
{
#if __APPLE__
- IOReturn ret = IODataQueueWaitForAvailableData(queue.notif.queue, queue.notif.port);
-
- uint64_t data[4];
- unsigned sz = sizeof(data);
- ret = IODataQueueDequeue(queue.notif.queue, data, &sz);
- assert(sz == sizeof(data));
- assert(data[0] == 0xABCD);
-
- ret = IODataQueueWaitForAvailableData(queue.notif.queue, queue.notif.port);
- ret = IODataQueueDequeue(queue.notif.queue, data, &sz);
- assert(sz == sizeof(data));
- assert(data[0] == 0x1234);
-
- assert(!IODataQueueDataAvailable(queue.notif.queue));
+ uint64_t data[4];
+ unsigned sz = sizeof(data);
+ unsigned message_id = 0;
+ uint64_t magic_numbers[2] = { 0xABCD, 0x1234 };
+
+ while (message_id < 2) {
+ IOReturn ret = IODataQueueWaitForAvailableData(queue.notif.queue, queue.notif.port);
+
+ if (ret) {
+ fprintf(stderr, "Error waiting for available data\n");
+ return;
+ }
+
+ while (IODataQueueDequeue(queue.notif.queue, data, &sz) == kIOReturnSuccess) {
+ assert(sz == sizeof(data));
+ assert(data[0] == magic_numbers[message_id]);
+ message_id++;
+ }
+ }
#endif
}
More information about the mesa-commit
mailing list