diff options
author | 2019-06-14 19:23:53 +0000 | |
---|---|---|
committer | 2019-06-14 19:23:53 +0000 | |
commit | 345f6e5566bb5c781592f1052b39774dc2847b8d (patch) | |
tree | cb9c99c5a2116a54b6134f26d2b7d4d697fc2127 | |
parent | Add TSC_ADJUST CPUID flag. (diff) | |
download | wireguard-openbsd-345f6e5566bb5c781592f1052b39774dc2847b8d.tar.xz wireguard-openbsd-345f6e5566bb5c781592f1052b39774dc2847b8d.zip |
new regress: clock_gettime(2); test if CLOCK_MONOTONIC is really monotonic
suggested by kettenis@, tweaked by anton@.
ok mpi@ jca@
-rw-r--r-- | regress/sys/kern/Makefile | 4 | ||||
-rw-r--r-- | regress/sys/kern/clock_gettime/Makefile | 15 | ||||
-rw-r--r-- | regress/sys/kern/clock_gettime/monotonicrelapse.c | 101 |
3 files changed, 118 insertions, 2 deletions
diff --git a/regress/sys/kern/Makefile b/regress/sys/kern/Makefile index 0ad0f7b0552..a2960ece924 100644 --- a/regress/sys/kern/Makefile +++ b/regress/sys/kern/Makefile @@ -1,6 +1,6 @@ -# $OpenBSD: Makefile,v 1.81 2019/05/17 20:08:38 beck Exp $ +# $OpenBSD: Makefile,v 1.82 2019/06/14 19:23:53 cheloha Exp $ -SUBDIR+= __syscall access accept cmsgsize +SUBDIR+= __syscall access accept cmsgsize clock_gettime SUBDIR+= dup2 dup2_accept dup2_self descrip SUBDIR+= exec_self execve exit extent SUBDIR+= fchdir diff --git a/regress/sys/kern/clock_gettime/Makefile b/regress/sys/kern/clock_gettime/Makefile new file mode 100644 index 00000000000..b8a73d7fd05 --- /dev/null +++ b/regress/sys/kern/clock_gettime/Makefile @@ -0,0 +1,15 @@ +# $OpenBSD: Makefile,v 1.1 2019/06/14 19:23:53 cheloha Exp $ + +PROG= monotonicrelapse +LDADD+= -lpthread +DPADD+= ${LIBPTHREAD} +WARNINGS= yes + +NCPUONLINE!= sysctl -n hw.ncpuonline + +REGRESS_TARGETS+= run-regress-monotonicrelapse + +run-regress-monotonicrelapse: ${PROG} + ${PROG} ${NCPUONLINE} + +.include <bsd.regress.mk> diff --git a/regress/sys/kern/clock_gettime/monotonicrelapse.c b/regress/sys/kern/clock_gettime/monotonicrelapse.c new file mode 100644 index 00000000000..a2239429a06 --- /dev/null +++ b/regress/sys/kern/clock_gettime/monotonicrelapse.c @@ -0,0 +1,101 @@ +/* $OpenBSD: monotonicrelapse.c,v 1.1 2019/06/14 19:23:53 cheloha Exp $ */ +/* + * Scott Cheloha <scottcheloha@gmail.com>, 2019. Public Domain. + */ + +#include <sys/param.h> +#include <sys/sysctl.h> +#include <sys/time.h> + +#include <err.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +void report_relapse(int, struct timespec *, struct timespec *); +void *thread_func(void *); +void thread_spawn(pthread_t **, int, void *(*)(void *)); + +/* + * Is the active timecounter monotonic? + * + * Spawn the given number of threads and measure the monotonic clock + * across nanosleep(2) calls. + * + * Threads have a tendency to wake up on new CPUs. If the active + * timecounter is not synchronized across CPUs this will be detected + * relatively quickly and the test will fail. + */ + +int +main(int argc, char *argv[]) +{ + const char *errstr; + pthread_t *thread; + int error, i, nthreads; + + if (argc != 2) { + fprintf(stderr, "usage: %s nthreads\n", getprogname()); + return 1; + } + nthreads = strtonum(argv[1], 1, INT_MAX, &errstr); + if (errstr != NULL) + errx(1, "nthreads is %s: %s", errstr, argv[1]); + + thread = calloc(nthreads, sizeof(*thread)); + if (thread == NULL) + err(1, NULL); + + for (i = 0; i < nthreads; i++) { + error = pthread_create(&thread[i], NULL, thread_func, + (void *)(i + 1)); + if (error) + errc(1, error, "pthread_create"); + } + + sleep(10); + + return 0; +} + +void +report_relapse(int num, struct timespec *before, struct timespec *after) +{ + static pthread_mutex_t report_mutex = PTHREAD_MUTEX_INITIALIZER; + struct timespec relapsed; + int error; + + error = pthread_mutex_lock(&report_mutex); + if (error) + errc(1, error, "T%d: pthread_mutex_lock", num); + + timespecsub(before, after, &relapsed); + errx(1, "T%d: monotonic clock relapsed %.9f seconds: %.9f -> %.9f", + num, relapsed.tv_sec + relapsed.tv_nsec / 1000000000.0, + before->tv_sec + before->tv_nsec / 1000000000.0, + after->tv_sec + after->tv_nsec / 1000000000.0); +} + +void * +thread_func(void *arg) +{ + struct timespec after, before, timeout; + int num; + + timeout.tv_sec = 0; + timeout.tv_nsec = 1; + num = (int)arg; + + for (;;) { + clock_gettime(CLOCK_MONOTONIC, &before); + if (nanosleep(&timeout, NULL) == -1) + err(1, "T%d: nanosleep", num); + clock_gettime(CLOCK_MONOTONIC, &after); + if (timespeccmp(&after, &before, <)) + report_relapse(num, &before, &after); + } + + return NULL; +} |