diff options
Diffstat (limited to 'kernel/time')
-rw-r--r-- | kernel/time/timekeeping.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 07a3f1420c27..acc417b5a9b7 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -47,10 +47,22 @@ EXPORT_SYMBOL(xtime_lock); | |||
47 | struct timespec xtime __attribute__ ((aligned (16))); | 47 | struct timespec xtime __attribute__ ((aligned (16))); |
48 | struct timespec wall_to_monotonic __attribute__ ((aligned (16))); | 48 | struct timespec wall_to_monotonic __attribute__ ((aligned (16))); |
49 | static unsigned long total_sleep_time; /* seconds */ | 49 | static unsigned long total_sleep_time; /* seconds */ |
50 | |||
51 | EXPORT_SYMBOL(xtime); | 50 | EXPORT_SYMBOL(xtime); |
52 | 51 | ||
53 | 52 | ||
53 | #ifdef CONFIG_NO_HZ | ||
54 | static struct timespec xtime_cache __attribute__ ((aligned (16))); | ||
55 | static inline void update_xtime_cache(u64 nsec) | ||
56 | { | ||
57 | xtime_cache = xtime; | ||
58 | timespec_add_ns(&xtime_cache, nsec); | ||
59 | } | ||
60 | #else | ||
61 | #define xtime_cache xtime | ||
62 | /* We do *not* want to evaluate the argument for this case */ | ||
63 | #define update_xtime_cache(n) do { } while (0) | ||
64 | #endif | ||
65 | |||
54 | static struct clocksource *clock; /* pointer to current clocksource */ | 66 | static struct clocksource *clock; /* pointer to current clocksource */ |
55 | 67 | ||
56 | 68 | ||
@@ -478,6 +490,8 @@ void update_wall_time(void) | |||
478 | xtime.tv_nsec = (s64)clock->xtime_nsec >> clock->shift; | 490 | xtime.tv_nsec = (s64)clock->xtime_nsec >> clock->shift; |
479 | clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift; | 491 | clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift; |
480 | 492 | ||
493 | update_xtime_cache(cyc2ns(clock, offset)); | ||
494 | |||
481 | /* check to see if there is a new clocksource to use */ | 495 | /* check to see if there is a new clocksource to use */ |
482 | change_clocksource(); | 496 | change_clocksource(); |
483 | update_vsyscall(&xtime, clock); | 497 | update_vsyscall(&xtime, clock); |
@@ -510,6 +524,13 @@ void monotonic_to_bootbased(struct timespec *ts) | |||
510 | ts->tv_sec += total_sleep_time; | 524 | ts->tv_sec += total_sleep_time; |
511 | } | 525 | } |
512 | 526 | ||
527 | unsigned long get_seconds(void) | ||
528 | { | ||
529 | return xtime_cache.tv_sec; | ||
530 | } | ||
531 | EXPORT_SYMBOL(get_seconds); | ||
532 | |||
533 | |||
513 | struct timespec current_kernel_time(void) | 534 | struct timespec current_kernel_time(void) |
514 | { | 535 | { |
515 | struct timespec now; | 536 | struct timespec now; |
@@ -518,10 +539,9 @@ struct timespec current_kernel_time(void) | |||
518 | do { | 539 | do { |
519 | seq = read_seqbegin(&xtime_lock); | 540 | seq = read_seqbegin(&xtime_lock); |
520 | 541 | ||
521 | now = xtime; | 542 | now = xtime_cache; |
522 | } while (read_seqretry(&xtime_lock, seq)); | 543 | } while (read_seqretry(&xtime_lock, seq)); |
523 | 544 | ||
524 | return now; | 545 | return now; |
525 | } | 546 | } |
526 | |||
527 | EXPORT_SYMBOL(current_kernel_time); | 547 | EXPORT_SYMBOL(current_kernel_time); |