diff options
-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 |