145 lines
3.2 KiB
C
145 lines
3.2 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
|
|
*/
|
|
|
|
#include <time.h>
|
|
|
|
#define TST_NO_DEFAULT_MAIN
|
|
#include "tst_test.h"
|
|
#include "tst_timer.h"
|
|
#include "tst_clocks.h"
|
|
#include "lapi/syscalls.h"
|
|
#include "lapi/posix_clocks.h"
|
|
|
|
typedef int (*mysyscall)(clockid_t clk_id, void *ts);
|
|
|
|
int syscall_supported_by_kernel(long sysnr)
|
|
{
|
|
int ret;
|
|
|
|
ret = syscall(sysnr, 0, NULL);
|
|
if (ret == -1 && errno == ENOSYS)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int tst_clock_getres(clockid_t clk_id, struct timespec *res)
|
|
{
|
|
static struct tst_ts tts = { 0, };
|
|
static mysyscall func;
|
|
int ret;
|
|
|
|
#if (__NR_clock_getres_time64 != __LTP__NR_INVALID_SYSCALL)
|
|
if (!func && syscall_supported_by_kernel(__NR_clock_getres_time64)) {
|
|
func = sys_clock_getres64;
|
|
tts.type = TST_KERN_TIMESPEC;
|
|
}
|
|
#endif
|
|
|
|
if (!func && syscall_supported_by_kernel(__NR_clock_getres)) {
|
|
func = sys_clock_getres;
|
|
tts.type = TST_KERN_OLD_TIMESPEC;
|
|
}
|
|
|
|
if (!func) {
|
|
tst_res(TCONF, "clock_getres() not available");
|
|
errno = ENOSYS;
|
|
return -1;
|
|
}
|
|
|
|
ret = func(clk_id, tst_ts_get(&tts));
|
|
res->tv_sec = tst_ts_get_sec(tts);
|
|
res->tv_nsec = tst_ts_get_nsec(tts);
|
|
return ret;
|
|
}
|
|
|
|
int tst_clock_gettime(clockid_t clk_id, struct timespec *ts)
|
|
{
|
|
static struct tst_ts tts = { 0, };
|
|
static mysyscall func;
|
|
int ret;
|
|
|
|
#if (__NR_clock_gettime64 != __LTP__NR_INVALID_SYSCALL)
|
|
if (!func && syscall_supported_by_kernel(__NR_clock_gettime64)) {
|
|
func = sys_clock_gettime64;
|
|
tts.type = TST_KERN_TIMESPEC;
|
|
}
|
|
#endif
|
|
|
|
if (!func && syscall_supported_by_kernel(__NR_clock_gettime)) {
|
|
func = sys_clock_gettime;
|
|
tts.type = TST_KERN_OLD_TIMESPEC;
|
|
}
|
|
|
|
if (!func) {
|
|
tst_res(TCONF, "clock_gettime() not available");
|
|
errno = ENOSYS;
|
|
return -1;
|
|
}
|
|
|
|
ret = func(clk_id, tst_ts_get(&tts));
|
|
ts->tv_sec = tst_ts_get_sec(tts);
|
|
ts->tv_nsec = tst_ts_get_nsec(tts);
|
|
return ret;
|
|
}
|
|
|
|
int tst_clock_settime(clockid_t clk_id, struct timespec *ts)
|
|
{
|
|
static struct tst_ts tts = { 0, };
|
|
static mysyscall func;
|
|
|
|
#if (__NR_clock_settime64 != __LTP__NR_INVALID_SYSCALL)
|
|
if (!func && syscall_supported_by_kernel(__NR_clock_settime64)) {
|
|
func = sys_clock_settime64;
|
|
tts.type = TST_KERN_TIMESPEC;
|
|
}
|
|
#endif
|
|
|
|
if (!func && syscall_supported_by_kernel(__NR_clock_settime)) {
|
|
func = sys_clock_settime;
|
|
tts.type = TST_KERN_OLD_TIMESPEC;
|
|
}
|
|
|
|
if (!func) {
|
|
tst_res(TCONF, "clock_settime() not available");
|
|
errno = ENOSYS;
|
|
return -1;
|
|
}
|
|
|
|
tst_ts_set_sec(&tts, ts->tv_sec);
|
|
tst_ts_set_nsec(&tts, ts->tv_nsec);
|
|
return func(clk_id, tst_ts_get(&tts));
|
|
}
|
|
|
|
const char *tst_clock_name(clockid_t clk_id)
|
|
{
|
|
switch (clk_id) {
|
|
case CLOCK_REALTIME:
|
|
return "CLOCK_REALTIME";
|
|
case CLOCK_MONOTONIC:
|
|
return "CLOCK_MONOTONIC";
|
|
case CLOCK_PROCESS_CPUTIME_ID:
|
|
return "CLOCK_PROCESS_CPUTIME_ID";
|
|
case CLOCK_THREAD_CPUTIME_ID:
|
|
return "CLOCK_THREAD_CPUTIME_ID";
|
|
case CLOCK_MONOTONIC_RAW:
|
|
return "CLOCK_MONOTONIC_RAW";
|
|
case CLOCK_REALTIME_COARSE:
|
|
return "CLOCK_REALTIME_COARSE";
|
|
case CLOCK_MONOTONIC_COARSE:
|
|
return "CLOCK_MONOTONIC_COARSE";
|
|
case CLOCK_BOOTTIME:
|
|
return "CLOCK_BOOTTIME";
|
|
case CLOCK_REALTIME_ALARM:
|
|
return "CLOCK_REALTIME_ALARM";
|
|
case CLOCK_BOOTTIME_ALARM:
|
|
return "CLOCK_BOOTTIME_ALARM";
|
|
case CLOCK_TAI:
|
|
return "CLOCK_TAI";
|
|
default:
|
|
return "INVALID/UNKNOWN CLOCK";
|
|
}
|
|
}
|