diff options
Diffstat (limited to 'kernel/time')
| -rw-r--r-- | kernel/time/timekeeping.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index ec1791fae965..a693270efafb 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
| @@ -417,7 +417,8 @@ EXPORT_SYMBOL_GPL(pvclock_gtod_unregister_notifier); | |||
| 417 | */ | 417 | */ |
| 418 | static inline void tk_update_ktime_data(struct timekeeper *tk) | 418 | static inline void tk_update_ktime_data(struct timekeeper *tk) |
| 419 | { | 419 | { |
| 420 | s64 nsec; | 420 | u64 seconds; |
| 421 | u32 nsec; | ||
| 421 | 422 | ||
| 422 | /* | 423 | /* |
| 423 | * The xtime based monotonic readout is: | 424 | * The xtime based monotonic readout is: |
| @@ -426,13 +427,22 @@ static inline void tk_update_ktime_data(struct timekeeper *tk) | |||
| 426 | * nsec = base_mono + now(); | 427 | * nsec = base_mono + now(); |
| 427 | * ==> base_mono = (xtime_sec + wtm_sec) * 1e9 + wtm_nsec | 428 | * ==> base_mono = (xtime_sec + wtm_sec) * 1e9 + wtm_nsec |
| 428 | */ | 429 | */ |
| 429 | nsec = (s64)(tk->xtime_sec + tk->wall_to_monotonic.tv_sec); | 430 | seconds = (u64)(tk->xtime_sec + tk->wall_to_monotonic.tv_sec); |
| 430 | nsec *= NSEC_PER_SEC; | 431 | nsec = (u32) tk->wall_to_monotonic.tv_nsec; |
| 431 | nsec += tk->wall_to_monotonic.tv_nsec; | 432 | tk->tkr.base_mono = ns_to_ktime(seconds * NSEC_PER_SEC + nsec); |
| 432 | tk->tkr.base_mono = ns_to_ktime(nsec); | ||
| 433 | 433 | ||
| 434 | /* Update the monotonic raw base */ | 434 | /* Update the monotonic raw base */ |
| 435 | tk->base_raw = timespec64_to_ktime(tk->raw_time); | 435 | tk->base_raw = timespec64_to_ktime(tk->raw_time); |
| 436 | |||
| 437 | /* | ||
| 438 | * The sum of the nanoseconds portions of xtime and | ||
| 439 | * wall_to_monotonic can be greater/equal one second. Take | ||
| 440 | * this into account before updating tk->ktime_sec. | ||
| 441 | */ | ||
| 442 | nsec += (u32)(tk->tkr.xtime_nsec >> tk->tkr.shift); | ||
| 443 | if (nsec >= NSEC_PER_SEC) | ||
| 444 | seconds++; | ||
| 445 | tk->ktime_sec = seconds; | ||
| 436 | } | 446 | } |
| 437 | 447 | ||
| 438 | /* must hold timekeeper_lock */ | 448 | /* must hold timekeeper_lock */ |
| @@ -648,6 +658,24 @@ void ktime_get_ts64(struct timespec64 *ts) | |||
| 648 | } | 658 | } |
| 649 | EXPORT_SYMBOL_GPL(ktime_get_ts64); | 659 | EXPORT_SYMBOL_GPL(ktime_get_ts64); |
| 650 | 660 | ||
| 661 | /** | ||
| 662 | * ktime_get_seconds - Get the seconds portion of CLOCK_MONOTONIC | ||
| 663 | * | ||
| 664 | * Returns the seconds portion of CLOCK_MONOTONIC with a single non | ||
| 665 | * serialized read. tk->ktime_sec is of type 'unsigned long' so this | ||
| 666 | * works on both 32 and 64 bit systems. On 32 bit systems the readout | ||
| 667 | * covers ~136 years of uptime which should be enough to prevent | ||
| 668 | * premature wrap arounds. | ||
| 669 | */ | ||
| 670 | time64_t ktime_get_seconds(void) | ||
| 671 | { | ||
| 672 | struct timekeeper *tk = &tk_core.timekeeper; | ||
| 673 | |||
| 674 | WARN_ON(timekeeping_suspended); | ||
| 675 | return tk->ktime_sec; | ||
| 676 | } | ||
| 677 | EXPORT_SYMBOL_GPL(ktime_get_seconds); | ||
| 678 | |||
| 651 | #ifdef CONFIG_NTP_PPS | 679 | #ifdef CONFIG_NTP_PPS |
| 652 | 680 | ||
| 653 | /** | 681 | /** |
