xf86-video-intel: 2 commits - src/sna/sna.h src/sna/sna_present.c test/Makefile.am test/present-speed.c

Chris Wilson ickle at kemper.freedesktop.org
Tue Sep 20 14:25:52 UTC 2016


 src/sna/sna.h         |    1 
 src/sna/sna_present.c |   64 +++++++++++++++++++++++++++++++++----
 test/Makefile.am      |    1 
 test/present-speed.c  |   86 +++++++++++++++++++++++++++++++++++++++++---------
 4 files changed, 131 insertions(+), 21 deletions(-)

New commits:
commit 8d6c8191e5c7e9f06e488576af2d59e2c7669e44
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 20 11:49:23 2016 +0100

    test/present: Stress multiple threads sending present requests
    
    At the kernel level, threads and processes are identical - they each get
    a fair share of CPU time. From this we can surmise the cause of any
    variation between threads and processes. If the threads are balanced
    (each thread completing the same number of requests), but the processes
    have unbalanced numbers, we know that X is not as fair.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/Makefile.am b/test/Makefile.am
index 7bda948..12b5d5d 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -50,6 +50,7 @@ stress_TESTS += \
 	present-speed \
 	present-test \
 	$(NULL)
+present_speed_CFLAGS = ${AM_CFLAGS} -pthread
 endif
 check_PROGRAMS = $(stress_TESTS)
 
diff --git a/test/present-speed.c b/test/present-speed.c
index 1e6e48b..bcaa623 100644
--- a/test/present-speed.c
+++ b/test/present-speed.c
@@ -149,6 +149,7 @@ struct buffer {
 
 #define DRI3 1
 #define NOCOPY 2
+#define ASYNC 4
 static void run(Display *dpy, Window win, const char *name, unsigned options)
 {
 	xcb_connection_t *c = XGetXCBConnection(dpy);
@@ -160,7 +161,7 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 	Window root;
 	unsigned int width, height;
 	unsigned border, depth;
-	unsigned present_flags = XCB_PRESENT_OPTION_ASYNC;
+	unsigned present_flags = 0;
 	xcb_xfixes_region_t update = 0;
 	int completed = 0;
 	int queued = 0;
@@ -203,6 +204,8 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 		buffer[n].busy = 0;
 		list_add(&buffer[n].link, &mru);
 	}
+	if (options & ASYNC)
+		present_flags |= XCB_PRESENT_OPTION_ASYNC;
 	if (options & NOCOPY) {
 		update = xcb_generate_id(c);
 		xcb_xfixes_create_region(c, update, 0, NULL);
@@ -312,20 +315,16 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
 		XFreePixmap(dpy, buffer[n].pixmap);
 	}
 
-	XSync(dpy, True);
-	if (_x_error_occurred)
-		abort();
-
-	_x_error_occurred = -1;
-	xcb_present_select_input(c, eid, win, 0);
+	xcb_discard_reply(c, xcb_present_select_input_checked(c, eid, win, 0).sequence);
 	XSync(dpy, True);
 	xcb_unregister_for_special_event(c, Q);
 
 	test_name[0] = '\0';
 	if (options) {
-		snprintf(test_name, sizeof(test_name), "(%s%s )",
+		snprintf(test_name, sizeof(test_name), "(%s%s%s )",
 			 options & NOCOPY ? " no-copy" : "",
-			 options & DRI3 ? " dri3" : "");
+			 options & DRI3 ? " dri3" : "",
+			 options & ASYNC ? " async" : "");
 	}
 	printf("%s%s: Completed %d presents in %.1fs, %.3fus each (%.1f FPS)\n",
 	       name, test_name,
@@ -343,7 +342,56 @@ static int isqrt(int x)
 	return i;
 }
 
-static void siblings(int max_width, int max_height, int ncpus, unsigned options)
+struct sibling {
+	pthread_t thread;
+	Display *dpy;
+	int x, y;
+	int width, height;
+	unsigned options;
+};
+
+static void *sibling(void *arg)
+{
+	struct sibling *s = arg;
+	XSetWindowAttributes attr = { .override_redirect = 1 };
+	Window win = XCreateWindow(s->dpy, DefaultRootWindow(s->dpy),
+				   s->x, s->y, s->width, s->height, 0,
+				   DefaultDepth(s->dpy, DefaultScreen(s->dpy)),
+				   InputOutput,
+				   DefaultVisual(s->dpy, DefaultScreen(s->dpy)),
+				   CWOverrideRedirect, &attr);
+	XMapWindow(s->dpy, win);
+	run(s->dpy, win, "sibling", s->options);
+	return NULL;
+}
+
+static void siblings(Display *dpy,
+		     int max_width, int max_height, int ncpus, unsigned options)
+{
+	int sq_ncpus = isqrt(ncpus);
+	int width = max_width / sq_ncpus;
+	int height = max_height/ sq_ncpus;
+	struct sibling s[ncpus];
+	int child;
+
+	if (ncpus <= 1)
+		return;
+
+	for (child = 0; child < ncpus; child++) {
+		s[child].dpy = dpy;
+		s[child].x = (child % sq_ncpus) * width;
+		s[child].y = (child / sq_ncpus) * height;
+		s[child].width = width;
+		s[child].height = height;
+		s[child].options = options;
+		pthread_create(&s[child].thread, NULL, sibling, &s[child]);
+	}
+
+	for (child = 0; child < ncpus; child++)
+		pthread_join(s[child].thread, NULL);
+}
+
+static void cousins(int max_width, int max_height, int ncpus, unsigned options)
 {
 	int sq_ncpus = isqrt(ncpus);
 	int width = max_width / sq_ncpus;
@@ -366,7 +414,7 @@ static void siblings(int max_width, int max_height, int ncpus, unsigned options)
 						   DefaultVisual(dpy, DefaultScreen(dpy)),
 						   CWOverrideRedirect, &attr);
 			XMapWindow(dpy, win);
-			run(dpy, win, "sibling", options);
+			run(dpy, win, "cousin", options);
 		}
 	}
 
@@ -580,7 +628,7 @@ static void loop(Display *dpy, XRRScreenResources *res, unsigned options)
 						    DefaultVisual(dpy, DefaultScreen(dpy)),
 						    CWOverrideRedirect, &attr);
 				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
-				damage = XDamageCreate(dpy, win, XDamageReportRawRectangles);
+				damage = XDamageCreate(dpy, win, XDamageReportNonEmpty);
 				XMapWindow(dpy, win);
 				XSync(dpy, True);
 				if (!_x_error_occurred)
@@ -601,16 +649,21 @@ static void loop(Display *dpy, XRRScreenResources *res, unsigned options)
 			XDestroyWindow(dpy, win);
 			XSync(dpy, True);
 
-			siblings(mode->width, mode->height,
+			siblings(dpy, mode->width, mode->height,
 				 sysconf(_SC_NPROCESSORS_ONLN),
 				 options);
 
+			cousins(mode->width, mode->height,
+				sysconf(_SC_NPROCESSORS_ONLN),
+				options);
+
 			XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime,
 					 0, 0, None, RR_Rotate_0, NULL, 0);
 		}
 
 		XRRFreeOutputInfo(output);
 	}
+
 }
 
 int main(void)
@@ -620,6 +673,8 @@ int main(void)
 	XRRCrtcInfo **original_crtc;
 	int i;
 
+	XInitThreads();
+
 	dpy = XOpenDisplay(NULL);
 	if (dpy == NULL)
 		return 77;
@@ -649,10 +704,13 @@ int main(void)
 				 0, 0, None, RR_Rotate_0, NULL, 0);
 
 	loop(dpy, res, 0);
+	loop(dpy, res, ASYNC);
 	if (has_xfixes(dpy))
 		loop(dpy, res, NOCOPY);
-	if (has_dri3(dpy))
+	if (has_dri3(dpy)) {
 		loop(dpy, res, DRI3);
+		loop(dpy, res, DRI3 | ASYNC);
+	}
 
 	for (i = 0; i < res->ncrtc; i++)
 		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
commit f0fbead9f24009c4d9900f28d4e5b3c07a93f560
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 20 08:56:02 2016 +0100

    sna/present: Prime the msc cache on first query
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index c4978cb..fb5c007 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -385,6 +385,7 @@ struct sna {
 #if HAVE_PRESENT
 		struct list vblank_queue;
 		uint64_t unflip;
+		void *freed_info;
 #endif
 	} present;
 
diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c
index f5d1515..cfff0f1 100644
--- a/src/sna/sna_present.c
+++ b/src/sna/sna_present.c
@@ -58,6 +58,29 @@ to_present_event(uintptr_t  data)
 	return (struct sna_present_event *)(data & ~3);
 }
 
+static struct sna_present_event *info_alloc(struct sna *sna)
+{
+	struct sna_present_event *info;
+
+	info = sna->present.freed_info;
+	if (info) {
+		sna->present.freed_info = NULL;
+		return info;
+	}
+
+	return malloc(sizeof(struct sna_present_event) + sizeof(uint64_t));
+}
+
+static void info_free(struct sna_present_event *info)
+{
+	struct sna *sna = info->sna;
+
+	if (sna->present.freed_info)
+		free(sna->present.freed_info);
+
+	sna->present.freed_info = info;
+}
+
 static inline bool msc_before(uint64_t msc, uint64_t target)
 {
 	return (int64_t)(msc - target) < 0;
@@ -141,7 +164,7 @@ static void vblank_complete(struct sna_present_event *info,
 	if (info->n_event_id > 1)
 		free(info->event_id);
 	list_del(&info->link);
-	free(info);
+	info_free(info);
 }
 
 static uint32_t msc_to_delay(xf86CrtcPtr crtc, uint64_t target)
@@ -354,8 +377,34 @@ sna_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
 	vbl.request.type = DRM_VBLANK_RELATIVE;
 	vbl.request.sequence = 0;
 	if (sna_wait_vblank(sna, &vbl, sna_crtc_pipe(crtc->devPrivate)) == 0) {
+		struct sna_present_event *info;
+
 		*ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec);
 		*msc = sna_crtc_record_vblank(crtc->devPrivate, &vbl);
+
+		info = info_alloc(sna);
+		if (info) {
+			info->crtc = crtc->devPrivate;
+			info->sna = sna;
+			info->target_msc = *msc + 1;
+			info->event_id = (uint64_t *)(info + 1);
+			info->n_event_id = 0;
+
+			vbl.request.type =
+				DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+			vbl.request.sequence = info->target_msc;
+			vbl.request.signal = (uintptr_t)MARK_PRESENT(info);
+
+			if (sna_wait_vblank(info->sna, &vbl,
+					    sna_crtc_pipe(info->crtc)) == 0) {
+				list_add(&info->link,
+					 &sna->present.vblank_queue);
+				info->queued = true;
+				sna_crtc_set_vblank(info->crtc);
+				info->crtc = mark_crtc(info->crtc);
+			} else
+				info_free(info);
+		}
 	} else {
 		const struct ust_msc *swap;
 last:
@@ -433,7 +482,8 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 		    unmask_crtc(tmp->crtc) == crtc->devPrivate) {
 			uint64_t *events = tmp->event_id;
 
-			if (is_power_of_two(tmp->n_event_id)) {
+			if (tmp->n_event_id &&
+			    is_power_of_two(tmp->n_event_id)) {
 				events = malloc(2*sizeof(uint64_t)*tmp->n_event_id);
 				if (events == NULL)
 					return BadAlloc;
@@ -458,7 +508,7 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 		}
 	}
 
-	info = malloc(sizeof(struct sna_present_event) + sizeof(uint64_t));
+	info = info_alloc(sna);
 	if (info == NULL)
 		return BadAlloc;
 
@@ -473,7 +523,7 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 
 	if (!sna_present_queue(info, swap->msc)) {
 		list_del(&info->link);
-		free(info);
+		info_free(info);
 		return BadAlloc;
 	}
 
@@ -661,7 +711,7 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
 				   info->sna->present.unflip);
 		info->sna->present.unflip = 0;
 	}
-	free(info);
+	info_free(info);
 }
 
 static Bool
@@ -679,7 +729,7 @@ flip(struct sna *sna,
 	     (long long)event_id,
 	     bo->handle));
 
-	info = malloc(sizeof(struct sna_present_event)+sizeof(uint64_t));
+	info = info_alloc(sna);
 	if (info == NULL)
 		return FALSE;
 
@@ -693,7 +743,7 @@ flip(struct sna *sna,
 
 	if (!sna_page_flip(sna, bo, present_flip_handler, info)) {
 		DBG(("%s: pageflip failed\n", __FUNCTION__));
-		free(info);
+		info_free(info);
 		return FALSE;
 	}
 


More information about the xorg-commit mailing list