tools/nolibc: add timer functions
This is used in various selftests and will be handy when integrating those with nolibc. Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de> Acked-by: Willy Tarreau <w@1wt.eu> Link: https://lore.kernel.org/r/20250428-nolibc-misc-v2-9-3c043eeab06c@linutronix.de Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
This commit is contained in:
committed by
Thomas Weißschuh
parent
50647213e1
commit
fa7bf84486
@@ -15,6 +15,7 @@
|
||||
#include "types.h"
|
||||
#include "sys.h"
|
||||
|
||||
#include <linux/signal.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
static __inline__
|
||||
@@ -120,4 +121,89 @@ time_t time(time_t *tptr)
|
||||
return tv.tv_sec;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid);
|
||||
* int timer_gettime(timer_t timerid, struct itimerspec *curr_value);
|
||||
* int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
|
||||
{
|
||||
return my_syscall3(__NR_timer_create, clockid, evp, timerid);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
|
||||
{
|
||||
return __sysret(sys_timer_create(clockid, evp, timerid));
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_timer_delete(timer_t timerid)
|
||||
{
|
||||
return my_syscall1(__NR_timer_delete, timerid);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int timer_delete(timer_t timerid)
|
||||
{
|
||||
return __sysret(sys_timer_delete(timerid));
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value)
|
||||
{
|
||||
#if defined(__NR_timer_gettime)
|
||||
return my_syscall2(__NR_timer_gettime, timerid, curr_value);
|
||||
#elif defined(__NR_timer_gettime64)
|
||||
struct __kernel_itimerspec kcurr_value;
|
||||
int ret;
|
||||
|
||||
ret = my_syscall2(__NR_timer_gettime64, timerid, &kcurr_value);
|
||||
__nolibc_timespec_kernel_to_user(&kcurr_value.it_interval, &curr_value->it_interval);
|
||||
__nolibc_timespec_kernel_to_user(&kcurr_value.it_value, &curr_value->it_value);
|
||||
return ret;
|
||||
#else
|
||||
return __nolibc_enosys(__func__, timerid, curr_value);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int timer_gettime(timer_t timerid, struct itimerspec *curr_value)
|
||||
{
|
||||
return __sysret(sys_timer_gettime(timerid, curr_value));
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_timer_settime(timer_t timerid, int flags,
|
||||
const struct itimerspec *new_value, struct itimerspec *old_value)
|
||||
{
|
||||
#if defined(__NR_timer_settime)
|
||||
return my_syscall4(__NR_timer_settime, timerid, flags, new_value, old_value);
|
||||
#elif defined(__NR_timer_settime64)
|
||||
struct __kernel_itimerspec knew_value, kold_value;
|
||||
int ret;
|
||||
|
||||
__nolibc_timespec_user_to_kernel(&new_value->it_value, &knew_value.it_value);
|
||||
__nolibc_timespec_user_to_kernel(&new_value->it_interval, &knew_value.it_interval);
|
||||
ret = my_syscall4(__NR_timer_settime64, timerid, flags, &knew_value, &kold_value);
|
||||
if (old_value) {
|
||||
__nolibc_timespec_kernel_to_user(&kold_value.it_interval, &old_value->it_interval);
|
||||
__nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value);
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
return __nolibc_enosys(__func__, timerid, flags, new_value, old_value);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int timer_settime(timer_t timerid, int flags,
|
||||
const struct itimerspec *new_value, struct itimerspec *old_value)
|
||||
{
|
||||
return __sysret(sys_timer_settime(timerid, flags, new_value, old_value));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_TIME_H */
|
||||
|
||||
@@ -188,6 +188,7 @@ struct stat {
|
||||
};
|
||||
|
||||
typedef __kernel_clockid_t clockid_t;
|
||||
typedef int timer_t;
|
||||
|
||||
/* WARNING, it only deals with the 4096 first majors and 256 first minors */
|
||||
#define makedev(major, minor) ((dev_t)((((major) & 0xfff) << 8) | ((minor) & 0xff)))
|
||||
|
||||
@@ -905,6 +905,56 @@ int test_stat_timestamps(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_timer(void)
|
||||
{
|
||||
struct itimerspec timerspec;
|
||||
struct sigevent evp;
|
||||
timer_t timer;
|
||||
int ret;
|
||||
|
||||
evp.sigev_notify = SIGEV_NONE;
|
||||
|
||||
ret = timer_create(CLOCK_MONOTONIC, &evp, &timer);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
timerspec = (struct itimerspec) {
|
||||
.it_value.tv_sec = 1000000,
|
||||
};
|
||||
ret = timer_settime(timer, 0, &timerspec, NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
timerspec = (struct itimerspec) {
|
||||
.it_value.tv_sec = -1,
|
||||
.it_value.tv_nsec = -1,
|
||||
.it_interval.tv_sec = -1,
|
||||
.it_interval.tv_nsec = -1,
|
||||
};
|
||||
ret = timer_gettime(timer, &timerspec);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
|
||||
if (timerspec.it_interval.tv_sec || timerspec.it_interval.tv_nsec)
|
||||
goto err;
|
||||
|
||||
if (timerspec.it_value.tv_sec > 1000000)
|
||||
goto err;
|
||||
|
||||
ret = timer_delete(timer);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
timer_delete(timer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int test_uname(void)
|
||||
{
|
||||
struct utsname buf;
|
||||
@@ -1186,6 +1236,7 @@ int run_syscall(int min, int max)
|
||||
CASE_TEST(stat_fault); EXPECT_SYSER(1, stat(NULL, &stat_buf), -1, EFAULT); break;
|
||||
CASE_TEST(stat_timestamps); EXPECT_SYSZR(1, test_stat_timestamps()); break;
|
||||
CASE_TEST(symlink_root); EXPECT_SYSER(1, symlink("/", "/"), -1, EEXIST); break;
|
||||
CASE_TEST(timer); EXPECT_SYSZR(1, test_timer()); break;
|
||||
CASE_TEST(uname); EXPECT_SYSZR(proc, test_uname()); break;
|
||||
CASE_TEST(uname_fault); EXPECT_SYSER(1, uname(NULL), -1, EFAULT); break;
|
||||
CASE_TEST(unlink_root); EXPECT_SYSER(1, unlink("/"), -1, EISDIR); break;
|
||||
|
||||
Reference in New Issue
Block a user