xf86-video-intel: 4 commits - src/sna/sna_dri.c test/dri2-race.c test/Makefile.am

Chris Wilson ickle at kemper.freedesktop.org
Mon Mar 11 09:42:11 PDT 2013


 src/sna/sna_dri.c |   49 +++++++++++++----------
 test/Makefile.am  |    1 
 test/dri2-race.c  |  113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 143 insertions(+), 20 deletions(-)

New commits:
commit 17a99f0743836997aa8e4f7eafc0ea4978244f44
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 11 16:41:16 2013 +0000

    sna/dri: Free the event on the impossible error path
    
    Just in case we end up with bogus data, don't leak.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 172855a..127793f 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -1692,10 +1692,12 @@ static void sna_dri_flip_event(struct sna *sna,
 		}
 		break;
 
-	default:
+	default: /* Unknown type */
 		xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING,
 			   "%s: unknown vblank event received\n", __func__);
-		/* Unknown type */
+		sna_dri_frame_event_info_free(sna, flip->draw, flip);
+		if (sna->dri.flip_pending)
+			chain_flip(sna);
 		break;
 	}
 }
commit 9d097d5140857fad209ee5c2c8b5461aac54e81e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 11 16:39:11 2013 +0000

    sna/dri: Free chained swaps upon CloseWindow
    
    The assumption that the chained swaps are freed after the next vblank
    turns out to be wrong, and in effect we would leak the bo if we
    happened to submit the final swap faster than vrefresh and close the
    window before the vblank.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index c18bfbf..172855a 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -1041,21 +1041,6 @@ sna_dri_remove_frame_event(WindowPtr win,
 	chain->chain = info->chain;
 }
 
-void sna_dri_destroy_window(WindowPtr win)
-{
-	struct sna_dri_frame_event *chain;
-
-	chain = sna_dri_window_get_chain(win);
-	if (chain == NULL)
-		return;
-
-	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.serialNumber));
-	while (chain) {
-		chain->draw = NULL;
-		chain = chain->chain;
-	}
-}
-
 static void
 sna_dri_add_frame_event(DrawablePtr draw, struct sna_dri_frame_event *info)
 {
@@ -1107,6 +1092,27 @@ sna_dri_frame_event_info_free(struct sna *sna,
 	free(info);
 }
 
+void sna_dri_destroy_window(WindowPtr win)
+{
+	struct sna *sna = to_sna_from_drawable(&win->drawable);
+	struct sna_dri_frame_event *info, *chain;
+
+	info = sna_dri_window_get_chain(win);
+	if (info == NULL)
+		return;
+
+	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.serialNumber));
+	info->draw = NULL;
+
+	chain = info->chain;
+	info->chain = NULL;
+
+	while ((info = chain)) {
+		chain = info->chain;
+		sna_dri_frame_event_info_free(sna, NULL, info);
+	}
+}
+
 static bool
 sna_dri_page_flip(struct sna *sna, struct sna_dri_frame_event *info)
 {
@@ -1725,8 +1731,8 @@ sna_dri_immediate_blit(struct sna *sna,
 	if (sna->flags & SNA_NO_WAIT)
 		sync = false;
 
-	DBG(("%s: emitting immediate blit, throttling client, synced? %d\n",
-	     __FUNCTION__, sync));
+	DBG(("%s: emitting immediate blit, throttling client, synced? %d, chained? %d\n",
+	     __FUNCTION__, sync, sna_dri_window_get_chain((WindowPtr)draw) == info));
 
 	if (sync) {
 		info->type = DRI2_SWAP_THROTTLE;
commit 2f6a9927952e25aa2a1628e66295f0903dcf865c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 11 14:40:52 2013 +0000

    sna/dri: Reorder assert to avoid NULL dereference
    
    Only try to dereference chain->draw after the check to see if it was
    already destroyed.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 6e60570..c18bfbf 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -1576,7 +1576,6 @@ static void chain_flip(struct sna *sna)
 {
 	struct sna_dri_frame_event *chain = sna->dri.flip_pending;
 
-	assert(chain == sna_dri_window_get_chain((WindowPtr)chain->draw));
 	assert(chain->type == DRI2_FLIP);
 	DBG(("%s: chaining type=%d\n", __FUNCTION__, chain->type));
 
@@ -1586,6 +1585,8 @@ static void chain_flip(struct sna *sna)
 		return;
 	}
 
+	assert(chain == sna_dri_window_get_chain((WindowPtr)chain->draw));
+
 	if (chain->type == DRI2_FLIP &&
 	    can_flip(sna, chain->draw, chain->front, chain->back) &&
 	    sna_dri_page_flip(sna, chain)) {
commit cffdd1eed0ca344142c165788ce7a31b80f1f55f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 11 14:16:27 2013 +0000

    test: Try to exercise races between DRI2SwapBuffers and CloseWindow
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/Makefile.am b/test/Makefile.am
index 0f9bd7d..96729c1 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -17,6 +17,7 @@ stress_TESTS = \
 	render-copy-alphaless \
 	mixed-stress \
 	dri2-swap \
+	dri2-race \
 	$(NULL)
 
 check_PROGRAMS = $(stress_TESTS)
diff --git a/test/dri2-race.c b/test/dri2-race.c
new file mode 100644
index 0000000..01b023a
--- /dev/null
+++ b/test/dri2-race.c
@@ -0,0 +1,113 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/Xfixes.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+
+#include <xf86drm.h>
+#include <drm.h>
+
+#include "dri2.h"
+
+#define COUNT 60
+
+static int dri2_open(Display *dpy)
+{
+	drm_auth_t auth;
+	char *driver, *device;
+	int fd;
+
+	if (!DRI2Connect(dpy, DefaultRootWindow(dpy), &driver, &device))
+		return -1;
+
+	printf ("Connecting to %s driver on %s\n", driver, device);
+
+	fd = open("/dev/dri/card0", O_RDWR);
+	if (fd < 0)
+		return -1;
+
+	if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
+		return -1;
+
+	if (!DRI2Authenticate(dpy, DefaultRootWindow(dpy), auth.magic))
+		return -1;
+
+	return fd;
+}
+
+static void run(Display *dpy, int width, int height,
+		unsigned int *attachments, int nattachments,
+		const char *name)
+{
+	Window win;
+	XSetWindowAttributes attr;
+	int count, loop;
+	DRI2Buffer *buffers;
+
+	/* Be nasty and install a fullscreen window on top so that we
+	 * can guarantee we do not get clipped by children.
+	 */
+	attr.override_redirect = 1;
+	loop = 100;
+	do {
+		win = XCreateWindow(dpy, DefaultRootWindow(dpy),
+				    0, 0, width, height, 0,
+				    DefaultDepth(dpy, DefaultScreen(dpy)),
+				    InputOutput,
+				    DefaultVisual(dpy, DefaultScreen(dpy)),
+				    CWOverrideRedirect, &attr);
+		XMapWindow(dpy, win);
+
+		DRI2CreateDrawable(dpy, win);
+
+		buffers = DRI2GetBuffers(dpy, win, &width, &height,
+					 attachments, nattachments, &count);
+		if (count != nattachments)
+			return;
+
+		free(buffers);
+		for (count = 0; count < loop; count++)
+			DRI2SwapBuffers(dpy, win, 0, 0, 0);
+		XDestroyWindow(dpy, win);
+	} while (--loop);
+
+	XSync(dpy, 1);
+	sleep(2);
+	XSync(dpy, 1);
+}
+
+int main(void)
+{
+	Display *dpy;
+	int width, height, fd;
+	unsigned int attachments[] = {
+		DRI2BufferBackLeft,
+		DRI2BufferFrontLeft,
+	};
+
+	dpy = XOpenDisplay (NULL);
+	if (dpy == NULL)
+		return 77;
+
+	fd = dri2_open(dpy);
+	if (fd < 0)
+		return 1;
+
+	width = WidthOfScreen(DefaultScreenOfDisplay(dpy));
+	height = HeightOfScreen(DefaultScreenOfDisplay(dpy));
+	run(dpy, width, height, attachments, 1, "fullscreen");
+	run(dpy, width, height, attachments, 2, "fullscreen (with front)");
+
+	width /= 2;
+	height /= 2;
+	run(dpy, width, height, attachments, 1, "windowed");
+	run(dpy, width, height, attachments, 2, "windowed (with front)");
+
+	return 0;
+}


More information about the xorg-commit mailing list