Intel-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] tests/gem_seqno_wrap: dont sync when crossing half of seqno space
@ 2012-12-12 14:15 Mika Kuoppala
  2012-12-12 15:55 ` gfx context switch Zhang, Xiong Y
  0 siblings, 1 reply; 3+ messages in thread
From: Mika Kuoppala @ 2012-12-12 14:15 UTC (permalink / raw)
  To: intel-gfx; +Cc: Mika Kuoppala

For seqno comparison to work they have to be less than UINT32_MAX/2
apart. So when crossing the half way of seqno space, be careful not
to sync anything as this causes gpu hangs. Do real test with
syncing only when we are about to wrap.
---
 tests/gem_seqno_wrap.c |  161 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 117 insertions(+), 44 deletions(-)

diff --git a/tests/gem_seqno_wrap.c b/tests/gem_seqno_wrap.c
index b70f886..5ce8c93 100644
--- a/tests/gem_seqno_wrap.c
+++ b/tests/gem_seqno_wrap.c
@@ -47,7 +47,7 @@
 #include "intel_gpu_tools.h"
 #include "rendercopy.h"
 
-#define BUFFERS_TO_SYNC 128
+#define SAFETY_REGION 0x1f
 
 static int devid;
 static uint32_t last_seqno = 0;
@@ -64,6 +64,8 @@ struct option_struct {
 	int timeout;
 	int dontwrap;
 	int prewrap_space;
+	int random;
+	int buffers;
 };
 
 static struct option_struct options;
@@ -159,21 +161,34 @@ static void render_copyfunc(struct scratch_buf *src,
 	}
 }
 
-static int run_sync_test(void)
+static void exchange_uint(void *array, unsigned i, unsigned j)
+{
+	unsigned *i_arr = array;
+	unsigned i_tmp;
+
+	i_tmp = i_arr[i];
+	i_arr[i] = i_arr[j];
+	i_arr[j] = i_tmp;
+}
+
+static int run_sync_test(int num_buffers, bool verify)
 {
 	drm_intel_bufmgr *bufmgr;
-	int num_buffers = BUFFERS_TO_SYNC, max;
+	int max;
 	drm_intel_bo *src[128], *dst1[128], *dst2[128];
 	int width = 128, height = 128;
 	int fd;
 	int i;
 	int r = -1;
 	int failed = 0;
-
+	unsigned int *p_dst1, *p_dst2;
 	struct scratch_buf s_src[128], s_dst[128];
 
 	fd = drm_open_any();
 	assert(fd >= 0);
+
+	gem_quiescent_gpu(fd);
+
 	devid = intel_get_drm_devid(fd);
 
 	max = gem_aperture_size (fd) / (1024 * 1024) / 2;
@@ -187,7 +202,16 @@ static int run_sync_test(void)
 	batch_3d = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
 	assert(batch_3d);
 
+	p_dst1 = malloc(num_buffers * sizeof(unsigned int));
+	if (p_dst1 == NULL)
+		return -ENOMEM;
+
+	p_dst2 = malloc(num_buffers * sizeof(unsigned int));
+	if (p_dst2 == NULL)
+		return -ENOMEM;
+
 	for (i = 0; i < num_buffers; i++) {
+		p_dst1[i] = p_dst2[i] = i;
 		src[i] = create_bo(bufmgr, i, width, height);
 		dst1[i] = create_bo(bufmgr, ~i, width, height);
 		dst2[i] = create_bo(bufmgr, ~i, width, height);
@@ -195,19 +219,27 @@ static int run_sync_test(void)
 		init_buffer(bufmgr, &s_dst[i], dst1[i], width, height);
 	}
 
-	/* dummy = create_bo(bufmgr, 0, width, height); */
-
-	for (i = 0; i < num_buffers; i++) {
-		render_copyfunc(&s_src[i], &s_dst[i], width, height);
-		intel_copy_bo(batch_blt, dst2[i], dst1[i], width, height);
-	}
-
-	for (i = 0; i < num_buffers; i++) {
-		r = cmp_bo(dst2[i], i, width, height);
-		if (r) {
-			printf("buffer %d differs, seqno_before_test 0x%x, approximated seqno on test fail 0x%x\n",
-			       i, last_seqno_write, last_seqno_write + i * 2);
-			failed = -1;
+	drmtest_permute_array(p_dst1, num_buffers, exchange_uint);
+	drmtest_permute_array(p_dst2, num_buffers, exchange_uint);
+
+	for (i = 0; i < num_buffers; i++)
+		render_copyfunc(&s_src[i], &s_dst[p_dst1[i]], width, height);
+
+	/* Only sync between buffers if this is actual test run and
+	 * not a seqno filler */
+	if (verify) {
+		for (i = 0; i < num_buffers; i++)
+			intel_copy_bo(batch_blt, dst2[p_dst2[i]], dst1[p_dst1[i]],
+				      width, height);
+
+		for (i = 0; i < num_buffers; i++) {
+			r = cmp_bo(dst2[p_dst2[i]], i, width, height);
+			if (r) {
+				printf("buffer %d differs, seqno_before_test 0x%x, "
+				       " approximated seqno on test fail 0x%x\n",
+				       i, last_seqno_write, last_seqno_write + i * 2);
+				failed = -1;
+			}
 		}
 	}
 
@@ -221,6 +253,11 @@ static int run_sync_test(void)
 	intel_batchbuffer_free(batch_blt);
 	drm_intel_bufmgr_destroy(bufmgr);
 
+	free(p_dst1);
+	free(p_dst2);
+
+	gem_quiescent_gpu(fd);
+
 	close(fd);
 
 	return failed;
@@ -270,7 +307,9 @@ static int run_cmd(char *s)
 			if (r == pid) {
 				if(WIFEXITED(status)) {
 					if (WEXITSTATUS(status))
-						fprintf(stderr, "child returned with %d\n", WEXITSTATUS(status));
+						fprintf(stderr,
+						    "child returned with %d\n",
+							WEXITSTATUS(status));
 					return WEXITSTATUS(status);
 				}
 			} else if (r != 0) {
@@ -365,9 +404,25 @@ static int write_seqno(uint32_t seqno)
 
 static uint32_t calc_prewrap_val(void)
 {
-	const int pval = options.prewrap_space - 1;
+	const int pval = options.prewrap_space;
+
+	if (options.random == 0)
+		return pval;
+
+	return random() % pval;
+}
+
+static int seqno_near_boundary(uint32_t seqno)
+{
+	if (seqno > UINT32_MAX - options.prewrap_space ||
+	    seqno < options.prewrap_space)
+		return 1;
 
-	return (pval >> 1) + (random() % (pval >> 1));
+	if (seqno < UINT32_MAX/2 + SAFETY_REGION &&
+	    seqno > UINT32_MAX/2 - SAFETY_REGION)
+		return 1;
+
+	return 0;
 }
 
 static int run_once(void)
@@ -382,29 +437,25 @@ static int run_once(void)
 	r = read_seqno(&seqno_before);
 	assert(r == 0);
 
-	if (seqno_before == last_seqno) {
-		sleep(2);
-		return 0;
-	}
-
 	seqno = last_seqno = seqno_before;
 
-	if (seqno < UINT32_MAX - options.prewrap_space) {
-		if (seqno < UINT32_MAX/2)
-			seqno = UINT32_MAX/2 - options.prewrap_space;
-		else
+	/* Skip seqno write if close to boundary */
+	if (!seqno_near_boundary(seqno)) {
+		if (seqno > UINT32_MAX/2 + 1)
 			seqno = UINT32_MAX - pw_val;
-
-		if ((int)(seqno - seqno_before) <= 0)
-			return 0;
+		else
+			seqno = UINT32_MAX/2 - SAFETY_REGION;
 
 		if (!options.dontwrap) {
 			r = write_seqno(seqno);
 			if (r < 0) {
-				fprintf(stderr, "write_seqno returned %d\n", r);
+				fprintf(stderr,
+					"write_seqno 0x%x returned %d\n",
+					seqno, r);
 
-				/* We might fail if we are at background and some
-				 * operations were done between seqno read and this write
+				/* We might fail if we are at background and
+				 * some operations were done between seqno
+				 * read and this write
 				 */
 				if (!options.background)
 					return r;
@@ -412,11 +463,18 @@ static int run_once(void)
 		}
 	}
 
-	if (options.background == 0) {
-		if (strnlen(options.cmd, sizeof(options.cmd)) > 0) {
-			r = run_cmd(options.cmd);
+	if (!options.background) {
+		/* Only run tests if we are across the half way of seqno space.
+		 * If we are not, run something which just increments seqnos
+		 */
+		if (seqno >= UINT32_MAX/2 + 1) {
+			if (strnlen(options.cmd, sizeof(options.cmd)) > 0) {
+				r = run_cmd(options.cmd);
+			} else {
+				r = run_sync_test(options.buffers, true);
+			}
 		} else {
-			r = run_sync_test();
+			r = run_sync_test(options.buffers, false);
 		}
 
 		if (r != 0) {
@@ -434,7 +492,8 @@ static int run_once(void)
 	if (seqno_before > seqno_after) {
 		if (options.verbose)
 			printf("before 0x%x, after 0x%x , diff %d\n",
-			       seqno_before, seqno_after, seqno_after - seqno_before);
+			       seqno_before, seqno_after,
+			       seqno_after - seqno_before);
 
 		return 1;
 	}
@@ -452,6 +511,8 @@ static void print_usage(const char *s)
 	printf("    -t --timeout=sec      set timeout to wait for testrun to sec seconds\n");
 	printf("    -d --dontwrap         don't wrap just run the test\n");
 	printf("    -p --prewrap=n        set seqno to WRAP - n for each testrun\n");
+	printf("    -r --norandom         dont randomize prewrap space\n");
+	printf("    -i --buffers          number of buffers to copy\n");
 	exit(-1);
 }
 
@@ -467,17 +528,21 @@ static void parse_options(int argc, char **argv)
 		{"dontwrap", no_argument, 0, 'd'},
 		{"verbose", no_argument, 0, 'v'},
 		{"prewrap", required_argument, 0, 'p'},
+		{"norandom", no_argument, 0, 'r'},
+		{"buffers", required_argument, 0, 'i'},
 	};
 
 	strcpy(options.cmd, "");
-	options.rounds = 5;
+	options.rounds = 50;
 	options.background = 0;
 	options.dontwrap = 0;
 	options.timeout = 20;
 	options.verbose = 0;
-	options.prewrap_space = BUFFERS_TO_SYNC/2;
+	options.random = 1;
+	options.prewrap_space = 30;
+	options.buffers = 20;
 
-	while((c = getopt_long(argc, argv, "c:n:bvt:dp:",
+	while((c = getopt_long(argc, argv, "c:n:bvt:dp:ri:",
 			       long_options, &option_index)) != -1) {
 		switch(c) {
 		case 'b':
@@ -497,15 +562,23 @@ static void parse_options(int argc, char **argv)
 			options.cmd[sizeof(options.cmd) - 1] = 0;
 			printf("cmd set to %s\n", options.cmd);
 			break;
+		case 'i':
+			options.buffers = atoi(optarg);
+			printf("buffers %d\n", options.buffers);
+			break;
 		case 't':
 			options.timeout = atoi(optarg);
 			if (options.timeout == 0)
 				options.timeout = 10;
-			printf("setting timeout to %d seconds\n", options.timeout);
+			printf("setting timeout to %d seconds\n",
+			       options.timeout);
 			break;
 		case 'v':
 			options.verbose = 1;
 			break;
+		case 'r':
+			options.random = 0;
+			break;
 		case 'p':
 			options.prewrap_space = atoi(optarg);
 			if (options.prewrap_space == 0)
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-12-12 20:34 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-12 14:15 [PATCH] tests/gem_seqno_wrap: dont sync when crossing half of seqno space Mika Kuoppala
2012-12-12 15:55 ` gfx context switch Zhang, Xiong Y
2012-12-12 20:34   ` Ben Widawsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox