[4/9] Add piglit_set_timeout for tests that might hang.

Submitted by Jamey Sharp on April 24, 2014, 12:27 a.m.

Details

Message ID 1398299243-7543-5-git-send-email-jamey@minilop.net
State New
Headers show

Not browsing as part of any series.

Commit Message

Jamey Sharp April 24, 2014, 12:27 a.m.
Signed-off-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Theo Hill <Theo0x48@gmail.com>
---
 CMakeLists.txt           | 31 ++++++++++++++++++++++++++++---
 tests/util/piglit-util.c | 40 ++++++++++++++++++++++++++++++++++++++++
 tests/util/piglit-util.h |  1 +
 3 files changed, 69 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/CMakeLists.txt b/CMakeLists.txt
index cbdccf1..481cfce 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -301,10 +301,16 @@  if (OPENGL_FOUND)
 	endif (APPLE)
 endif()
 
+if(CMAKE_USE_PTHREADS_INIT)
+	set(PIGLIT_HAS_PTHREADS true)
+	add_definitions(-DPIGLIT_HAS_PTHREADS)
+endif()
+
 FIND_LIBRARY(HAVE_LIBRT NAMES rt)
 if(HAVE_LIBRT)
 	set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
 endif()
+
 check_c_source_compiles(
 	"
 	#define _POSIX_C_SOURCE 199309L
@@ -313,15 +319,34 @@  check_c_source_compiles(
 	"
 	PIGLIT_HAS_POSIX_CLOCK_MONOTONIC
 )
+
+if(PIGLIT_HAS_PTHREADS AND PIGLIT_HAS_POSIX_CLOCK_MONOTONIC)
+	check_c_source_compiles(
+		"
+		#include <signal.h>
+		#include <time.h>
+		static void timeout(union sigval val) { }
+		int main() {
+			struct sigevent sev = {
+				.sigev_notify = SIGEV_THREAD,
+				.sigev_notify_function = timeout,
+			};
+			timer_t timerid;
+			return timer_create(CLOCK_MONOTONIC, &sev, &timerid);
+		}
+		"
+		PIGLIT_HAS_POSIX_TIMER_NOTIFY_THREAD
+	)
+endif()
+
 set(CMAKE_REQUIRED_LIBRARIES)
 
 if(PIGLIT_HAS_POSIX_CLOCK_MONOTONIC)
 	add_definitions(-DPIGLIT_HAS_POSIX_CLOCK_MONOTONIC)
 endif()
 
-if(CMAKE_USE_PTHREADS_INIT)
-	set(PIGLIT_HAS_PTHREADS true)
-	add_definitions(-DPIGLIT_HAS_PTHREADS)
+if(PIGLIT_HAS_POSIX_TIMER_NOTIFY_THREAD)
+	add_definitions(-DPIGLIT_HAS_POSIX_TIMER_NOTIFY_THREAD)
 endif()
 
 if(PIGLIT_USE_WAFFLE AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
diff --git a/tests/util/piglit-util.c b/tests/util/piglit-util.c
index cefc303..ecb91ea 100644
--- a/tests/util/piglit-util.c
+++ b/tests/util/piglit-util.c
@@ -43,6 +43,10 @@ 
 #include <inttypes.h>
 
 #ifdef PIGLIT_HAS_POSIX_CLOCK_MONOTONIC
+#ifdef PIGLIT_HAS_POSIX_TIMER_NOTIFY_THREAD
+#include <pthread.h>
+#include <signal.h>
+#endif
 #include <time.h>
 #endif
 
@@ -218,6 +222,12 @@  piglit_report_result(enum piglit_result result)
 {
 	const char *result_str = piglit_result_to_string(result);
 
+#ifdef PIGLIT_HAS_POSIX_TIMER_NOTIFY_THREAD
+	/* Ensure we only report one result in case we race with timeout */
+	static pthread_mutex_t result_lock = PTHREAD_MUTEX_INITIALIZER;
+	pthread_mutex_lock(&result_lock);
+#endif
+
 	fflush(stderr);
 
 	printf("PIGLIT: {'result': '%s' }\n", result_str);
@@ -233,6 +243,36 @@  piglit_report_result(enum piglit_result result)
 	}
 }
 
+#ifdef PIGLIT_HAS_POSIX_TIMER_NOTIFY_THREAD
+static void
+timeout_expired(union sigval val)
+{
+	piglit_loge("Test timed out.");
+	piglit_report_result(val.sival_int);
+}
+#endif
+
+void
+piglit_set_timeout(double seconds, enum piglit_result timeout_result)
+{
+#ifdef PIGLIT_HAS_POSIX_TIMER_NOTIFY_THREAD
+	struct sigevent sev = {
+		.sigev_notify = SIGEV_THREAD,
+		.sigev_notify_function = timeout_expired,
+		.sigev_value = { .sival_int = timeout_result },
+	};
+	time_t sec = seconds;
+	struct itimerspec spec = {
+		.it_value = { .tv_sec = sec, .tv_nsec = (seconds - sec) * 1e9 },
+	};
+	timer_t timerid;
+	timer_create(CLOCK_MONOTONIC, &sev, &timerid);
+	timer_settime(timerid, 0, &spec, NULL);
+#else
+	piglit_logi("Cannot abort this test for timeout on this platform");
+#endif
+}
+
 void
 piglit_report_subtest_result(enum piglit_result result, const char *format, ...)
 {
diff --git a/tests/util/piglit-util.h b/tests/util/piglit-util.h
index 23e0539..c3b939a 100644
--- a/tests/util/piglit-util.h
+++ b/tests/util/piglit-util.h
@@ -197,6 +197,7 @@  int piglit_find_line(const char *program, int position);
 void piglit_merge_result(enum piglit_result *all, enum piglit_result subtest);
 const char * piglit_result_to_string(enum piglit_result result);
 NORETURN void piglit_report_result(enum piglit_result result);
+void piglit_set_timeout(double seconds, enum piglit_result timeout_result);
 void piglit_report_subtest_result(enum piglit_result result,
 				  const char *format, ...) PRINTFLIKE(2, 3);