lib/dummyload: Handle timeout in a new thread instead of signal handler

Currently, the main thread needs to wakeup to run the signal handler
that ends a spin batch. When testing whether a function call succesfully
waits for a batch to complete, this behavior is undesired. It actually
invalidates the test.

Fix this by spawning a new thread to handle the timeout.

v2: Get rid of mutexes. (Chris)
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
diff --git a/lib/igt_dummyload.c b/lib/igt_dummyload.c
index 019c1fb..b25e023 100644
--- a/lib/igt_dummyload.c
+++ b/lib/igt_dummyload.c
@@ -174,27 +174,11 @@
 	return spin;
 }
 
-static void clear_sig_handler(int sig)
+static void notify(union sigval arg)
 {
-	struct sigaction act;
+	igt_spin_t *spin = arg.sival_ptr;
 
-	memset(&act, 0, sizeof(act));
-	act.sa_handler = SIG_DFL;
-	igt_assert(sigaction(sig, &act, NULL) == 0);
-}
-
-static void sig_handler(int sig, siginfo_t *info, void *arg)
-{
-	struct igt_spin *iter;
-
-	igt_list_for_each(iter, &spin_list, link) {
-		if (iter->signo == info->si_signo) {
-			igt_spin_batch_end(iter);
-			return;
-		}
-	}
-
-	clear_sig_handler(sig);
+	igt_spin_batch_end(spin);
 }
 
 /**
@@ -208,10 +192,8 @@
  */
 void igt_spin_batch_set_timeout(igt_spin_t *spin, int64_t ns)
 {
-	static int spin_signo = 48; /* Midpoint of SIGRTMIN, SIGRTMAX */
 	timer_t timer;
 	struct sigevent sev;
-	struct sigaction act, oldact;
 	struct itimerspec its;
 
 	igt_assert(ns > 0);
@@ -220,25 +202,13 @@
 
 	igt_assert(!spin->timer);
 
-	/* SIGRTMAX is used by valgrind, SIGRTMAX - 1 by igt_fork_hang_detector */
-	if (spin_signo >= SIGRTMAX - 2)
-		spin_signo = SIGRTMIN;
-	spin->signo = ++spin_signo;
-
 	memset(&sev, 0, sizeof(sev));
-	sev.sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID;
-	sev.sigev_notify_thread_id = gettid();
-	sev.sigev_signo = spin->signo;
+	sev.sigev_notify = SIGEV_THREAD;
+	sev.sigev_value.sival_ptr = spin;
+	sev.sigev_notify_function = notify;
 	igt_assert(timer_create(CLOCK_MONOTONIC, &sev, &timer) == 0);
 	igt_assert(timer);
 
-	memset(&oldact, 0, sizeof(oldact));
-	memset(&act, 0, sizeof(act));
-	act.sa_sigaction = sig_handler;
-	act.sa_flags = SA_SIGINFO;
-	igt_assert(sigaction(spin->signo, &act, &oldact) == 0);
-	igt_assert(oldact.sa_sigaction == NULL);
-
 	memset(&its, 0, sizeof(its));
 	its.it_value.tv_sec = ns / NSEC_PER_SEC;
 	its.it_value.tv_nsec = ns % NSEC_PER_SEC;
@@ -260,9 +230,6 @@
 
 	*spin->batch = MI_BATCH_BUFFER_END;
 	__sync_synchronize();
-
-	if (spin->signo)
-		clear_sig_handler(spin->signo);
 }
 
 /**
diff --git a/lib/igt_dummyload.h b/lib/igt_dummyload.h
index 2adfadf..41125e3 100644
--- a/lib/igt_dummyload.h
+++ b/lib/igt_dummyload.h
@@ -33,7 +33,6 @@
 typedef struct igt_spin {
 	unsigned int handle;
 	timer_t timer;
-	int signo;
 	struct igt_list link;
 	uint32_t *batch;
 } igt_spin_t;