diff options
author | Richard Cochran <richardcochran@gmail.com> | 2011-02-01 08:52:26 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2011-02-02 09:28:19 -0500 |
commit | f1f1d5ebd10ffa4242bce7a90a56a222d6b7bc77 (patch) | |
tree | ca04ea979512e0037c52bca855dbf050b1b08360 /kernel | |
parent | 65f5d80bdf83ec0d7f3887db10153bf3f36ed73c (diff) |
posix-timers: Introduce a syscall for clock tuning.
A new syscall is introduced that allows tuning of a POSIX clock. The
new call, clock_adjtime, takes two parameters, the clock ID and a
pointer to a struct timex. Any ADJTIMEX(2) operation may be requested
via this system call, but various POSIX clocks may or may not support
tuning.
[ tglx: Adapted to the posix-timer cleanup series. Avoid copy_to_user
in the error case ]
Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
Acked-by: John Stultz <johnstul@us.ibm.com>
LKML-Reference: <20110201134419.869804645@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/compat.c | 23 | ||||
-rw-r--r-- | kernel/posix-timers.c | 30 |
2 files changed, 53 insertions, 0 deletions
diff --git a/kernel/compat.c b/kernel/compat.c index 449e853cf41d..38b1d2c1cbe8 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -675,6 +675,29 @@ long compat_sys_clock_gettime(clockid_t which_clock, | |||
675 | return err; | 675 | return err; |
676 | } | 676 | } |
677 | 677 | ||
678 | long compat_sys_clock_adjtime(clockid_t which_clock, | ||
679 | struct compat_timex __user *utp) | ||
680 | { | ||
681 | struct timex txc; | ||
682 | mm_segment_t oldfs; | ||
683 | int err, ret; | ||
684 | |||
685 | err = compat_get_timex(&txc, utp); | ||
686 | if (err) | ||
687 | return err; | ||
688 | |||
689 | oldfs = get_fs(); | ||
690 | set_fs(KERNEL_DS); | ||
691 | ret = sys_clock_adjtime(which_clock, (struct timex __user *) &txc); | ||
692 | set_fs(oldfs); | ||
693 | |||
694 | err = compat_put_timex(utp, &txc); | ||
695 | if (err) | ||
696 | return err; | ||
697 | |||
698 | return ret; | ||
699 | } | ||
700 | |||
678 | long compat_sys_clock_getres(clockid_t which_clock, | 701 | long compat_sys_clock_getres(clockid_t which_clock, |
679 | struct compat_timespec __user *tp) | 702 | struct compat_timespec __user *tp) |
680 | { | 703 | { |
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index a3fdfd4be0ec..5a5a4f1c0971 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c | |||
@@ -170,6 +170,12 @@ static int posix_clock_realtime_set(const clockid_t which_clock, | |||
170 | return do_sys_settimeofday(tp, NULL); | 170 | return do_sys_settimeofday(tp, NULL); |
171 | } | 171 | } |
172 | 172 | ||
173 | static int posix_clock_realtime_adj(const clockid_t which_clock, | ||
174 | struct timex *t) | ||
175 | { | ||
176 | return do_adjtimex(t); | ||
177 | } | ||
178 | |||
173 | /* | 179 | /* |
174 | * Get monotonic time for posix timers | 180 | * Get monotonic time for posix timers |
175 | */ | 181 | */ |
@@ -216,6 +222,7 @@ static __init int init_posix_timers(void) | |||
216 | .clock_getres = hrtimer_get_res, | 222 | .clock_getres = hrtimer_get_res, |
217 | .clock_get = posix_clock_realtime_get, | 223 | .clock_get = posix_clock_realtime_get, |
218 | .clock_set = posix_clock_realtime_set, | 224 | .clock_set = posix_clock_realtime_set, |
225 | .clock_adj = posix_clock_realtime_adj, | ||
219 | .nsleep = common_nsleep, | 226 | .nsleep = common_nsleep, |
220 | .nsleep_restart = hrtimer_nanosleep_restart, | 227 | .nsleep_restart = hrtimer_nanosleep_restart, |
221 | .timer_create = common_timer_create, | 228 | .timer_create = common_timer_create, |
@@ -948,6 +955,29 @@ SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, | |||
948 | return error; | 955 | return error; |
949 | } | 956 | } |
950 | 957 | ||
958 | SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock, | ||
959 | struct timex __user *, utx) | ||
960 | { | ||
961 | struct k_clock *kc = clockid_to_kclock(which_clock); | ||
962 | struct timex ktx; | ||
963 | int err; | ||
964 | |||
965 | if (!kc) | ||
966 | return -EINVAL; | ||
967 | if (!kc->clock_adj) | ||
968 | return -EOPNOTSUPP; | ||
969 | |||
970 | if (copy_from_user(&ktx, utx, sizeof(ktx))) | ||
971 | return -EFAULT; | ||
972 | |||
973 | err = kc->clock_adj(which_clock, &ktx); | ||
974 | |||
975 | if (!err && copy_to_user(utx, &ktx, sizeof(ktx))) | ||
976 | return -EFAULT; | ||
977 | |||
978 | return err; | ||
979 | } | ||
980 | |||
951 | SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, | 981 | SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, |
952 | struct timespec __user *, tp) | 982 | struct timespec __user *, tp) |
953 | { | 983 | { |