aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/posix-timers.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/posix-timers.c')
-rw-r--r--kernel/time/posix-timers.c61
1 files changed, 50 insertions, 11 deletions
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index d7f2d91acdac..0ec5b7a1d769 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -442,7 +442,7 @@ static struct k_itimer * alloc_posix_timer(void)
442 442
443static void k_itimer_rcu_free(struct rcu_head *head) 443static void k_itimer_rcu_free(struct rcu_head *head)
444{ 444{
445 struct k_itimer *tmr = container_of(head, struct k_itimer, it.rcu); 445 struct k_itimer *tmr = container_of(head, struct k_itimer, rcu);
446 446
447 kmem_cache_free(posix_timers_cache, tmr); 447 kmem_cache_free(posix_timers_cache, tmr);
448} 448}
@@ -459,7 +459,7 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set)
459 } 459 }
460 put_pid(tmr->it_pid); 460 put_pid(tmr->it_pid);
461 sigqueue_free(tmr->sigq); 461 sigqueue_free(tmr->sigq);
462 call_rcu(&tmr->it.rcu, k_itimer_rcu_free); 462 call_rcu(&tmr->rcu, k_itimer_rcu_free);
463} 463}
464 464
465static int common_timer_create(struct k_itimer *new_timer) 465static int common_timer_create(struct k_itimer *new_timer)
@@ -805,6 +805,35 @@ static int common_hrtimer_try_to_cancel(struct k_itimer *timr)
805 return hrtimer_try_to_cancel(&timr->it.real.timer); 805 return hrtimer_try_to_cancel(&timr->it.real.timer);
806} 806}
807 807
808static void common_timer_wait_running(struct k_itimer *timer)
809{
810 hrtimer_cancel_wait_running(&timer->it.real.timer);
811}
812
813/*
814 * On PREEMPT_RT this prevent priority inversion against softirq kthread in
815 * case it gets preempted while executing a timer callback. See comments in
816 * hrtimer_cancel_wait_running. For PREEMPT_RT=n this just results in a
817 * cpu_relax().
818 */
819static struct k_itimer *timer_wait_running(struct k_itimer *timer,
820 unsigned long *flags)
821{
822 const struct k_clock *kc = READ_ONCE(timer->kclock);
823 timer_t timer_id = READ_ONCE(timer->it_id);
824
825 /* Prevent kfree(timer) after dropping the lock */
826 rcu_read_lock();
827 unlock_timer(timer, *flags);
828
829 if (!WARN_ON_ONCE(!kc->timer_wait_running))
830 kc->timer_wait_running(timer);
831
832 rcu_read_unlock();
833 /* Relock the timer. It might be not longer hashed. */
834 return lock_timer(timer_id, flags);
835}
836
808/* Set a POSIX.1b interval timer. */ 837/* Set a POSIX.1b interval timer. */
809int common_timer_set(struct k_itimer *timr, int flags, 838int common_timer_set(struct k_itimer *timr, int flags,
810 struct itimerspec64 *new_setting, 839 struct itimerspec64 *new_setting,
@@ -844,13 +873,13 @@ int common_timer_set(struct k_itimer *timr, int flags,
844 return 0; 873 return 0;
845} 874}
846 875
847static int do_timer_settime(timer_t timer_id, int flags, 876static int do_timer_settime(timer_t timer_id, int tmr_flags,
848 struct itimerspec64 *new_spec64, 877 struct itimerspec64 *new_spec64,
849 struct itimerspec64 *old_spec64) 878 struct itimerspec64 *old_spec64)
850{ 879{
851 const struct k_clock *kc; 880 const struct k_clock *kc;
852 struct k_itimer *timr; 881 struct k_itimer *timr;
853 unsigned long flag; 882 unsigned long flags;
854 int error = 0; 883 int error = 0;
855 884
856 if (!timespec64_valid(&new_spec64->it_interval) || 885 if (!timespec64_valid(&new_spec64->it_interval) ||
@@ -859,8 +888,9 @@ static int do_timer_settime(timer_t timer_id, int flags,
859 888
860 if (old_spec64) 889 if (old_spec64)
861 memset(old_spec64, 0, sizeof(*old_spec64)); 890 memset(old_spec64, 0, sizeof(*old_spec64));
891
892 timr = lock_timer(timer_id, &flags);
862retry: 893retry:
863 timr = lock_timer(timer_id, &flag);
864 if (!timr) 894 if (!timr)
865 return -EINVAL; 895 return -EINVAL;
866 896
@@ -868,13 +898,16 @@ retry:
868 if (WARN_ON_ONCE(!kc || !kc->timer_set)) 898 if (WARN_ON_ONCE(!kc || !kc->timer_set))
869 error = -EINVAL; 899 error = -EINVAL;
870 else 900 else
871 error = kc->timer_set(timr, flags, new_spec64, old_spec64); 901 error = kc->timer_set(timr, tmr_flags, new_spec64, old_spec64);
872 902
873 unlock_timer(timr, flag);
874 if (error == TIMER_RETRY) { 903 if (error == TIMER_RETRY) {
875 old_spec64 = NULL; // We already got the old time... 904 // We already got the old time...
905 old_spec64 = NULL;
906 /* Unlocks and relocks the timer if it still exists */
907 timr = timer_wait_running(timr, &flags);
876 goto retry; 908 goto retry;
877 } 909 }
910 unlock_timer(timr, flags);
878 911
879 return error; 912 return error;
880} 913}
@@ -951,13 +984,15 @@ SYSCALL_DEFINE1(timer_delete, timer_t, timer_id)
951 struct k_itimer *timer; 984 struct k_itimer *timer;
952 unsigned long flags; 985 unsigned long flags;
953 986
954retry_delete:
955 timer = lock_timer(timer_id, &flags); 987 timer = lock_timer(timer_id, &flags);
988
989retry_delete:
956 if (!timer) 990 if (!timer)
957 return -EINVAL; 991 return -EINVAL;
958 992
959 if (timer_delete_hook(timer) == TIMER_RETRY) { 993 if (unlikely(timer_delete_hook(timer) == TIMER_RETRY)) {
960 unlock_timer(timer, flags); 994 /* Unlocks and relocks the timer if it still exists */
995 timer = timer_wait_running(timer, &flags);
961 goto retry_delete; 996 goto retry_delete;
962 } 997 }
963 998
@@ -1238,6 +1273,7 @@ static const struct k_clock clock_realtime = {
1238 .timer_forward = common_hrtimer_forward, 1273 .timer_forward = common_hrtimer_forward,
1239 .timer_remaining = common_hrtimer_remaining, 1274 .timer_remaining = common_hrtimer_remaining,
1240 .timer_try_to_cancel = common_hrtimer_try_to_cancel, 1275 .timer_try_to_cancel = common_hrtimer_try_to_cancel,
1276 .timer_wait_running = common_timer_wait_running,
1241 .timer_arm = common_hrtimer_arm, 1277 .timer_arm = common_hrtimer_arm,
1242}; 1278};
1243 1279
@@ -1253,6 +1289,7 @@ static const struct k_clock clock_monotonic = {
1253 .timer_forward = common_hrtimer_forward, 1289 .timer_forward = common_hrtimer_forward,
1254 .timer_remaining = common_hrtimer_remaining, 1290 .timer_remaining = common_hrtimer_remaining,
1255 .timer_try_to_cancel = common_hrtimer_try_to_cancel, 1291 .timer_try_to_cancel = common_hrtimer_try_to_cancel,
1292 .timer_wait_running = common_timer_wait_running,
1256 .timer_arm = common_hrtimer_arm, 1293 .timer_arm = common_hrtimer_arm,
1257}; 1294};
1258 1295
@@ -1283,6 +1320,7 @@ static const struct k_clock clock_tai = {
1283 .timer_forward = common_hrtimer_forward, 1320 .timer_forward = common_hrtimer_forward,
1284 .timer_remaining = common_hrtimer_remaining, 1321 .timer_remaining = common_hrtimer_remaining,
1285 .timer_try_to_cancel = common_hrtimer_try_to_cancel, 1322 .timer_try_to_cancel = common_hrtimer_try_to_cancel,
1323 .timer_wait_running = common_timer_wait_running,
1286 .timer_arm = common_hrtimer_arm, 1324 .timer_arm = common_hrtimer_arm,
1287}; 1325};
1288 1326
@@ -1298,6 +1336,7 @@ static const struct k_clock clock_boottime = {
1298 .timer_forward = common_hrtimer_forward, 1336 .timer_forward = common_hrtimer_forward,
1299 .timer_remaining = common_hrtimer_remaining, 1337 .timer_remaining = common_hrtimer_remaining,
1300 .timer_try_to_cancel = common_hrtimer_try_to_cancel, 1338 .timer_try_to_cancel = common_hrtimer_try_to_cancel,
1339 .timer_wait_running = common_timer_wait_running,
1301 .timer_arm = common_hrtimer_arm, 1340 .timer_arm = common_hrtimer_arm,
1302}; 1341};
1303 1342