Module: xenomai-3 Branch: next Commit: fde7cf60551f56e6d974ee057f4cc2edb068be0b URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=fde7cf60551f56e6d974ee057f4cc2edb068be0b
Author: Philippe Gerum <r...@xenomai.org> Date: Mon Feb 12 18:09:59 2018 +0100 cobalt/kernel: add clock_adjtime() syscall --- include/cobalt/kernel/clock.h | 11 +++++++ include/cobalt/kernel/compat.h | 6 ++++ include/cobalt/uapi/syscall.h | 1 + kernel/cobalt/posix/clock.c | 37 +++++++++++++++++++++ kernel/cobalt/posix/clock.h | 6 ++++ kernel/cobalt/posix/compat.c | 63 ++++++++++++++++++++++++++++++++++++ kernel/cobalt/posix/syscall32.c | 17 ++++++++++ kernel/cobalt/posix/syscall32.h | 4 +++ kernel/cobalt/trace/cobalt-posix.h | 20 ++++++++++++ 9 files changed, 165 insertions(+) diff --git a/include/cobalt/kernel/clock.h b/include/cobalt/kernel/clock.h index bb56f52..bf03c59 100644 --- a/include/cobalt/kernel/clock.h +++ b/include/cobalt/kernel/clock.h @@ -53,6 +53,8 @@ struct xnclock { xnticks_t (*read_monotonic)(struct xnclock *clock); int (*set_time)(struct xnclock *clock, const struct timespec *ts); + int (*adjust_time)(struct xnclock *clock, + struct timex *tx); xnsticks_t (*ns_to_ticks)(struct xnclock *clock, xnsticks_t ns); xnsticks_t (*ticks_to_ns)(struct xnclock *clock, @@ -252,6 +254,15 @@ static inline int xnclock_set_time(struct xnclock *clock, #endif /* !CONFIG_XENO_OPT_EXTCLOCK */ +static inline int xnclock_adjust_time(struct xnclock *clock, + struct timex *tx) +{ + if (clock->ops.adjust_time == NULL) + return -EOPNOTSUPP; + + return clock->ops.adjust_time(clock, tx); +} + #ifdef CONFIG_SMP int xnclock_get_default_cpu(struct xnclock *clock, int cpu); #else diff --git a/include/cobalt/kernel/compat.h b/include/cobalt/kernel/compat.h index bb6c754..05754cb 100644 --- a/include/cobalt/kernel/compat.h +++ b/include/cobalt/kernel/compat.h @@ -104,6 +104,12 @@ int sys32_get_timeval(struct timeval *tv, int sys32_put_timeval(struct compat_timeval __user *ctv, const struct timeval *tv); +int sys32_get_timex(struct timex *tx, + const struct compat_timex __user *ctx); + +int sys32_put_timex(struct compat_timex __user *ctx, + const struct timex *tx); + ssize_t sys32_get_fdset(fd_set *fds, const compat_fd_set __user *cfds, size_t cfdsize); diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h index d246f0b..58f9c07 100644 --- a/include/cobalt/uapi/syscall.h +++ b/include/cobalt/uapi/syscall.h @@ -120,6 +120,7 @@ #define sc_cobalt_ftrace_puts 97 #define sc_cobalt_recvmmsg 98 #define sc_cobalt_sendmmsg 99 +#define sc_cobalt_clock_adjtime 100 #define __NR_COBALT_SYSCALLS 128 /* Power of 2 */ diff --git a/kernel/cobalt/posix/clock.c b/kernel/cobalt/posix/clock.c index 3ebf016..6ba389e 100644 --- a/kernel/cobalt/posix/clock.c +++ b/kernel/cobalt/posix/clock.c @@ -221,6 +221,27 @@ int __cobalt_clock_settime(clockid_t clock_id, const struct timespec *ts) return 0; } +int __cobalt_clock_adjtime(clockid_t clock_id, struct timex *tx) +{ + int _ret, ret = 0; + + switch (clock_id) { + case CLOCK_REALTIME: + case CLOCK_MONOTONIC: + case CLOCK_MONOTONIC_RAW: + case CLOCK_HOST_REALTIME: + return -EOPNOTSUPP; + default: + _ret = do_ext_clock(clock_id, adjust_time, ret, tx); + if (_ret || ret) + return _ret ?: ret; + } + + trace_cobalt_clock_adjtime(clock_id, tx); + + return 0; +} + COBALT_SYSCALL(clock_settime, current, (clockid_t clock_id, const struct timespec __user *u_ts)) { @@ -232,6 +253,22 @@ COBALT_SYSCALL(clock_settime, current, return __cobalt_clock_settime(clock_id, &ts); } +COBALT_SYSCALL(clock_adjtime, current, + (clockid_t clock_id, struct timex __user *u_tx)) +{ + struct timex tx; + int ret; + + if (cobalt_copy_from_user(&tx, u_tx, sizeof(tx))) + return -EFAULT; + + ret = __cobalt_clock_adjtime(clock_id, &tx); + if (ret) + return ret; + + return cobalt_copy_to_user(u_tx, &tx, sizeof(tx)); +} + int __cobalt_clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqt, struct timespec *rmt) diff --git a/kernel/cobalt/posix/clock.h b/kernel/cobalt/posix/clock.h index c77c3a5..0b06b93 100644 --- a/kernel/cobalt/posix/clock.h +++ b/kernel/cobalt/posix/clock.h @@ -88,6 +88,9 @@ int __cobalt_clock_gettime(clockid_t clock_id, int __cobalt_clock_settime(clockid_t clock_id, const struct timespec *ts); +int __cobalt_clock_adjtime(clockid_t clock_id, + struct timex *tx); + int __cobalt_clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqt, struct timespec *rmt); @@ -101,6 +104,9 @@ COBALT_SYSCALL_DECL(clock_gettime, COBALT_SYSCALL_DECL(clock_settime, (clockid_t clock_id, const struct timespec __user *u_ts)); +COBALT_SYSCALL_DECL(clock_adjtime, + (clockid_t clock_id, struct timex __user *u_tx)); + COBALT_SYSCALL_DECL(clock_nanosleep, (clockid_t clock_id, int flags, const struct timespec __user *u_rqt, diff --git a/kernel/cobalt/posix/compat.c b/kernel/cobalt/posix/compat.c index 3921510..d7195be 100644 --- a/kernel/cobalt/posix/compat.c +++ b/kernel/cobalt/posix/compat.c @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <linux/err.h> +#include <linux/memory.h> #include <linux/module.h> #include <cobalt/kernel/compat.h> #include <asm/xenomai/syscall.h> @@ -79,6 +80,68 @@ int sys32_put_timeval(struct compat_timeval __user *ctv, } EXPORT_SYMBOL_GPL(sys32_put_timeval); +int sys32_get_timex(struct timex *tx, + const struct compat_timex __user *ctx) +{ + memset(tx, 0, sizeof(*tx)); + + if (!access_rok(ctx, sizeof(*ctx)) || + __xn_get_user(tx->modes, &ctx->modes) || + __xn_get_user(tx->offset, &ctx->offset) || + __xn_get_user(tx->freq, &ctx->freq) || + __xn_get_user(tx->maxerror, &ctx->maxerror) || + __xn_get_user(tx->esterror, &ctx->esterror) || + __xn_get_user(tx->status, &ctx->status) || + __xn_get_user(tx->constant, &ctx->constant) || + __xn_get_user(tx->precision, &ctx->precision) || + __xn_get_user(tx->tolerance, &ctx->tolerance) || + __xn_get_user(tx->time.tv_sec, &ctx->time.tv_sec) || + __xn_get_user(tx->time.tv_usec, &ctx->time.tv_usec) || + __xn_get_user(tx->tick, &ctx->tick) || + __xn_get_user(tx->ppsfreq, &ctx->ppsfreq) || + __xn_get_user(tx->jitter, &ctx->jitter) || + __xn_get_user(tx->shift, &ctx->shift) || + __xn_get_user(tx->stabil, &ctx->stabil) || + __xn_get_user(tx->jitcnt, &ctx->jitcnt) || + __xn_get_user(tx->calcnt, &ctx->calcnt) || + __xn_get_user(tx->errcnt, &ctx->errcnt) || + __xn_get_user(tx->stbcnt, &ctx->stbcnt)) + return -EFAULT; + + return 0; +} +EXPORT_SYMBOL_GPL(sys32_get_timex); + +int sys32_put_timex(struct compat_timex __user *ctx, + const struct timex *tx) +{ + if (!access_wok(ctx, sizeof(*ctx)) || + __xn_put_user(tx->modes, &ctx->modes) || + __xn_put_user(tx->offset, &ctx->offset) || + __xn_put_user(tx->freq, &ctx->freq) || + __xn_put_user(tx->maxerror, &ctx->maxerror) || + __xn_put_user(tx->esterror, &ctx->esterror) || + __xn_put_user(tx->status, &ctx->status) || + __xn_put_user(tx->constant, &ctx->constant) || + __xn_put_user(tx->precision, &ctx->precision) || + __xn_put_user(tx->tolerance, &ctx->tolerance) || + __xn_put_user(tx->time.tv_sec, &ctx->time.tv_sec) || + __xn_put_user(tx->time.tv_usec, &ctx->time.tv_usec) || + __xn_put_user(tx->tick, &ctx->tick) || + __xn_put_user(tx->ppsfreq, &ctx->ppsfreq) || + __xn_put_user(tx->jitter, &ctx->jitter) || + __xn_put_user(tx->shift, &ctx->shift) || + __xn_put_user(tx->stabil, &ctx->stabil) || + __xn_put_user(tx->jitcnt, &ctx->jitcnt) || + __xn_put_user(tx->calcnt, &ctx->calcnt) || + __xn_put_user(tx->errcnt, &ctx->errcnt) || + __xn_put_user(tx->stbcnt, &ctx->stbcnt)) + return -EFAULT; + + return 0; +} +EXPORT_SYMBOL_GPL(sys32_put_timex); + ssize_t sys32_get_fdset(fd_set *fds, const compat_fd_set __user *cfds, size_t cfdsize) { diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c index 93e5077..9559991 100644 --- a/kernel/cobalt/posix/syscall32.c +++ b/kernel/cobalt/posix/syscall32.c @@ -162,6 +162,23 @@ COBALT_SYSCALL32emu(clock_settime, current, return __cobalt_clock_settime(clock_id, &ts); } +COBALT_SYSCALL32emu(clock_adjtime, current, + (clockid_t clock_id, struct compat_timex __user *u_tx)) +{ + struct timex tx; + int ret; + + ret = sys32_get_timex(&tx, u_tx); + if (ret) + return ret; + + ret = __cobalt_clock_adjtime(clock_id, &tx); + if (ret) + return ret; + + return sys32_put_timex(u_tx, &tx); +} + COBALT_SYSCALL32emu(clock_nanosleep, nonrestartable, (clockid_t clock_id, int flags, const struct compat_timespec __user *u_rqt, diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h index 730568c..5ba6513 100644 --- a/kernel/cobalt/posix/syscall32.h +++ b/kernel/cobalt/posix/syscall32.h @@ -57,6 +57,10 @@ COBALT_SYSCALL32emu_DECL(clock_settime, (clockid_t clock_id, const struct compat_timespec __user *u_ts)); +COBALT_SYSCALL32emu_DECL(clock_adjtime, + (clockid_t clock_id, + struct compat_timex __user *u_tx)); + COBALT_SYSCALL32emu_DECL(clock_nanosleep, (clockid_t clock_id, int flags, const struct compat_timespec __user *u_rqt, diff --git a/kernel/cobalt/trace/cobalt-posix.h b/kernel/cobalt/trace/cobalt-posix.h index 4ce67d2..a85a3e6 100644 --- a/kernel/cobalt/trace/cobalt-posix.h +++ b/kernel/cobalt/trace/cobalt-posix.h @@ -748,6 +748,26 @@ DEFINE_EVENT(cobalt_clock_timespec, cobalt_clock_settime, TP_ARGS(clk_id, time) ); +TRACE_EVENT(cobalt_clock_adjtime, + TP_PROTO(clockid_t clk_id, struct timex *tx), + TP_ARGS(clk_id, tx), + + TP_STRUCT__entry( + __field(clockid_t, clk_id) + __field(struct timex *, tx) + ), + + TP_fast_assign( + __entry->clk_id = clk_id; + __entry->tx = tx; + ), + + TP_printk("clock_id=%d timex=%p", + __entry->clk_id, + __entry->tx + ) +); + #define cobalt_print_timer_flags(__flags) \ __print_flags(__flags, "|", \ {TIMER_ABSTIME, "TIMER_ABSTIME"}) _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org https://xenomai.org/mailman/listinfo/xenomai-git