diff options
author | George Anzinger <george@wildturkeyranch.net> | 2006-02-01 06:05:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-01 11:53:13 -0500 |
commit | 7978672c4d9a1e6a6081de3a9d9ba5e5b24904a0 (patch) | |
tree | a7deb3a6e339e691078c770d4b9cbc05d99a2243 | |
parent | ff60a5dc4fa584d47022d2533bc5c53b80096fb5 (diff) |
[PATCH] hrtimers: cleanups and simplifications
Clean up the interface to hrtimers by changing the init code to pass the mode
as well as the clock. This allow the init code to select the correct base and
eliminates extra timer re-init code in posix-timers. We also simplify the
restart interface nanosleep use.
Signed-off-by: George Anzinger <george@mvista.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | include/linux/hrtimer.h | 5 | ||||
-rw-r--r-- | kernel/fork.c | 2 | ||||
-rw-r--r-- | kernel/hrtimer.c | 59 | ||||
-rw-r--r-- | kernel/posix-timers.c | 37 |
4 files changed, 36 insertions, 67 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index c657f3d4924a..6361544bb6ae 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
@@ -101,9 +101,8 @@ struct hrtimer_base { | |||
101 | /* Exported timer functions: */ | 101 | /* Exported timer functions: */ |
102 | 102 | ||
103 | /* Initialize timers: */ | 103 | /* Initialize timers: */ |
104 | extern void hrtimer_init(struct hrtimer *timer, const clockid_t which_clock); | 104 | extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock, |
105 | extern void hrtimer_rebase(struct hrtimer *timer, const clockid_t which_clock); | 105 | enum hrtimer_mode mode); |
106 | |||
107 | 106 | ||
108 | /* Basic timer operations: */ | 107 | /* Basic timer operations: */ |
109 | extern int hrtimer_start(struct hrtimer *timer, ktime_t tim, | 108 | extern int hrtimer_start(struct hrtimer *timer, ktime_t tim, |
diff --git a/kernel/fork.c b/kernel/fork.c index 4ae8cfc1c89c..7f0ab5ee948c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -802,7 +802,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts | |||
802 | init_sigpending(&sig->shared_pending); | 802 | init_sigpending(&sig->shared_pending); |
803 | INIT_LIST_HEAD(&sig->posix_timers); | 803 | INIT_LIST_HEAD(&sig->posix_timers); |
804 | 804 | ||
805 | hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC); | 805 | hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_REL); |
806 | sig->it_real_incr.tv64 = 0; | 806 | sig->it_real_incr.tv64 = 0; |
807 | sig->real_timer.function = it_real_fn; | 807 | sig->real_timer.function = it_real_fn; |
808 | sig->real_timer.data = tsk; | 808 | sig->real_timer.data = tsk; |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index f580dd9db286..efff9496b2fa 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -66,6 +66,12 @@ EXPORT_SYMBOL_GPL(ktime_get_real); | |||
66 | 66 | ||
67 | /* | 67 | /* |
68 | * The timer bases: | 68 | * The timer bases: |
69 | * | ||
70 | * Note: If we want to add new timer bases, we have to skip the two | ||
71 | * clock ids captured by the cpu-timers. We do this by holding empty | ||
72 | * entries rather than doing math adjustment of the clock ids. | ||
73 | * This ensures that we capture erroneous accesses to these clock ids | ||
74 | * rather than moving them into the range of valid clock id's. | ||
69 | */ | 75 | */ |
70 | 76 | ||
71 | #define MAX_HRTIMER_BASES 2 | 77 | #define MAX_HRTIMER_BASES 2 |
@@ -483,29 +489,25 @@ ktime_t hrtimer_get_remaining(const struct hrtimer *timer) | |||
483 | } | 489 | } |
484 | 490 | ||
485 | /** | 491 | /** |
486 | * hrtimer_rebase - rebase an initialized hrtimer to a different base | 492 | * hrtimer_init - initialize a timer to the given clock |
487 | * | 493 | * |
488 | * @timer: the timer to be rebased | 494 | * @timer: the timer to be initialized |
489 | * @clock_id: the clock to be used | 495 | * @clock_id: the clock to be used |
496 | * @mode: timer mode abs/rel | ||
490 | */ | 497 | */ |
491 | void hrtimer_rebase(struct hrtimer *timer, const clockid_t clock_id) | 498 | void hrtimer_init(struct hrtimer *timer, clockid_t clock_id, |
499 | enum hrtimer_mode mode) | ||
492 | { | 500 | { |
493 | struct hrtimer_base *bases; | 501 | struct hrtimer_base *bases; |
494 | 502 | ||
503 | memset(timer, 0, sizeof(struct hrtimer)); | ||
504 | |||
495 | bases = per_cpu(hrtimer_bases, raw_smp_processor_id()); | 505 | bases = per_cpu(hrtimer_bases, raw_smp_processor_id()); |
496 | timer->base = &bases[clock_id]; | ||
497 | } | ||
498 | 506 | ||
499 | /** | 507 | if (clock_id == CLOCK_REALTIME && mode != HRTIMER_ABS) |
500 | * hrtimer_init - initialize a timer to the given clock | 508 | clock_id = CLOCK_MONOTONIC; |
501 | * | 509 | |
502 | * @timer: the timer to be initialized | 510 | 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 | } | 511 | } |
510 | 512 | ||
511 | /** | 513 | /** |
@@ -643,8 +645,7 @@ schedule_hrtimer_interruptible(struct hrtimer *timer, | |||
643 | return schedule_hrtimer(timer, mode); | 645 | return schedule_hrtimer(timer, mode); |
644 | } | 646 | } |
645 | 647 | ||
646 | static long __sched | 648 | static long __sched nanosleep_restart(struct restart_block *restart) |
647 | nanosleep_restart(struct restart_block *restart, clockid_t clockid) | ||
648 | { | 649 | { |
649 | struct timespec __user *rmtp; | 650 | struct timespec __user *rmtp; |
650 | struct timespec tu; | 651 | struct timespec tu; |
@@ -654,7 +655,7 @@ nanosleep_restart(struct restart_block *restart, clockid_t clockid) | |||
654 | 655 | ||
655 | restart->fn = do_no_restart_syscall; | 656 | restart->fn = do_no_restart_syscall; |
656 | 657 | ||
657 | hrtimer_init(&timer, clockid); | 658 | hrtimer_init(&timer, (clockid_t) restart->arg3, HRTIMER_ABS); |
658 | 659 | ||
659 | timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0; | 660 | timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0; |
660 | 661 | ||
@@ -674,16 +675,6 @@ nanosleep_restart(struct restart_block *restart, clockid_t clockid) | |||
674 | return -ERESTART_RESTARTBLOCK; | 675 | return -ERESTART_RESTARTBLOCK; |
675 | } | 676 | } |
676 | 677 | ||
677 | static long __sched nanosleep_restart_mono(struct restart_block *restart) | ||
678 | { | ||
679 | return nanosleep_restart(restart, CLOCK_MONOTONIC); | ||
680 | } | ||
681 | |||
682 | static long __sched nanosleep_restart_real(struct restart_block *restart) | ||
683 | { | ||
684 | return nanosleep_restart(restart, CLOCK_REALTIME); | ||
685 | } | ||
686 | |||
687 | long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | 678 | long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, |
688 | const enum hrtimer_mode mode, const clockid_t clockid) | 679 | const enum hrtimer_mode mode, const clockid_t clockid) |
689 | { | 680 | { |
@@ -692,7 +683,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | |||
692 | struct timespec tu; | 683 | struct timespec tu; |
693 | ktime_t rem; | 684 | ktime_t rem; |
694 | 685 | ||
695 | hrtimer_init(&timer, clockid); | 686 | hrtimer_init(&timer, clockid, mode); |
696 | 687 | ||
697 | timer.expires = timespec_to_ktime(*rqtp); | 688 | timer.expires = timespec_to_ktime(*rqtp); |
698 | 689 | ||
@@ -700,7 +691,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | |||
700 | if (rem.tv64 <= 0) | 691 | if (rem.tv64 <= 0) |
701 | return 0; | 692 | return 0; |
702 | 693 | ||
703 | /* Absolute timers do not update the rmtp value: */ | 694 | /* Absolute timers do not update the rmtp value and restart: */ |
704 | if (mode == HRTIMER_ABS) | 695 | if (mode == HRTIMER_ABS) |
705 | return -ERESTARTNOHAND; | 696 | return -ERESTARTNOHAND; |
706 | 697 | ||
@@ -710,11 +701,11 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | |||
710 | return -EFAULT; | 701 | return -EFAULT; |
711 | 702 | ||
712 | restart = ¤t_thread_info()->restart_block; | 703 | restart = ¤t_thread_info()->restart_block; |
713 | restart->fn = (clockid == CLOCK_MONOTONIC) ? | 704 | restart->fn = nanosleep_restart; |
714 | nanosleep_restart_mono : nanosleep_restart_real; | ||
715 | restart->arg0 = timer.expires.tv64 & 0xFFFFFFFF; | 705 | restart->arg0 = timer.expires.tv64 & 0xFFFFFFFF; |
716 | restart->arg1 = timer.expires.tv64 >> 32; | 706 | restart->arg1 = timer.expires.tv64 >> 32; |
717 | restart->arg2 = (unsigned long) rmtp; | 707 | restart->arg2 = (unsigned long) rmtp; |
708 | restart->arg3 = (unsigned long) timer.base->index; | ||
718 | 709 | ||
719 | return -ERESTART_RESTARTBLOCK; | 710 | return -ERESTART_RESTARTBLOCK; |
720 | } | 711 | } |
@@ -741,10 +732,8 @@ static void __devinit init_hrtimers_cpu(int cpu) | |||
741 | struct hrtimer_base *base = per_cpu(hrtimer_bases, cpu); | 732 | struct hrtimer_base *base = per_cpu(hrtimer_bases, cpu); |
742 | int i; | 733 | int i; |
743 | 734 | ||
744 | for (i = 0; i < MAX_HRTIMER_BASES; i++) { | 735 | for (i = 0; i < MAX_HRTIMER_BASES; i++, base++) |
745 | spin_lock_init(&base->lock); | 736 | spin_lock_init(&base->lock); |
746 | base++; | ||
747 | } | ||
748 | } | 737 | } |
749 | 738 | ||
750 | #ifdef CONFIG_HOTPLUG_CPU | 739 | #ifdef CONFIG_HOTPLUG_CPU |
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 3b606d361b52..28e72fd0029f 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c | |||
@@ -194,9 +194,7 @@ static inline int common_clock_set(const clockid_t which_clock, | |||
194 | 194 | ||
195 | static int common_timer_create(struct k_itimer *new_timer) | 195 | static int common_timer_create(struct k_itimer *new_timer) |
196 | { | 196 | { |
197 | hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock); | 197 | hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock, 0); |
198 | new_timer->it.real.timer.data = new_timer; | ||
199 | new_timer->it.real.timer.function = posix_timer_fn; | ||
200 | return 0; | 198 | return 0; |
201 | } | 199 | } |
202 | 200 | ||
@@ -693,6 +691,7 @@ common_timer_set(struct k_itimer *timr, int flags, | |||
693 | struct itimerspec *new_setting, struct itimerspec *old_setting) | 691 | struct itimerspec *new_setting, struct itimerspec *old_setting) |
694 | { | 692 | { |
695 | struct hrtimer *timer = &timr->it.real.timer; | 693 | struct hrtimer *timer = &timr->it.real.timer; |
694 | enum hrtimer_mode mode; | ||
696 | 695 | ||
697 | if (old_setting) | 696 | if (old_setting) |
698 | common_timer_get(timr, old_setting); | 697 | common_timer_get(timr, old_setting); |
@@ -714,14 +713,10 @@ common_timer_set(struct k_itimer *timr, int flags, | |||
714 | if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec) | 713 | if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec) |
715 | return 0; | 714 | return 0; |
716 | 715 | ||
717 | /* Posix madness. Only absolute CLOCK_REALTIME timers | 716 | mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL; |
718 | * are affected by clock sets. So we must reiniatilize | 717 | hrtimer_init(&timr->it.real.timer, timr->it_clock, mode); |
719 | * the timer. | 718 | timr->it.real.timer.data = timr; |
720 | */ | 719 | timr->it.real.timer.function = posix_timer_fn; |
721 | if (timr->it_clock == CLOCK_REALTIME && (flags & TIMER_ABSTIME)) | ||
722 | hrtimer_rebase(timer, CLOCK_REALTIME); | ||
723 | else | ||
724 | hrtimer_rebase(timer, CLOCK_MONOTONIC); | ||
725 | 720 | ||
726 | timer->expires = timespec_to_ktime(new_setting->it_value); | 721 | timer->expires = timespec_to_ktime(new_setting->it_value); |
727 | 722 | ||
@@ -732,8 +727,7 @@ common_timer_set(struct k_itimer *timr, int flags, | |||
732 | if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) | 727 | if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) |
733 | return 0; | 728 | return 0; |
734 | 729 | ||
735 | hrtimer_start(timer, timer->expires, (flags & TIMER_ABSTIME) ? | 730 | hrtimer_start(timer, timer->expires, mode); |
736 | HRTIMER_ABS : HRTIMER_REL); | ||
737 | return 0; | 731 | return 0; |
738 | } | 732 | } |
739 | 733 | ||
@@ -948,21 +942,8 @@ sys_clock_getres(const clockid_t which_clock, struct timespec __user *tp) | |||
948 | static int common_nsleep(const clockid_t which_clock, int flags, | 942 | static int common_nsleep(const clockid_t which_clock, int flags, |
949 | struct timespec *tsave, struct timespec __user *rmtp) | 943 | struct timespec *tsave, struct timespec __user *rmtp) |
950 | { | 944 | { |
951 | int mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL; | 945 | return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ? |
952 | int clockid = which_clock; | 946 | HRTIMER_ABS : HRTIMER_REL, which_clock); |
953 | |||
954 | switch (which_clock) { | ||
955 | case CLOCK_REALTIME: | ||
956 | /* Posix madness. Only absolute timers on clock realtime | ||
957 | are affected by clock set. */ | ||
958 | if (mode != HRTIMER_ABS) | ||
959 | clockid = CLOCK_MONOTONIC; | ||
960 | case CLOCK_MONOTONIC: | ||
961 | break; | ||
962 | default: | ||
963 | return -EINVAL; | ||
964 | } | ||
965 | return hrtimer_nanosleep(tsave, rmtp, mode, clockid); | ||
966 | } | 947 | } |
967 | 948 | ||
968 | asmlinkage long | 949 | asmlinkage long |