aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/timekeeping.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/timekeeping.c')
-rw-r--r--kernel/time/timekeeping.c70
1 files changed, 65 insertions, 5 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index d66b21308f7c..3447cfaf11e7 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -70,6 +70,12 @@ struct timekeeper {
70 /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ 70 /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
71 struct timespec raw_time; 71 struct timespec raw_time;
72 72
73 /* Offset clock monotonic -> clock realtime */
74 ktime_t offs_real;
75
76 /* Offset clock monotonic -> clock boottime */
77 ktime_t offs_boot;
78
73 /* Seqlock for all timekeeper values */ 79 /* Seqlock for all timekeeper values */
74 seqlock_t lock; 80 seqlock_t lock;
75}; 81};
@@ -172,6 +178,14 @@ static inline s64 timekeeping_get_ns_raw(void)
172 return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift); 178 return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
173} 179}
174 180
181static void update_rt_offset(void)
182{
183 struct timespec tmp, *wtm = &timekeeper.wall_to_monotonic;
184
185 set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec);
186 timekeeper.offs_real = timespec_to_ktime(tmp);
187}
188
175/* must hold write on timekeeper.lock */ 189/* must hold write on timekeeper.lock */
176static void timekeeping_update(bool clearntp) 190static void timekeeping_update(bool clearntp)
177{ 191{
@@ -179,6 +193,7 @@ static void timekeeping_update(bool clearntp)
179 timekeeper.ntp_error = 0; 193 timekeeper.ntp_error = 0;
180 ntp_clear(); 194 ntp_clear();
181 } 195 }
196 update_rt_offset();
182 update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, 197 update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic,
183 timekeeper.clock, timekeeper.mult); 198 timekeeper.clock, timekeeper.mult);
184} 199}
@@ -240,7 +255,6 @@ void getnstimeofday(struct timespec *ts)
240 255
241 timespec_add_ns(ts, nsecs); 256 timespec_add_ns(ts, nsecs);
242} 257}
243
244EXPORT_SYMBOL(getnstimeofday); 258EXPORT_SYMBOL(getnstimeofday);
245 259
246ktime_t ktime_get(void) 260ktime_t ktime_get(void)
@@ -357,8 +371,8 @@ void do_gettimeofday(struct timeval *tv)
357 tv->tv_sec = now.tv_sec; 371 tv->tv_sec = now.tv_sec;
358 tv->tv_usec = now.tv_nsec/1000; 372 tv->tv_usec = now.tv_nsec/1000;
359} 373}
360
361EXPORT_SYMBOL(do_gettimeofday); 374EXPORT_SYMBOL(do_gettimeofday);
375
362/** 376/**
363 * do_settimeofday - Sets the time of day 377 * do_settimeofday - Sets the time of day
364 * @tv: pointer to the timespec variable containing the new time 378 * @tv: pointer to the timespec variable containing the new time
@@ -392,7 +406,6 @@ int do_settimeofday(const struct timespec *tv)
392 406
393 return 0; 407 return 0;
394} 408}
395
396EXPORT_SYMBOL(do_settimeofday); 409EXPORT_SYMBOL(do_settimeofday);
397 410
398 411
@@ -606,6 +619,7 @@ void __init timekeeping_init(void)
606 } 619 }
607 set_normalized_timespec(&timekeeper.wall_to_monotonic, 620 set_normalized_timespec(&timekeeper.wall_to_monotonic,
608 -boot.tv_sec, -boot.tv_nsec); 621 -boot.tv_sec, -boot.tv_nsec);
622 update_rt_offset();
609 timekeeper.total_sleep_time.tv_sec = 0; 623 timekeeper.total_sleep_time.tv_sec = 0;
610 timekeeper.total_sleep_time.tv_nsec = 0; 624 timekeeper.total_sleep_time.tv_nsec = 0;
611 write_sequnlock_irqrestore(&timekeeper.lock, flags); 625 write_sequnlock_irqrestore(&timekeeper.lock, flags);
@@ -614,6 +628,12 @@ void __init timekeeping_init(void)
614/* time in seconds when suspend began */ 628/* time in seconds when suspend began */
615static struct timespec timekeeping_suspend_time; 629static struct timespec timekeeping_suspend_time;
616 630
631static void update_sleep_time(struct timespec t)
632{
633 timekeeper.total_sleep_time = t;
634 timekeeper.offs_boot = timespec_to_ktime(t);
635}
636
617/** 637/**
618 * __timekeeping_inject_sleeptime - Internal function to add sleep interval 638 * __timekeeping_inject_sleeptime - Internal function to add sleep interval
619 * @delta: pointer to a timespec delta value 639 * @delta: pointer to a timespec delta value
@@ -632,8 +652,7 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta)
632 timekeeper.xtime = timespec_add(timekeeper.xtime, *delta); 652 timekeeper.xtime = timespec_add(timekeeper.xtime, *delta);
633 timekeeper.wall_to_monotonic = 653 timekeeper.wall_to_monotonic =
634 timespec_sub(timekeeper.wall_to_monotonic, *delta); 654 timespec_sub(timekeeper.wall_to_monotonic, *delta);
635 timekeeper.total_sleep_time = timespec_add( 655 update_sleep_time(timespec_add(timekeeper.total_sleep_time, *delta));
636 timekeeper.total_sleep_time, *delta);
637} 656}
638 657
639 658
@@ -698,6 +717,7 @@ static void timekeeping_resume(void)
698 timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); 717 timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock);
699 timekeeper.ntp_error = 0; 718 timekeeper.ntp_error = 0;
700 timekeeping_suspended = 0; 719 timekeeping_suspended = 0;
720 timekeeping_update(false);
701 write_sequnlock_irqrestore(&timekeeper.lock, flags); 721 write_sequnlock_irqrestore(&timekeeper.lock, flags);
702 722
703 touch_softlockup_watchdog(); 723 touch_softlockup_watchdog();
@@ -964,6 +984,9 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
964 timekeeper.xtime.tv_sec++; 984 timekeeper.xtime.tv_sec++;
965 leap = second_overflow(timekeeper.xtime.tv_sec); 985 leap = second_overflow(timekeeper.xtime.tv_sec);
966 timekeeper.xtime.tv_sec += leap; 986 timekeeper.xtime.tv_sec += leap;
987 timekeeper.wall_to_monotonic.tv_sec -= leap;
988 if (leap)
989 clock_was_set_delayed();
967 } 990 }
968 991
969 /* Accumulate raw time */ 992 /* Accumulate raw time */
@@ -1079,6 +1102,9 @@ static void update_wall_time(void)
1079 timekeeper.xtime.tv_sec++; 1102 timekeeper.xtime.tv_sec++;
1080 leap = second_overflow(timekeeper.xtime.tv_sec); 1103 leap = second_overflow(timekeeper.xtime.tv_sec);
1081 timekeeper.xtime.tv_sec += leap; 1104 timekeeper.xtime.tv_sec += leap;
1105 timekeeper.wall_to_monotonic.tv_sec -= leap;
1106 if (leap)
1107 clock_was_set_delayed();
1082 } 1108 }
1083 1109
1084 timekeeping_update(false); 1110 timekeeping_update(false);
@@ -1246,6 +1272,40 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,
1246 } while (read_seqretry(&timekeeper.lock, seq)); 1272 } while (read_seqretry(&timekeeper.lock, seq));
1247} 1273}
1248 1274
1275#ifdef CONFIG_HIGH_RES_TIMERS
1276/**
1277 * ktime_get_update_offsets - hrtimer helper
1278 * @offs_real: pointer to storage for monotonic -> realtime offset
1279 * @offs_boot: pointer to storage for monotonic -> boottime offset
1280 *
1281 * Returns current monotonic time and updates the offsets
1282 * Called from hrtimer_interupt() or retrigger_next_event()
1283 */
1284ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot)
1285{
1286 ktime_t now;
1287 unsigned int seq;
1288 u64 secs, nsecs;
1289
1290 do {
1291 seq = read_seqbegin(&timekeeper.lock);
1292
1293 secs = timekeeper.xtime.tv_sec;
1294 nsecs = timekeeper.xtime.tv_nsec;
1295 nsecs += timekeeping_get_ns();
1296 /* If arch requires, add in gettimeoffset() */
1297 nsecs += arch_gettimeoffset();
1298
1299 *offs_real = timekeeper.offs_real;
1300 *offs_boot = timekeeper.offs_boot;
1301 } while (read_seqretry(&timekeeper.lock, seq));
1302
1303 now = ktime_add_ns(ktime_set(secs, 0), nsecs);
1304 now = ktime_sub(now, *offs_real);
1305 return now;
1306}
1307#endif
1308
1249/** 1309/**
1250 * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format 1310 * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format
1251 */ 1311 */