summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfgang Hommel <wolfgang.hommel@unibw.de>2019-08-21 18:04:48 +0200
committerWolfgang Hommel <wolfgang.hommel@unibw.de>2019-08-21 18:05:17 +0200
commit314b1298c96d29c38b84ff8e5e027e2e65c81966 (patch)
treebcb091dcea1614a9e234ba0284fb1bb3caedfd11
parent7573d20cd4db40bfb4eda9b20e9fafb5dad8e562 (diff)
downloadlibfaketime-314b1298c96d29c38b84ff8e5e027e2e65c81966.tar.gz
Added support for clock_nanosleep() (#105)
-rw-r--r--NEWS1
-rw-r--r--src/libfaketime.c85
2 files changed, 86 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index a718198..eeaad30 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,7 @@ Since 0.9.7:
- Fixes for shared memory related issues, especially when
not using the faketime wrapper
- Updated glibc compatibility settings for various platforms
+ - Support for clock_nanosleep() with realtime and monotonic clocks
Since 0.9.6:
- Julien Gilli added an option to disable monotonic time faking
diff --git a/src/libfaketime.c b/src/libfaketime.c
index 74c34e8..d84a799 100644
--- a/src/libfaketime.c
+++ b/src/libfaketime.c
@@ -166,6 +166,9 @@ static int (*real_timer_gettime_233) (timer_t timerid,
#endif
#ifdef FAKE_SLEEP
static int (*real_nanosleep) (const struct timespec *req, struct timespec *rem);
+#ifndef __APPLE__
+static int (*real_clock_nanosleep) (clockid_t clock_id, int flags, const struct timespec *req, struct timespec *rem);
+#endif
static int (*real_usleep) (useconds_t usec);
static unsigned int (*real_sleep) (unsigned int seconds);
static unsigned int (*real_alarm) (unsigned int seconds);
@@ -1052,6 +1055,85 @@ int nanosleep(const struct timespec *req, struct timespec *rem)
return result;
}
+#ifndef __APPLE__
+/*
+ * Faked clock_nanosleep()
+ */
+int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *req, struct timespec *rem)
+{
+ int result;
+ struct timespec real_req;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (real_clock_nanosleep == NULL)
+ {
+ return -1;
+ }
+ if (req != NULL)
+ {
+ if (flags & TIMER_ABSTIME) /* sleep until absolute time */
+ {
+ struct timespec tdiff, timeadj;
+ timespecsub(req, &user_faked_time_timespec, &timeadj);
+ if (user_rate_set)
+ {
+ timespecmul(&timeadj, 1.0/user_rate, &tdiff);
+ }
+ else
+ {
+ tdiff = timeadj;
+ }
+ if (clock_id == CLOCK_REALTIME)
+ {
+ timespecadd(&ftpl_starttime.real, &tdiff, &real_req);
+ }
+ else if (clock_id == CLOCK_MONOTONIC)
+ {
+ timespecadd(&ftpl_starttime.mon, &tdiff, &real_req);
+ }
+ else /* presumably only CLOCK_PROCESS_CPUTIME_ID, leave untouched */
+ {
+ real_req = *req;
+ }
+ }
+ else /* sleep for a relative time interval */
+ {
+ if (user_rate_set && !dont_fake && ((clock_id == CLOCK_REALTIME) || (clock_id == CLOCK_MONOTONIC))) /* don't touch CLOCK_PROCESS_CPUTIME_ID */
+ {
+ timespecmul(req, 1.0 / user_rate, &real_req);
+ }
+ else
+ {
+ real_req = *req;
+ }
+ }
+ }
+ else
+ {
+ return -1;
+ }
+
+ DONT_FAKE_TIME(result = (*real_clock_nanosleep)(clock_id, flags, &real_req, rem));
+ if (result == -1)
+ {
+ return result;
+ }
+ /* fake returned parts */
+ if ((rem != NULL) && ((rem->tv_sec != 0) || (rem->tv_nsec != 0)))
+ {
+ if (user_rate_set && !dont_fake)
+ {
+ timespecmul(rem, user_rate, rem);
+ }
+ }
+ /* return the result to the caller */
+ return result;
+}
+#endif
+
/*
* Faked usleep()
*/
@@ -1928,6 +2010,9 @@ static void ftpl_init(void)
#endif
#ifdef FAKE_SLEEP
real_nanosleep = dlsym(RTLD_NEXT, "nanosleep");
+#ifndef __APPLE__
+ real_clock_nanosleep = dlsym(RTLD_NEXT, "clock_nanosleep");
+#endif
real_usleep = dlsym(RTLD_NEXT, "usleep");
real_sleep = dlsym(RTLD_NEXT, "sleep");
real_alarm = dlsym(RTLD_NEXT, "alarm");