hc
2023-11-22 f743a7adbd6e230d66a6206fa115b59fec2d88eb
kernel/kernel/time/posix-timers.c
....@@ -463,7 +463,7 @@
463463
464464 static void k_itimer_rcu_free(struct rcu_head *head)
465465 {
466
- struct k_itimer *tmr = container_of(head, struct k_itimer, it.rcu);
466
+ struct k_itimer *tmr = container_of(head, struct k_itimer, rcu);
467467
468468 kmem_cache_free(posix_timers_cache, tmr);
469469 }
....@@ -480,7 +480,7 @@
480480 }
481481 put_pid(tmr->it_pid);
482482 sigqueue_free(tmr->sigq);
483
- call_rcu(&tmr->it.rcu, k_itimer_rcu_free);
483
+ call_rcu(&tmr->rcu, k_itimer_rcu_free);
484484 }
485485
486486 static int common_timer_create(struct k_itimer *new_timer)
....@@ -826,6 +826,17 @@
826826 return hrtimer_try_to_cancel(&timr->it.real.timer);
827827 }
828828
829
+static void timer_wait_for_callback(const struct k_clock *kc, struct k_itimer *timer)
830
+{
831
+ if (kc->timer_arm == common_hrtimer_arm)
832
+ hrtimer_grab_expiry_lock(&timer->it.real.timer);
833
+ else if (kc == &alarm_clock)
834
+ hrtimer_grab_expiry_lock(&timer->it.alarm.alarmtimer.timer);
835
+ else
836
+ /* posix-cpu-timers */
837
+ cpu_timers_grab_expiry_lock(timer);
838
+}
839
+
829840 /* Set a POSIX.1b interval timer. */
830841 int common_timer_set(struct k_itimer *timr, int flags,
831842 struct itimerspec64 *new_setting,
....@@ -891,11 +902,15 @@
891902 else
892903 error = kc->timer_set(timr, flags, new_spec64, old_spec64);
893904
894
- unlock_timer(timr, flag);
895905 if (error == TIMER_RETRY) {
906
+ rcu_read_lock();
907
+ unlock_timer(timr, flag);
908
+ timer_wait_for_callback(kc, timr);
909
+ rcu_read_unlock();
896910 old_spec64 = NULL; // We already got the old time...
897911 goto retry;
898912 }
913
+ unlock_timer(timr, flag);
899914
900915 return error;
901916 }
....@@ -957,13 +972,21 @@
957972 return 0;
958973 }
959974
960
-static inline int timer_delete_hook(struct k_itimer *timer)
975
+static int timer_delete_hook(struct k_itimer *timer)
961976 {
962977 const struct k_clock *kc = timer->kclock;
978
+ int ret;
963979
964980 if (WARN_ON_ONCE(!kc || !kc->timer_del))
965981 return -EINVAL;
966
- return kc->timer_del(timer);
982
+ ret = kc->timer_del(timer);
983
+ if (ret == TIMER_RETRY) {
984
+ rcu_read_lock();
985
+ spin_unlock_irq(&timer->it_lock);
986
+ timer_wait_for_callback(kc, timer);
987
+ rcu_read_unlock();
988
+ }
989
+ return ret;
967990 }
968991
969992 /* Delete a POSIX.1b interval timer. */
....@@ -977,10 +1000,8 @@
9771000 if (!timer)
9781001 return -EINVAL;
9791002
980
- if (timer_delete_hook(timer) == TIMER_RETRY) {
981
- unlock_timer(timer, flags);
1003
+ if (timer_delete_hook(timer) == TIMER_RETRY)
9821004 goto retry_delete;
983
- }
9841005
9851006 spin_lock(&current->sighand->siglock);
9861007 list_del(&timer->list);
....@@ -1006,10 +1027,9 @@
10061027 retry_delete:
10071028 spin_lock_irqsave(&timer->it_lock, flags);
10081029
1009
- if (timer_delete_hook(timer) == TIMER_RETRY) {
1010
- unlock_timer(timer, flags);
1030
+ if (timer_delete_hook(timer) == TIMER_RETRY)
10111031 goto retry_delete;
1012
- }
1032
+
10131033 list_del(&timer->list);
10141034 /*
10151035 * This keeps any tasks waiting on the spin lock from thinking