diff options
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r-- | kernel/hrtimer.c | 70 |
1 files changed, 35 insertions, 35 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index f1c4155b49ac..2b6e1757aedd 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -21,6 +21,12 @@ | |||
21 | * Credits: | 21 | * Credits: |
22 | * based on kernel/timer.c | 22 | * based on kernel/timer.c |
23 | * | 23 | * |
24 | * Help, testing, suggestions, bugfixes, improvements were | ||
25 | * provided by: | ||
26 | * | ||
27 | * George Anzinger, Andrew Morton, Steven Rostedt, Roman Zippel | ||
28 | * et. al. | ||
29 | * | ||
24 | * For licencing details see kernel-base/COPYING | 30 | * For licencing details see kernel-base/COPYING |
25 | */ | 31 | */ |
26 | 32 | ||
@@ -66,6 +72,12 @@ EXPORT_SYMBOL_GPL(ktime_get_real); | |||
66 | 72 | ||
67 | /* | 73 | /* |
68 | * The timer bases: | 74 | * The timer bases: |
75 | * | ||
76 | * Note: If we want to add new timer bases, we have to skip the two | ||
77 | * clock ids captured by the cpu-timers. We do this by holding empty | ||
78 | * entries rather than doing math adjustment of the clock ids. | ||
79 | * This ensures that we capture erroneous accesses to these clock ids | ||
80 | * rather than moving them into the range of valid clock id's. | ||
69 | */ | 81 | */ |
70 | 82 | ||
71 | #define MAX_HRTIMER_BASES 2 | 83 | #define MAX_HRTIMER_BASES 2 |
@@ -483,29 +495,25 @@ ktime_t hrtimer_get_remaining(const struct hrtimer *timer) | |||
483 | } | 495 | } |
484 | 496 | ||
485 | /** | 497 | /** |
486 | * hrtimer_rebase - rebase an initialized hrtimer to a different base | 498 | * hrtimer_init - initialize a timer to the given clock |
487 | * | 499 | * |
488 | * @timer: the timer to be rebased | 500 | * @timer: the timer to be initialized |
489 | * @clock_id: the clock to be used | 501 | * @clock_id: the clock to be used |
502 | * @mode: timer mode abs/rel | ||
490 | */ | 503 | */ |
491 | void hrtimer_rebase(struct hrtimer *timer, const clockid_t clock_id) | 504 | void hrtimer_init(struct hrtimer *timer, clockid_t clock_id, |
505 | enum hrtimer_mode mode) | ||
492 | { | 506 | { |
493 | struct hrtimer_base *bases; | 507 | struct hrtimer_base *bases; |
494 | 508 | ||
509 | memset(timer, 0, sizeof(struct hrtimer)); | ||
510 | |||
495 | bases = per_cpu(hrtimer_bases, raw_smp_processor_id()); | 511 | bases = per_cpu(hrtimer_bases, raw_smp_processor_id()); |
496 | timer->base = &bases[clock_id]; | ||
497 | } | ||
498 | 512 | ||
499 | /** | 513 | if (clock_id == CLOCK_REALTIME && mode != HRTIMER_ABS) |
500 | * hrtimer_init - initialize a timer to the given clock | 514 | clock_id = CLOCK_MONOTONIC; |
501 | * | 515 | |
502 | * @timer: the timer to be initialized | 516 | timer->base = &bases[clock_id]; |
503 | * @clock_id: the clock to be used | ||
504 | */ | ||
505 | void hrtimer_init(struct hrtimer *timer, const clockid_t clock_id) | ||
506 | { | ||
507 | memset(timer, 0, sizeof(struct hrtimer)); | ||
508 | hrtimer_rebase(timer, clock_id); | ||
509 | } | 517 | } |
510 | 518 | ||
511 | /** | 519 | /** |
@@ -550,6 +558,7 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base) | |||
550 | fn = timer->function; | 558 | fn = timer->function; |
551 | data = timer->data; | 559 | data = timer->data; |
552 | set_curr_timer(base, timer); | 560 | set_curr_timer(base, timer); |
561 | timer->state = HRTIMER_RUNNING; | ||
553 | __remove_hrtimer(timer, base); | 562 | __remove_hrtimer(timer, base); |
554 | spin_unlock_irq(&base->lock); | 563 | spin_unlock_irq(&base->lock); |
555 | 564 | ||
@@ -565,6 +574,10 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base) | |||
565 | 574 | ||
566 | spin_lock_irq(&base->lock); | 575 | spin_lock_irq(&base->lock); |
567 | 576 | ||
577 | /* Another CPU has added back the timer */ | ||
578 | if (timer->state != HRTIMER_RUNNING) | ||
579 | continue; | ||
580 | |||
568 | if (restart == HRTIMER_RESTART) | 581 | if (restart == HRTIMER_RESTART) |
569 | enqueue_hrtimer(timer, base); | 582 | enqueue_hrtimer(timer, base); |
570 | else | 583 | else |
@@ -638,8 +651,7 @@ schedule_hrtimer_interruptible(struct hrtimer *timer, | |||
638 | return schedule_hrtimer(timer, mode); | 651 | return schedule_hrtimer(timer, mode); |
639 | } | 652 | } |
640 | 653 | ||
641 | static long __sched | 654 | static long __sched nanosleep_restart(struct restart_block *restart) |
642 | nanosleep_restart(struct restart_block *restart, clockid_t clockid) | ||
643 | { | 655 | { |
644 | struct timespec __user *rmtp; | 656 | struct timespec __user *rmtp; |
645 | struct timespec tu; | 657 | struct timespec tu; |
@@ -649,7 +661,7 @@ nanosleep_restart(struct restart_block *restart, clockid_t clockid) | |||
649 | 661 | ||
650 | restart->fn = do_no_restart_syscall; | 662 | restart->fn = do_no_restart_syscall; |
651 | 663 | ||
652 | hrtimer_init(&timer, clockid); | 664 | hrtimer_init(&timer, (clockid_t) restart->arg3, HRTIMER_ABS); |
653 | 665 | ||
654 | timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0; | 666 | timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0; |
655 | 667 | ||
@@ -669,16 +681,6 @@ nanosleep_restart(struct restart_block *restart, clockid_t clockid) | |||
669 | return -ERESTART_RESTARTBLOCK; | 681 | return -ERESTART_RESTARTBLOCK; |
670 | } | 682 | } |
671 | 683 | ||
672 | static long __sched nanosleep_restart_mono(struct restart_block *restart) | ||
673 | { | ||
674 | return nanosleep_restart(restart, CLOCK_MONOTONIC); | ||
675 | } | ||
676 | |||
677 | static long __sched nanosleep_restart_real(struct restart_block *restart) | ||
678 | { | ||
679 | return nanosleep_restart(restart, CLOCK_REALTIME); | ||
680 | } | ||
681 | |||
682 | long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | 684 | long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, |
683 | const enum hrtimer_mode mode, const clockid_t clockid) | 685 | const enum hrtimer_mode mode, const clockid_t clockid) |
684 | { | 686 | { |
@@ -687,7 +689,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | |||
687 | struct timespec tu; | 689 | struct timespec tu; |
688 | ktime_t rem; | 690 | ktime_t rem; |
689 | 691 | ||
690 | hrtimer_init(&timer, clockid); | 692 | hrtimer_init(&timer, clockid, mode); |
691 | 693 | ||
692 | timer.expires = timespec_to_ktime(*rqtp); | 694 | timer.expires = timespec_to_ktime(*rqtp); |
693 | 695 | ||
@@ -695,7 +697,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | |||
695 | if (rem.tv64 <= 0) | 697 | if (rem.tv64 <= 0) |
696 | return 0; | 698 | return 0; |
697 | 699 | ||
698 | /* Absolute timers do not update the rmtp value: */ | 700 | /* Absolute timers do not update the rmtp value and restart: */ |
699 | if (mode == HRTIMER_ABS) | 701 | if (mode == HRTIMER_ABS) |
700 | return -ERESTARTNOHAND; | 702 | return -ERESTARTNOHAND; |
701 | 703 | ||
@@ -705,11 +707,11 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | |||
705 | return -EFAULT; | 707 | return -EFAULT; |
706 | 708 | ||
707 | restart = ¤t_thread_info()->restart_block; | 709 | restart = ¤t_thread_info()->restart_block; |
708 | restart->fn = (clockid == CLOCK_MONOTONIC) ? | 710 | restart->fn = nanosleep_restart; |
709 | nanosleep_restart_mono : nanosleep_restart_real; | ||
710 | restart->arg0 = timer.expires.tv64 & 0xFFFFFFFF; | 711 | restart->arg0 = timer.expires.tv64 & 0xFFFFFFFF; |
711 | restart->arg1 = timer.expires.tv64 >> 32; | 712 | restart->arg1 = timer.expires.tv64 >> 32; |
712 | restart->arg2 = (unsigned long) rmtp; | 713 | restart->arg2 = (unsigned long) rmtp; |
714 | restart->arg3 = (unsigned long) timer.base->index; | ||
713 | 715 | ||
714 | return -ERESTART_RESTARTBLOCK; | 716 | return -ERESTART_RESTARTBLOCK; |
715 | } | 717 | } |
@@ -736,10 +738,8 @@ static void __devinit init_hrtimers_cpu(int cpu) | |||
736 | struct hrtimer_base *base = per_cpu(hrtimer_bases, cpu); | 738 | struct hrtimer_base *base = per_cpu(hrtimer_bases, cpu); |
737 | int i; | 739 | int i; |
738 | 740 | ||
739 | for (i = 0; i < MAX_HRTIMER_BASES; i++) { | 741 | for (i = 0; i < MAX_HRTIMER_BASES; i++, base++) |
740 | spin_lock_init(&base->lock); | 742 | spin_lock_init(&base->lock); |
741 | base++; | ||
742 | } | ||
743 | } | 743 | } |
744 | 744 | ||
745 | #ifdef CONFIG_HOTPLUG_CPU | 745 | #ifdef CONFIG_HOTPLUG_CPU |