diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2015-08-20 15:13:22 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2015-08-20 15:13:22 -0400 |
commit | 05ddaa4d6d3806bebdf14f7c5de742a6e0e3b689 (patch) | |
tree | cbad6d1db5ce324c75b0eecdfd4c0857cfee9347 | |
parent | b48362d8aaf32aeb4a75f5c556c652ffeeb1be5d (diff) | |
parent | 9ca308506062fc4a4ee8ca7ad2f71033c831c2fb (diff) |
Merge branch 'fortglx/4.3/time' of https://git.linaro.org/people/john.stultz/linux into timers/core
- A handful or y2038 related items
- A walltime to monotonic limit
- Small fixes for timespec_trunc() and timer_list output
-rw-r--r-- | include/linux/jiffies.h | 22 | ||||
-rw-r--r-- | include/linux/time64.h | 35 | ||||
-rw-r--r-- | include/linux/timekeeping.h | 9 | ||||
-rw-r--r-- | kernel/time/ntp.c | 5 | ||||
-rw-r--r-- | kernel/time/time.c | 43 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 19 | ||||
-rw-r--r-- | kernel/time/timer_list.c | 2 |
7 files changed, 102 insertions, 33 deletions
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 535fd3bb1ba8..bf96d9f27bd0 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h | |||
@@ -416,9 +416,25 @@ static inline unsigned long usecs_to_jiffies(const unsigned int u) | |||
416 | } | 416 | } |
417 | } | 417 | } |
418 | 418 | ||
419 | extern unsigned long timespec_to_jiffies(const struct timespec *value); | 419 | extern unsigned long timespec64_to_jiffies(const struct timespec64 *value); |
420 | extern void jiffies_to_timespec(const unsigned long jiffies, | 420 | extern void jiffies_to_timespec64(const unsigned long jiffies, |
421 | struct timespec *value); | 421 | struct timespec64 *value); |
422 | static inline unsigned long timespec_to_jiffies(const struct timespec *value) | ||
423 | { | ||
424 | struct timespec64 ts = timespec_to_timespec64(*value); | ||
425 | |||
426 | return timespec64_to_jiffies(&ts); | ||
427 | } | ||
428 | |||
429 | static inline void jiffies_to_timespec(const unsigned long jiffies, | ||
430 | struct timespec *value) | ||
431 | { | ||
432 | struct timespec64 ts; | ||
433 | |||
434 | jiffies_to_timespec64(jiffies, &ts); | ||
435 | *value = timespec64_to_timespec(ts); | ||
436 | } | ||
437 | |||
422 | extern unsigned long timeval_to_jiffies(const struct timeval *value); | 438 | extern unsigned long timeval_to_jiffies(const struct timeval *value); |
423 | extern void jiffies_to_timeval(const unsigned long jiffies, | 439 | extern void jiffies_to_timeval(const unsigned long jiffies, |
424 | struct timeval *value); | 440 | struct timeval *value); |
diff --git a/include/linux/time64.h b/include/linux/time64.h index 77b5df2acd2a..367d5af899e8 100644 --- a/include/linux/time64.h +++ b/include/linux/time64.h | |||
@@ -12,11 +12,18 @@ typedef __s64 time64_t; | |||
12 | */ | 12 | */ |
13 | #if __BITS_PER_LONG == 64 | 13 | #if __BITS_PER_LONG == 64 |
14 | # define timespec64 timespec | 14 | # define timespec64 timespec |
15 | #define itimerspec64 itimerspec | ||
15 | #else | 16 | #else |
16 | struct timespec64 { | 17 | struct timespec64 { |
17 | time64_t tv_sec; /* seconds */ | 18 | time64_t tv_sec; /* seconds */ |
18 | long tv_nsec; /* nanoseconds */ | 19 | long tv_nsec; /* nanoseconds */ |
19 | }; | 20 | }; |
21 | |||
22 | struct itimerspec64 { | ||
23 | struct timespec64 it_interval; | ||
24 | struct timespec64 it_value; | ||
25 | }; | ||
26 | |||
20 | #endif | 27 | #endif |
21 | 28 | ||
22 | /* Parameters used to convert the timespec values: */ | 29 | /* Parameters used to convert the timespec values: */ |
@@ -45,6 +52,16 @@ static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) | |||
45 | return ts; | 52 | return ts; |
46 | } | 53 | } |
47 | 54 | ||
55 | static inline struct itimerspec itimerspec64_to_itimerspec(struct itimerspec64 *its64) | ||
56 | { | ||
57 | return *its64; | ||
58 | } | ||
59 | |||
60 | static inline struct itimerspec64 itimerspec_to_itimerspec64(struct itimerspec *its) | ||
61 | { | ||
62 | return *its; | ||
63 | } | ||
64 | |||
48 | # define timespec64_equal timespec_equal | 65 | # define timespec64_equal timespec_equal |
49 | # define timespec64_compare timespec_compare | 66 | # define timespec64_compare timespec_compare |
50 | # define set_normalized_timespec64 set_normalized_timespec | 67 | # define set_normalized_timespec64 set_normalized_timespec |
@@ -77,6 +94,24 @@ static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) | |||
77 | return ret; | 94 | return ret; |
78 | } | 95 | } |
79 | 96 | ||
97 | static inline struct itimerspec itimerspec64_to_itimerspec(struct itimerspec64 *its64) | ||
98 | { | ||
99 | struct itimerspec ret; | ||
100 | |||
101 | ret.it_interval = timespec64_to_timespec(its64->it_interval); | ||
102 | ret.it_value = timespec64_to_timespec(its64->it_value); | ||
103 | return ret; | ||
104 | } | ||
105 | |||
106 | static inline struct itimerspec64 itimerspec_to_itimerspec64(struct itimerspec *its) | ||
107 | { | ||
108 | struct itimerspec64 ret; | ||
109 | |||
110 | ret.it_interval = timespec_to_timespec64(its->it_interval); | ||
111 | ret.it_value = timespec_to_timespec64(its->it_value); | ||
112 | return ret; | ||
113 | } | ||
114 | |||
80 | static inline int timespec64_equal(const struct timespec64 *a, | 115 | static inline int timespec64_equal(const struct timespec64 *a, |
81 | const struct timespec64 *b) | 116 | const struct timespec64 *b) |
82 | { | 117 | { |
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 6e191e4e6ab6..ba0ae09cbb21 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h | |||
@@ -18,10 +18,17 @@ extern int do_sys_settimeofday(const struct timespec *tv, | |||
18 | * Kernel time accessors | 18 | * Kernel time accessors |
19 | */ | 19 | */ |
20 | unsigned long get_seconds(void); | 20 | unsigned long get_seconds(void); |
21 | struct timespec current_kernel_time(void); | 21 | struct timespec64 current_kernel_time64(void); |
22 | /* does not take xtime_lock */ | 22 | /* does not take xtime_lock */ |
23 | struct timespec __current_kernel_time(void); | 23 | struct timespec __current_kernel_time(void); |
24 | 24 | ||
25 | static inline struct timespec current_kernel_time(void) | ||
26 | { | ||
27 | struct timespec64 now = current_kernel_time64(); | ||
28 | |||
29 | return timespec64_to_timespec(now); | ||
30 | } | ||
31 | |||
25 | /* | 32 | /* |
26 | * timespec based interfaces | 33 | * timespec based interfaces |
27 | */ | 34 | */ |
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index fb4d98c7fd43..df68cb875248 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -487,6 +487,11 @@ out: | |||
487 | } | 487 | } |
488 | 488 | ||
489 | #ifdef CONFIG_GENERIC_CMOS_UPDATE | 489 | #ifdef CONFIG_GENERIC_CMOS_UPDATE |
490 | int __weak update_persistent_clock(struct timespec now) | ||
491 | { | ||
492 | return -ENODEV; | ||
493 | } | ||
494 | |||
490 | int __weak update_persistent_clock64(struct timespec64 now64) | 495 | int __weak update_persistent_clock64(struct timespec64 now64) |
491 | { | 496 | { |
492 | struct timespec now; | 497 | struct timespec now; |
diff --git a/kernel/time/time.c b/kernel/time/time.c index 85d5bb1d67eb..f18ab105ed87 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c | |||
@@ -287,26 +287,20 @@ EXPORT_SYMBOL(jiffies_to_usecs); | |||
287 | * @t: Timespec | 287 | * @t: Timespec |
288 | * @gran: Granularity in ns. | 288 | * @gran: Granularity in ns. |
289 | * | 289 | * |
290 | * Truncate a timespec to a granularity. gran must be smaller than a second. | 290 | * Truncate a timespec to a granularity. Always rounds down. gran must |
291 | * Always rounds down. | 291 | * not be 0 nor greater than a second (NSEC_PER_SEC, or 10^9 ns). |
292 | * | ||
293 | * This function should be only used for timestamps returned by | ||
294 | * current_kernel_time() or CURRENT_TIME, not with do_gettimeofday() because | ||
295 | * it doesn't handle the better resolution of the latter. | ||
296 | */ | 292 | */ |
297 | struct timespec timespec_trunc(struct timespec t, unsigned gran) | 293 | struct timespec timespec_trunc(struct timespec t, unsigned gran) |
298 | { | 294 | { |
299 | /* | 295 | /* Avoid division in the common cases 1 ns and 1 s. */ |
300 | * Division is pretty slow so avoid it for common cases. | 296 | if (gran == 1) { |
301 | * Currently current_kernel_time() never returns better than | ||
302 | * jiffies resolution. Exploit that. | ||
303 | */ | ||
304 | if (gran <= jiffies_to_usecs(1) * 1000) { | ||
305 | /* nothing */ | 297 | /* nothing */ |
306 | } else if (gran == 1000000000) { | 298 | } else if (gran == NSEC_PER_SEC) { |
307 | t.tv_nsec = 0; | 299 | t.tv_nsec = 0; |
308 | } else { | 300 | } else if (gran > 1 && gran < NSEC_PER_SEC) { |
309 | t.tv_nsec -= t.tv_nsec % gran; | 301 | t.tv_nsec -= t.tv_nsec % gran; |
302 | } else { | ||
303 | WARN(1, "illegal file time granularity: %u", gran); | ||
310 | } | 304 | } |
311 | return t; | 305 | return t; |
312 | } | 306 | } |
@@ -546,7 +540,7 @@ EXPORT_SYMBOL(__usecs_to_jiffies); | |||
546 | * value to a scaled second value. | 540 | * value to a scaled second value. |
547 | */ | 541 | */ |
548 | static unsigned long | 542 | static unsigned long |
549 | __timespec_to_jiffies(unsigned long sec, long nsec) | 543 | __timespec64_to_jiffies(u64 sec, long nsec) |
550 | { | 544 | { |
551 | nsec = nsec + TICK_NSEC - 1; | 545 | nsec = nsec + TICK_NSEC - 1; |
552 | 546 | ||
@@ -554,22 +548,27 @@ __timespec_to_jiffies(unsigned long sec, long nsec) | |||
554 | sec = MAX_SEC_IN_JIFFIES; | 548 | sec = MAX_SEC_IN_JIFFIES; |
555 | nsec = 0; | 549 | nsec = 0; |
556 | } | 550 | } |
557 | return (((u64)sec * SEC_CONVERSION) + | 551 | return ((sec * SEC_CONVERSION) + |
558 | (((u64)nsec * NSEC_CONVERSION) >> | 552 | (((u64)nsec * NSEC_CONVERSION) >> |
559 | (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC; | 553 | (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC; |
560 | 554 | ||
561 | } | 555 | } |
562 | 556 | ||
563 | unsigned long | 557 | static unsigned long |
564 | timespec_to_jiffies(const struct timespec *value) | 558 | __timespec_to_jiffies(unsigned long sec, long nsec) |
565 | { | 559 | { |
566 | return __timespec_to_jiffies(value->tv_sec, value->tv_nsec); | 560 | return __timespec64_to_jiffies((u64)sec, nsec); |
567 | } | 561 | } |
568 | 562 | ||
569 | EXPORT_SYMBOL(timespec_to_jiffies); | 563 | unsigned long |
564 | timespec64_to_jiffies(const struct timespec64 *value) | ||
565 | { | ||
566 | return __timespec64_to_jiffies(value->tv_sec, value->tv_nsec); | ||
567 | } | ||
568 | EXPORT_SYMBOL(timespec64_to_jiffies); | ||
570 | 569 | ||
571 | void | 570 | void |
572 | jiffies_to_timespec(const unsigned long jiffies, struct timespec *value) | 571 | jiffies_to_timespec64(const unsigned long jiffies, struct timespec64 *value) |
573 | { | 572 | { |
574 | /* | 573 | /* |
575 | * Convert jiffies to nanoseconds and separate with | 574 | * Convert jiffies to nanoseconds and separate with |
@@ -580,7 +579,7 @@ jiffies_to_timespec(const unsigned long jiffies, struct timespec *value) | |||
580 | NSEC_PER_SEC, &rem); | 579 | NSEC_PER_SEC, &rem); |
581 | value->tv_nsec = rem; | 580 | value->tv_nsec = rem; |
582 | } | 581 | } |
583 | EXPORT_SYMBOL(jiffies_to_timespec); | 582 | EXPORT_SYMBOL(jiffies_to_timespec64); |
584 | 583 | ||
585 | /* | 584 | /* |
586 | * We could use a similar algorithm to timespec_to_jiffies (with a | 585 | * We could use a similar algorithm to timespec_to_jiffies (with a |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index bca3667a2de1..f6ee2e6b6f5d 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -911,6 +911,7 @@ int do_settimeofday64(const struct timespec64 *ts) | |||
911 | struct timekeeper *tk = &tk_core.timekeeper; | 911 | struct timekeeper *tk = &tk_core.timekeeper; |
912 | struct timespec64 ts_delta, xt; | 912 | struct timespec64 ts_delta, xt; |
913 | unsigned long flags; | 913 | unsigned long flags; |
914 | int ret = 0; | ||
914 | 915 | ||
915 | if (!timespec64_valid_strict(ts)) | 916 | if (!timespec64_valid_strict(ts)) |
916 | return -EINVAL; | 917 | return -EINVAL; |
@@ -924,10 +925,15 @@ int do_settimeofday64(const struct timespec64 *ts) | |||
924 | ts_delta.tv_sec = ts->tv_sec - xt.tv_sec; | 925 | ts_delta.tv_sec = ts->tv_sec - xt.tv_sec; |
925 | ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec; | 926 | ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec; |
926 | 927 | ||
928 | if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) { | ||
929 | ret = -EINVAL; | ||
930 | goto out; | ||
931 | } | ||
932 | |||
927 | tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta)); | 933 | tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta)); |
928 | 934 | ||
929 | tk_set_xtime(tk, ts); | 935 | tk_set_xtime(tk, ts); |
930 | 936 | out: | |
931 | timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET); | 937 | timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET); |
932 | 938 | ||
933 | write_seqcount_end(&tk_core.seq); | 939 | write_seqcount_end(&tk_core.seq); |
@@ -936,7 +942,7 @@ int do_settimeofday64(const struct timespec64 *ts) | |||
936 | /* signal hrtimers about time change */ | 942 | /* signal hrtimers about time change */ |
937 | clock_was_set(); | 943 | clock_was_set(); |
938 | 944 | ||
939 | return 0; | 945 | return ret; |
940 | } | 946 | } |
941 | EXPORT_SYMBOL(do_settimeofday64); | 947 | EXPORT_SYMBOL(do_settimeofday64); |
942 | 948 | ||
@@ -965,7 +971,8 @@ int timekeeping_inject_offset(struct timespec *ts) | |||
965 | 971 | ||
966 | /* Make sure the proposed value is valid */ | 972 | /* Make sure the proposed value is valid */ |
967 | tmp = timespec64_add(tk_xtime(tk), ts64); | 973 | tmp = timespec64_add(tk_xtime(tk), ts64); |
968 | if (!timespec64_valid_strict(&tmp)) { | 974 | if (timespec64_compare(&tk->wall_to_monotonic, &ts64) > 0 || |
975 | !timespec64_valid_strict(&tmp)) { | ||
969 | ret = -EINVAL; | 976 | ret = -EINVAL; |
970 | goto error; | 977 | goto error; |
971 | } | 978 | } |
@@ -1874,7 +1881,7 @@ struct timespec __current_kernel_time(void) | |||
1874 | return timespec64_to_timespec(tk_xtime(tk)); | 1881 | return timespec64_to_timespec(tk_xtime(tk)); |
1875 | } | 1882 | } |
1876 | 1883 | ||
1877 | struct timespec current_kernel_time(void) | 1884 | struct timespec64 current_kernel_time64(void) |
1878 | { | 1885 | { |
1879 | struct timekeeper *tk = &tk_core.timekeeper; | 1886 | struct timekeeper *tk = &tk_core.timekeeper; |
1880 | struct timespec64 now; | 1887 | struct timespec64 now; |
@@ -1886,9 +1893,9 @@ struct timespec current_kernel_time(void) | |||
1886 | now = tk_xtime(tk); | 1893 | now = tk_xtime(tk); |
1887 | } while (read_seqcount_retry(&tk_core.seq, seq)); | 1894 | } while (read_seqcount_retry(&tk_core.seq, seq)); |
1888 | 1895 | ||
1889 | return timespec64_to_timespec(now); | 1896 | return now; |
1890 | } | 1897 | } |
1891 | EXPORT_SYMBOL(current_kernel_time); | 1898 | EXPORT_SYMBOL(current_kernel_time64); |
1892 | 1899 | ||
1893 | struct timespec64 get_monotonic_coarse64(void) | 1900 | struct timespec64 get_monotonic_coarse64(void) |
1894 | { | 1901 | { |
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index a4536e1e3e2a..129c96033e46 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c | |||
@@ -137,7 +137,7 @@ print_base(struct seq_file *m, struct hrtimer_clock_base *base, u64 now) | |||
137 | (unsigned long long) ktime_to_ns(base->offset)); | 137 | (unsigned long long) ktime_to_ns(base->offset)); |
138 | #endif | 138 | #endif |
139 | SEQ_printf(m, "active timers:\n"); | 139 | SEQ_printf(m, "active timers:\n"); |
140 | print_active_timers(m, base, now); | 140 | print_active_timers(m, base, now + ktime_to_ns(base->offset)); |
141 | } | 141 | } |
142 | 142 | ||
143 | static void print_cpu(struct seq_file *m, int cpu, u64 now) | 143 | static void print_cpu(struct seq_file *m, int cpu, u64 now) |