[PATCH xf86-video-ati 06/13] Move deferred vblank events to separate drm_vblank_deferred list

Michel Dänzer michel at daenzer.net
Fri Dec 21 17:49:00 UTC 2018


From: Michel Dänzer <michel.daenzer at amd.com>

It was still possible for nested xorg_list_for_each_entry_safe loops
to occur over the drm_vblank_signalled list, which could mess up that
list. Moving deferred events to a separate list allows processing the
drm_vblank_signalled list without xorg_list_for_each_entry_safe.

Bugzilla: https://bugs.freedesktop.org/108600
(Ported from amdgpu commit 51ba6dddee40c3688d4c7b12eabeab516ed153b7)

Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
 src/radeon_drm_queue.c | 57 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 46 insertions(+), 11 deletions(-)

diff --git a/src/radeon_drm_queue.c b/src/radeon_drm_queue.c
index acfea3daf..d8a8243c5 100644
--- a/src/radeon_drm_queue.c
+++ b/src/radeon_drm_queue.c
@@ -56,6 +56,7 @@ static int radeon_drm_queue_refcnt;
 static struct xorg_list radeon_drm_queue;
 static struct xorg_list radeon_drm_flip_signalled;
 static struct xorg_list radeon_drm_vblank_signalled;
+static struct xorg_list radeon_drm_vblank_deferred;
 static uintptr_t radeon_drm_queue_seq;
 
 
@@ -111,6 +112,31 @@ radeon_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
     }
 }
 
+/*
+ * Handle signalled vblank events. If we're waiting for a flip event,
+ * put events for that CRTC in the vblank_deferred list.
+ */
+static void
+radeon_drm_handle_vblank_signalled(void)
+{
+    drmmode_crtc_private_ptr drmmode_crtc;
+    struct radeon_drm_queue_entry *e;
+
+    while (!xorg_list_is_empty(&radeon_drm_vblank_signalled)) {
+	e = xorg_list_first_entry(&radeon_drm_vblank_signalled,
+				  struct radeon_drm_queue_entry, list);
+	drmmode_crtc = e->crtc->driver_private;
+
+	if (drmmode_crtc->wait_flip_nesting_level == 0) {
+	    radeon_drm_queue_handle_one(e);
+	    continue;
+	}
+
+	xorg_list_del(&e->list);
+	xorg_list_append(&e->list, &radeon_drm_vblank_deferred);
+    }
+}
+
 /*
  * Handle deferred DRM vblank events
  *
@@ -127,12 +153,18 @@ radeon_drm_queue_handle_deferred(xf86CrtcPtr crtc)
 	--drmmode_crtc->wait_flip_nesting_level > 0)
 	return;
 
-    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list) {
-	drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private;
+    /* Put previously deferred vblank events for this CRTC back in the
+     * signalled queue
+     */
+    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_deferred, list) {
+	if (e->crtc != crtc)
+	    continue;
 
-	if (drmmode_crtc->wait_flip_nesting_level == 0)
-	    radeon_drm_queue_handle_one(e);
+	xorg_list_del(&e->list);
+	xorg_list_append(&e->list, &radeon_drm_vblank_signalled);
     }
+
+    radeon_drm_handle_vblank_signalled();
 }
 
 /*
@@ -205,6 +237,13 @@ radeon_drm_abort_entry(uintptr_t seq)
 	}
     }
 
+    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_deferred, list) {
+	if (e->seq == seq) {
+	    radeon_drm_abort_one(e);
+	    return;
+	}
+    }
+
     xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
 	if (e->seq == seq) {
 	    radeon_drm_abort_one(e);
@@ -235,7 +274,7 @@ radeon_drm_abort_id(uint64_t id)
 int
 radeon_drm_handle_event(int fd, drmEventContext *event_context)
 {
-    struct radeon_drm_queue_entry *e, *tmp;
+    struct radeon_drm_queue_entry *e;
     int r;
 
     r = drmHandleEvent(fd, event_context);
@@ -246,12 +285,7 @@ radeon_drm_handle_event(int fd, drmEventContext *event_context)
 	radeon_drm_queue_handle_one(e);
     }
 
-    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list) {
-	drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private;
-
-	if (drmmode_crtc->wait_flip_nesting_level == 0)
-	    radeon_drm_queue_handle_one(e);
-    }
+    radeon_drm_handle_vblank_signalled();
 
     return r;
 }
@@ -298,6 +332,7 @@ radeon_drm_queue_init(ScrnInfoPtr scrn)
     xorg_list_init(&radeon_drm_queue);
     xorg_list_init(&radeon_drm_flip_signalled);
     xorg_list_init(&radeon_drm_vblank_signalled);
+    xorg_list_init(&radeon_drm_vblank_deferred);
 }
 
 /*
-- 
2.20.1



More information about the amd-gfx mailing list