This patch series changes the 32-bit time type (timespec/itimerspec) to the 64-bit one (timespec64/itimerspec64), since 32-bit time types will break in the year 2038.
This patch series introduces new methods with timespec64/itimerspec64 type, and removes the old ones with timespec/itimerspec type for posix_clock_operations and k_clock structure.
Also introduces some new functions with timespec64/itimerspec64 type, like current_kernel_time64(), hrtimer_get_res64(), cputime_to_timespec64() and timespec64_to_cputime().
Changes since V1: -Split some patch into small patch. -Add some default function for new 64bit methods for syscall function. -Move do_sys_settimeofday() function to head file. -Modify the EXPORT_SYMPOL issue. -Add new 64bit methods in cputime_nsecs.h file.
Baolin Wang (15): linux/time64.h:Introduce the 'struct itimerspec64' for 64bit timekeeping:Introduce the current_kernel_time64() function with timespec64 type time/hrtimer:Introduce hrtimer_get_res64() with timespec64 type for getting the timer resolution posix timers:Introduce the 64bit methods with timespec64 type for k_clock structure posix-timers:Split out the guts of the syscall and change the implementation posix-timers:Convert to the 64bit methods for the syscall function time:Introduce the do_sys_settimeofday64() function with timespec64 type time/posix-timers:Convert to the 64bit methods for k_clock callback functions char/mmtimer:Convert to the 64bit methods for k_clock callback function time/alarmtimer:Convert to the new methods for k_clock structure time/posix-clock:Convert to the 64bit methods for k_clock and posix_clock_operations structure time/time:Introduce the timespec64_to_jiffies/jiffies_to_timespec64 function cputime:Introduce the cputime_to_timespec64/timespec64_to_cputime function time/posix-cpu-timers:Convert to the 64bit methods for k_clock structure k_clock:Remove the 32bit methods with timespec/itimerspec type
arch/powerpc/include/asm/cputime.h | 6 +- arch/s390/include/asm/cputime.h | 8 +- drivers/char/mmtimer.c | 36 +++-- drivers/ptp/ptp_clock.c | 26 +--- include/asm-generic/cputime_jiffies.h | 10 +- include/asm-generic/cputime_nsecs.h | 4 +- include/linux/cputime.h | 15 ++ include/linux/hrtimer.h | 12 +- include/linux/jiffies.h | 21 ++- include/linux/posix-clock.h | 10 +- include/linux/posix-timers.h | 18 +-- include/linux/time64.h | 35 +++++ include/linux/timekeeping.h | 26 +++- kernel/time/alarmtimer.c | 43 +++--- kernel/time/hrtimer.c | 10 +- kernel/time/posix-clock.c | 20 +-- kernel/time/posix-cpu-timers.c | 83 +++++----- kernel/time/posix-timers.c | 269 ++++++++++++++++++++++----------- kernel/time/time.c | 22 +-- kernel/time/timekeeping.c | 6 +- kernel/time/timekeeping.h | 2 +- 21 files changed, 428 insertions(+), 254 deletions(-)
This patch introduces the 'struct itimerspec64' for 64bit to replace itimerspec, and also introduces the conversion methods: itimerspec64_to_itimerspec() and itimerspec_to_itimerspec64(), that makes itimerspec ready for 2038 year.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- include/linux/time64.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
diff --git a/include/linux/time64.h b/include/linux/time64.h index a383147..61dc4cb 100644 --- a/include/linux/time64.h +++ b/include/linux/time64.h @@ -11,11 +11,18 @@ typedef __s64 time64_t; */ #if __BITS_PER_LONG == 64 # define timespec64 timespec +#define itimerspec64 itimerspec #else struct timespec64 { time64_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; + +struct itimerspec64 { + struct timespec64 it_interval; /* timer period */ + struct timespec64 it_value; /* timer expiration */ +}; + #endif
/* Parameters used to convert the timespec values: */ @@ -43,6 +50,16 @@ static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) return ts; }
+static inline struct itimerspec itimerspec64_to_itimerspec(struct itimerspec64 *its64) +{ + return *its64; +} + +static inline struct itimerspec64 itimerspec_to_itimerspec64(struct itimerspec *its) +{ + return *its; +} + # define timespec64_equal timespec_equal # define timespec64_compare timespec_compare # define set_normalized_timespec64 set_normalized_timespec @@ -75,6 +92,24 @@ static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) return ret; }
+static inline struct itimerspec itimerspec64_to_itimerspec(struct itimerspec64 *its64) +{ + struct itimerspec ret; + + ret.it_interval = timespec64_to_timespec(its64->it_interval); + ret.it_value = timespec64_to_timespec(its64->it_value); + return ret; +} + +static inline struct itimerspec64 itimerspec_to_itimerspec64(struct itimerspec *its) +{ + struct itimerspec64 ret; + + ret.it_interval = timespec_to_timespec64(its->it_interval); + ret.it_value = timespec_to_timespec64(its->it_value); + return ret; +} + static inline int timespec64_equal(const struct timespec64 *a, const struct timespec64 *b) {
This patch adds current_kernel_time64() function with timespec64 type, and makes current_kernel_time() 'static inline' and moves it to timekeeping.h file.
It is convenient for user to get the current kernel time with timespec64 type, and delete the current_kernel_time() function easily in timekeeping.h file. That is ready for 2038 when get the current time.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- include/linux/timekeeping.h | 10 +++++++++- kernel/time/timekeeping.c | 6 +++--- 2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 3eaae47..c6d5ae9 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -18,10 +18,18 @@ extern int do_sys_settimeofday(const struct timespec *tv, * Kernel time accessors */ unsigned long get_seconds(void); -struct timespec current_kernel_time(void); +struct timespec64 current_kernel_time64(void); /* does not take xtime_lock */ struct timespec __current_kernel_time(void);
+static inline struct timespec current_kernel_time(void) +{ + struct timespec64 now; + + now = current_kernel_time64(); + return timespec64_to_timespec(now); +} + /* * timespec based interfaces */ diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 91db941..8ccc02c 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1721,7 +1721,7 @@ struct timespec __current_kernel_time(void) return timespec64_to_timespec(tk_xtime(tk)); }
-struct timespec current_kernel_time(void) +struct timespec64 current_kernel_time64(void) { struct timekeeper *tk = &tk_core.timekeeper; struct timespec64 now; @@ -1733,9 +1733,9 @@ struct timespec current_kernel_time(void) now = tk_xtime(tk); } while (read_seqcount_retry(&tk_core.seq, seq));
- return timespec64_to_timespec(now); + return now; } -EXPORT_SYMBOL(current_kernel_time); +EXPORT_SYMBOL(current_kernel_time64);
struct timespec64 get_monotonic_coarse64(void) {
This patch introduces hrtimer_get_res64() function to get the timer resolution with timespec64 type, and moves the hrtimer_get_res() function into include/linux/hrtimer.h as a 'static inline' helper that just calls hrtimer_get_res64.
It is ready for 2038 year when getting the timer resolution by hrtimer_get_res64() function with timespec64 type, and it is convenient to delete the old hrtimer_get_res() function in hrtimer.h file.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- include/linux/hrtimer.h | 12 +++++++++++- kernel/time/hrtimer.c | 10 +++++----- 2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 05f6df1..ee8ed44 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -383,7 +383,17 @@ static inline int hrtimer_restart(struct hrtimer *timer)
/* Query timers: */ extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer); -extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp); +extern int hrtimer_get_res64(const clockid_t which_clock, + struct timespec64 *tp); + +static inline int hrtimer_get_res(const clockid_t which_clock, + struct timespec *tp) +{ + struct timespec64 *ts64; + + *ts64 = timespec_to_timespec64(*tp); + return hrtimer_get_res64(which_clock, ts64); +}
extern ktime_t hrtimer_get_next_event(void);
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index bee0c1f..508d936 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1175,24 +1175,24 @@ void hrtimer_init(struct hrtimer *timer, clockid_t clock_id, EXPORT_SYMBOL_GPL(hrtimer_init);
/** - * hrtimer_get_res - get the timer resolution for a clock + * hrtimer_get_res64 - get the timer resolution for a clock * @which_clock: which clock to query - * @tp: pointer to timespec variable to store the resolution + * @tp: pointer to timespec64 variable to store the resolution * * Store the resolution of the clock selected by @which_clock in the * variable pointed to by @tp. */ -int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp) +int hrtimer_get_res64(const clockid_t which_clock, struct timespec64 *tp) { struct hrtimer_cpu_base *cpu_base; int base = hrtimer_clockid_to_base(which_clock);
cpu_base = raw_cpu_ptr(&hrtimer_bases); - *tp = ktime_to_timespec(cpu_base->clock_base[base].resolution); + *tp = ktime_to_timespec64(cpu_base->clock_base[base].resolution);
return 0; } -EXPORT_SYMBOL_GPL(hrtimer_get_res); +EXPORT_SYMBOL_GPL(hrtimer_get_res64);
static void __run_hrtimer(struct hrtimer *timer, ktime_t *now) {
This patch introduces the new methods with timespec64/itimerspec64 type for k_clcok structure,converts the timepsec type to timespec64 type in k_clock structure and converts the itimerspec type to itimerspec64 type to ready for 2038 issue.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- include/linux/posix-timers.h | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 907f3fd..35786c5 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -98,9 +98,13 @@ struct k_itimer {
struct k_clock { int (*clock_getres) (const clockid_t which_clock, struct timespec *tp); + int (*clock_getres64) (const clockid_t which_clock, struct timespec64 *tp); int (*clock_set) (const clockid_t which_clock, const struct timespec *tp); + int (*clock_set64) (const clockid_t which_clock, + const struct timespec64 *tp); int (*clock_get) (const clockid_t which_clock, struct timespec * tp); + int (*clock_get64) (const clockid_t which_clock, struct timespec64 *tp); int (*clock_adj) (const clockid_t which_clock, struct timex *tx); int (*timer_create) (struct k_itimer *timer); int (*nsleep) (const clockid_t which_clock, int flags, @@ -109,10 +113,15 @@ struct k_clock { int (*timer_set) (struct k_itimer * timr, int flags, struct itimerspec * new_setting, struct itimerspec * old_setting); + int (*timer_set64) (struct k_itimer *timr, int flags, + struct itimerspec64 *new_setting, + struct itimerspec64 *old_setting); int (*timer_del) (struct k_itimer * timr); #define TIMER_RETRY 1 void (*timer_get) (struct k_itimer * timr, struct itimerspec * cur_setting); + void (*timer_get64) (struct k_itimer *timr, + struct itimerspec64 *cur_setting); };
extern struct k_clock clock_posix_cpu;
This patch splits out the guts of the syscall and changes the syscall implementation to prepare the converting to 64bit methods for the syscall function in posix-timers.c file. And next patch will convert the syscall to 64bit methods with timespec64/itimerspec64 type.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- kernel/time/posix-timers.c | 107 +++++++++++++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 36 deletions(-)
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 31ea01f..0db7f02 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -766,11 +766,8 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) cur_setting->it_value = ktime_to_timespec(remaining); }
-/* Get the time remaining on a POSIX.1b interval timer. */ -SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, - struct itimerspec __user *, setting) +static int __timer_gettime(timer_t timer_id, struct itimerspec *cur_setting) { - struct itimerspec cur_setting; struct k_itimer *timr; struct k_clock *kc; unsigned long flags; @@ -784,9 +781,18 @@ SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, if (WARN_ON_ONCE(!kc || !kc->timer_get)) ret = -EINVAL; else - kc->timer_get(timr, &cur_setting); + kc->timer_get(timr, cur_setting);
unlock_timer(timr, flags); + return ret; +} + +/* Get the time remaining on a POSIX.1b interval timer. */ +SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, + struct itimerspec __user *, setting) +{ + struct itimerspec cur_setting; + int ret = __timer_gettime(timer_id, &cur_setting);
if (!ret && copy_to_user(setting, &cur_setting, sizeof (cur_setting))) return -EFAULT; @@ -870,27 +876,14 @@ common_timer_set(struct k_itimer *timr, int flags, return 0; }
-/* Set a POSIX.1b interval timer */ -SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, - const struct itimerspec __user *, new_setting, - struct itimerspec __user *, old_setting) +static int __timer_settime(timer_t timer_id, int flags, struct itimerspec *new_spec, + struct itimerspec *old_spec) { struct k_itimer *timr; - struct itimerspec new_spec, old_spec; int error = 0; unsigned long flag; - struct itimerspec *rtn = old_setting ? &old_spec : NULL; struct k_clock *kc;
- if (!new_setting) - return -EINVAL; - - if (copy_from_user(&new_spec, new_setting, sizeof (new_spec))) - return -EFAULT; - - if (!timespec_valid(&new_spec.it_interval) || - !timespec_valid(&new_spec.it_value)) - return -EINVAL; retry: timr = lock_timer(timer_id, &flag); if (!timr) @@ -900,14 +893,38 @@ retry: if (WARN_ON_ONCE(!kc || !kc->timer_set)) error = -EINVAL; else - error = kc->timer_set(timr, flags, &new_spec, rtn); + error = kc->timer_set(timr, flags, new_spec, old_spec);
unlock_timer(timr, flag); if (error == TIMER_RETRY) { - rtn = NULL; // We already got the old time... + old_spec = NULL; // We already got the old time... goto retry; }
+ return error; +} + +/* Set a POSIX.1b interval timer */ +SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, + const struct itimerspec __user *, new_setting, + struct itimerspec __user *, old_setting) +{ + struct itimerspec new_spec, old_spec; + int error = 0; + struct itimerspec *rtn = old_setting ? &old_spec : NULL; + + if (!new_setting) + return -EINVAL; + + if (copy_from_user(&new_spec, new_setting, sizeof (new_spec))) + return -EFAULT; + + if (!timespec_valid(&new_spec.it_interval) || + !timespec_valid(&new_spec.it_value)) + return -EINVAL; + + error = __timer_settime(timer_id, flags, &new_spec, rtn); + if (old_setting && !error && copy_to_user(old_setting, &old_spec, sizeof (old_spec))) error = -EFAULT; @@ -1002,32 +1019,44 @@ void exit_itimers(struct signal_struct *sig) } }
-SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, - const struct timespec __user *, tp) +static int __clock_settime(clockid_t which_clock, struct timespec *ts) { struct k_clock *kc = clockid_to_kclock(which_clock); - struct timespec new_tp;
if (!kc || !kc->clock_set) return -EINVAL;
+ return kc->clock_set(which_clock, ts); +} + +SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, + const struct timespec __user *, tp) +{ + struct timespec new_tp; + if (copy_from_user(&new_tp, tp, sizeof (*tp))) return -EFAULT;
- return kc->clock_set(which_clock, &new_tp); + return __clock_settime(which_clock, &new_tp); }
-SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, - struct timespec __user *,tp) +static int __clock_gettime(clockid_t which_clock, struct timespec *ts) { struct k_clock *kc = clockid_to_kclock(which_clock); - struct timespec kernel_tp; - int error;
if (!kc) return -EINVAL;
- error = kc->clock_get(which_clock, &kernel_tp); + return kc->clock_get(which_clock, ts); +} + +SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, + struct timespec __user *,tp) +{ + struct timespec kernel_tp; + int error; + + error = __clock_gettime(which_clock, &kernel_tp);
if (!error && copy_to_user(tp, &kernel_tp, sizeof (kernel_tp))) error = -EFAULT; @@ -1058,17 +1087,23 @@ SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock, return err; }
-SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, - struct timespec __user *, tp) +static int __clock_getres(clockid_t which_clock, struct timespec *ts) { struct k_clock *kc = clockid_to_kclock(which_clock); - struct timespec rtn_tp; - int error;
if (!kc) return -EINVAL;
- error = kc->clock_getres(which_clock, &rtn_tp); + return kc->clock_getres(which_clock, ts); +} + +SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, + struct timespec __user *, tp) +{ + struct timespec rtn_tp; + int error; + + error = __clock_getres(which_clock, &rtn_tp);
if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp))) error = -EFAULT;
This patch converts to the 64bit methods with timespec64/itimerspec64 type for the syscall function, and changes the syscall implementation according to the CONFIG_64BIT macro.
Also introduces some default functions with timespec64/itimerspec64 type for the 64bit methods.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- kernel/time/posix-timers.c | 166 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 141 insertions(+), 25 deletions(-)
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 0db7f02..4c7c7d3 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -140,6 +140,7 @@ static int common_timer_del(struct k_itimer *timer); static enum hrtimer_restart posix_timer_fn(struct hrtimer *data);
static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags); +static struct k_clock *clockid_to_kclock(const clockid_t id);
#define lock_timer(tid, flags) \ ({ struct k_itimer *__timr; \ @@ -513,6 +514,57 @@ static struct pid *good_sigevent(sigevent_t * event) return task_pid(rtn); }
+static int default_timer_get64(struct k_itimer *timr, + struct itimerspec64 *cur_setting64) +{ + struct itimerspec cur_setting; + struct k_clock *kc = clockid_to_kclock(timr->it_clock); + + kc->timer_get(timr, &cur_setting); + return 0; +} + +static int default_timer_set64(struct k_itimer *timr, int flags, + struct itimerspec64 *new_setting64, + struct itimerspec64 *old_setting64) +{ + struct k_clock *kc = clockid_to_kclock(timr->it_clock); + struct itimerspec new_setting, old_setting; + + kc->timer_set(timr, flags, &new_setting, &old_setting); + return 0; +} + +static int default_clock_set64(const clockid_t which_clock, + const struct timespec64 *tp64) +{ + struct k_clock *kc = clockid_to_kclock(which_clock); + struct timespec tp; + + kc->clock_set(which_clock, &tp); + return 0; +} + +static int default_clock_get64(const clockid_t which_clock, + struct timespec64 *tp64) +{ + struct k_clock *kc = clockid_to_kclock(which_clock); + struct timespec tp; + + kc->clock_get(which_clock, &tp); + return 0; +} + +static int default_clock_getres64(const clockid_t which_clock, + struct timespec64 *tp64) +{ + struct k_clock *kc = clockid_to_kclock(which_clock); + struct timespec tp; + + kc->clock_getres(which_clock, &tp); + return 0; +} + void posix_timers_register_clock(const clockid_t clock_id, struct k_clock *new_clock) { @@ -522,17 +574,28 @@ void posix_timers_register_clock(const clockid_t clock_id, return; }
- if (!new_clock->clock_get) { - printk(KERN_WARNING "POSIX clock id %d lacks clock_get()\n", + if (!new_clock->clock_get && !new_clock->clock_get64) { + printk(KERN_WARNING "POSIX clock id %d lacks clock_get() and clock_get64()\n", clock_id); return; } - if (!new_clock->clock_getres) { - printk(KERN_WARNING "POSIX clock id %d lacks clock_getres()\n", + if (!new_clock->clock_getres && !new_clock->clock_getres64) { + printk(KERN_WARNING "POSIX clock id %d lacks clock_getres() and clock_getres64()\n", clock_id); return; }
+ if (new_clock->timer_get && !new_clock->timer_get64) + new_clock->timer_get64 = default_timer_get64; + if (new_clock->timer_set && !new_clock->timer_set64) + new_clock->timer_set64 = default_timer_set64; + if (new_clock->clock_set && !new_clock->clock_set64) + new_clock->clock_set64 = default_clock_set64; + if (new_clock->clock_get && !new_clock->clock_get64) + new_clock->clock_get64 = default_clock_get64; + if (new_clock->clock_getres && !new_clock->clock_getres64) + new_clock->clock_getres64 = default_clock_getres64; + posix_clocks[clock_id] = *new_clock; } EXPORT_SYMBOL_GPL(posix_timers_register_clock); @@ -579,7 +642,8 @@ static struct k_clock *clockid_to_kclock(const clockid_t id) return (id & CLOCKFD_MASK) == CLOCKFD ? &clock_posix_dynamic : &clock_posix_cpu;
- if (id >= MAX_CLOCKS || !posix_clocks[id].clock_getres) + if (id >= MAX_CLOCKS || (!posix_clocks[id].clock_getres + && !posix_clocks[id].clock_getres64)) return NULL; return &posix_clocks[id]; } @@ -766,7 +830,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) cur_setting->it_value = ktime_to_timespec(remaining); }
-static int __timer_gettime(timer_t timer_id, struct itimerspec *cur_setting) +static int __timer_gettime(timer_t timer_id, struct itimerspec64 *cur_setting) { struct k_itimer *timr; struct k_clock *kc; @@ -778,10 +842,10 @@ static int __timer_gettime(timer_t timer_id, struct itimerspec *cur_setting) return -EINVAL;
kc = clockid_to_kclock(timr->it_clock); - if (WARN_ON_ONCE(!kc || !kc->timer_get)) + if (WARN_ON_ONCE(!kc || !kc->timer_get64)) ret = -EINVAL; else - kc->timer_get(timr, cur_setting); + kc->timer_get64(timr, cur_setting);
unlock_timer(timr, flags); return ret; @@ -791,8 +855,17 @@ static int __timer_gettime(timer_t timer_id, struct itimerspec *cur_setting) SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, struct itimerspec __user *, setting) { - struct itimerspec cur_setting; +#ifdef CONFIG_64BIT + struct itimerspec64 cur_setting; int ret = __timer_gettime(timer_id, &cur_setting); +#else + struct itimerspec64 cur_setting64; + struct itimerspec cur_setting; + int ret = __timer_gettime(timer_id, &cur_setting64); + + if (!ret) + cur_setting = itimerspec64_to_itimerspec(&cur_setting64); +#endif
if (!ret && copy_to_user(setting, &cur_setting, sizeof (cur_setting))) return -EFAULT; @@ -876,8 +949,8 @@ common_timer_set(struct k_itimer *timr, int flags, return 0; }
-static int __timer_settime(timer_t timer_id, int flags, struct itimerspec *new_spec, - struct itimerspec *old_spec) +static int __timer_settime(timer_t timer_id, int flags, struct itimerspec64 *new_spec, + struct itimerspec64 *old_spec) { struct k_itimer *timr; int error = 0; @@ -890,10 +963,10 @@ retry: return -EINVAL;
kc = clockid_to_kclock(timr->it_clock); - if (WARN_ON_ONCE(!kc || !kc->timer_set)) + if (WARN_ON_ONCE(!kc || !kc->timer_set64)) error = -EINVAL; else - error = kc->timer_set(timr, flags, new_spec, old_spec); + error = kc->timer_set64(timr, flags, new_spec, old_spec);
unlock_timer(timr, flag); if (error == TIMER_RETRY) { @@ -909,9 +982,16 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, const struct itimerspec __user *, new_setting, struct itimerspec __user *, old_setting) { - struct itimerspec new_spec, old_spec; int error = 0; +#ifdef CONFIG_64BIT + struct itimerspec64 new_spec, old_spec; + struct itimerspec64 *rtn = old_setting ? &old_spec : NULL; +#else + struct itimerspec new_spec, old_spec; struct itimerspec *rtn = old_setting ? &old_spec : NULL; + struct itimerspec64 new_spec64; + struct itimerspec64 *rtn64; +#endif
if (!new_setting) return -EINVAL; @@ -923,7 +1003,17 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, !timespec_valid(&new_spec.it_value)) return -EINVAL;
+#ifdef CONFIG_64BIT error = __timer_settime(timer_id, flags, &new_spec, rtn); +#else + new_spec64 = itimerspec_to_itimerspec64(&new_spec); + if (rtn) + *rtn64 = itimerspec_to_itimerspec64(rtn); + else + rtn64 = NULL; + + error = __timer_settime(timer_id, flags, &new_spec64, rtn64); +#endif
if (old_setting && !error && copy_to_user(old_setting, &old_spec, sizeof (old_spec))) @@ -1019,44 +1109,62 @@ void exit_itimers(struct signal_struct *sig) } }
-static int __clock_settime(clockid_t which_clock, struct timespec *ts) +static int __clock_settime(clockid_t which_clock, struct timespec64 *ts) { struct k_clock *kc = clockid_to_kclock(which_clock);
- if (!kc || !kc->clock_set) + if (!kc || !kc->clock_set64) return -EINVAL;
- return kc->clock_set(which_clock, ts); + return kc->clock_set64(which_clock, ts); }
SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, const struct timespec __user *, tp) { +#ifdef CONFIG_64BIT + struct timespec64 new_tp; +#else struct timespec new_tp; + struct timespec64 new_tp64; +#endif
if (copy_from_user(&new_tp, tp, sizeof (*tp))) return -EFAULT;
+#ifdef CONFIG_64BIT return __clock_settime(which_clock, &new_tp); +#else + new_tp64 = timespec_to_timespec64(new_tp); + return __clock_settime(which_clock, &new_tp64); +#endif }
-static int __clock_gettime(clockid_t which_clock, struct timespec *ts) +static int __clock_gettime(clockid_t which_clock, struct timespec64 *ts) { struct k_clock *kc = clockid_to_kclock(which_clock);
if (!kc) return -EINVAL;
- return kc->clock_get(which_clock, ts); + return kc->clock_get64(which_clock, ts); }
SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, struct timespec __user *,tp) { - struct timespec kernel_tp; int error; - +#ifdef CONFIG_64BIT + struct timespec64 kernel_tp; error = __clock_gettime(which_clock, &kernel_tp); +#else + struct timespec64 kernel_tp64; + struct timespec kernel_tp; + + error = __clock_gettime(which_clock, &kernel_tp64); + if (!error) + kernel_tp = timespec64_to_timespec(kernel_tp64); +#endif
if (!error && copy_to_user(tp, &kernel_tp, sizeof (kernel_tp))) error = -EFAULT; @@ -1087,23 +1195,31 @@ SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock, return err; }
-static int __clock_getres(clockid_t which_clock, struct timespec *ts) +static int __clock_getres(clockid_t which_clock, struct timespec64 *ts) { struct k_clock *kc = clockid_to_kclock(which_clock);
if (!kc) return -EINVAL;
- return kc->clock_getres(which_clock, ts); + return kc->clock_getres64(which_clock, ts); }
SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp) { - struct timespec rtn_tp; int error; - +#ifdef CONFIG_64BIT + struct timespec64 rtn_tp; error = __clock_getres(which_clock, &rtn_tp); +#else + struct timespec64 rtn_tp64; + struct timespec rtn_tp; + + error = __clock_getres(which_clock, &rtn_tp64); + if (!error) + rtn_tp = timespec64_to_timespec(rtn_tp64); +#endif
if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp))) error = -EFAULT;
This patch introduces the do_sys_settimeofday64() function with timespec64 type, that makes this function ready for 2038 issue when setting the time of day. And moves the do_sys_settimeofday() function to the timekeeping.h file.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- include/linux/timekeeping.h | 12 ++++++++++-- kernel/time/time.c | 10 ++++++---- 2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index c6d5ae9..89beb62 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -11,8 +11,16 @@ extern int timekeeping_suspended; */ extern void do_gettimeofday(struct timeval *tv); extern int do_settimeofday64(const struct timespec64 *ts); -extern int do_sys_settimeofday(const struct timespec *tv, - const struct timezone *tz); +extern int do_sys_settimeofday64(const struct timespec64 *tv, + const struct timezone *tz); +static inline int do_sys_settimeofday(const struct timespec *tv, + const struct timezone *tz) +{ + struct timespec64 ts64; + + ts64 = timespec_to_timespec64(*tv); + return do_sys_settimeofday64(&ts64, tz); +}
/* * Kernel time accessors diff --git a/kernel/time/time.c b/kernel/time/time.c index 2c85b77..f43011b 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -160,15 +160,17 @@ static inline void warp_clock(void) * various programs will get confused when the clock gets warped. */
-int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz) +int do_sys_settimeofday64(const struct timespec64 *tv, const struct timezone *tz) { static int firsttime = 1; int error = 0; + struct timespec ts;
- if (tv && !timespec_valid(tv)) + if (tv && !timespec64_valid(tv)) return -EINVAL;
- error = security_settime(tv, tz); + ts = timespec64_to_timespec(*tv); + error = security_settime(&ts, tz); if (error) return error;
@@ -182,7 +184,7 @@ int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz) } } if (tv) - return do_settimeofday(tv); + return do_settimeofday64(tv); return 0; }
This patch converts the timepsec type to timespec64 type, and converts the itimerspec type to itimerspec64 type for the k_clock callback functions.
This patch also converts the timespec type to timespec64 type for timekeeping_clocktai() function which is used only in the posix-timers.c file.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- include/linux/timekeeping.h | 4 +- kernel/time/posix-timers.c | 96 +++++++++++++++++++++---------------------- kernel/time/timekeeping.h | 2 +- 3 files changed, 51 insertions(+), 51 deletions(-)
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 89beb62..c3345d5 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -250,9 +250,9 @@ static inline void get_monotonic_boottime64(struct timespec64 *ts) *ts = ktime_to_timespec64(ktime_get_boottime()); }
-static inline void timekeeping_clocktai(struct timespec *ts) +static inline void timekeeping_clocktai(struct timespec64 *ts) { - *ts = ktime_to_timespec(ktime_get_clocktai()); + *ts = ktime_to_timespec64(ktime_get_clocktai()); }
/* diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 4c7c7d3..8ced634 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -132,9 +132,9 @@ static struct k_clock posix_clocks[MAX_CLOCKS]; static int common_nsleep(const clockid_t, int flags, struct timespec *t, struct timespec __user *rmtp); static int common_timer_create(struct k_itimer *new_timer); -static void common_timer_get(struct k_itimer *, struct itimerspec *); +static void common_timer_get(struct k_itimer *, struct itimerspec64 *); static int common_timer_set(struct k_itimer *, int, - struct itimerspec *, struct itimerspec *); + struct itimerspec64 *, struct itimerspec64 *); static int common_timer_del(struct k_itimer *timer);
static enum hrtimer_restart posix_timer_fn(struct hrtimer *data); @@ -204,17 +204,17 @@ static inline void unlock_timer(struct k_itimer *timr, unsigned long flags) }
/* Get clock_realtime */ -static int posix_clock_realtime_get(clockid_t which_clock, struct timespec *tp) +static int posix_clock_realtime_get(clockid_t which_clock, struct timespec64 *tp) { - ktime_get_real_ts(tp); + ktime_get_real_ts64(tp); return 0; }
/* Set clock_realtime */ static int posix_clock_realtime_set(const clockid_t which_clock, - const struct timespec *tp) + const struct timespec64 *tp) { - return do_sys_settimeofday(tp, NULL); + return do_sys_settimeofday64(tp, NULL); }
static int posix_clock_realtime_adj(const clockid_t which_clock, @@ -226,48 +226,48 @@ static int posix_clock_realtime_adj(const clockid_t which_clock, /* * Get monotonic time for posix timers */ -static int posix_ktime_get_ts(clockid_t which_clock, struct timespec *tp) +static int posix_ktime_get_ts(clockid_t which_clock, struct timespec64 *tp) { - ktime_get_ts(tp); + ktime_get_ts64(tp); return 0; }
/* * Get monotonic-raw time for posix timers */ -static int posix_get_monotonic_raw(clockid_t which_clock, struct timespec *tp) +static int posix_get_monotonic_raw(clockid_t which_clock, struct timespec64 *tp) { - getrawmonotonic(tp); + getrawmonotonic64(tp); return 0; }
-static int posix_get_realtime_coarse(clockid_t which_clock, struct timespec *tp) +static int posix_get_realtime_coarse(clockid_t which_clock, struct timespec64 *tp) { - *tp = current_kernel_time(); + *tp = current_kernel_time64(); return 0; }
static int posix_get_monotonic_coarse(clockid_t which_clock, - struct timespec *tp) + struct timespec64 *tp) { - *tp = get_monotonic_coarse(); + *tp = get_monotonic_coarse64(); return 0; }
-static int posix_get_coarse_res(const clockid_t which_clock, struct timespec *tp) +static int posix_get_coarse_res(const clockid_t which_clock, struct timespec64 *tp) { - *tp = ktime_to_timespec(KTIME_LOW_RES); + *tp = ktime_to_timespec64(KTIME_LOW_RES); return 0; }
-static int posix_get_boottime(const clockid_t which_clock, struct timespec *tp) +static int posix_get_boottime(const clockid_t which_clock, struct timespec64 *tp) { - get_monotonic_boottime(tp); + get_monotonic_boottime64(tp); return 0; }
-static int posix_get_tai(clockid_t which_clock, struct timespec *tp) +static int posix_get_tai(clockid_t which_clock, struct timespec64 *tp) { timekeeping_clocktai(tp); return 0; @@ -279,57 +279,57 @@ static int posix_get_tai(clockid_t which_clock, struct timespec *tp) static __init int init_posix_timers(void) { struct k_clock clock_realtime = { - .clock_getres = hrtimer_get_res, - .clock_get = posix_clock_realtime_get, - .clock_set = posix_clock_realtime_set, + .clock_getres64 = hrtimer_get_res64, + .clock_get64 = posix_clock_realtime_get, + .clock_set64 = posix_clock_realtime_set, .clock_adj = posix_clock_realtime_adj, .nsleep = common_nsleep, .nsleep_restart = hrtimer_nanosleep_restart, .timer_create = common_timer_create, - .timer_set = common_timer_set, - .timer_get = common_timer_get, + .timer_set64 = common_timer_set, + .timer_get64 = common_timer_get, .timer_del = common_timer_del, }; struct k_clock clock_monotonic = { - .clock_getres = hrtimer_get_res, - .clock_get = posix_ktime_get_ts, + .clock_getres64 = hrtimer_get_res64, + .clock_get64 = posix_ktime_get_ts, .nsleep = common_nsleep, .nsleep_restart = hrtimer_nanosleep_restart, .timer_create = common_timer_create, - .timer_set = common_timer_set, - .timer_get = common_timer_get, + .timer_set64 = common_timer_set, + .timer_get64 = common_timer_get, .timer_del = common_timer_del, }; struct k_clock clock_monotonic_raw = { - .clock_getres = hrtimer_get_res, - .clock_get = posix_get_monotonic_raw, + .clock_getres64 = hrtimer_get_res64, + .clock_get64 = posix_get_monotonic_raw, }; struct k_clock clock_realtime_coarse = { - .clock_getres = posix_get_coarse_res, - .clock_get = posix_get_realtime_coarse, + .clock_getres64 = posix_get_coarse_res, + .clock_get64 = posix_get_realtime_coarse, }; struct k_clock clock_monotonic_coarse = { - .clock_getres = posix_get_coarse_res, - .clock_get = posix_get_monotonic_coarse, + .clock_getres64 = posix_get_coarse_res, + .clock_get64 = posix_get_monotonic_coarse, }; struct k_clock clock_tai = { - .clock_getres = hrtimer_get_res, - .clock_get = posix_get_tai, + .clock_getres64 = hrtimer_get_res64, + .clock_get64 = posix_get_tai, .nsleep = common_nsleep, .nsleep_restart = hrtimer_nanosleep_restart, .timer_create = common_timer_create, - .timer_set = common_timer_set, - .timer_get = common_timer_get, + .timer_set64 = common_timer_set, + .timer_get64 = common_timer_get, .timer_del = common_timer_del, }; struct k_clock clock_boottime = { - .clock_getres = hrtimer_get_res, - .clock_get = posix_get_boottime, + .clock_getres64 = hrtimer_get_res64, + .clock_get64 = posix_get_boottime, .nsleep = common_nsleep, .nsleep_restart = hrtimer_nanosleep_restart, .timer_create = common_timer_create, - .timer_set = common_timer_set, - .timer_get = common_timer_get, + .timer_set64 = common_timer_set, + .timer_get64 = common_timer_get, .timer_del = common_timer_del, };
@@ -790,7 +790,7 @@ static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags) * report. */ static void -common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) +common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) { ktime_t now, remaining, iv; struct hrtimer *timer = &timr->it.real.timer; @@ -801,7 +801,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
/* interval timer ? */ if (iv.tv64) - cur_setting->it_interval = ktime_to_timespec(iv); + cur_setting->it_interval = ktime_to_timespec64(iv); else if (!hrtimer_active(timer) && (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) return; @@ -827,7 +827,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) cur_setting->it_value.tv_nsec = 1; } else - cur_setting->it_value = ktime_to_timespec(remaining); + cur_setting->it_value = ktime_to_timespec64(remaining); }
static int __timer_gettime(timer_t timer_id, struct itimerspec64 *cur_setting) @@ -902,7 +902,7 @@ SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id) /* timr->it_lock is taken. */ static int common_timer_set(struct k_itimer *timr, int flags, - struct itimerspec *new_setting, struct itimerspec *old_setting) + struct itimerspec64 *new_setting, struct itimerspec64 *old_setting) { struct hrtimer *timer = &timr->it.real.timer; enum hrtimer_mode mode; @@ -931,10 +931,10 @@ common_timer_set(struct k_itimer *timr, int flags, hrtimer_init(&timr->it.real.timer, timr->it_clock, mode); timr->it.real.timer.function = posix_timer_fn;
- hrtimer_set_expires(timer, timespec_to_ktime(new_setting->it_value)); + hrtimer_set_expires(timer, timespec64_to_ktime(new_setting->it_value));
/* Convert interval */ - timr->it.real.interval = timespec_to_ktime(new_setting->it_interval); + timr->it.real.interval = timespec64_to_ktime(new_setting->it_interval);
/* SIGEV_NONE timers are not queued ! See common_timer_get */ if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) { diff --git a/kernel/time/timekeeping.h b/kernel/time/timekeeping.h index 1d91416..144af14 100644 --- a/kernel/time/timekeeping.h +++ b/kernel/time/timekeeping.h @@ -15,7 +15,7 @@ extern u64 timekeeping_max_deferment(void); extern int timekeeping_inject_offset(struct timespec *ts); extern s32 timekeeping_get_tai_offset(void); extern void timekeeping_set_tai_offset(s32 tai_offset); -extern void timekeeping_clocktai(struct timespec *ts); +extern void timekeeping_clocktai(struct timespec64 *ts); extern int timekeeping_suspend(void); extern void timekeeping_resume(void);
This patch converts to the 64bit methods for k_clock callback function, that converts the timespec type to timespec64 type and converts the itimerspec type to itimerspec64 type.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- drivers/char/mmtimer.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-)
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index 3d6c067..213d0bb 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -478,18 +478,18 @@ static int sgi_clock_period; static struct timespec sgi_clock_offset; static int sgi_clock_period;
-static int sgi_clock_get(clockid_t clockid, struct timespec *tp) +static int sgi_clock_get(clockid_t clockid, struct timespec64 *tp) { u64 nsec;
nsec = rtc_time() * sgi_clock_period + sgi_clock_offset.tv_nsec; - *tp = ns_to_timespec(nsec); + *tp = ns_to_timespec64(nsec); tp->tv_sec += sgi_clock_offset.tv_sec; return 0; };
-static int sgi_clock_set(const clockid_t clockid, const struct timespec *tp) +static int sgi_clock_set(const clockid_t clockid, const struct timespec64 *tp) {
u64 nsec; @@ -657,7 +657,7 @@ static int sgi_timer_del(struct k_itimer *timr) }
/* Assumption: it_lock is already held with irq's disabled */ -static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) +static void sgi_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) {
if (timr->it.mmtimer.clock == TIMER_OFF) { @@ -668,14 +668,14 @@ static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) return; }
- cur_setting->it_interval = ns_to_timespec(timr->it.mmtimer.incr * sgi_clock_period); - cur_setting->it_value = ns_to_timespec((timr->it.mmtimer.expires - rtc_time()) * sgi_clock_period); + cur_setting->it_interval = ns_to_timespec64(timr->it.mmtimer.incr * sgi_clock_period); + cur_setting->it_value = ns_to_timespec64((timr->it.mmtimer.expires - rtc_time()) * sgi_clock_period); }
static int sgi_timer_set(struct k_itimer *timr, int flags, - struct itimerspec * new_setting, - struct itimerspec * old_setting) + struct itimerspec64 *new_setting, + struct itimerspec64 *old_setting) { unsigned long when, period, irqflags; int err = 0; @@ -687,8 +687,8 @@ static int sgi_timer_set(struct k_itimer *timr, int flags, sgi_timer_get(timr, old_setting);
sgi_timer_del(timr); - when = timespec_to_ns(&new_setting->it_value); - period = timespec_to_ns(&new_setting->it_interval); + when = timespec64_to_ns(&new_setting->it_value); + period = timespec64_to_ns(&new_setting->it_interval);
if (when == 0) /* Clear timer */ @@ -699,11 +699,9 @@ static int sgi_timer_set(struct k_itimer *timr, int flags, return -ENOMEM;
if (flags & TIMER_ABSTIME) { - struct timespec n; unsigned long now;
- getnstimeofday(&n); - now = timespec_to_ns(&n); + now = ktime_get_real_ns(); if (when > now) when -= now; else @@ -765,7 +763,7 @@ static int sgi_timer_set(struct k_itimer *timr, int flags, return err; }
-static int sgi_clock_getres(const clockid_t which_clock, struct timespec *tp) +static int sgi_clock_getres(const clockid_t which_clock, struct timespec64 *tp) { tp->tv_sec = 0; tp->tv_nsec = sgi_clock_period; @@ -773,13 +771,13 @@ static int sgi_clock_getres(const clockid_t which_clock, struct timespec *tp) }
static struct k_clock sgi_clock = { - .clock_set = sgi_clock_set, - .clock_get = sgi_clock_get, - .clock_getres = sgi_clock_getres, + .clock_set64 = sgi_clock_set, + .clock_get64 = sgi_clock_get, + .clock_getres64 = sgi_clock_getres, .timer_create = sgi_timer_create, - .timer_set = sgi_timer_set, + .timer_set64 = sgi_timer_set, .timer_del = sgi_timer_del, - .timer_get = sgi_timer_get + .timer_get64 = sgi_timer_get };
/**
This patch changes to the new methods with timespec64/itimerspec64 type of k_clock structure, and converts the timespec/itimerspec type to timespec64/itimerspec64 typein alarmtimer.c file.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- kernel/time/alarmtimer.c | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-)
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 1b001ed..68186e1 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -489,35 +489,36 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, /** * alarm_clock_getres - posix getres interface * @which_clock: clockid - * @tp: timespec to fill + * @tp: timespec64 to fill * * Returns the granularity of underlying alarm base clock */ -static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp) +static int alarm_clock_getres(const clockid_t which_clock, + struct timespec64 *tp) { clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid;
if (!alarmtimer_get_rtcdev()) return -EINVAL;
- return hrtimer_get_res(baseid, tp); + return hrtimer_get_res64(baseid, tp); }
/** * alarm_clock_get - posix clock_get interface * @which_clock: clockid - * @tp: timespec to fill. + * @tp: timespec64 to fill. * * Provides the underlying alarm base time. */ -static int alarm_clock_get(clockid_t which_clock, struct timespec *tp) +static int alarm_clock_get(clockid_t which_clock, struct timespec64 *tp) { struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)];
if (!alarmtimer_get_rtcdev()) return -EINVAL;
- *tp = ktime_to_timespec(base->gettime()); + *tp = ktime_to_timespec64(base->gettime()); return 0; }
@@ -547,24 +548,24 @@ static int alarm_timer_create(struct k_itimer *new_timer) /** * alarm_timer_get - posix timer_get interface * @new_timer: k_itimer pointer - * @cur_setting: itimerspec data to fill + * @cur_setting: itimerspec64 data to fill * * Copies out the current itimerspec data */ static void alarm_timer_get(struct k_itimer *timr, - struct itimerspec *cur_setting) + struct itimerspec64 *cur_setting) { ktime_t relative_expiry_time = alarm_expires_remaining(&(timr->it.alarm.alarmtimer));
if (ktime_to_ns(relative_expiry_time) > 0) { - cur_setting->it_value = ktime_to_timespec(relative_expiry_time); + cur_setting->it_value = ktime_to_timespec64(relative_expiry_time); } else { cur_setting->it_value.tv_sec = 0; cur_setting->it_value.tv_nsec = 0; }
- cur_setting->it_interval = ktime_to_timespec(timr->it.alarm.interval); + cur_setting->it_interval = ktime_to_timespec64(timr->it.alarm.interval); }
/** @@ -588,14 +589,14 @@ static int alarm_timer_del(struct k_itimer *timr) * alarm_timer_set - posix timer_set interface * @timr: k_itimer pointer to be deleted * @flags: timer flags - * @new_setting: itimerspec to be used - * @old_setting: itimerspec being replaced + * @new_setting: itimerspec64 to be used + * @old_setting: itimerspec64 being replaced * * Sets the timer to new_setting, and starts the timer. */ static int alarm_timer_set(struct k_itimer *timr, int flags, - struct itimerspec *new_setting, - struct itimerspec *old_setting) + struct itimerspec64 *new_setting, + struct itimerspec64 *old_setting) { ktime_t exp;
@@ -613,8 +614,8 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, return TIMER_RETRY;
/* start the timer */ - timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval); - exp = timespec_to_ktime(new_setting->it_value); + timr->it.alarm.interval = timespec64_to_ktime(new_setting->it_interval); + exp = timespec64_to_ktime(new_setting->it_value); /* Convert (if necessary) to absolute time */ if (flags != TIMER_ABSTIME) { ktime_t now; @@ -670,7 +671,7 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp)
/** - * update_rmtp - Update remaining timespec value + * update_rmtp - Update remaining timespec64 value * @exp: expiration time * @type: timer type * @rmtp: user pointer to remaining timepsec value @@ -824,12 +825,12 @@ static int __init alarmtimer_init(void) int error = 0; int i; struct k_clock alarm_clock = { - .clock_getres = alarm_clock_getres, - .clock_get = alarm_clock_get, + .clock_getres64 = alarm_clock_getres, + .clock_get64 = alarm_clock_get, .timer_create = alarm_timer_create, - .timer_set = alarm_timer_set, + .timer_set64 = alarm_timer_set, .timer_del = alarm_timer_del, - .timer_get = alarm_timer_get, + .timer_get64 = alarm_timer_get, .nsleep = alarm_timer_nsleep, };
This patch converts the posix clock operations over to the new methods with timespec64/itimerspec64 type to making them ready for 2038, and it is based on the ptp patch series.
And also changes to the 64bit methods for k_clock structure, that converts the timespec/itimerspec type to timespec64/itimerspec64 type.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- drivers/ptp/ptp_clock.c | 26 ++++++++------------------ include/linux/posix-clock.h | 10 +++++----- kernel/time/posix-clock.c | 20 ++++++++++---------- 3 files changed, 23 insertions(+), 33 deletions(-)
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c index bee8270..8c086e7 100644 --- a/drivers/ptp/ptp_clock.c +++ b/drivers/ptp/ptp_clock.c @@ -97,32 +97,24 @@ static s32 scaled_ppm_to_ppb(long ppm)
/* posix clock implementation */
-static int ptp_clock_getres(struct posix_clock *pc, struct timespec *tp) +static int ptp_clock_getres(struct posix_clock *pc, struct timespec64 *tp) { tp->tv_sec = 0; tp->tv_nsec = 1; return 0; }
-static int ptp_clock_settime(struct posix_clock *pc, const struct timespec *tp) +static int ptp_clock_settime(struct posix_clock *pc, + const struct timespec64 *tp) { struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock); - struct timespec64 ts = timespec_to_timespec64(*tp); - - return ptp->info->settime64(ptp->info, &ts); + return ptp->info->settime64(ptp->info, tp); }
-static int ptp_clock_gettime(struct posix_clock *pc, struct timespec *tp) +static int ptp_clock_gettime(struct posix_clock *pc, struct timespec64 *tp) { struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock); - struct timespec64 ts; - int err; - - err = ptp->info->gettime64(ptp->info, &ts); - if (!err) - *tp = timespec64_to_timespec(ts); - - return err; + return ptp->info->gettime64(ptp->info, tp); }
static int ptp_clock_adjtime(struct posix_clock *pc, struct timex *tx) @@ -134,8 +126,7 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct timex *tx) ops = ptp->info;
if (tx->modes & ADJ_SETOFFSET) { - struct timespec ts; - ktime_t kt; + struct timespec64 ts; s64 delta;
ts.tv_sec = tx->time.tv_sec; @@ -147,8 +138,7 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct timex *tx) if ((unsigned long) ts.tv_nsec >= NSEC_PER_SEC) return -EINVAL;
- kt = timespec_to_ktime(ts); - delta = ktime_to_ns(kt); + delta = timespec64_to_ns(&ts); err = ops->adjtime(ops, delta); } else if (tx->modes & ADJ_FREQUENCY) { s32 ppb = scaled_ppm_to_ppb(tx->freq); diff --git a/include/linux/posix-clock.h b/include/linux/posix-clock.h index 34c4498..fd7e22c 100644 --- a/include/linux/posix-clock.h +++ b/include/linux/posix-clock.h @@ -59,23 +59,23 @@ struct posix_clock_operations {
int (*clock_adjtime)(struct posix_clock *pc, struct timex *tx);
- int (*clock_gettime)(struct posix_clock *pc, struct timespec *ts); + int (*clock_gettime)(struct posix_clock *pc, struct timespec64 *ts);
- int (*clock_getres) (struct posix_clock *pc, struct timespec *ts); + int (*clock_getres)(struct posix_clock *pc, struct timespec64 *ts);
int (*clock_settime)(struct posix_clock *pc, - const struct timespec *ts); + const struct timespec64 *ts);
int (*timer_create) (struct posix_clock *pc, struct k_itimer *kit);
int (*timer_delete) (struct posix_clock *pc, struct k_itimer *kit);
void (*timer_gettime)(struct posix_clock *pc, - struct k_itimer *kit, struct itimerspec *tsp); + struct k_itimer *kit, struct itimerspec64 *tsp);
int (*timer_settime)(struct posix_clock *pc, struct k_itimer *kit, int flags, - struct itimerspec *tsp, struct itimerspec *old); + struct itimerspec64 *tsp, struct itimerspec64 *old); /* * Optional character device methods: */ diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c index ce033c7..e21e4c1 100644 --- a/kernel/time/posix-clock.c +++ b/kernel/time/posix-clock.c @@ -297,7 +297,7 @@ out: return err; }
-static int pc_clock_gettime(clockid_t id, struct timespec *ts) +static int pc_clock_gettime(clockid_t id, struct timespec64 *ts) { struct posix_clock_desc cd; int err; @@ -316,7 +316,7 @@ static int pc_clock_gettime(clockid_t id, struct timespec *ts) return err; }
-static int pc_clock_getres(clockid_t id, struct timespec *ts) +static int pc_clock_getres(clockid_t id, struct timespec64 *ts) { struct posix_clock_desc cd; int err; @@ -335,7 +335,7 @@ static int pc_clock_getres(clockid_t id, struct timespec *ts) return err; }
-static int pc_clock_settime(clockid_t id, const struct timespec *ts) +static int pc_clock_settime(clockid_t id, const struct timespec64 *ts) { struct posix_clock_desc cd; int err; @@ -399,7 +399,7 @@ static int pc_timer_delete(struct k_itimer *kit) return err; }
-static void pc_timer_gettime(struct k_itimer *kit, struct itimerspec *ts) +static void pc_timer_gettime(struct k_itimer *kit, struct itimerspec64 *ts) { clockid_t id = kit->it_clock; struct posix_clock_desc cd; @@ -414,7 +414,7 @@ static void pc_timer_gettime(struct k_itimer *kit, struct itimerspec *ts) }
static int pc_timer_settime(struct k_itimer *kit, int flags, - struct itimerspec *ts, struct itimerspec *old) + struct itimerspec64 *ts, struct itimerspec64 *old) { clockid_t id = kit->it_clock; struct posix_clock_desc cd; @@ -435,12 +435,12 @@ static int pc_timer_settime(struct k_itimer *kit, int flags, }
struct k_clock clock_posix_dynamic = { - .clock_getres = pc_clock_getres, - .clock_set = pc_clock_settime, - .clock_get = pc_clock_gettime, + .clock_getres64 = pc_clock_getres, + .clock_set64 = pc_clock_settime, + .clock_get64 = pc_clock_gettime, .clock_adj = pc_clock_adjtime, .timer_create = pc_timer_create, - .timer_set = pc_timer_settime, + .timer_set64 = pc_timer_settime, .timer_del = pc_timer_delete, - .timer_get = pc_timer_gettime, + .timer_get64 = pc_timer_gettime, };
This patch introduces the timespec64_to_jiffies() and jiffies_to_timespec64() functions, that implement the conversion between cputime and timespec64. And remove the old functions timespec64_to_jiffies()/jiffies_to_timespec64() to jiffies.h file.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- include/linux/jiffies.h | 21 ++++++++++++++++++--- kernel/time/time.c | 12 ++++++------ 2 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index c367cbd..16a30c1 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -290,9 +290,24 @@ static inline u64 jiffies_to_nsecs(const unsigned long j)
extern unsigned long msecs_to_jiffies(const unsigned int m); extern unsigned long usecs_to_jiffies(const unsigned int u); -extern unsigned long timespec_to_jiffies(const struct timespec *value); -extern void jiffies_to_timespec(const unsigned long jiffies, - struct timespec *value); +extern unsigned long __timespec_to_jiffies(unsigned long sec, long nsec); +extern unsigned long timespec64_to_jiffies(const struct timespec64 *value); +extern void jiffies_to_timespec64(const unsigned long jiffies, + struct timespec64 *value); +static inline unsigned long timespec_to_jiffies(const struct timespec *value) +{ + return __timespec_to_jiffies(value->tv_sec, value->tv_nsec); +} + +static inline void jiffies_to_timespec(const unsigned long jiffies, + struct timespec *value) +{ + struct timespec64 *ts; + + *ts = timespec_to_timespec64(*value); + jiffies_to_timespec64(jiffies, ts); +} + extern unsigned long timeval_to_jiffies(const struct timeval *value); extern void jiffies_to_timeval(const unsigned long jiffies, struct timeval *value); diff --git a/kernel/time/time.c b/kernel/time/time.c index f43011b..3aba16f 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -571,7 +571,7 @@ EXPORT_SYMBOL(usecs_to_jiffies); * The >> (NSEC_JIFFIE_SC - SEC_JIFFIE_SC) converts the scaled nsec * value to a scaled second value. */ -static unsigned long +unsigned long __timespec_to_jiffies(unsigned long sec, long nsec) { nsec = nsec + TICK_NSEC - 1; @@ -585,17 +585,17 @@ __timespec_to_jiffies(unsigned long sec, long nsec) (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
} +EXPORT_SYMBOL(__timespec_to_jiffies);
unsigned long -timespec_to_jiffies(const struct timespec *value) +timespec64_to_jiffies(const struct timespec64 *value) { return __timespec_to_jiffies(value->tv_sec, value->tv_nsec); } - -EXPORT_SYMBOL(timespec_to_jiffies); +EXPORT_SYMBOL(timespec64_to_jiffies);
void -jiffies_to_timespec(const unsigned long jiffies, struct timespec *value) +jiffies_to_timespec64(const unsigned long jiffies, struct timespec64 *value) { /* * Convert jiffies to nanoseconds and separate with @@ -606,7 +606,7 @@ jiffies_to_timespec(const unsigned long jiffies, struct timespec *value) NSEC_PER_SEC, &rem); value->tv_nsec = rem; } -EXPORT_SYMBOL(jiffies_to_timespec); +EXPORT_SYMBOL(jiffies_to_timespec64);
/* * We could use a similar algorithm to timespec_to_jiffies (with a
This patch introduces some functions for converting cputime to timespec64 and back, that repalce the timespec type with timespec64 type, as well as for arch/s390 and arch/powerpc architecture.
And these new methods will replace the old cputime_to_timespec/timespec_to_cputime function to ready for 2038 issue. The cputime_to_timespec/timespec_to_cputime functions are moved to include/linux/cputime.h file for removing conveniently.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- arch/powerpc/include/asm/cputime.h | 6 +++--- arch/s390/include/asm/cputime.h | 8 ++++---- include/asm-generic/cputime_jiffies.h | 10 +++++----- include/asm-generic/cputime_nsecs.h | 4 ++-- include/linux/cputime.h | 15 +++++++++++++++ 5 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h index e245255..5dda5c0 100644 --- a/arch/powerpc/include/asm/cputime.h +++ b/arch/powerpc/include/asm/cputime.h @@ -154,9 +154,9 @@ static inline cputime_t secs_to_cputime(const unsigned long sec) }
/* - * Convert cputime <-> timespec + * Convert cputime <-> timespec64 */ -static inline void cputime_to_timespec(const cputime_t ct, struct timespec *p) +static inline void cputime_to_timespec64(const cputime_t ct, struct timespec64 *p) { u64 x = (__force u64) ct; unsigned int frac; @@ -168,7 +168,7 @@ static inline void cputime_to_timespec(const cputime_t ct, struct timespec *p) p->tv_nsec = x; }
-static inline cputime_t timespec_to_cputime(const struct timespec *p) +static inline cputime_t timespec64_to_cputime(const struct timespec64 *p) { u64 ct;
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index b91e960..1266697 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h @@ -89,16 +89,16 @@ static inline cputime_t secs_to_cputime(const unsigned int s) }
/* - * Convert cputime to timespec and back. + * Convert cputime to timespec64 and back. */ -static inline cputime_t timespec_to_cputime(const struct timespec *value) +static inline cputime_t timespec64_to_cputime(const struct timespec64 *value) { unsigned long long ret = value->tv_sec * CPUTIME_PER_SEC; return (__force cputime_t)(ret + __div(value->tv_nsec * CPUTIME_PER_USEC, NSEC_PER_USEC)); }
-static inline void cputime_to_timespec(const cputime_t cputime, - struct timespec *value) +static inline void cputime_to_timespec64(const cputime_t cputime, + struct timespec64 *value) { unsigned long long __cputime = (__force unsigned long long) cputime; #ifndef CONFIG_64BIT diff --git a/include/asm-generic/cputime_jiffies.h b/include/asm-generic/cputime_jiffies.h index fe386fc..54e034c 100644 --- a/include/asm-generic/cputime_jiffies.h +++ b/include/asm-generic/cputime_jiffies.h @@ -44,12 +44,12 @@ typedef u64 __nocast cputime64_t; #define secs_to_cputime(sec) jiffies_to_cputime((sec) * HZ)
/* - * Convert cputime to timespec and back. + * Convert cputime to timespec64 and back. */ -#define timespec_to_cputime(__val) \ - jiffies_to_cputime(timespec_to_jiffies(__val)) -#define cputime_to_timespec(__ct,__val) \ - jiffies_to_timespec(cputime_to_jiffies(__ct),__val) +#define timespec64_to_cputime(__val) \ + jiffies_to_cputime(timespec64_to_jiffies(__val)) +#define cputime_to_timespec64(__ct,__val) \ + jiffies_to_timespec64(cputime_to_jiffies(__ct),__val)
/* * Convert cputime to timeval and back. diff --git a/include/asm-generic/cputime_nsecs.h b/include/asm-generic/cputime_nsecs.h index 0419485..65c875b 100644 --- a/include/asm-generic/cputime_nsecs.h +++ b/include/asm-generic/cputime_nsecs.h @@ -73,12 +73,12 @@ typedef u64 __nocast cputime64_t; /* * Convert cputime <-> timespec (nsec) */ -static inline cputime_t timespec_to_cputime(const struct timespec *val) +static inline cputime_t timespec64_to_cputime(const struct timespec64 *val) { u64 ret = val->tv_sec * NSEC_PER_SEC + val->tv_nsec; return (__force cputime_t) ret; } -static inline void cputime_to_timespec(const cputime_t ct, struct timespec *val) +static inline void cputime_to_timespec64(const cputime_t ct, struct timespec64 *val) { u32 rem;
diff --git a/include/linux/cputime.h b/include/linux/cputime.h index f2eb2ee..f01896f 100644 --- a/include/linux/cputime.h +++ b/include/linux/cputime.h @@ -13,4 +13,19 @@ usecs_to_cputime((__nsecs) / NSEC_PER_USEC) #endif
+static inline cputime_t timespec_to_cputime(const struct timespec *ts) +{ + struct timespec64 ts64 = timespec_to_timespec64(*ts); + return timespec64_to_cputime(&ts64); +} + +static inline void cputime_to_timespec(const cputime_t cputime, + struct timespec *value) +{ + struct timespec64 *ts64; + + *ts64 = timespec_to_timespec64(*value); + cputime_to_timespec64(cputime, ts64); +} + #endif /* __LINUX_CPUTIME_H */
This patch changes to the new methods of k_clock structure with timespec64 type, converts the timespec/itimerspec type to timespec64/itimerspec64 type for the callback function in posix-cpu-timers.c file.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- kernel/time/posix-cpu-timers.c | 83 +++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 39 deletions(-)
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index 0075da7..a4651cd 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -52,7 +52,7 @@ static int check_clock(const clockid_t which_clock) }
static inline unsigned long long -timespec_to_sample(const clockid_t which_clock, const struct timespec *tp) +timespec64_to_sample(const clockid_t which_clock, const struct timespec64 *tp) { unsigned long long ret;
@@ -60,19 +60,19 @@ timespec_to_sample(const clockid_t which_clock, const struct timespec *tp) if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) { ret = (unsigned long long)tp->tv_sec * NSEC_PER_SEC + tp->tv_nsec; } else { - ret = cputime_to_expires(timespec_to_cputime(tp)); + ret = cputime_to_expires(timespec64_to_cputime(tp)); } return ret; }
-static void sample_to_timespec(const clockid_t which_clock, +static void sample_to_timespec64(const clockid_t which_clock, unsigned long long expires, - struct timespec *tp) + struct timespec64 *tp) { if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) - *tp = ns_to_timespec(expires); + *tp = ns_to_timespec64(expires); else - cputime_to_timespec((__force cputime_t)expires, tp); + cputime_to_timespec64((__force cputime_t)expires, tp); }
/* @@ -141,7 +141,7 @@ static inline unsigned long long virt_ticks(struct task_struct *p) }
static int -posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp) +posix_cpu_clock_getres(const clockid_t which_clock, struct timespec64 *tp) { int error = check_clock(which_clock); if (!error) { @@ -160,7 +160,7 @@ posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp) }
static int -posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp) +posix_cpu_clock_set(const clockid_t which_clock, const struct timespec64 *tp) { /* * You can never reset a CPU clock, but we check for other errors @@ -263,7 +263,7 @@ static int cpu_clock_sample_group(const clockid_t which_clock,
static int posix_cpu_clock_get_task(struct task_struct *tsk, const clockid_t which_clock, - struct timespec *tp) + struct timespec64 *tp) { int err = -EINVAL; unsigned long long rtn; @@ -277,13 +277,14 @@ static int posix_cpu_clock_get_task(struct task_struct *tsk, }
if (!err) - sample_to_timespec(which_clock, rtn, tp); + sample_to_timespec64(which_clock, rtn, tp);
return err; }
-static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) +static int posix_cpu_clock_get(const clockid_t which_clock, + struct timespec64 *tp) { const pid_t pid = CPUCLOCK_PID(which_clock); int err = -EINVAL; @@ -598,7 +599,7 @@ static inline void posix_cpu_timer_kick_nohz(void) { } * and try again. (This happens when the timer is in the middle of firing.) */ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags, - struct itimerspec *new, struct itimerspec *old) + struct itimerspec64 *new, struct itimerspec64 *old) { unsigned long flags; struct sighand_struct *sighand; @@ -608,7 +609,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
WARN_ON_ONCE(p == NULL);
- new_expires = timespec_to_sample(timer->it_clock, &new->it_value); + new_expires = timespec64_to_sample(timer->it_clock, &new->it_value);
/* * Protect against sighand release/switch in exit/exec and p->cpu_timers @@ -669,7 +670,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags, bump_cpu_timer(timer, val); if (val < timer->it.cpu.expires) { old_expires = timer->it.cpu.expires - val; - sample_to_timespec(timer->it_clock, + sample_to_timespec64(timer->it_clock, old_expires, &old->it_value); } else { @@ -709,7 +710,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags, * Install the new reload setting, and * set up the signal and overrun bookkeeping. */ - timer->it.cpu.incr = timespec_to_sample(timer->it_clock, + timer->it.cpu.incr = timespec64_to_sample(timer->it_clock, &new->it_interval);
/* @@ -734,7 +735,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags, ret = 0; out: if (old) { - sample_to_timespec(timer->it_clock, + sample_to_timespec64(timer->it_clock, old_incr, &old->it_interval); } if (!ret) @@ -742,7 +743,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags, return ret; }
-static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) +static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp) { unsigned long long now; struct task_struct *p = timer->it.cpu.task; @@ -752,7 +753,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) /* * Easy part: convert the reload time. */ - sample_to_timespec(timer->it_clock, + sample_to_timespec64(timer->it_clock, timer->it.cpu.incr, &itp->it_interval);
if (timer->it.cpu.expires == 0) { /* Timer not armed at all. */ @@ -782,7 +783,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) * Call the timer disarmed, nothing else to do. */ timer->it.cpu.expires = 0; - sample_to_timespec(timer->it_clock, timer->it.cpu.expires, + sample_to_timespec64(timer->it_clock, timer->it.cpu.expires, &itp->it_value); } else { cpu_timer_sample_group(timer->it_clock, p, &now); @@ -791,7 +792,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) }
if (now < timer->it.cpu.expires) { - sample_to_timespec(timer->it_clock, + sample_to_timespec64(timer->it_clock, timer->it.cpu.expires - now, &itp->it_value); } else { @@ -1248,6 +1249,8 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, struct timespec *rqtp, struct itimerspec *it) { struct k_itimer timer; + struct timespec64 ts64; + struct itimerspec64 *it64; int error;
/* @@ -1260,13 +1263,14 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, error = posix_cpu_timer_create(&timer); timer.it_process = current; if (!error) { - static struct itimerspec zero_it; + static struct itimerspec64 zero_it;
memset(it, 0, sizeof *it); it->it_value = *rqtp;
spin_lock_irq(&timer.it_lock); - error = posix_cpu_timer_set(&timer, flags, it, NULL); + *it64 = itimerspec_to_itimerspec64(it); + error = posix_cpu_timer_set(&timer, flags, it64, NULL); if (error) { spin_unlock_irq(&timer.it_lock); return error; @@ -1295,8 +1299,9 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, /* * We were interrupted by a signal. */ - sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp); - error = posix_cpu_timer_set(&timer, 0, &zero_it, it); + sample_to_timespec64(which_clock, timer.it.cpu.expires, &ts64); + *rqtp = timespec64_to_timespec(ts64); + error = posix_cpu_timer_set(&timer, 0, &zero_it, it64); if (!error) { /* * Timer is now unarmed, deletion can not fail. @@ -1395,12 +1400,12 @@ static long posix_cpu_nsleep_restart(struct restart_block *restart_block) #define THREAD_CLOCK MAKE_THREAD_CPUCLOCK(0, CPUCLOCK_SCHED)
static int process_cpu_clock_getres(const clockid_t which_clock, - struct timespec *tp) + struct timespec64 *tp) { return posix_cpu_clock_getres(PROCESS_CLOCK, tp); } static int process_cpu_clock_get(const clockid_t which_clock, - struct timespec *tp) + struct timespec64 *tp) { return posix_cpu_clock_get(PROCESS_CLOCK, tp); } @@ -1420,12 +1425,12 @@ static long process_cpu_nsleep_restart(struct restart_block *restart_block) return -EINVAL; } static int thread_cpu_clock_getres(const clockid_t which_clock, - struct timespec *tp) + struct timespec64 *tp) { return posix_cpu_clock_getres(THREAD_CLOCK, tp); } static int thread_cpu_clock_get(const clockid_t which_clock, - struct timespec *tp) + struct timespec64 *tp) { return posix_cpu_clock_get(THREAD_CLOCK, tp); } @@ -1436,37 +1441,37 @@ static int thread_cpu_timer_create(struct k_itimer *timer) }
struct k_clock clock_posix_cpu = { - .clock_getres = posix_cpu_clock_getres, - .clock_set = posix_cpu_clock_set, - .clock_get = posix_cpu_clock_get, + .clock_getres64 = posix_cpu_clock_getres, + .clock_set64 = posix_cpu_clock_set, + .clock_get64 = posix_cpu_clock_get, .timer_create = posix_cpu_timer_create, .nsleep = posix_cpu_nsleep, .nsleep_restart = posix_cpu_nsleep_restart, - .timer_set = posix_cpu_timer_set, + .timer_set64 = posix_cpu_timer_set, .timer_del = posix_cpu_timer_del, - .timer_get = posix_cpu_timer_get, + .timer_get64 = posix_cpu_timer_get, };
static __init int init_posix_cpu_timers(void) { struct k_clock process = { - .clock_getres = process_cpu_clock_getres, - .clock_get = process_cpu_clock_get, + .clock_getres64 = process_cpu_clock_getres, + .clock_get64 = process_cpu_clock_get, .timer_create = process_cpu_timer_create, .nsleep = process_cpu_nsleep, .nsleep_restart = process_cpu_nsleep_restart, }; struct k_clock thread = { - .clock_getres = thread_cpu_clock_getres, - .clock_get = thread_cpu_clock_get, + .clock_getres64 = thread_cpu_clock_getres, + .clock_get64 = thread_cpu_clock_get, .timer_create = thread_cpu_timer_create, }; - struct timespec ts; + struct timespec64 ts;
posix_timers_register_clock(CLOCK_PROCESS_CPUTIME_ID, &process); posix_timers_register_clock(CLOCK_THREAD_CPUTIME_ID, &thread);
- cputime_to_timespec(cputime_one_jiffy, &ts); + cputime_to_timespec64(cputime_one_jiffy, &ts); onecputick = ts.tv_nsec; WARN_ON(ts.tv_sec != 0);
All of the k_clock users have been converted to the new methods. This patch removes the older methods with timepsec/itimerspec type. As a result, the k_clock structure is ready for the year 2038.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- include/linux/posix-timers.h | 9 ----- kernel/time/posix-timers.c | 74 +++--------------------------------------- 2 files changed, 5 insertions(+), 78 deletions(-)
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 35786c5..7c3dae2 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -97,29 +97,20 @@ struct k_itimer { };
struct k_clock { - int (*clock_getres) (const clockid_t which_clock, struct timespec *tp); int (*clock_getres64) (const clockid_t which_clock, struct timespec64 *tp); - int (*clock_set) (const clockid_t which_clock, - const struct timespec *tp); int (*clock_set64) (const clockid_t which_clock, const struct timespec64 *tp); - int (*clock_get) (const clockid_t which_clock, struct timespec * tp); int (*clock_get64) (const clockid_t which_clock, struct timespec64 *tp); int (*clock_adj) (const clockid_t which_clock, struct timex *tx); int (*timer_create) (struct k_itimer *timer); int (*nsleep) (const clockid_t which_clock, int flags, struct timespec *, struct timespec __user *); long (*nsleep_restart) (struct restart_block *restart_block); - int (*timer_set) (struct k_itimer * timr, int flags, - struct itimerspec * new_setting, - struct itimerspec * old_setting); int (*timer_set64) (struct k_itimer *timr, int flags, struct itimerspec64 *new_setting, struct itimerspec64 *old_setting); int (*timer_del) (struct k_itimer * timr); #define TIMER_RETRY 1 - void (*timer_get) (struct k_itimer * timr, - struct itimerspec * cur_setting); void (*timer_get64) (struct k_itimer *timr, struct itimerspec64 *cur_setting); }; diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 8ced634..ba95172 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -140,7 +140,6 @@ static int common_timer_del(struct k_itimer *timer); static enum hrtimer_restart posix_timer_fn(struct hrtimer *data);
static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags); -static struct k_clock *clockid_to_kclock(const clockid_t id);
#define lock_timer(tid, flags) \ ({ struct k_itimer *__timr; \ @@ -514,57 +513,6 @@ static struct pid *good_sigevent(sigevent_t * event) return task_pid(rtn); }
-static int default_timer_get64(struct k_itimer *timr, - struct itimerspec64 *cur_setting64) -{ - struct itimerspec cur_setting; - struct k_clock *kc = clockid_to_kclock(timr->it_clock); - - kc->timer_get(timr, &cur_setting); - return 0; -} - -static int default_timer_set64(struct k_itimer *timr, int flags, - struct itimerspec64 *new_setting64, - struct itimerspec64 *old_setting64) -{ - struct k_clock *kc = clockid_to_kclock(timr->it_clock); - struct itimerspec new_setting, old_setting; - - kc->timer_set(timr, flags, &new_setting, &old_setting); - return 0; -} - -static int default_clock_set64(const clockid_t which_clock, - const struct timespec64 *tp64) -{ - struct k_clock *kc = clockid_to_kclock(which_clock); - struct timespec tp; - - kc->clock_set(which_clock, &tp); - return 0; -} - -static int default_clock_get64(const clockid_t which_clock, - struct timespec64 *tp64) -{ - struct k_clock *kc = clockid_to_kclock(which_clock); - struct timespec tp; - - kc->clock_get(which_clock, &tp); - return 0; -} - -static int default_clock_getres64(const clockid_t which_clock, - struct timespec64 *tp64) -{ - struct k_clock *kc = clockid_to_kclock(which_clock); - struct timespec tp; - - kc->clock_getres(which_clock, &tp); - return 0; -} - void posix_timers_register_clock(const clockid_t clock_id, struct k_clock *new_clock) { @@ -574,28 +522,17 @@ void posix_timers_register_clock(const clockid_t clock_id, return; }
- if (!new_clock->clock_get && !new_clock->clock_get64) { - printk(KERN_WARNING "POSIX clock id %d lacks clock_get() and clock_get64()\n", + if (!new_clock->clock_get64) { + printk(KERN_WARNING "POSIX clock id %d lacks clock_get64()\n", clock_id); return; } - if (!new_clock->clock_getres && !new_clock->clock_getres64) { - printk(KERN_WARNING "POSIX clock id %d lacks clock_getres() and clock_getres64()\n", + if (!new_clock->clock_getres64) { + printk(KERN_WARNING "POSIX clock id %d lacks clock_getres64()\n", clock_id); return; }
- if (new_clock->timer_get && !new_clock->timer_get64) - new_clock->timer_get64 = default_timer_get64; - if (new_clock->timer_set && !new_clock->timer_set64) - new_clock->timer_set64 = default_timer_set64; - if (new_clock->clock_set && !new_clock->clock_set64) - new_clock->clock_set64 = default_clock_set64; - if (new_clock->clock_get && !new_clock->clock_get64) - new_clock->clock_get64 = default_clock_get64; - if (new_clock->clock_getres && !new_clock->clock_getres64) - new_clock->clock_getres64 = default_clock_getres64; - posix_clocks[clock_id] = *new_clock; } EXPORT_SYMBOL_GPL(posix_timers_register_clock); @@ -642,8 +579,7 @@ static struct k_clock *clockid_to_kclock(const clockid_t id) return (id & CLOCKFD_MASK) == CLOCKFD ? &clock_posix_dynamic : &clock_posix_cpu;
- if (id >= MAX_CLOCKS || (!posix_clocks[id].clock_getres - && !posix_clocks[id].clock_getres64)) + if (id >= MAX_CLOCKS || !posix_clocks[id].clock_getres64) return NULL; return &posix_clocks[id]; }
On Wednesday 29 April 2015 22:55:23 Baolin Wang wrote:
This patch series changes the 32-bit time type (timespec/itimerspec) to the 64-bit one (timespec64/itimerspec64), since 32-bit time types will break in the year 2038.
This patch series introduces new methods with timespec64/itimerspec64 type, and removes the old ones with timespec/itimerspec type for posix_clock_operations and k_clock structure.
Looks all good to me now. Can you post it again with the mailing lists and some of the key people on Cc?
Last time, you actually had more people than necessary on Cc, and that can end up in spam filters. If someone is a maintainer for just one or two patches out of the series, it can be better to add an explicit 'Cc: person@example.org' statement in those patches, and not Cc them for the whole series.
One last thing: make sure you always increase the version number on the patches, to make it easier to see which one people are replying to, in case there is still discussion on an older version of the patch set. The first version is just [PATCH 1/x], after that you use [PATCH 1/x v2] for the second version, not 'v1'.
Arnd