aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/time/posix-timers.c181
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
747static 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
765static 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. */
749static int 771static int
750common_timer_set(struct k_itimer *timr, int flags, 772common_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
848static int common_timer_del(struct k_itimer *timer) 858static 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
1065static const struct k_clock clock_realtime = { 1076static 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
1081static const struct k_clock clock_monotonic = { 1094static 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
1095static const struct k_clock clock_monotonic_raw = { 1110static 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
1100static const struct k_clock clock_realtime_coarse = { 1115static 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
1105static const struct k_clock clock_monotonic_coarse = { 1120static 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
1110static const struct k_clock clock_tai = { 1125static 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
1124static const struct k_clock clock_boottime = { 1141static 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
1138static const struct k_clock * const posix_clocks[] = { 1157static const struct k_clock * const posix_clocks[] = {