diff options
Diffstat (limited to 'kernel/time')
-rw-r--r-- | kernel/time/timekeeping.c | 69 |
1 files changed, 37 insertions, 32 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 8427cc20bad6..5655ca3a86d7 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -48,6 +48,21 @@ struct timekeeper { | |||
48 | /* NTP adjusted clock multiplier */ | 48 | /* NTP adjusted clock multiplier */ |
49 | u32 mult; | 49 | u32 mult; |
50 | 50 | ||
51 | /* | ||
52 | * wall_to_monotonic is what we need to add to xtime (or xtime corrected | ||
53 | * for sub jiffie times) to get to monotonic time. Monotonic is pegged | ||
54 | * at zero at system boot time, so wall_to_monotonic will be negative, | ||
55 | * however, we will ALWAYS keep the tv_nsec part positive so we can use | ||
56 | * the usual normalization. | ||
57 | * | ||
58 | * wall_to_monotonic is moved after resume from suspend for the | ||
59 | * monotonic time not to jump. We need to add total_sleep_time to | ||
60 | * wall_to_monotonic to get the real boot based time offset. | ||
61 | * | ||
62 | * - wall_to_monotonic is no longer the boot time, getboottime must be | ||
63 | * used instead. | ||
64 | */ | ||
65 | struct timespec wall_to_monotonic; | ||
51 | /* time spent in suspend */ | 66 | /* time spent in suspend */ |
52 | struct timespec total_sleep_time; | 67 | struct timespec total_sleep_time; |
53 | 68 | ||
@@ -148,21 +163,8 @@ __cacheline_aligned_in_smp DEFINE_SEQLOCK(xtime_lock); | |||
148 | 163 | ||
149 | /* | 164 | /* |
150 | * The current time | 165 | * The current time |
151 | * wall_to_monotonic is what we need to add to xtime (or xtime corrected | ||
152 | * for sub jiffie times) to get to monotonic time. Monotonic is pegged | ||
153 | * at zero at system boot time, so wall_to_monotonic will be negative, | ||
154 | * however, we will ALWAYS keep the tv_nsec part positive so we can use | ||
155 | * the usual normalization. | ||
156 | * | ||
157 | * wall_to_monotonic is moved after resume from suspend for the monotonic | ||
158 | * time not to jump. We need to add total_sleep_time to wall_to_monotonic | ||
159 | * to get the real boot based time offset. | ||
160 | * | ||
161 | * - wall_to_monotonic is no longer the boot time, getboottime must be | ||
162 | * used instead. | ||
163 | */ | 166 | */ |
164 | static struct timespec xtime __attribute__ ((aligned (16))); | 167 | static struct timespec xtime __attribute__ ((aligned (16))); |
165 | static struct timespec wall_to_monotonic __attribute__ ((aligned (16))); | ||
166 | 168 | ||
167 | /* | 169 | /* |
168 | * The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. | 170 | * The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. |
@@ -176,8 +178,8 @@ int __read_mostly timekeeping_suspended; | |||
176 | void timekeeping_leap_insert(int leapsecond) | 178 | void timekeeping_leap_insert(int leapsecond) |
177 | { | 179 | { |
178 | xtime.tv_sec += leapsecond; | 180 | xtime.tv_sec += leapsecond; |
179 | wall_to_monotonic.tv_sec -= leapsecond; | 181 | timekeeper.wall_to_monotonic.tv_sec -= leapsecond; |
180 | update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock, | 182 | update_vsyscall(&xtime, &timekeeper.wall_to_monotonic, timekeeper.clock, |
181 | timekeeper.mult); | 183 | timekeeper.mult); |
182 | } | 184 | } |
183 | 185 | ||
@@ -249,8 +251,8 @@ ktime_t ktime_get(void) | |||
249 | 251 | ||
250 | do { | 252 | do { |
251 | seq = read_seqbegin(&xtime_lock); | 253 | seq = read_seqbegin(&xtime_lock); |
252 | secs = xtime.tv_sec + wall_to_monotonic.tv_sec; | 254 | secs = xtime.tv_sec + timekeeper.wall_to_monotonic.tv_sec; |
253 | nsecs = xtime.tv_nsec + wall_to_monotonic.tv_nsec; | 255 | nsecs = xtime.tv_nsec + timekeeper.wall_to_monotonic.tv_nsec; |
254 | nsecs += timekeeping_get_ns(); | 256 | nsecs += timekeeping_get_ns(); |
255 | /* If arch requires, add in gettimeoffset() */ | 257 | /* If arch requires, add in gettimeoffset() */ |
256 | nsecs += arch_gettimeoffset(); | 258 | nsecs += arch_gettimeoffset(); |
@@ -283,7 +285,7 @@ void ktime_get_ts(struct timespec *ts) | |||
283 | do { | 285 | do { |
284 | seq = read_seqbegin(&xtime_lock); | 286 | seq = read_seqbegin(&xtime_lock); |
285 | *ts = xtime; | 287 | *ts = xtime; |
286 | tomono = wall_to_monotonic; | 288 | tomono = timekeeper.wall_to_monotonic; |
287 | nsecs = timekeeping_get_ns(); | 289 | nsecs = timekeeping_get_ns(); |
288 | /* If arch requires, add in gettimeoffset() */ | 290 | /* If arch requires, add in gettimeoffset() */ |
289 | nsecs += arch_gettimeoffset(); | 291 | nsecs += arch_gettimeoffset(); |
@@ -374,14 +376,15 @@ int do_settimeofday(const struct timespec *tv) | |||
374 | 376 | ||
375 | ts_delta.tv_sec = tv->tv_sec - xtime.tv_sec; | 377 | ts_delta.tv_sec = tv->tv_sec - xtime.tv_sec; |
376 | ts_delta.tv_nsec = tv->tv_nsec - xtime.tv_nsec; | 378 | ts_delta.tv_nsec = tv->tv_nsec - xtime.tv_nsec; |
377 | wall_to_monotonic = timespec_sub(wall_to_monotonic, ts_delta); | 379 | timekeeper.wall_to_monotonic = |
380 | timespec_sub(timekeeper.wall_to_monotonic, ts_delta); | ||
378 | 381 | ||
379 | xtime = *tv; | 382 | xtime = *tv; |
380 | 383 | ||
381 | timekeeper.ntp_error = 0; | 384 | timekeeper.ntp_error = 0; |
382 | ntp_clear(); | 385 | ntp_clear(); |
383 | 386 | ||
384 | update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock, | 387 | update_vsyscall(&xtime, &timekeeper.wall_to_monotonic, timekeeper.clock, |
385 | timekeeper.mult); | 388 | timekeeper.mult); |
386 | 389 | ||
387 | write_sequnlock_irqrestore(&xtime_lock, flags); | 390 | write_sequnlock_irqrestore(&xtime_lock, flags); |
@@ -413,12 +416,13 @@ int timekeeping_inject_offset(struct timespec *ts) | |||
413 | timekeeping_forward_now(); | 416 | timekeeping_forward_now(); |
414 | 417 | ||
415 | xtime = timespec_add(xtime, *ts); | 418 | xtime = timespec_add(xtime, *ts); |
416 | wall_to_monotonic = timespec_sub(wall_to_monotonic, *ts); | 419 | timekeeper.wall_to_monotonic = |
420 | timespec_sub(timekeeper.wall_to_monotonic, *ts); | ||
417 | 421 | ||
418 | timekeeper.ntp_error = 0; | 422 | timekeeper.ntp_error = 0; |
419 | ntp_clear(); | 423 | ntp_clear(); |
420 | 424 | ||
421 | update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock, | 425 | update_vsyscall(&xtime, &timekeeper.wall_to_monotonic, timekeeper.clock, |
422 | timekeeper.mult); | 426 | timekeeper.mult); |
423 | 427 | ||
424 | write_sequnlock_irqrestore(&xtime_lock, flags); | 428 | write_sequnlock_irqrestore(&xtime_lock, flags); |
@@ -592,7 +596,7 @@ void __init timekeeping_init(void) | |||
592 | boot.tv_sec = xtime.tv_sec; | 596 | boot.tv_sec = xtime.tv_sec; |
593 | boot.tv_nsec = xtime.tv_nsec; | 597 | boot.tv_nsec = xtime.tv_nsec; |
594 | } | 598 | } |
595 | set_normalized_timespec(&wall_to_monotonic, | 599 | set_normalized_timespec(&timekeeper.wall_to_monotonic, |
596 | -boot.tv_sec, -boot.tv_nsec); | 600 | -boot.tv_sec, -boot.tv_nsec); |
597 | timekeeper.total_sleep_time.tv_sec = 0; | 601 | timekeeper.total_sleep_time.tv_sec = 0; |
598 | timekeeper.total_sleep_time.tv_nsec = 0; | 602 | timekeeper.total_sleep_time.tv_nsec = 0; |
@@ -618,7 +622,8 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta) | |||
618 | } | 622 | } |
619 | 623 | ||
620 | xtime = timespec_add(xtime, *delta); | 624 | xtime = timespec_add(xtime, *delta); |
621 | wall_to_monotonic = timespec_sub(wall_to_monotonic, *delta); | 625 | timekeeper.wall_to_monotonic = |
626 | timespec_sub(timekeeper.wall_to_monotonic, *delta); | ||
622 | timekeeper.total_sleep_time = timespec_add( | 627 | timekeeper.total_sleep_time = timespec_add( |
623 | timekeeper.total_sleep_time, *delta); | 628 | timekeeper.total_sleep_time, *delta); |
624 | } | 629 | } |
@@ -651,7 +656,7 @@ void timekeeping_inject_sleeptime(struct timespec *delta) | |||
651 | 656 | ||
652 | timekeeper.ntp_error = 0; | 657 | timekeeper.ntp_error = 0; |
653 | ntp_clear(); | 658 | ntp_clear(); |
654 | update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock, | 659 | update_vsyscall(&xtime, &timekeeper.wall_to_monotonic, timekeeper.clock, |
655 | timekeeper.mult); | 660 | timekeeper.mult); |
656 | 661 | ||
657 | write_sequnlock_irqrestore(&xtime_lock, flags); | 662 | write_sequnlock_irqrestore(&xtime_lock, flags); |
@@ -1060,7 +1065,7 @@ static void update_wall_time(void) | |||
1060 | } | 1065 | } |
1061 | 1066 | ||
1062 | /* check to see if there is a new clocksource to use */ | 1067 | /* check to see if there is a new clocksource to use */ |
1063 | update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock, | 1068 | update_vsyscall(&xtime, &timekeeper.wall_to_monotonic, timekeeper.clock, |
1064 | timekeeper.mult); | 1069 | timekeeper.mult); |
1065 | } | 1070 | } |
1066 | 1071 | ||
@@ -1078,9 +1083,9 @@ static void update_wall_time(void) | |||
1078 | void getboottime(struct timespec *ts) | 1083 | void getboottime(struct timespec *ts) |
1079 | { | 1084 | { |
1080 | struct timespec boottime = { | 1085 | struct timespec boottime = { |
1081 | .tv_sec = wall_to_monotonic.tv_sec + | 1086 | .tv_sec = timekeeper.wall_to_monotonic.tv_sec + |
1082 | timekeeper.total_sleep_time.tv_sec, | 1087 | timekeeper.total_sleep_time.tv_sec, |
1083 | .tv_nsec = wall_to_monotonic.tv_nsec + | 1088 | .tv_nsec = timekeeper.wall_to_monotonic.tv_nsec + |
1084 | timekeeper.total_sleep_time.tv_nsec | 1089 | timekeeper.total_sleep_time.tv_nsec |
1085 | }; | 1090 | }; |
1086 | 1091 | ||
@@ -1109,7 +1114,7 @@ void get_monotonic_boottime(struct timespec *ts) | |||
1109 | do { | 1114 | do { |
1110 | seq = read_seqbegin(&xtime_lock); | 1115 | seq = read_seqbegin(&xtime_lock); |
1111 | *ts = xtime; | 1116 | *ts = xtime; |
1112 | tomono = wall_to_monotonic; | 1117 | tomono = timekeeper.wall_to_monotonic; |
1113 | sleep = timekeeper.total_sleep_time; | 1118 | sleep = timekeeper.total_sleep_time; |
1114 | nsecs = timekeeping_get_ns(); | 1119 | nsecs = timekeeping_get_ns(); |
1115 | 1120 | ||
@@ -1182,7 +1187,7 @@ struct timespec get_monotonic_coarse(void) | |||
1182 | seq = read_seqbegin(&xtime_lock); | 1187 | seq = read_seqbegin(&xtime_lock); |
1183 | 1188 | ||
1184 | now = xtime; | 1189 | now = xtime; |
1185 | mono = wall_to_monotonic; | 1190 | mono = timekeeper.wall_to_monotonic; |
1186 | } while (read_seqretry(&xtime_lock, seq)); | 1191 | } while (read_seqretry(&xtime_lock, seq)); |
1187 | 1192 | ||
1188 | set_normalized_timespec(&now, now.tv_sec + mono.tv_sec, | 1193 | set_normalized_timespec(&now, now.tv_sec + mono.tv_sec, |
@@ -1217,7 +1222,7 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, | |||
1217 | do { | 1222 | do { |
1218 | seq = read_seqbegin(&xtime_lock); | 1223 | seq = read_seqbegin(&xtime_lock); |
1219 | *xtim = xtime; | 1224 | *xtim = xtime; |
1220 | *wtom = wall_to_monotonic; | 1225 | *wtom = timekeeper.wall_to_monotonic; |
1221 | *sleep = timekeeper.total_sleep_time; | 1226 | *sleep = timekeeper.total_sleep_time; |
1222 | } while (read_seqretry(&xtime_lock, seq)); | 1227 | } while (read_seqretry(&xtime_lock, seq)); |
1223 | } | 1228 | } |
@@ -1232,7 +1237,7 @@ ktime_t ktime_get_monotonic_offset(void) | |||
1232 | 1237 | ||
1233 | do { | 1238 | do { |
1234 | seq = read_seqbegin(&xtime_lock); | 1239 | seq = read_seqbegin(&xtime_lock); |
1235 | wtom = wall_to_monotonic; | 1240 | wtom = timekeeper.wall_to_monotonic; |
1236 | } while (read_seqretry(&xtime_lock, seq)); | 1241 | } while (read_seqretry(&xtime_lock, seq)); |
1237 | return timespec_to_ktime(wtom); | 1242 | return timespec_to_ktime(wtom); |
1238 | } | 1243 | } |