diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/hrtimer.c | 53 | ||||
| -rw-r--r-- | kernel/time/timekeeping.c | 63 |
2 files changed, 98 insertions, 18 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index ae34bf51682b..6db7a5ed52b5 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -657,6 +657,14 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | |||
| 657 | return 0; | 657 | return 0; |
| 658 | } | 658 | } |
| 659 | 659 | ||
| 660 | static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) | ||
| 661 | { | ||
| 662 | ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset; | ||
| 663 | ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset; | ||
| 664 | |||
| 665 | return ktime_get_update_offsets(offs_real, offs_boot); | ||
| 666 | } | ||
| 667 | |||
| 660 | /* | 668 | /* |
| 661 | * Retrigger next event is called after clock was set | 669 | * Retrigger next event is called after clock was set |
| 662 | * | 670 | * |
| @@ -665,22 +673,12 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | |||
| 665 | static void retrigger_next_event(void *arg) | 673 | static void retrigger_next_event(void *arg) |
| 666 | { | 674 | { |
| 667 | struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); | 675 | struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); |
| 668 | struct timespec realtime_offset, xtim, wtm, sleep; | ||
| 669 | 676 | ||
| 670 | if (!hrtimer_hres_active()) | 677 | if (!hrtimer_hres_active()) |
| 671 | return; | 678 | return; |
| 672 | 679 | ||
| 673 | /* Optimized out for !HIGH_RES */ | ||
| 674 | get_xtime_and_monotonic_and_sleep_offset(&xtim, &wtm, &sleep); | ||
| 675 | set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec); | ||
| 676 | |||
| 677 | /* Adjust CLOCK_REALTIME offset */ | ||
| 678 | raw_spin_lock(&base->lock); | 680 | raw_spin_lock(&base->lock); |
| 679 | base->clock_base[HRTIMER_BASE_REALTIME].offset = | 681 | hrtimer_update_base(base); |
| 680 | timespec_to_ktime(realtime_offset); | ||
| 681 | base->clock_base[HRTIMER_BASE_BOOTTIME].offset = | ||
| 682 | timespec_to_ktime(sleep); | ||
| 683 | |||
| 684 | hrtimer_force_reprogram(base, 0); | 682 | hrtimer_force_reprogram(base, 0); |
| 685 | raw_spin_unlock(&base->lock); | 683 | raw_spin_unlock(&base->lock); |
| 686 | } | 684 | } |
| @@ -710,13 +708,25 @@ static int hrtimer_switch_to_hres(void) | |||
| 710 | base->clock_base[i].resolution = KTIME_HIGH_RES; | 708 | base->clock_base[i].resolution = KTIME_HIGH_RES; |
| 711 | 709 | ||
| 712 | tick_setup_sched_timer(); | 710 | tick_setup_sched_timer(); |
| 713 | |||
| 714 | /* "Retrigger" the interrupt to get things going */ | 711 | /* "Retrigger" the interrupt to get things going */ |
| 715 | retrigger_next_event(NULL); | 712 | retrigger_next_event(NULL); |
| 716 | local_irq_restore(flags); | 713 | local_irq_restore(flags); |
| 717 | return 1; | 714 | return 1; |
| 718 | } | 715 | } |
| 719 | 716 | ||
| 717 | /* | ||
| 718 | * Called from timekeeping code to reprogramm the hrtimer interrupt | ||
| 719 | * device. If called from the timer interrupt context we defer it to | ||
| 720 | * softirq context. | ||
| 721 | */ | ||
| 722 | void clock_was_set_delayed(void) | ||
| 723 | { | ||
| 724 | struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); | ||
| 725 | |||
| 726 | cpu_base->clock_was_set = 1; | ||
| 727 | __raise_softirq_irqoff(HRTIMER_SOFTIRQ); | ||
| 728 | } | ||
| 729 | |||
| 720 | #else | 730 | #else |
| 721 | 731 | ||
| 722 | static inline int hrtimer_hres_active(void) { return 0; } | 732 | static inline int hrtimer_hres_active(void) { return 0; } |
| @@ -1250,11 +1260,10 @@ void hrtimer_interrupt(struct clock_event_device *dev) | |||
| 1250 | cpu_base->nr_events++; | 1260 | cpu_base->nr_events++; |
| 1251 | dev->next_event.tv64 = KTIME_MAX; | 1261 | dev->next_event.tv64 = KTIME_MAX; |
| 1252 | 1262 | ||
| 1253 | entry_time = now = ktime_get(); | 1263 | raw_spin_lock(&cpu_base->lock); |
| 1264 | entry_time = now = hrtimer_update_base(cpu_base); | ||
| 1254 | retry: | 1265 | retry: |
| 1255 | expires_next.tv64 = KTIME_MAX; | 1266 | expires_next.tv64 = KTIME_MAX; |
| 1256 | |||
| 1257 | raw_spin_lock(&cpu_base->lock); | ||
| 1258 | /* | 1267 | /* |
| 1259 | * We set expires_next to KTIME_MAX here with cpu_base->lock | 1268 | * We set expires_next to KTIME_MAX here with cpu_base->lock |
| 1260 | * held to prevent that a timer is enqueued in our queue via | 1269 | * held to prevent that a timer is enqueued in our queue via |
| @@ -1330,8 +1339,12 @@ retry: | |||
| 1330 | * We need to prevent that we loop forever in the hrtimer | 1339 | * We need to prevent that we loop forever in the hrtimer |
| 1331 | * interrupt routine. We give it 3 attempts to avoid | 1340 | * interrupt routine. We give it 3 attempts to avoid |
| 1332 | * overreacting on some spurious event. | 1341 | * overreacting on some spurious event. |
| 1342 | * | ||
| 1343 | * Acquire base lock for updating the offsets and retrieving | ||
| 1344 | * the current time. | ||
| 1333 | */ | 1345 | */ |
| 1334 | now = ktime_get(); | 1346 | raw_spin_lock(&cpu_base->lock); |
| 1347 | now = hrtimer_update_base(cpu_base); | ||
| 1335 | cpu_base->nr_retries++; | 1348 | cpu_base->nr_retries++; |
| 1336 | if (++retries < 3) | 1349 | if (++retries < 3) |
| 1337 | goto retry; | 1350 | goto retry; |
| @@ -1343,6 +1356,7 @@ retry: | |||
| 1343 | */ | 1356 | */ |
| 1344 | cpu_base->nr_hangs++; | 1357 | cpu_base->nr_hangs++; |
| 1345 | cpu_base->hang_detected = 1; | 1358 | cpu_base->hang_detected = 1; |
| 1359 | raw_spin_unlock(&cpu_base->lock); | ||
| 1346 | delta = ktime_sub(now, entry_time); | 1360 | delta = ktime_sub(now, entry_time); |
| 1347 | if (delta.tv64 > cpu_base->max_hang_time.tv64) | 1361 | if (delta.tv64 > cpu_base->max_hang_time.tv64) |
| 1348 | cpu_base->max_hang_time = delta; | 1362 | cpu_base->max_hang_time = delta; |
| @@ -1395,6 +1409,13 @@ void hrtimer_peek_ahead_timers(void) | |||
| 1395 | 1409 | ||
| 1396 | static void run_hrtimer_softirq(struct softirq_action *h) | 1410 | static void run_hrtimer_softirq(struct softirq_action *h) |
| 1397 | { | 1411 | { |
| 1412 | struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); | ||
| 1413 | |||
| 1414 | if (cpu_base->clock_was_set) { | ||
| 1415 | cpu_base->clock_was_set = 0; | ||
| 1416 | clock_was_set(); | ||
| 1417 | } | ||
| 1418 | |||
| 1398 | hrtimer_peek_ahead_timers(); | 1419 | hrtimer_peek_ahead_timers(); |
| 1399 | } | 1420 | } |
| 1400 | 1421 | ||
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 6f46a00a1e8a..269b1fe5f2ae 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 | ||
| 181 | static 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 */ |
| 176 | static void timekeeping_update(bool clearntp) | 190 | static 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 | } |
| @@ -604,6 +619,7 @@ void __init timekeeping_init(void) | |||
| 604 | } | 619 | } |
| 605 | set_normalized_timespec(&timekeeper.wall_to_monotonic, | 620 | set_normalized_timespec(&timekeeper.wall_to_monotonic, |
| 606 | -boot.tv_sec, -boot.tv_nsec); | 621 | -boot.tv_sec, -boot.tv_nsec); |
| 622 | update_rt_offset(); | ||
| 607 | timekeeper.total_sleep_time.tv_sec = 0; | 623 | timekeeper.total_sleep_time.tv_sec = 0; |
| 608 | timekeeper.total_sleep_time.tv_nsec = 0; | 624 | timekeeper.total_sleep_time.tv_nsec = 0; |
| 609 | write_sequnlock_irqrestore(&timekeeper.lock, flags); | 625 | write_sequnlock_irqrestore(&timekeeper.lock, flags); |
| @@ -612,6 +628,12 @@ void __init timekeeping_init(void) | |||
| 612 | /* time in seconds when suspend began */ | 628 | /* time in seconds when suspend began */ |
| 613 | static struct timespec timekeeping_suspend_time; | 629 | static struct timespec timekeeping_suspend_time; |
| 614 | 630 | ||
| 631 | static void update_sleep_time(struct timespec t) | ||
| 632 | { | ||
| 633 | timekeeper.total_sleep_time = t; | ||
| 634 | timekeeper.offs_boot = timespec_to_ktime(t); | ||
| 635 | } | ||
| 636 | |||
| 615 | /** | 637 | /** |
| 616 | * __timekeeping_inject_sleeptime - Internal function to add sleep interval | 638 | * __timekeeping_inject_sleeptime - Internal function to add sleep interval |
| 617 | * @delta: pointer to a timespec delta value | 639 | * @delta: pointer to a timespec delta value |
| @@ -630,8 +652,7 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta) | |||
| 630 | timekeeper.xtime = timespec_add(timekeeper.xtime, *delta); | 652 | timekeeper.xtime = timespec_add(timekeeper.xtime, *delta); |
| 631 | timekeeper.wall_to_monotonic = | 653 | timekeeper.wall_to_monotonic = |
| 632 | timespec_sub(timekeeper.wall_to_monotonic, *delta); | 654 | timespec_sub(timekeeper.wall_to_monotonic, *delta); |
| 633 | timekeeper.total_sleep_time = timespec_add( | 655 | update_sleep_time(timespec_add(timekeeper.total_sleep_time, *delta)); |
| 634 | timekeeper.total_sleep_time, *delta); | ||
| 635 | } | 656 | } |
| 636 | 657 | ||
| 637 | 658 | ||
| @@ -963,6 +984,8 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) | |||
| 963 | leap = second_overflow(timekeeper.xtime.tv_sec); | 984 | leap = second_overflow(timekeeper.xtime.tv_sec); |
| 964 | timekeeper.xtime.tv_sec += leap; | 985 | timekeeper.xtime.tv_sec += leap; |
| 965 | timekeeper.wall_to_monotonic.tv_sec -= leap; | 986 | timekeeper.wall_to_monotonic.tv_sec -= leap; |
| 987 | if (leap) | ||
| 988 | clock_was_set_delayed(); | ||
| 966 | } | 989 | } |
| 967 | 990 | ||
| 968 | /* Accumulate raw time */ | 991 | /* Accumulate raw time */ |
| @@ -1079,6 +1102,8 @@ static void update_wall_time(void) | |||
| 1079 | leap = second_overflow(timekeeper.xtime.tv_sec); | 1102 | leap = second_overflow(timekeeper.xtime.tv_sec); |
| 1080 | timekeeper.xtime.tv_sec += leap; | 1103 | timekeeper.xtime.tv_sec += leap; |
| 1081 | timekeeper.wall_to_monotonic.tv_sec -= leap; | 1104 | timekeeper.wall_to_monotonic.tv_sec -= leap; |
| 1105 | if (leap) | ||
| 1106 | clock_was_set_delayed(); | ||
| 1082 | } | 1107 | } |
| 1083 | 1108 | ||
| 1084 | timekeeping_update(false); | 1109 | timekeeping_update(false); |
| @@ -1246,6 +1271,40 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, | |||
| 1246 | } while (read_seqretry(&timekeeper.lock, seq)); | 1271 | } while (read_seqretry(&timekeeper.lock, seq)); |
| 1247 | } | 1272 | } |
| 1248 | 1273 | ||
| 1274 | #ifdef CONFIG_HIGH_RES_TIMERS | ||
| 1275 | /** | ||
| 1276 | * ktime_get_update_offsets - hrtimer helper | ||
| 1277 | * @offs_real: pointer to storage for monotonic -> realtime offset | ||
| 1278 | * @offs_boot: pointer to storage for monotonic -> boottime offset | ||
| 1279 | * | ||
| 1280 | * Returns current monotonic time and updates the offsets | ||
| 1281 | * Called from hrtimer_interupt() or retrigger_next_event() | ||
| 1282 | */ | ||
| 1283 | ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) | ||
| 1284 | { | ||
| 1285 | ktime_t now; | ||
| 1286 | unsigned int seq; | ||
| 1287 | u64 secs, nsecs; | ||
| 1288 | |||
| 1289 | do { | ||
| 1290 | seq = read_seqbegin(&timekeeper.lock); | ||
| 1291 | |||
| 1292 | secs = timekeeper.xtime.tv_sec; | ||
| 1293 | nsecs = timekeeper.xtime.tv_nsec; | ||
| 1294 | nsecs += timekeeping_get_ns(); | ||
| 1295 | /* If arch requires, add in gettimeoffset() */ | ||
| 1296 | nsecs += arch_gettimeoffset(); | ||
| 1297 | |||
| 1298 | *offs_real = timekeeper.offs_real; | ||
| 1299 | *offs_boot = timekeeper.offs_boot; | ||
| 1300 | } while (read_seqretry(&timekeeper.lock, seq)); | ||
| 1301 | |||
| 1302 | now = ktime_add_ns(ktime_set(secs, 0), nsecs); | ||
| 1303 | now = ktime_sub(now, *offs_real); | ||
| 1304 | return now; | ||
| 1305 | } | ||
| 1306 | #endif | ||
| 1307 | |||
| 1249 | /** | 1308 | /** |
| 1250 | * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format | 1309 | * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format |
| 1251 | */ | 1310 | */ |
