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