aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Cochran <richardcochran@gmail.com>2011-02-01 08:52:26 -0500
committerThomas Gleixner <tglx@linutronix.de>2011-02-02 09:28:19 -0500
commitf1f1d5ebd10ffa4242bce7a90a56a222d6b7bc77 (patch)
treeca04ea979512e0037c52bca855dbf050b1b08360
parent65f5d80bdf83ec0d7f3887db10153bf3f36ed73c (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>
-rw-r--r--include/linux/posix-timers.h2
-rw-r--r--include/linux/syscalls.h2
-rw-r--r--kernel/compat.c23
-rw-r--r--kernel/posix-timers.c30
4 files changed, 57 insertions, 0 deletions
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 8206255a547c..79a1cea7f6ed 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -4,6 +4,7 @@
4#include <linux/spinlock.h> 4#include <linux/spinlock.h>
5#include <linux/list.h> 5#include <linux/list.h>
6#include <linux/sched.h> 6#include <linux/sched.h>
7#include <linux/timex.h>
7 8
8union cpu_time_count { 9union cpu_time_count {
9 cputime_t cpu; 10 cputime_t cpu;
@@ -71,6 +72,7 @@ struct k_clock {
71 int (*clock_set) (const clockid_t which_clock, 72 int (*clock_set) (const clockid_t which_clock,
72 const struct timespec *tp); 73 const struct timespec *tp);
73 int (*clock_get) (const clockid_t which_clock, struct timespec * tp); 74 int (*clock_get) (const clockid_t which_clock, struct timespec * tp);
75 int (*clock_adj) (const clockid_t which_clock, struct timex *tx);
74 int (*timer_create) (struct k_itimer *timer); 76 int (*timer_create) (struct k_itimer *timer);
75 int (*nsleep) (const clockid_t which_clock, int flags, 77 int (*nsleep) (const clockid_t which_clock, int flags,
76 struct timespec *, struct timespec __user *); 78 struct timespec *, struct timespec __user *);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 18cd0684fc4e..bfacab921239 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -311,6 +311,8 @@ asmlinkage long sys_clock_settime(clockid_t which_clock,
311 const struct timespec __user *tp); 311 const struct timespec __user *tp);
312asmlinkage long sys_clock_gettime(clockid_t which_clock, 312asmlinkage long sys_clock_gettime(clockid_t which_clock,
313 struct timespec __user *tp); 313 struct timespec __user *tp);
314asmlinkage long sys_clock_adjtime(clockid_t which_clock,
315 struct timex __user *tx);
314asmlinkage long sys_clock_getres(clockid_t which_clock, 316asmlinkage long sys_clock_getres(clockid_t which_clock,
315 struct timespec __user *tp); 317 struct timespec __user *tp);
316asmlinkage long sys_clock_nanosleep(clockid_t which_clock, int flags, 318asmlinkage long sys_clock_nanosleep(clockid_t which_clock, int flags,
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
678long 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
678long compat_sys_clock_getres(clockid_t which_clock, 701long 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
173static 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
958SYSCALL_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
951SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, 981SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
952 struct timespec __user *, tp) 982 struct timespec __user *, tp)
953{ 983{