diff mbox

tests: add gem_seqno_wrap test

Message ID 1352814674-1794-1-git-send-email-mika.kuoppala@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Mika Kuoppala Nov. 13, 2012, 1:51 p.m. UTC
This test uses debugfs entry to set next_seqno close
to a wrapping point and then creates a load with gem_stress
to induce the wrap.

Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com>
---
 tests/Makefile.am      |    1 +
 tests/gem_seqno_wrap.c |  248 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 249 insertions(+)
 create mode 100644 tests/gem_seqno_wrap.c
diff mbox

Patch

diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6e6bd7e..cfa0cee 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -44,6 +44,7 @@  TESTS_progs = \
 	gem_linear_blits \
 	gem_vmap_blits \
 	gem_threaded_access_tiled \
+	gem_seqno_wrap \
 	gem_tiled_blits \
 	gem_tiled_fence_blits \
 	gem_largeobject \
diff --git a/tests/gem_seqno_wrap.c b/tests/gem_seqno_wrap.c
new file mode 100644
index 0000000..b7135ad
--- /dev/null
+++ b/tests/gem_seqno_wrap.c
@@ -0,0 +1,248 @@ 
+/*
+ * Copyright (c) 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Mika Kuoppala <mika.kuoppala@intel.com>
+ */
+
+/*
+ * This test runs gem_stress test multiple times while setting the
+ * next_seqno close to wrapping point. Driver can only handle INT_MAX-1
+ * increments to seqno.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <limits.h>
+
+#include "drmtest.h"
+#include "i915_drm.h"
+#include "intel_bufmgr.h"
+
+#define NUM_WRAPS 3
+
+static int verbose = 0;
+
+static int run_gem_stress(int times)
+{
+	int pid;
+	int r = -1;
+	int status = 0;
+
+	pid = fork();
+	if (pid == 0) {
+		char *argv[3];
+		char cmd[32];
+		char opt1[32];
+		char path[PATH_MAX];
+		char full_path[PATH_MAX];
+
+		strncpy(cmd, "gem_stress", sizeof(cmd));
+		argv[0] = cmd;
+		argv[1] = opt1;
+		argv[2] = NULL;
+
+		assert(snprintf(opt1, sizeof(opt1), "-o%d", times) > 0);
+
+		if (getcwd(path, PATH_MAX) == NULL)
+			perror("getcwd");
+
+		assert(snprintf(full_path, PATH_MAX, "%s/%s", path, argv[0]) > 0);
+
+		if (!verbose) {
+			close(STDOUT_FILENO);
+			close(STDERR_FILENO);
+		}
+
+		r = execv(full_path, argv);
+		if (r == -1)
+			perror("execv failed");
+	} else {
+		int waitcount = 20;
+
+		while(waitcount-- > 0) {
+			r = waitpid(pid, &status, WNOHANG);
+			if (r == pid) {
+				if(WIFEXITED(status)) {
+					if (WEXITSTATUS(status))
+						fprintf(stderr, "child returned with %d\n", WEXITSTATUS(status));
+					return WEXITSTATUS(status);
+				}
+			} else if (r != 0) {
+				perror("waitpid");
+				return -errno;
+			}
+
+			sleep(1);
+		}
+
+		kill(pid, SIGKILL);
+		return -ETIMEDOUT;
+	}
+
+	return r;
+}
+
+static const char *debug_fs_entry = "/sys/kernel/debug/dri/0/i915_next_seqno";
+
+static int read_seqno(uint32_t *seqno)
+{
+	int fh;
+	char buf[32];
+	int r;
+	char *p;
+	unsigned long int tmp;
+
+	fh = open(debug_fs_entry, O_RDWR);
+	if (fh == -1) {
+		perror("open");
+		fprintf(stderr, "no %s found, too old kernel?\n", debug_fs_entry);
+		return -errno;
+	}
+
+	r = read(fh, buf, sizeof(buf) - 1);
+	if (r < 0) {
+		perror("read");
+		close(fh);
+		return -errno;
+	}
+
+	close(fh);
+	buf[r] = 0;
+
+	p = strstr(buf, "0x");
+	if (!p)
+		p = buf;
+
+	tmp = strtoul(p, NULL, 0);
+	if (tmp == ULONG_MAX) {
+		perror("strtoul");
+		return -errno;
+	}
+
+	*seqno = tmp;
+
+	return 0;
+}
+
+static int write_seqno(uint32_t seqno)
+{
+	int fh;
+	char buf[32];
+	int r;
+
+	fh = open(debug_fs_entry, O_RDWR);
+	if (fh == -1) {
+		perror("open");
+		return -errno;
+	}
+
+	assert(snprintf(buf, sizeof(buf), "0x%x", seqno) > 0);
+
+	r = write(fh, buf, strnlen(buf, sizeof(buf)));
+	if (r < 0)
+		return r;
+
+	assert(r == strnlen(buf, sizeof(buf)));
+
+	close(fh);
+
+	return 0;
+}
+
+static int run_once(void)
+{
+	int r;
+	uint32_t seqno = 0;
+	uint32_t seqno_after = 0;
+	uint32_t incr;
+
+	r = read_seqno(&seqno);
+	assert(r == 0);
+
+	incr = (UINT32_MAX >> 1) - 0x1000;
+	if (seqno + incr < seqno)
+		seqno = UINT32_MAX - 0x1000;
+	else
+		seqno += incr;
+
+	seqno++;
+
+	r = write_seqno(seqno);
+	if (r < 0) {
+		fprintf(stderr, "write_seqno returned %d\n", r);
+		return r;
+	}
+
+	// XXX we lose drm auth/master if we are too hasty to reopen /dev/dri wtf?!
+	// usleep(200*1000);
+	r = run_gem_stress(1);
+	if (r != 0) {
+		fprintf(stderr, "run_gem_stress returned %d\n", r);
+		return -1;
+	}
+
+	r = read_seqno(&seqno_after);
+	assert(r == 0);
+
+	if (seqno > seqno_after)
+		return 1;
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+
+	int wraps = 0;
+	int wr;
+	int r;
+
+	if (argc > 1)
+		wr = atoi(argv[1]);
+	else
+		wr = NUM_WRAPS;
+
+	while(wraps < wr) {
+		r = run_once();
+		if (r < 0) {
+			if (verbose) fprintf(stderr, "run once returned %d\n", r);
+			return r;
+		}
+
+		wraps += r;
+	}
+
+	if (wraps == wr) {
+		if (verbose)
+			printf("done %d wraps successfully\n", wraps);
+
+		return 0;
+	}
+
+	return -1;
+}