From fb91c4fcde6a622a8ab799fa1ca4e4d09f854d8b Mon Sep 17 00:00:00 2001 From: Matthias Liertzer Date: Sun, 31 Dec 2017 02:23:56 +0100 Subject: Implement a fix for pthread_cond_timedwait with faketime pthread_cond_timedwait takes an absolute time as an argument, which the function directly passes on to the kernel via the futex syscall. In an application this absolute time argument is calculated via the fake times provided by libfaketime. Since the kernel has no knowledge of the fake time, pthread_cond_timedwait must be redefined such that it converts the fake time back to real time before passing it on. --- test/Makefile | 2 +- test/timetest.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/Makefile b/test/Makefile index f2d2f92..94d1a2e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,7 @@ CC = gcc CFLAGS = -std=gnu99 -Wall -DFAKE_STAT -Werror -Wextra -LDFLAGS = -lrt +LDFLAGS = -lrt -lpthread SRC = timetest.c OBJ = ${SRC:.c=.o} diff --git a/test/timetest.c b/test/timetest.c index 79597b0..4e3515c 100644 --- a/test/timetest.c +++ b/test/timetest.c @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define _GNU_SOURCE #include #include #include @@ -31,6 +32,8 @@ #endif #ifndef __APPLE__ +#include +#include #include #define VERBOSE 0 @@ -49,6 +52,64 @@ handler(int sig, siginfo_t *si, void *uc) printf("Caught signal %d\n", sig); } } + +void* pthread_test(void* args) +{ + pthread_mutex_t fakeMutex = PTHREAD_MUTEX_INITIALIZER; + pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER; + + pthread_cond_t monotonic_cond; + pthread_condattr_t attr; + + struct timespec timeToWait, now; + int rt; + + args = args; // silence compiler warning about unused argument + + clock_gettime(CLOCK_REALTIME, &now); + timeToWait.tv_sec = now.tv_sec+1; + timeToWait.tv_nsec = now.tv_nsec; + + printf("pthread_cond_timedwait: CLOCK_REALTIME test\n"); + printf("(Intentionally sleeping 1 second...)\n"); + fflush(stdout); + + pthread_mutex_lock(&fakeMutex); + rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &timeToWait); + if (rt != ETIMEDOUT) + { + printf("pthread_cond_timedwait failed\n"); + exit(EXIT_FAILURE); + } + pthread_mutex_unlock(&fakeMutex); + + + pthread_condattr_init(&attr); + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + pthread_cond_init(&monotonic_cond, &attr); + + clock_gettime(CLOCK_MONOTONIC, &now); + timeToWait.tv_sec = now.tv_sec+1; + timeToWait.tv_nsec = now.tv_nsec; + + printf("pthread_cond_timedwait: CLOCK_MONOTONIC test\n"); + printf("(Intentionally sleeping 1 second...)\n"); + fflush(stdout); + + pthread_mutex_lock(&fakeMutex); + rt = pthread_cond_timedwait(&monotonic_cond, &fakeMutex, &timeToWait); + if (rt != ETIMEDOUT) + { + printf("pthread_cond_timedwait failed\n"); + exit(EXIT_FAILURE); + } + pthread_mutex_unlock(&fakeMutex); + + pthread_cond_destroy(&monotonic_cond); + + return NULL; +} + #endif int main (int argc, char **argv) @@ -69,6 +130,12 @@ int main (int argc, char **argv) #endif #ifndef __APPLE__ + pthread_t thread; + void *ret; + + pthread_create(&thread, NULL, pthread_test, NULL); + pthread_join(thread, &ret); + sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = handler; sigemptyset(&sa.sa_mask); -- cgit v1.2.1