[Intel-gfx] [i-g-t RFC 2/3] lib: Capture kcov around ioctls
Chris Wilson
chris at chris-wilson.co.uk
Wed Jun 8 08:52:04 UTC 2016
Use our ioctl overload to enable kcov capture around every ioctl.
---
lib/igt_aux.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
lib/igt_aux.h | 5 ++++
2 files changed, 84 insertions(+), 5 deletions(-)
diff --git a/lib/igt_aux.c b/lib/igt_aux.c
index fb1dac2..71067b3 100644
--- a/lib/igt_aux.c
+++ b/lib/igt_aux.c
@@ -60,6 +60,7 @@
#include "config.h"
#include "intel_reg.h"
#include "ioctl_wrappers.h"
+#include "igt_kcov.h"
#include "igt_kms.h"
#include "igt_pm.h"
#include "igt_stats.h"
@@ -74,6 +75,77 @@
* fit into any other topic.
*/
+static struct __igt_kcov_ioctl_global {
+ struct igt_kcov kcov;
+ void (*trace)(struct igt_kcov *, void *data);
+ void *data;
+ bool enable;
+} __igt_kcov_ioctl;
+
+static int
+__kcov_ioctl(int fd, unsigned long request, void *arg)
+{
+ int ret;
+
+ if (__igt_kcov_ioctl.enable)
+ igt_kcov_enable(&__igt_kcov_ioctl.kcov);
+
+ ret = ioctl(fd, request, arg);
+
+ if (__igt_kcov_ioctl.enable) {
+ int err = errno;
+
+ igt_kcov_disable(&__igt_kcov_ioctl.kcov);
+ __igt_kcov_ioctl.trace(&__igt_kcov_ioctl.kcov,
+ __igt_kcov_ioctl.data);
+ igt_kcov_reset(&__igt_kcov_ioctl.kcov);
+ errno = err;
+ }
+
+ return ret;
+}
+
+static int
+kcov_ioctl(int fd, unsigned long request, void *arg)
+{
+ int ret;
+ do {
+ ret = __kcov_ioctl(fd, request, arg);
+ } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+ return ret;
+}
+
+void igt_kcov_setup(void (*trace)(struct igt_kcov *, void *),
+ void *data)
+{
+ if (!trace) {
+ igt_kcov_fini(&__igt_kcov_ioctl.kcov);
+ memset(&__igt_kcov_ioctl, 0, sizeof(__igt_kcov_ioctl));
+ return;
+ }
+
+ if (igt_kcov_init(&__igt_kcov_ioctl.kcov))
+ return;
+
+ __igt_kcov_ioctl.trace = trace;
+ __igt_kcov_ioctl.data = data;
+}
+
+void igt_kcov_start(void)
+{
+ if (__igt_kcov_ioctl.trace) {
+ __igt_kcov_ioctl.enable = true;
+ igt_ioctl = kcov_ioctl;
+ } else
+ igt_ioctl = drmIoctl;
+}
+
+void igt_kcov_stop(void)
+{
+ __igt_kcov_ioctl.enable = false;
+ igt_ioctl = drmIoctl;
+}
+
/* signal interrupt helpers */
@@ -86,6 +158,7 @@
#define sigev_notify_thread_id _sigev_un._tid
static struct __igt_sigiter_global {
+ int (*old_ioctl)(int fd, unsigned long request, void *arg);
pid_t tid;
timer_t timer;
struct timespec offset;
@@ -118,8 +191,8 @@ sig_ioctl(int fd, unsigned long request, void *arg)
memset(&its, 0, sizeof(its));
if (timer_settime(__igt_sigiter.timer, 0, &its, NULL)) {
/* oops, we didn't undo the interrupter (i.e. !unwound abort) */
- igt_ioctl = drmIoctl;
- return drmIoctl(fd, request, arg);
+ igt_ioctl = __igt_sigiter.old_ioctl;
+ return igt_ioctl(fd, request, arg);
}
its.it_value = __igt_sigiter.offset;
@@ -131,7 +204,7 @@ sig_ioctl(int fd, unsigned long request, void *arg)
ret = 0;
serial = __igt_sigiter.stat.signals;
igt_assert(timer_settime(__igt_sigiter.timer, 0, &its, NULL) == 0);
- if (ioctl(fd, request, arg))
+ if (__kcov_ioctl(fd, request, arg))
ret = errno;
if (__igt_sigiter.stat.signals == serial)
__igt_sigiter.stat.miss++;
@@ -166,7 +239,7 @@ static bool igt_sigiter_start(struct __igt_sigiter *iter, bool enable)
* tests, we cannot assume the state of the igt_ioctl indirection.
*/
SIG_ASSERT(igt_ioctl == drmIoctl);
- igt_ioctl = drmIoctl;
+ igt_ioctl = __igt_sigiter.old_ioctl;
if (enable) {
struct timespec start, end;
@@ -174,6 +247,7 @@ static bool igt_sigiter_start(struct __igt_sigiter *iter, bool enable)
struct sigaction act;
struct itimerspec its;
+ __igt_sigiter.old_ioctl = igt_ioctl;
igt_ioctl = sig_ioctl;
__igt_sigiter.tid = gettid();
@@ -226,7 +300,7 @@ static bool igt_sigiter_stop(struct __igt_sigiter *iter, bool enable)
SIG_ASSERT(igt_ioctl == sig_ioctl);
SIG_ASSERT(__igt_sigiter.tid == gettid());
- igt_ioctl = drmIoctl;
+ igt_ioctl = __igt_sigiter.old_ioctl;
timer_delete(__igt_sigiter.timer);
diff --git a/lib/igt_aux.h b/lib/igt_aux.h
index be0d2d6..3bfe3af 100644
--- a/lib/igt_aux.h
+++ b/lib/igt_aux.h
@@ -43,6 +43,11 @@ void igt_stop_signal_helper(void);
void igt_fork_hang_detector(int fd);
void igt_stop_hang_detector(void);
+struct igt_kcov;
+void igt_kcov_setup(void (*trace)(struct igt_kcov *, void *), void *data);
+void igt_kcov_start(void);
+void igt_kcov_stop(void);
+
struct __igt_sigiter {
unsigned pass;
};
--
2.8.1
More information about the Intel-gfx
mailing list