mirror of
https://github.com/wolfcw/libfaketime.git
synced 2026-05-17 00:26:16 +03:00
Merge pull request #522 from rbalint/fake-syscall-clock-nanosleep
Fake the clock_nanosleep syscall
This commit is contained in:
@@ -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) {
|
||||
|
||||
32
test/snippets/syscall_clock_nanosleep.c
Normal file
32
test/snippets/syscall_clock_nanosleep.c
Normal 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
|
||||
|
||||
1
test/snippets/syscall_clock_nanosleep.variable
Normal file
1
test/snippets/syscall_clock_nanosleep.variable
Normal file
@@ -0,0 +1 @@
|
||||
FAKETIME 2020-01-01 00:00:00
|
||||
Reference in New Issue
Block a user