diff options
author | Matthias Liertzer <matthias@liertzer.at> | 2017-12-31 02:23:56 +0100 |
---|---|---|
committer | Matthias Liertzer <matthias@liertzer.at> | 2018-01-02 02:22:59 +0100 |
commit | fb91c4fcde6a622a8ab799fa1ca4e4d09f854d8b (patch) | |
tree | 33450213354787a13b4334d24787281d7f4198f7 /test | |
parent | ab7a2302f2fa19b96c3597946be9e67b6b286d72 (diff) | |
download | libfaketime-fb91c4fcde6a622a8ab799fa1ca4e4d09f854d8b.tar.gz |
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.
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile | 2 | ||||
-rw-r--r-- | test/timetest.c | 67 |
2 files changed, 68 insertions, 1 deletions
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 <stdio.h> #include <stdlib.h> #include <time.h> @@ -31,6 +32,8 @@ #endif #ifndef __APPLE__ +#include <pthread.h> +#include <errno.h> #include <signal.h> #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); |