#include <err.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/debug.h>
#include <sys/sysmacros.h>
#include <stdbool.h>
#include <errno.h>
#include <string.h>
#include "clock_lock.h"
const struct timespec clock_to_100ms = { 0, MSEC2NSEC(100) };
const struct timespec clock_to_invns = { 0, NANOSEC * 2 };
const struct timespec clock_to_invnegs = { -12345, 0 };
const struct timespec clock_to_invnegns = { 100, -0x23 };
void
clock_rel_to_abs(clockid_t clock, const struct timespec *restrict rel,
struct timespec *restrict abs)
{
if (clock_gettime(clock, abs) != 0) {
err(EXIT_FAILURE, "failed to get absolute time for clock %d",
clock);
}
abs->tv_nsec += rel->tv_nsec;
abs->tv_sec += rel->tv_sec;
if (abs->tv_nsec > NANOSEC) {
abs->tv_sec += abs->tv_nsec / NANOSEC;
abs->tv_nsec %= NANOSEC;
}
}
bool
clock_abs_after(clockid_t clock, const struct timespec *to)
{
struct timespec now;
if (clock_gettime(clock, &now) != 0) {
err(EXIT_FAILURE, "failed to get absolute time for clock %d",
clock);
}
if (now.tv_sec > to->tv_sec)
return (true);
return (now.tv_sec == to->tv_sec && now.tv_nsec > to->tv_nsec);
}
bool
clock_rel_after(clockid_t clock, const struct timespec *start,
const struct timespec *to)
{
struct timespec now, absto;
if (clock_gettime(clock, &now) != 0) {
err(EXIT_FAILURE, "failed to get absolute time for clock %d",
clock);
}
absto.tv_nsec = start->tv_nsec + to->tv_nsec;
absto.tv_sec = start->tv_sec + to->tv_sec;
if (absto.tv_nsec > NANOSEC) {
absto.tv_sec += absto.tv_nsec / NANOSEC;
absto.tv_nsec %= NANOSEC;
}
if (now.tv_sec > absto.tv_sec)
return (true);
return (now.tv_sec == absto.tv_sec && now.tv_nsec > absto.tv_nsec);
}
typedef struct {
const clock_test_t *cthr_test;
void *cthr_prim;
bool cthr_ret;
} clock_test_thr_t;
static void *
clock_test_thr(void *arg)
{
clock_test_thr_t *thr = arg;
thr->cthr_ret = thr->cthr_test->ct_test(thr->cthr_test,
thr->cthr_prim);
return (NULL);
}
static bool
clock_test_one(const clock_test_t *test)
{
void *prim;
bool ret;
test->ct_ops->lo_create(test->ct_desc, &prim);
if (test->ct_enter) {
clock_test_thr_t thr_test;
pthread_t thr;
int pret;
test->ct_ops->lo_lock(prim);
thr_test.cthr_test = test;
thr_test.cthr_prim = prim;
thr_test.cthr_ret = false;
if ((pret = pthread_create(&thr, NULL, clock_test_thr,
&thr_test)) != 0) {
errc(EXIT_FAILURE, pret, "TEST FAILED: %s: internal "
"error creating test thread", test->ct_desc);
}
if ((pret = pthread_join(thr, NULL)) != 0) {
errc(EXIT_FAILURE, pret, "TEST FAILED: %s: internal "
"error joining test thread", test->ct_desc);
}
ret = thr_test.cthr_ret;
test->ct_ops->lo_unlock(prim);
} else {
ret = test->ct_test(test, prim);
}
test->ct_ops->lo_destroy(prim);
if (ret) {
(void) printf("TEST PASSED: %s\n", test->ct_desc);
}
return (ret);
}
int
main(void)
{
int ret = EXIT_SUCCESS;
for (size_t i = 0; i < clock_mutex_ntests; i++) {
if (!clock_test_one(&clock_mutex_tests[i])) {
ret = EXIT_FAILURE;
}
}
for (size_t i = 0; i < clock_rwlock_ntests; i++) {
if (!clock_test_one(&clock_rwlock_tests[i])) {
ret = EXIT_FAILURE;
}
}
for (size_t i = 0; i < clock_sem_ntests; i++) {
if (!clock_test_one(&clock_sem_tests[i])) {
ret = EXIT_FAILURE;
}
}
for (size_t i = 0; i < clock_cond_ntests; i++) {
if (!clock_test_one(&clock_cond_tests[i])) {
ret = EXIT_FAILURE;
}
}
return (ret);
}