diff options
-rw-r--r-- | kernel/time/posix-timers.c | 181 |
1 files changed, 100 insertions, 81 deletions
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 0332f7a60fd6..8acc9ee2c2d6 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c | |||
@@ -744,25 +744,49 @@ SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id) | |||
744 | return overrun; | 744 | return overrun; |
745 | } | 745 | } |
746 | 746 | ||
747 | static void common_hrtimer_arm(struct k_itimer *timr, ktime_t expires, | ||
748 | bool absolute, bool sigev_none) | ||
749 | { | ||
750 | struct hrtimer *timer = &timr->it.real.timer; | ||
751 | enum hrtimer_mode mode; | ||
752 | |||
753 | mode = absolute ? HRTIMER_MODE_ABS : HRTIMER_MODE_REL; | ||
754 | hrtimer_init(&timr->it.real.timer, timr->it_clock, mode); | ||
755 | timr->it.real.timer.function = posix_timer_fn; | ||
756 | |||
757 | if (!absolute) | ||
758 | expires = ktime_add_safe(expires, timer->base->get_time()); | ||
759 | hrtimer_set_expires(timer, expires); | ||
760 | |||
761 | if (!sigev_none) | ||
762 | hrtimer_start_expires(timer, HRTIMER_MODE_ABS); | ||
763 | } | ||
764 | |||
765 | static int common_hrtimer_try_to_cancel(struct k_itimer *timr) | ||
766 | { | ||
767 | return hrtimer_try_to_cancel(&timr->it.real.timer); | ||
768 | } | ||
769 | |||
747 | /* Set a POSIX.1b interval timer. */ | 770 | /* Set a POSIX.1b interval timer. */ |
748 | /* timr->it_lock is taken. */ | ||
749 | static int | 771 | static int |
750 | common_timer_set(struct k_itimer *timr, int flags, | 772 | common_timer_set(struct k_itimer *timr, int flags, |
751 | struct itimerspec64 *new_setting, struct itimerspec64 *old_setting) | 773 | struct itimerspec64 *new_setting, |
774 | struct itimerspec64 *old_setting) | ||
752 | { | 775 | { |
753 | struct hrtimer *timer = &timr->it.real.timer; | 776 | const struct k_clock *kc = timr->kclock; |
754 | enum hrtimer_mode mode; | 777 | bool sigev_none; |
778 | ktime_t expires; | ||
755 | 779 | ||
756 | if (old_setting) | 780 | if (old_setting) |
757 | common_timer_get(timr, old_setting); | 781 | common_timer_get(timr, old_setting); |
758 | 782 | ||
759 | /* disable the timer */ | 783 | /* Prevent rearming by clearing the interval */ |
760 | timr->it_interval = 0; | 784 | timr->it_interval = 0; |
761 | /* | 785 | /* |
762 | * careful here. If smp we could be in the "fire" routine which will | 786 | * Careful here. On SMP systems the timer expiry function could be |
763 | * be spinning as we hold the lock. But this is ONLY an SMP issue. | 787 | * active and spinning on timr->it_lock. |
764 | */ | 788 | */ |
765 | if (hrtimer_try_to_cancel(timer) < 0) | 789 | if (kc->timer_try_to_cancel(timr) < 0) |
766 | return TIMER_RETRY; | 790 | return TIMER_RETRY; |
767 | 791 | ||
768 | timr->it_active = 0; | 792 | timr->it_active = 0; |
@@ -770,30 +794,16 @@ common_timer_set(struct k_itimer *timr, int flags, | |||
770 | ~REQUEUE_PENDING; | 794 | ~REQUEUE_PENDING; |
771 | timr->it_overrun_last = 0; | 795 | timr->it_overrun_last = 0; |
772 | 796 | ||
773 | /* switch off the timer when it_value is zero */ | 797 | /* Switch off the timer when it_value is zero */ |
774 | if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec) | 798 | if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec) |
775 | return 0; | 799 | return 0; |
776 | 800 | ||
777 | mode = flags & TIMER_ABSTIME ? HRTIMER_MODE_ABS : HRTIMER_MODE_REL; | ||
778 | hrtimer_init(&timr->it.real.timer, timr->it_clock, mode); | ||
779 | timr->it.real.timer.function = posix_timer_fn; | ||
780 | |||
781 | hrtimer_set_expires(timer, timespec64_to_ktime(new_setting->it_value)); | ||
782 | |||
783 | /* Convert interval */ | ||
784 | timr->it_interval = timespec64_to_ktime(new_setting->it_interval); | 801 | timr->it_interval = timespec64_to_ktime(new_setting->it_interval); |
802 | expires = timespec64_to_ktime(new_setting->it_value); | ||
803 | sigev_none = (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE; | ||
785 | 804 | ||
786 | /* SIGEV_NONE timers are not queued ! See common_timer_get */ | 805 | kc->timer_arm(timr, expires, flags & TIMER_ABSTIME, sigev_none); |
787 | if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) { | 806 | timr->it_active = !sigev_none; |
788 | /* Setup correct expiry time for relative timers */ | ||
789 | if (mode == HRTIMER_MODE_REL) { | ||
790 | hrtimer_add_expires(timer, timer->base->get_time()); | ||
791 | } | ||
792 | return 0; | ||
793 | } | ||
794 | |||
795 | timr->it_active = 1; | ||
796 | hrtimer_start_expires(timer, mode); | ||
797 | return 0; | 807 | return 0; |
798 | } | 808 | } |
799 | 809 | ||
@@ -847,9 +857,10 @@ retry: | |||
847 | 857 | ||
848 | static int common_timer_del(struct k_itimer *timer) | 858 | static int common_timer_del(struct k_itimer *timer) |
849 | { | 859 | { |
850 | timer->it_interval = 0; | 860 | const struct k_clock *kc = timer->kclock; |
851 | 861 | ||
852 | if (hrtimer_try_to_cancel(&timer->it.real.timer) < 0) | 862 | timer->it_interval = 0; |
863 | if (kc->timer_try_to_cancel(timer) < 0) | ||
853 | return TIMER_RETRY; | 864 | return TIMER_RETRY; |
854 | timer->it_active = 0; | 865 | timer->it_active = 0; |
855 | return 0; | 866 | return 0; |
@@ -1063,76 +1074,84 @@ long clock_nanosleep_restart(struct restart_block *restart_block) | |||
1063 | } | 1074 | } |
1064 | 1075 | ||
1065 | static const struct k_clock clock_realtime = { | 1076 | static const struct k_clock clock_realtime = { |
1066 | .clock_getres = posix_get_hrtimer_res, | 1077 | .clock_getres = posix_get_hrtimer_res, |
1067 | .clock_get = posix_clock_realtime_get, | 1078 | .clock_get = posix_clock_realtime_get, |
1068 | .clock_set = posix_clock_realtime_set, | 1079 | .clock_set = posix_clock_realtime_set, |
1069 | .clock_adj = posix_clock_realtime_adj, | 1080 | .clock_adj = posix_clock_realtime_adj, |
1070 | .nsleep = common_nsleep, | 1081 | .nsleep = common_nsleep, |
1071 | .nsleep_restart = hrtimer_nanosleep_restart, | 1082 | .nsleep_restart = hrtimer_nanosleep_restart, |
1072 | .timer_create = common_timer_create, | 1083 | .timer_create = common_timer_create, |
1073 | .timer_set = common_timer_set, | 1084 | .timer_set = common_timer_set, |
1074 | .timer_get = common_timer_get, | 1085 | .timer_get = common_timer_get, |
1075 | .timer_del = common_timer_del, | 1086 | .timer_del = common_timer_del, |
1076 | .timer_rearm = common_hrtimer_rearm, | 1087 | .timer_rearm = common_hrtimer_rearm, |
1077 | .timer_forward = common_hrtimer_forward, | 1088 | .timer_forward = common_hrtimer_forward, |
1078 | .timer_remaining= common_hrtimer_remaining, | 1089 | .timer_remaining = common_hrtimer_remaining, |
1090 | .timer_try_to_cancel = common_hrtimer_try_to_cancel, | ||
1091 | .timer_arm = common_hrtimer_arm, | ||
1079 | }; | 1092 | }; |
1080 | 1093 | ||
1081 | static const struct k_clock clock_monotonic = { | 1094 | static const struct k_clock clock_monotonic = { |
1082 | .clock_getres = posix_get_hrtimer_res, | 1095 | .clock_getres = posix_get_hrtimer_res, |
1083 | .clock_get = posix_ktime_get_ts, | 1096 | .clock_get = posix_ktime_get_ts, |
1084 | .nsleep = common_nsleep, | 1097 | .nsleep = common_nsleep, |
1085 | .nsleep_restart = hrtimer_nanosleep_restart, | 1098 | .nsleep_restart = hrtimer_nanosleep_restart, |
1086 | .timer_create = common_timer_create, | 1099 | .timer_create = common_timer_create, |
1087 | .timer_set = common_timer_set, | 1100 | .timer_set = common_timer_set, |
1088 | .timer_get = common_timer_get, | 1101 | .timer_get = common_timer_get, |
1089 | .timer_del = common_timer_del, | 1102 | .timer_del = common_timer_del, |
1090 | .timer_rearm = common_hrtimer_rearm, | 1103 | .timer_rearm = common_hrtimer_rearm, |
1091 | .timer_forward = common_hrtimer_forward, | 1104 | .timer_forward = common_hrtimer_forward, |
1092 | .timer_remaining= common_hrtimer_remaining, | 1105 | .timer_remaining = common_hrtimer_remaining, |
1106 | .timer_try_to_cancel = common_hrtimer_try_to_cancel, | ||
1107 | .timer_arm = common_hrtimer_arm, | ||
1093 | }; | 1108 | }; |
1094 | 1109 | ||
1095 | static const struct k_clock clock_monotonic_raw = { | 1110 | static const struct k_clock clock_monotonic_raw = { |
1096 | .clock_getres = posix_get_hrtimer_res, | 1111 | .clock_getres = posix_get_hrtimer_res, |
1097 | .clock_get = posix_get_monotonic_raw, | 1112 | .clock_get = posix_get_monotonic_raw, |
1098 | }; | 1113 | }; |
1099 | 1114 | ||
1100 | static const struct k_clock clock_realtime_coarse = { | 1115 | static const struct k_clock clock_realtime_coarse = { |
1101 | .clock_getres = posix_get_coarse_res, | 1116 | .clock_getres = posix_get_coarse_res, |
1102 | .clock_get = posix_get_realtime_coarse, | 1117 | .clock_get = posix_get_realtime_coarse, |
1103 | }; | 1118 | }; |
1104 | 1119 | ||
1105 | static const struct k_clock clock_monotonic_coarse = { | 1120 | static const struct k_clock clock_monotonic_coarse = { |
1106 | .clock_getres = posix_get_coarse_res, | 1121 | .clock_getres = posix_get_coarse_res, |
1107 | .clock_get = posix_get_monotonic_coarse, | 1122 | .clock_get = posix_get_monotonic_coarse, |
1108 | }; | 1123 | }; |
1109 | 1124 | ||
1110 | static const struct k_clock clock_tai = { | 1125 | static const struct k_clock clock_tai = { |
1111 | .clock_getres = posix_get_hrtimer_res, | 1126 | .clock_getres = posix_get_hrtimer_res, |
1112 | .clock_get = posix_get_tai, | 1127 | .clock_get = posix_get_tai, |
1113 | .nsleep = common_nsleep, | 1128 | .nsleep = common_nsleep, |
1114 | .nsleep_restart = hrtimer_nanosleep_restart, | 1129 | .nsleep_restart = hrtimer_nanosleep_restart, |
1115 | .timer_create = common_timer_create, | 1130 | .timer_create = common_timer_create, |
1116 | .timer_set = common_timer_set, | 1131 | .timer_set = common_timer_set, |
1117 | .timer_get = common_timer_get, | 1132 | .timer_get = common_timer_get, |
1118 | .timer_del = common_timer_del, | 1133 | .timer_del = common_timer_del, |
1119 | .timer_rearm = common_hrtimer_rearm, | 1134 | .timer_rearm = common_hrtimer_rearm, |
1120 | .timer_forward = common_hrtimer_forward, | 1135 | .timer_forward = common_hrtimer_forward, |
1121 | .timer_remaining= common_hrtimer_remaining, | 1136 | .timer_remaining = common_hrtimer_remaining, |
1137 | .timer_try_to_cancel = common_hrtimer_try_to_cancel, | ||
1138 | .timer_arm = common_hrtimer_arm, | ||
1122 | }; | 1139 | }; |
1123 | 1140 | ||
1124 | static const struct k_clock clock_boottime = { | 1141 | static const struct k_clock clock_boottime = { |
1125 | .clock_getres = posix_get_hrtimer_res, | 1142 | .clock_getres = posix_get_hrtimer_res, |
1126 | .clock_get = posix_get_boottime, | 1143 | .clock_get = posix_get_boottime, |
1127 | .nsleep = common_nsleep, | 1144 | .nsleep = common_nsleep, |
1128 | .nsleep_restart = hrtimer_nanosleep_restart, | 1145 | .nsleep_restart = hrtimer_nanosleep_restart, |
1129 | .timer_create = common_timer_create, | 1146 | .timer_create = common_timer_create, |
1130 | .timer_set = common_timer_set, | 1147 | .timer_set = common_timer_set, |
1131 | .timer_get = common_timer_get, | 1148 | .timer_get = common_timer_get, |
1132 | .timer_del = common_timer_del, | 1149 | .timer_del = common_timer_del, |
1133 | .timer_rearm = common_hrtimer_rearm, | 1150 | .timer_rearm = common_hrtimer_rearm, |
1134 | .timer_forward = common_hrtimer_forward, | 1151 | .timer_forward = common_hrtimer_forward, |
1135 | .timer_remaining= common_hrtimer_remaining, | 1152 | .timer_remaining = common_hrtimer_remaining, |
1153 | .timer_try_to_cancel = common_hrtimer_try_to_cancel, | ||
1154 | .timer_arm = common_hrtimer_arm, | ||
1136 | }; | 1155 | }; |
1137 | 1156 | ||
1138 | static const struct k_clock * const posix_clocks[] = { | 1157 | static const struct k_clock * const posix_clocks[] = { |