public inbox for igt-dev@lists.freedesktop.org
 help / color / mirror / Atom feed
* [PATCH] lib: implement systemic timeout scaling via IGT_TIMEOUT_MULTIPLIER
@ 2026-02-19 18:52 Jim Cromie
  2026-02-19 19:47 ` ✓ Xe.CI.BAT: success for " Patchwork
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Jim Cromie @ 2026-02-19 18:52 UTC (permalink / raw)
  To: igt-dev; +Cc: Jim Cromie, Gemini CLI

IGT contains numerous hardcoded timing assertions and poll timeouts
(e.g., 150ms in kms_sysfs_edid_timing and 1s in prime_busy) that
appear to be tuned for bare-metal execution.

Specifically, DRM-CI testing of DRM_USE_DYNAMIC_DEBUG=y patchset
triggers spurious timeouts, because toggling the static-keys under
numerous drm_*dbg() callsites takes far longer than just changing the
single word under /sys/module/drm/parameters/debug.

So this patch introduces a "Time Dilator" system to globally scale the
suite's sensitivity, making it adjustable to varying environments.  It
adds a global igt_timeout_multiplier, automatically initialized from
the IGT_TIMEOUT_MULTIPLIER environment variable via a library
constructor in lib/igt_poll.c.

The system scales timing in two directions:

1. Clock Dilation: igt_nsec_elapsed() is patched to divide actual
   elapsed time by the multiplier. This makes internal test logic
   perceive time as moving slower, allowing existing assertions to
   pass even when wall-clock duration is longer.

2. Wait Scaling: Standard poll() and ppoll() calls are intercepted via
   variadic macros and redirected to wrappers that multiply the
   requested timeout duration.

I considered 2 different "dilations" for these, to allow separate
tailoring of the 2 timeout flavors, but had no strong basis to do so,
and it felt like "too many knobs".  That said, it might be appropriate
to dilate *only* for drm.debug (/sys/module/drm/parameters/debug)
adjustments.

This should allow at least IGT tests to be adjusted for environmental
variations and kernel configurations, without requiring manual source
modifications for every hardcoded constant.

Assisted-by: Gemini CLI <gemini-cli@google.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 lib/igt_core.c  |  7 +++++--
 lib/igt_core.h  |  8 ++++++++
 lib/igt_poll.c  | 50 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/meson.build |  6 ++++--
 4 files changed, 67 insertions(+), 4 deletions(-)
 create mode 100644 lib/igt_poll.c

diff --git a/lib/igt_core.c b/lib/igt_core.c
index 3ee670a41..8a1a07ff6 100644
--- a/lib/igt_core.c
+++ b/lib/igt_core.c
@@ -748,6 +748,7 @@ error:
 uint64_t igt_nsec_elapsed(struct timespec *start)
 {
 	struct timespec now;
+	uint64_t elapsed;
 
 	igt_gettime(&now);
 	if ((start->tv_sec | start->tv_nsec) == 0) {
@@ -755,8 +756,10 @@ uint64_t igt_nsec_elapsed(struct timespec *start)
 		return 0;
 	}
 
-	return ((now.tv_nsec - start->tv_nsec) +
-		(uint64_t)NSEC_PER_SEC*(now.tv_sec - start->tv_sec));
+	elapsed = ((now.tv_nsec - start->tv_nsec) +
+		   (uint64_t)NSEC_PER_SEC*(now.tv_sec - start->tv_sec));
+
+	return elapsed / igt_timeout_multiplier;
 }
 
 void __igt_assert_in_outer_scope(void)
diff --git a/lib/igt_core.h b/lib/igt_core.h
index 6845f853c..4538375ff 100644
--- a/lib/igt_core.h
+++ b/lib/igt_core.h
@@ -44,6 +44,7 @@
 #include <stdarg.h>
 #include <getopt.h>
 #include <unistd.h>
+#include <poll.h>
 
 #ifdef __FreeBSD__
 #include "igt_freebsd.h"
@@ -53,6 +54,13 @@
 #define IGT_LOG_DOMAIN (NULL)
 #endif
 
+extern double igt_timeout_multiplier;
+int igt_poll(struct pollfd *fds, nfds_t nfds, int timeout);
+int igt_ppoll(struct pollfd *fds, nfds_t nfds,
+              const struct timespec *tmo_p, const sigset_t *sigmask);
+#define poll(...) igt_poll(__VA_ARGS__)
+#define ppoll(...) igt_ppoll(__VA_ARGS__)
+
 
 #ifndef STATIC_ANALYSIS_BUILD
 #if defined(__clang_analyzer__) || defined(__COVERITY__) || defined(__KLOCWORK__)
diff --git a/lib/igt_poll.c b/lib/igt_poll.c
new file mode 100644
index 000000000..d94fc902d
--- /dev/null
+++ b/lib/igt_poll.c
@@ -0,0 +1,50 @@
+#include <poll.h>
+#include <time.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include "igt_core.h"
+
+#undef poll
+#undef ppoll
+
+double igt_timeout_multiplier = 1.0;
+
+static void igt_timeout_multiplier_init(void) __attribute__((constructor));
+static void igt_timeout_multiplier_init(void)
+{
+	const char *env = getenv("IGT_TIMEOUT_MULTIPLIER");
+	if (env) {
+		igt_timeout_multiplier = atof(env);
+		if (igt_timeout_multiplier <= 0.0)
+			igt_timeout_multiplier = 1.0;
+	}
+}
+
+int igt_poll(struct pollfd *fds, nfds_t nfds, int timeout)
+{
+	int old_timeout = timeout;
+
+	if (timeout > 0)
+		timeout = (int)(timeout * igt_timeout_multiplier);
+
+	if (igt_timeout_multiplier != 1.0 && old_timeout > 0)
+		igt_debug("igt_poll: scaling timeout %dms -> %dms\n", old_timeout, timeout);
+
+	return poll(fds, nfds, timeout);
+}
+
+int igt_ppoll(struct pollfd *fds, nfds_t nfds,
+	      const struct timespec *tmo_p, const sigset_t *sigmask)
+{
+	struct timespec scaled_tmo;
+
+	if (tmo_p) {
+		uint64_t nsec = (uint64_t)tmo_p->tv_sec * NSEC_PER_SEC + tmo_p->tv_nsec;
+		nsec *= igt_timeout_multiplier;
+		scaled_tmo.tv_sec = nsec / NSEC_PER_SEC;
+		scaled_tmo.tv_nsec = nsec % NSEC_PER_SEC;
+		tmo_p = &scaled_tmo;
+	}
+
+	return ppoll(fds, nfds, tmo_p, sigmask);
+}
diff --git a/lib/meson.build b/lib/meson.build
index ea721ecf7..fb7e83543 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -97,6 +97,7 @@ lib_sources = [
 	'igt_core.c',
 	'igt_dir.c',
 	'igt_draw.c',
+	'igt_poll.c',
 	'igt_list.c',
 	'igt_map.c',
 	'igt_panel.c',
@@ -328,7 +329,7 @@ lib_igt_chipset = declare_dependency(link_with : lin_igt_chipset_build,
                                      include_directories : inc)
 
 lib_igt_perf_build = static_library('igt_perf',
-	['igt_perf.c'],
+	['igt_perf.c', 'igt_poll.c'],
 	include_directories : inc)
 
 lib_igt_perf = declare_dependency(link_with : lib_igt_perf_build,
@@ -347,6 +348,7 @@ lib_igt_device_scan_build = static_library('igt_device_scan',
 	'igt_tools_stub.c',
 	'intel_device_info.c',
 	'intel_cmds_info.c',
+	'igt_poll.c',
 	],
 	dependencies : scan_dep,
 	include_directories : inc)
@@ -362,7 +364,7 @@ lib_igt_drm_clients = declare_dependency(link_with : lib_igt_drm_clients_build,
 				         include_directories : inc)
 
 lib_igt_drm_fdinfo_build = static_library('igt_drm_fdinfo',
-	['igt_drm_fdinfo.c'],
+	['igt_drm_fdinfo.c', 'igt_poll.c'],
 	include_directories : inc)
 
 lib_igt_drm_fdinfo = declare_dependency(link_with : lib_igt_drm_fdinfo_build,
-- 
2.53.0


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

end of thread, other threads:[~2026-03-16 19:17 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-19 18:52 [PATCH] lib: implement systemic timeout scaling via IGT_TIMEOUT_MULTIPLIER Jim Cromie
2026-02-19 19:47 ` ✓ Xe.CI.BAT: success for " Patchwork
2026-02-19 20:02 ` ✓ i915.CI.BAT: " Patchwork
2026-02-19 21:48 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-02-20  2:10 ` ✗ i915.CI.Full: " Patchwork
2026-03-16 19:17 ` [PATCH] " Kamil Konieczny

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