diff options
| author | John Stultz <john.stultz@linaro.org> | 2011-11-14 15:48:10 -0500 |
|---|---|---|
| committer | John Stultz <john.stultz@linaro.org> | 2012-01-26 22:44:18 -0500 |
| commit | 70471f2f061d59375e959b4e7d47ee62121babb1 (patch) | |
| tree | f2799ccaaed2d976748d6ecd8708c0886c142bf5 /kernel/time | |
| parent | 8fcce546be16130865550136831f71097d7fc228 (diff) | |
time: Add timekeeper lock
Now that all the timekeeping variables are stored in
the timekeeper structure, add a new lock to protect the
structure.
For now, this lock nests under the xtime_lock for writes.
For readers, we don't need to take xtime_lock anymore.
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Eric Dumazet <eric.dumazet@gmail.com>
CC: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'kernel/time')
| -rw-r--r-- | kernel/time/timekeeping.c | 126 |
1 files changed, 82 insertions, 44 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 5df2e7e556c..f5d4d226def 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
| @@ -69,6 +69,9 @@ struct timekeeper { | |||
| 69 | struct timespec total_sleep_time; | 69 | struct timespec total_sleep_time; |
| 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 | |||
| 73 | /* Seqlock for all timekeeper values */ | ||
| 74 | seqlock_t lock; | ||
| 72 | }; | 75 | }; |
| 73 | 76 | ||
| 74 | static struct timekeeper timekeeper; | 77 | static struct timekeeper timekeeper; |
| @@ -172,10 +175,17 @@ static inline s64 timekeeping_get_ns_raw(void) | |||
| 172 | /* must hold xtime_lock */ | 175 | /* must hold xtime_lock */ |
| 173 | void timekeeping_leap_insert(int leapsecond) | 176 | void timekeeping_leap_insert(int leapsecond) |
| 174 | { | 177 | { |
| 178 | unsigned long flags; | ||
| 179 | |||
| 180 | write_seqlock_irqsave(&timekeeper.lock, flags); | ||
| 181 | |||
| 175 | timekeeper.xtime.tv_sec += leapsecond; | 182 | timekeeper.xtime.tv_sec += leapsecond; |
| 176 | timekeeper.wall_to_monotonic.tv_sec -= leapsecond; | 183 | timekeeper.wall_to_monotonic.tv_sec -= leapsecond; |
| 177 | update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, | 184 | update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, |
| 178 | timekeeper.clock, timekeeper.mult); | 185 | timekeeper.clock, timekeeper.mult); |
| 186 | |||
| 187 | write_sequnlock_irqrestore(&timekeeper.lock, flags); | ||
| 188 | |||
| 179 | } | 189 | } |
| 180 | 190 | ||
| 181 | /** | 191 | /** |
| @@ -222,7 +232,7 @@ void getnstimeofday(struct timespec *ts) | |||
| 222 | WARN_ON(timekeeping_suspended); | 232 | WARN_ON(timekeeping_suspended); |
| 223 | 233 | ||
| 224 | do { | 234 | do { |
| 225 | seq = read_seqbegin(&xtime_lock); | 235 | seq = read_seqbegin(&timekeeper.lock); |
| 226 | 236 | ||
| 227 | *ts = timekeeper.xtime; | 237 | *ts = timekeeper.xtime; |
| 228 | nsecs = timekeeping_get_ns(); | 238 | nsecs = timekeeping_get_ns(); |
| @@ -230,7 +240,7 @@ void getnstimeofday(struct timespec *ts) | |||
| 230 | /* If arch requires, add in gettimeoffset() */ | 240 | /* If arch requires, add in gettimeoffset() */ |
| 231 | nsecs += arch_gettimeoffset(); | 241 | nsecs += arch_gettimeoffset(); |
| 232 | 242 | ||
| 233 | } while (read_seqretry(&xtime_lock, seq)); | 243 | } while (read_seqretry(&timekeeper.lock, seq)); |
| 234 | 244 | ||
| 235 | timespec_add_ns(ts, nsecs); | 245 | timespec_add_ns(ts, nsecs); |
| 236 | } | 246 | } |
| @@ -245,7 +255,7 @@ ktime_t ktime_get(void) | |||
| 245 | WARN_ON(timekeeping_suspended); | 255 | WARN_ON(timekeeping_suspended); |
| 246 | 256 | ||
| 247 | do { | 257 | do { |
| 248 | seq = read_seqbegin(&xtime_lock); | 258 | seq = read_seqbegin(&timekeeper.lock); |
| 249 | secs = timekeeper.xtime.tv_sec + | 259 | secs = timekeeper.xtime.tv_sec + |
| 250 | timekeeper.wall_to_monotonic.tv_sec; | 260 | timekeeper.wall_to_monotonic.tv_sec; |
| 251 | nsecs = timekeeper.xtime.tv_nsec + | 261 | nsecs = timekeeper.xtime.tv_nsec + |
| @@ -254,7 +264,7 @@ ktime_t ktime_get(void) | |||
| 254 | /* If arch requires, add in gettimeoffset() */ | 264 | /* If arch requires, add in gettimeoffset() */ |
| 255 | nsecs += arch_gettimeoffset(); | 265 | nsecs += arch_gettimeoffset(); |
| 256 | 266 | ||
| 257 | } while (read_seqretry(&xtime_lock, seq)); | 267 | } while (read_seqretry(&timekeeper.lock, seq)); |
| 258 | /* | 268 | /* |
| 259 | * Use ktime_set/ktime_add_ns to create a proper ktime on | 269 | * Use ktime_set/ktime_add_ns to create a proper ktime on |
| 260 | * 32-bit architectures without CONFIG_KTIME_SCALAR. | 270 | * 32-bit architectures without CONFIG_KTIME_SCALAR. |
| @@ -280,14 +290,14 @@ void ktime_get_ts(struct timespec *ts) | |||
| 280 | WARN_ON(timekeeping_suspended); | 290 | WARN_ON(timekeeping_suspended); |
| 281 | 291 | ||
| 282 | do { | 292 | do { |
| 283 | seq = read_seqbegin(&xtime_lock); | 293 | seq = read_seqbegin(&timekeeper.lock); |
| 284 | *ts = timekeeper.xtime; | 294 | *ts = timekeeper.xtime; |
| 285 | tomono = timekeeper.wall_to_monotonic; | 295 | tomono = timekeeper.wall_to_monotonic; |
| 286 | nsecs = timekeeping_get_ns(); | 296 | nsecs = timekeeping_get_ns(); |
| 287 | /* If arch requires, add in gettimeoffset() */ | 297 | /* If arch requires, add in gettimeoffset() */ |
| 288 | nsecs += arch_gettimeoffset(); | 298 | nsecs += arch_gettimeoffset(); |
| 289 | 299 | ||
| 290 | } while (read_seqretry(&xtime_lock, seq)); | 300 | } while (read_seqretry(&timekeeper.lock, seq)); |
| 291 | 301 | ||
| 292 | set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec, | 302 | set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec, |
| 293 | ts->tv_nsec + tomono.tv_nsec + nsecs); | 303 | ts->tv_nsec + tomono.tv_nsec + nsecs); |
| @@ -315,7 +325,7 @@ void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real) | |||
| 315 | do { | 325 | do { |
| 316 | u32 arch_offset; | 326 | u32 arch_offset; |
| 317 | 327 | ||
| 318 | seq = read_seqbegin(&xtime_lock); | 328 | seq = read_seqbegin(&timekeeper.lock); |
| 319 | 329 | ||
| 320 | *ts_raw = timekeeper.raw_time; | 330 | *ts_raw = timekeeper.raw_time; |
| 321 | *ts_real = timekeeper.xtime; | 331 | *ts_real = timekeeper.xtime; |
| @@ -328,7 +338,7 @@ void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real) | |||
| 328 | nsecs_raw += arch_offset; | 338 | nsecs_raw += arch_offset; |
| 329 | nsecs_real += arch_offset; | 339 | nsecs_real += arch_offset; |
| 330 | 340 | ||
| 331 | } while (read_seqretry(&xtime_lock, seq)); | 341 | } while (read_seqretry(&timekeeper.lock, seq)); |
| 332 | 342 | ||
| 333 | timespec_add_ns(ts_raw, nsecs_raw); | 343 | timespec_add_ns(ts_raw, nsecs_raw); |
| 334 | timespec_add_ns(ts_real, nsecs_real); | 344 | timespec_add_ns(ts_real, nsecs_real); |
| @@ -362,12 +372,13 @@ EXPORT_SYMBOL(do_gettimeofday); | |||
| 362 | int do_settimeofday(const struct timespec *tv) | 372 | int do_settimeofday(const struct timespec *tv) |
| 363 | { | 373 | { |
| 364 | struct timespec ts_delta; | 374 | struct timespec ts_delta; |
| 365 | unsigned long flags; | 375 | unsigned long flags1,flags2; |
| 366 | 376 | ||
| 367 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | 377 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) |
| 368 | return -EINVAL; | 378 | return -EINVAL; |
| 369 | 379 | ||
| 370 | write_seqlock_irqsave(&xtime_lock, flags); | 380 | write_seqlock_irqsave(&xtime_lock, flags1); |
| 381 | write_seqlock_irqsave(&timekeeper.lock, flags2); | ||
| 371 | 382 | ||
| 372 | timekeeping_forward_now(); | 383 | timekeeping_forward_now(); |
| 373 | 384 | ||
| @@ -384,7 +395,8 @@ int do_settimeofday(const struct timespec *tv) | |||
| 384 | update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, | 395 | update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, |
| 385 | timekeeper.clock, timekeeper.mult); | 396 | timekeeper.clock, timekeeper.mult); |
| 386 | 397 | ||
| 387 | write_sequnlock_irqrestore(&xtime_lock, flags); | 398 | write_sequnlock_irqrestore(&timekeeper.lock, flags2); |
| 399 | write_sequnlock_irqrestore(&xtime_lock, flags1); | ||
| 388 | 400 | ||
| 389 | /* signal hrtimers about time change */ | 401 | /* signal hrtimers about time change */ |
| 390 | clock_was_set(); | 402 | clock_was_set(); |
| @@ -403,12 +415,13 @@ EXPORT_SYMBOL(do_settimeofday); | |||
| 403 | */ | 415 | */ |
| 404 | int timekeeping_inject_offset(struct timespec *ts) | 416 | int timekeeping_inject_offset(struct timespec *ts) |
| 405 | { | 417 | { |
| 406 | unsigned long flags; | 418 | unsigned long flags1,flags2; |
| 407 | 419 | ||
| 408 | if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) | 420 | if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) |
| 409 | return -EINVAL; | 421 | return -EINVAL; |
| 410 | 422 | ||
| 411 | write_seqlock_irqsave(&xtime_lock, flags); | 423 | write_seqlock_irqsave(&xtime_lock, flags1); |
| 424 | write_seqlock_irqsave(&timekeeper.lock, flags2); | ||
| 412 | 425 | ||
| 413 | timekeeping_forward_now(); | 426 | timekeeping_forward_now(); |
| 414 | 427 | ||
| @@ -422,7 +435,8 @@ int timekeeping_inject_offset(struct timespec *ts) | |||
| 422 | update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, | 435 | update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, |
| 423 | timekeeper.clock, timekeeper.mult); | 436 | timekeeper.clock, timekeeper.mult); |
| 424 | 437 | ||
| 425 | write_sequnlock_irqrestore(&xtime_lock, flags); | 438 | write_sequnlock_irqrestore(&timekeeper.lock, flags2); |
| 439 | write_sequnlock_irqrestore(&xtime_lock, flags1); | ||
| 426 | 440 | ||
| 427 | /* signal hrtimers about time change */ | 441 | /* signal hrtimers about time change */ |
| 428 | clock_was_set(); | 442 | clock_was_set(); |
| @@ -494,11 +508,11 @@ void getrawmonotonic(struct timespec *ts) | |||
| 494 | s64 nsecs; | 508 | s64 nsecs; |
| 495 | 509 | ||
| 496 | do { | 510 | do { |
| 497 | seq = read_seqbegin(&xtime_lock); | 511 | seq = read_seqbegin(&timekeeper.lock); |
| 498 | nsecs = timekeeping_get_ns_raw(); | 512 | nsecs = timekeeping_get_ns_raw(); |
| 499 | *ts = timekeeper.raw_time; | 513 | *ts = timekeeper.raw_time; |
| 500 | 514 | ||
| 501 | } while (read_seqretry(&xtime_lock, seq)); | 515 | } while (read_seqretry(&timekeeper.lock, seq)); |
| 502 | 516 | ||
| 503 | timespec_add_ns(ts, nsecs); | 517 | timespec_add_ns(ts, nsecs); |
| 504 | } | 518 | } |
| @@ -514,24 +528,30 @@ int timekeeping_valid_for_hres(void) | |||
| 514 | int ret; | 528 | int ret; |
| 515 | 529 | ||
| 516 | do { | 530 | do { |
| 517 | seq = read_seqbegin(&xtime_lock); | 531 | seq = read_seqbegin(&timekeeper.lock); |
| 518 | 532 | ||
| 519 | ret = timekeeper.clock->flags & CLOCK_SOURCE_VALID_FOR_HRES; | 533 | ret = timekeeper.clock->flags & CLOCK_SOURCE_VALID_FOR_HRES; |
| 520 | 534 | ||
| 521 | } while (read_seqretry(&xtime_lock, seq)); | 535 | } while (read_seqretry(&timekeeper.lock, seq)); |
| 522 | 536 | ||
| 523 | return ret; | 537 | return ret; |
| 524 | } | 538 | } |
| 525 | 539 | ||
| 526 | /** | 540 | /** |
| 527 | * timekeeping_max_deferment - Returns max time the clocksource can be deferred | 541 | * timekeeping_max_deferment - Returns max time the clocksource can be deferred |
| 528 | * | ||
| 529 | * Caller must observe xtime_lock via read_seqbegin/read_seqretry to | ||
| 530 | * ensure that the clocksource does not change! | ||
| 531 | */ | 542 | */ |
| 532 | u64 timekeeping_max_deferment(void) | 543 | u64 timekeeping_max_deferment(void) |
| 533 | { | 544 | { |
| 534 | return timekeeper.clock->max_idle_ns; | 545 | unsigned long seq; |
| 546 | u64 ret; | ||
| 547 | do { | ||
| 548 | seq = read_seqbegin(&timekeeper.lock); | ||
| 549 | |||
| 550 | ret = timekeeper.clock->max_idle_ns; | ||
| 551 | |||
| 552 | } while (read_seqretry(&timekeeper.lock, seq)); | ||
| 553 | |||
| 554 | return ret; | ||
| 535 | } | 555 | } |
| 536 | 556 | ||
| 537 | /** | 557 | /** |
| @@ -576,10 +596,13 @@ void __init timekeeping_init(void) | |||
| 576 | read_persistent_clock(&now); | 596 | read_persistent_clock(&now); |
| 577 | read_boot_clock(&boot); | 597 | read_boot_clock(&boot); |
| 578 | 598 | ||
| 579 | write_seqlock_irqsave(&xtime_lock, flags); | 599 | seqlock_init(&timekeeper.lock); |
| 580 | 600 | ||
| 601 | write_seqlock_irqsave(&xtime_lock, flags); | ||
| 581 | ntp_init(); | 602 | ntp_init(); |
| 603 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
| 582 | 604 | ||
| 605 | write_seqlock_irqsave(&timekeeper.lock, flags); | ||
| 583 | clock = clocksource_default_clock(); | 606 | clock = clocksource_default_clock(); |
| 584 | if (clock->enable) | 607 | if (clock->enable) |
| 585 | clock->enable(clock); | 608 | clock->enable(clock); |
| @@ -597,7 +620,7 @@ void __init timekeeping_init(void) | |||
| 597 | -boot.tv_sec, -boot.tv_nsec); | 620 | -boot.tv_sec, -boot.tv_nsec); |
| 598 | timekeeper.total_sleep_time.tv_sec = 0; | 621 | timekeeper.total_sleep_time.tv_sec = 0; |
| 599 | timekeeper.total_sleep_time.tv_nsec = 0; | 622 | timekeeper.total_sleep_time.tv_nsec = 0; |
| 600 | write_sequnlock_irqrestore(&xtime_lock, flags); | 623 | write_sequnlock_irqrestore(&timekeeper.lock, flags); |
| 601 | } | 624 | } |
| 602 | 625 | ||
| 603 | /* time in seconds when suspend began */ | 626 | /* time in seconds when suspend began */ |
| @@ -638,7 +661,7 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta) | |||
| 638 | */ | 661 | */ |
| 639 | void timekeeping_inject_sleeptime(struct timespec *delta) | 662 | void timekeeping_inject_sleeptime(struct timespec *delta) |
| 640 | { | 663 | { |
| 641 | unsigned long flags; | 664 | unsigned long flags1,flags2; |
| 642 | struct timespec ts; | 665 | struct timespec ts; |
| 643 | 666 | ||
| 644 | /* Make sure we don't set the clock twice */ | 667 | /* Make sure we don't set the clock twice */ |
| @@ -646,7 +669,9 @@ void timekeeping_inject_sleeptime(struct timespec *delta) | |||
| 646 | if (!(ts.tv_sec == 0 && ts.tv_nsec == 0)) | 669 | if (!(ts.tv_sec == 0 && ts.tv_nsec == 0)) |
| 647 | return; | 670 | return; |
| 648 | 671 | ||
| 649 | write_seqlock_irqsave(&xtime_lock, flags); | 672 | write_seqlock_irqsave(&xtime_lock, flags1); |
| 673 | write_seqlock_irqsave(&timekeeper.lock, flags2); | ||
| 674 | |||
| 650 | timekeeping_forward_now(); | 675 | timekeeping_forward_now(); |
| 651 | 676 | ||
| 652 | __timekeeping_inject_sleeptime(delta); | 677 | __timekeeping_inject_sleeptime(delta); |
| @@ -656,7 +681,8 @@ void timekeeping_inject_sleeptime(struct timespec *delta) | |||
| 656 | update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, | 681 | update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, |
| 657 | timekeeper.clock, timekeeper.mult); | 682 | timekeeper.clock, timekeeper.mult); |
| 658 | 683 | ||
| 659 | write_sequnlock_irqrestore(&xtime_lock, flags); | 684 | write_sequnlock_irqrestore(&timekeeper.lock, flags2); |
| 685 | write_sequnlock_irqrestore(&xtime_lock, flags1); | ||
| 660 | 686 | ||
| 661 | /* signal hrtimers about time change */ | 687 | /* signal hrtimers about time change */ |
| 662 | clock_was_set(); | 688 | clock_was_set(); |
| @@ -672,14 +698,15 @@ void timekeeping_inject_sleeptime(struct timespec *delta) | |||
| 672 | */ | 698 | */ |
| 673 | static void timekeeping_resume(void) | 699 | static void timekeeping_resume(void) |
| 674 | { | 700 | { |
| 675 | unsigned long flags; | 701 | unsigned long flags1,flags2; |
| 676 | struct timespec ts; | 702 | struct timespec ts; |
| 677 | 703 | ||
| 678 | read_persistent_clock(&ts); | 704 | read_persistent_clock(&ts); |
| 679 | 705 | ||
| 680 | clocksource_resume(); | 706 | clocksource_resume(); |
| 681 | 707 | ||
| 682 | write_seqlock_irqsave(&xtime_lock, flags); | 708 | write_seqlock_irqsave(&xtime_lock, flags1); |
| 709 | write_seqlock_irqsave(&timekeeper.lock, flags2); | ||
| 683 | 710 | ||
| 684 | if (timespec_compare(&ts, &timekeeping_suspend_time) > 0) { | 711 | if (timespec_compare(&ts, &timekeeping_suspend_time) > 0) { |
| 685 | ts = timespec_sub(ts, timekeeping_suspend_time); | 712 | ts = timespec_sub(ts, timekeeping_suspend_time); |
| @@ -689,7 +716,8 @@ static void timekeeping_resume(void) | |||
| 689 | timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); | 716 | timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); |
| 690 | timekeeper.ntp_error = 0; | 717 | timekeeper.ntp_error = 0; |
| 691 | timekeeping_suspended = 0; | 718 | timekeeping_suspended = 0; |
| 692 | write_sequnlock_irqrestore(&xtime_lock, flags); | 719 | write_sequnlock_irqrestore(&timekeeper.lock, flags2); |
| 720 | write_sequnlock_irqrestore(&xtime_lock, flags1); | ||
| 693 | 721 | ||
| 694 | touch_softlockup_watchdog(); | 722 | touch_softlockup_watchdog(); |
| 695 | 723 | ||
| @@ -701,13 +729,14 @@ static void timekeeping_resume(void) | |||
| 701 | 729 | ||
| 702 | static int timekeeping_suspend(void) | 730 | static int timekeeping_suspend(void) |
| 703 | { | 731 | { |
| 704 | unsigned long flags; | 732 | unsigned long flags1,flags2; |
| 705 | struct timespec delta, delta_delta; | 733 | struct timespec delta, delta_delta; |
| 706 | static struct timespec old_delta; | 734 | static struct timespec old_delta; |
| 707 | 735 | ||
| 708 | read_persistent_clock(&timekeeping_suspend_time); | 736 | read_persistent_clock(&timekeeping_suspend_time); |
| 709 | 737 | ||
| 710 | write_seqlock_irqsave(&xtime_lock, flags); | 738 | write_seqlock_irqsave(&xtime_lock, flags1); |
| 739 | write_seqlock_irqsave(&timekeeper.lock, flags2); | ||
| 711 | timekeeping_forward_now(); | 740 | timekeeping_forward_now(); |
| 712 | timekeeping_suspended = 1; | 741 | timekeeping_suspended = 1; |
| 713 | 742 | ||
| @@ -730,7 +759,8 @@ static int timekeeping_suspend(void) | |||
| 730 | timekeeping_suspend_time = | 759 | timekeeping_suspend_time = |
| 731 | timespec_add(timekeeping_suspend_time, delta_delta); | 760 | timespec_add(timekeeping_suspend_time, delta_delta); |
| 732 | } | 761 | } |
| 733 | write_sequnlock_irqrestore(&xtime_lock, flags); | 762 | write_sequnlock_irqrestore(&timekeeper.lock, flags2); |
| 763 | write_sequnlock_irqrestore(&xtime_lock, flags1); | ||
| 734 | 764 | ||
| 735 | clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL); | 765 | clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL); |
| 736 | clocksource_suspend(); | 766 | clocksource_suspend(); |
| @@ -983,10 +1013,13 @@ static void update_wall_time(void) | |||
| 983 | struct clocksource *clock; | 1013 | struct clocksource *clock; |
| 984 | cycle_t offset; | 1014 | cycle_t offset; |
| 985 | int shift = 0, maxshift; | 1015 | int shift = 0, maxshift; |
| 1016 | unsigned long flags; | ||
| 1017 | |||
| 1018 | write_seqlock_irqsave(&timekeeper.lock, flags); | ||
| 986 | 1019 | ||
| 987 | /* Make sure we're fully resumed: */ | 1020 | /* Make sure we're fully resumed: */ |
| 988 | if (unlikely(timekeeping_suspended)) | 1021 | if (unlikely(timekeeping_suspended)) |
| 989 | return; | 1022 | goto out; |
| 990 | 1023 | ||
| 991 | clock = timekeeper.clock; | 1024 | clock = timekeeper.clock; |
| 992 | 1025 | ||
| @@ -1067,6 +1100,10 @@ static void update_wall_time(void) | |||
| 1067 | /* check to see if there is a new clocksource to use */ | 1100 | /* check to see if there is a new clocksource to use */ |
| 1068 | update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, | 1101 | update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, |
| 1069 | timekeeper.clock, timekeeper.mult); | 1102 | timekeeper.clock, timekeeper.mult); |
| 1103 | |||
| 1104 | out: | ||
| 1105 | write_sequnlock_irqrestore(&timekeeper.lock, flags); | ||
| 1106 | |||
| 1070 | } | 1107 | } |
| 1071 | 1108 | ||
| 1072 | /** | 1109 | /** |
| @@ -1112,13 +1149,13 @@ void get_monotonic_boottime(struct timespec *ts) | |||
| 1112 | WARN_ON(timekeeping_suspended); | 1149 | WARN_ON(timekeeping_suspended); |
| 1113 | 1150 | ||
| 1114 | do { | 1151 | do { |
| 1115 | seq = read_seqbegin(&xtime_lock); | 1152 | seq = read_seqbegin(&timekeeper.lock); |
| 1116 | *ts = timekeeper.xtime; | 1153 | *ts = timekeeper.xtime; |
| 1117 | tomono = timekeeper.wall_to_monotonic; | 1154 | tomono = timekeeper.wall_to_monotonic; |
| 1118 | sleep = timekeeper.total_sleep_time; | 1155 | sleep = timekeeper.total_sleep_time; |
| 1119 | nsecs = timekeeping_get_ns(); | 1156 | nsecs = timekeeping_get_ns(); |
| 1120 | 1157 | ||
| 1121 | } while (read_seqretry(&xtime_lock, seq)); | 1158 | } while (read_seqretry(&timekeeper.lock, seq)); |
| 1122 | 1159 | ||
| 1123 | set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec + sleep.tv_sec, | 1160 | set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec + sleep.tv_sec, |
| 1124 | ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec + nsecs); | 1161 | ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec + nsecs); |
| @@ -1169,10 +1206,10 @@ struct timespec current_kernel_time(void) | |||
| 1169 | unsigned long seq; | 1206 | unsigned long seq; |
| 1170 | 1207 | ||
| 1171 | do { | 1208 | do { |
| 1172 | seq = read_seqbegin(&xtime_lock); | 1209 | seq = read_seqbegin(&timekeeper.lock); |
| 1173 | 1210 | ||
| 1174 | now = timekeeper.xtime; | 1211 | now = timekeeper.xtime; |
| 1175 | } while (read_seqretry(&xtime_lock, seq)); | 1212 | } while (read_seqretry(&timekeeper.lock, seq)); |
| 1176 | 1213 | ||
| 1177 | return now; | 1214 | return now; |
| 1178 | } | 1215 | } |
| @@ -1184,11 +1221,11 @@ struct timespec get_monotonic_coarse(void) | |||
| 1184 | unsigned long seq; | 1221 | unsigned long seq; |
| 1185 | 1222 | ||
| 1186 | do { | 1223 | do { |
| 1187 | seq = read_seqbegin(&xtime_lock); | 1224 | seq = read_seqbegin(&timekeeper.lock); |
| 1188 | 1225 | ||
| 1189 | now = timekeeper.xtime; | 1226 | now = timekeeper.xtime; |
| 1190 | mono = timekeeper.wall_to_monotonic; | 1227 | mono = timekeeper.wall_to_monotonic; |
| 1191 | } while (read_seqretry(&xtime_lock, seq)); | 1228 | } while (read_seqretry(&timekeeper.lock, seq)); |
| 1192 | 1229 | ||
| 1193 | set_normalized_timespec(&now, now.tv_sec + mono.tv_sec, | 1230 | set_normalized_timespec(&now, now.tv_sec + mono.tv_sec, |
| 1194 | now.tv_nsec + mono.tv_nsec); | 1231 | now.tv_nsec + mono.tv_nsec); |
| @@ -1220,11 +1257,11 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, | |||
| 1220 | unsigned long seq; | 1257 | unsigned long seq; |
| 1221 | 1258 | ||
| 1222 | do { | 1259 | do { |
| 1223 | seq = read_seqbegin(&xtime_lock); | 1260 | seq = read_seqbegin(&timekeeper.lock); |
| 1224 | *xtim = timekeeper.xtime; | 1261 | *xtim = timekeeper.xtime; |
| 1225 | *wtom = timekeeper.wall_to_monotonic; | 1262 | *wtom = timekeeper.wall_to_monotonic; |
| 1226 | *sleep = timekeeper.total_sleep_time; | 1263 | *sleep = timekeeper.total_sleep_time; |
| 1227 | } while (read_seqretry(&xtime_lock, seq)); | 1264 | } while (read_seqretry(&timekeeper.lock, seq)); |
| 1228 | } | 1265 | } |
| 1229 | 1266 | ||
| 1230 | /** | 1267 | /** |
| @@ -1236,9 +1273,10 @@ ktime_t ktime_get_monotonic_offset(void) | |||
| 1236 | struct timespec wtom; | 1273 | struct timespec wtom; |
| 1237 | 1274 | ||
| 1238 | do { | 1275 | do { |
| 1239 | seq = read_seqbegin(&xtime_lock); | 1276 | seq = read_seqbegin(&timekeeper.lock); |
| 1240 | wtom = timekeeper.wall_to_monotonic; | 1277 | wtom = timekeeper.wall_to_monotonic; |
| 1241 | } while (read_seqretry(&xtime_lock, seq)); | 1278 | } while (read_seqretry(&timekeeper.lock, seq)); |
| 1279 | |||
| 1242 | return timespec_to_ktime(wtom); | 1280 | return timespec_to_ktime(wtom); |
| 1243 | } | 1281 | } |
| 1244 | 1282 | ||
