Merge pull request #522 from rbalint/fake-syscall-clock-nanosleep

Fake the clock_nanosleep syscall
This commit is contained in:
Wolfgang Hommel
2025-11-09 10:02:16 +01:00
committed by GitHub
3 changed files with 116 additions and 0 deletions

View File

@@ -4485,6 +4485,8 @@ long syscall(long number, ...) {
}
#endif
// static int (*real_clock_gettime) (clockid_t clk_id, struct timespec *tp);
/* Intercept clock_gettime syscall if available */
#ifdef __NR_clock_gettime
if (number == __NR_clock_gettime && (getenv("FAKETIME") || getenv("FAKETIME_TIMESTAMP_FILE"))) {
clockid_t clk_id;
struct timespec *tp;
@@ -4493,6 +4495,87 @@ long syscall(long number, ...) {
va_end(ap);
return clock_gettime(clk_id, tp);
}
#endif
#ifdef FAKE_SLEEP
#ifdef __NR_clock_nanosleep
/* Intercept raw clock_nanosleep syscall */
if (number == __NR_clock_nanosleep && (getenv("FAKETIME") || getenv("FAKETIME_TIMESTAMP_FILE")))
{
clockid_t clk_id;
int flags;
const struct timespec *req;
struct timespec *rem;
clk_id = va_arg(ap, clockid_t);
flags = va_arg(ap, int);
req = va_arg(ap, const struct timespec*);
rem = va_arg(ap, struct timespec*);
va_end(ap);
if (req == NULL)
{
/* Pass through invalid input to maintain behavior */
return real_syscall(number, clk_id, flags, req, rem);
}
struct timespec real_req;
if (flags & TIMER_ABSTIME)
{
/* Sleep until absolute fake time 'req': convert to corresponding real abstime */
struct timespec tdiff, timeadj;
/* time difference between target fake abstime and fake base */
timespecsub(req, &user_faked_time_timespec, &timeadj);
if (user_rate_set) {
timespecmul(&timeadj, 1.0 / user_rate, &tdiff);
} else {
tdiff = timeadj;
}
if (clk_id == CLOCK_REALTIME)
{
timespecadd(&ftpl_starttime.real, &tdiff, &real_req);
} else if (clk_id == CLOCK_MONOTONIC)
{
get_fake_monotonic_setting(&fake_monotonic_clock);
if (fake_monotonic_clock) {
timespecadd(&ftpl_starttime.mon, &tdiff, &real_req);
} else {
/* leave untouched if monotonic faking disabled */
real_req = *req;
}
} else {
/* other clocks: leave untouched */
real_req = *req;
}
} else
{
/* Relative sleep: scale by 1/rate for realtime/monotonic when faking */
if (user_rate_set && !dont_fake && ((clk_id == CLOCK_REALTIME) || (clk_id == CLOCK_MONOTONIC)))
{
timespecmul(req, 1.0 / user_rate, &real_req);
} else {
real_req = *req;
}
}
long rc = real_syscall(number, clk_id, flags, &real_req, rem);
if (rc != 0)
{
return rc;
}
if (rem != NULL && (rem->tv_sec != 0 || rem->tv_nsec != 0))
{
if (user_rate_set && !dont_fake)
{
timespecmul(rem, user_rate, rem);
}
}
return rc;
}
#endif /* __NR_clock_nanosleep */
#endif /* FAKE_SLEEP */
#ifdef INTERCEPT_FUTEX
if (number == __NR_futex) {

View File

@@ -0,0 +1,32 @@
/* Test raw syscall(__NR_clock_nanosleep): relative and TIMER_ABSTIME */
#ifdef __NR_clock_nanosleep
struct timespec start_fake, end_fake_rel, end_fake_abs;
struct timespec req_rel = {0, 200 * 1000 * 1000}; /* 200ms fake sleep */
struct timespec req_abs;
long ret;
/* Capture starting time (fake view) */
clock_gettime(CLOCK_REALTIME, &start_fake);
/* Relative sleep via syscall */
ret = syscall(__NR_clock_nanosleep, CLOCK_REALTIME, 0, &req_rel, NULL);
clock_gettime(CLOCK_REALTIME, &end_fake_rel);
/* Absolute sleep target: 300ms after start_fake *./test_variable_data.sh */
req_abs.tv_sec = start_fake.tv_sec;
req_abs.tv_nsec = start_fake.tv_nsec + 300 * 1000 * 1000;
if (req_abs.tv_nsec >= 1000000000) { req_abs.tv_sec += 1; req_abs.tv_nsec -= 1000000000; }
/* Absolute sleep via syscall */
ret = syscall(__NR_clock_nanosleep, CLOCK_REALTIME, TIMER_ABSTIME, &req_abs, NULL);
clock_gettime(CLOCK_REALTIME, &end_fake_abs);
/* Report durations (fake view). */
long rel_ns = (end_fake_rel.tv_sec - start_fake.tv_sec) * 1000000000L + (end_fake_rel.tv_nsec - start_fake.tv_nsec);
long abs_ns = (end_fake_abs.tv_sec - start_fake.tv_sec) * 1000000000L + (end_fake_abs.tv_nsec - start_fake.tv_nsec);
printf("[%s] syscall(clock_nanosleep) relative 200ms -> ~%ld ns, absolute +300ms -> ~%ld ns\n", where, rel_ns, abs_ns);
return ret;
#else
printf("[%s] __NR_clock_nanosleep not defined on this platform\n", where);
#endif

View File

@@ -0,0 +1 @@
FAKETIME 2020-01-01 00:00:00