.. | .. |
---|
463 | 463 | |
---|
464 | 464 | static void k_itimer_rcu_free(struct rcu_head *head) |
---|
465 | 465 | { |
---|
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); |
---|
467 | 467 | |
---|
468 | 468 | kmem_cache_free(posix_timers_cache, tmr); |
---|
469 | 469 | } |
---|
.. | .. |
---|
480 | 480 | } |
---|
481 | 481 | put_pid(tmr->it_pid); |
---|
482 | 482 | sigqueue_free(tmr->sigq); |
---|
483 | | - call_rcu(&tmr->it.rcu, k_itimer_rcu_free); |
---|
| 483 | + call_rcu(&tmr->rcu, k_itimer_rcu_free); |
---|
484 | 484 | } |
---|
485 | 485 | |
---|
486 | 486 | static int common_timer_create(struct k_itimer *new_timer) |
---|
.. | .. |
---|
826 | 826 | return hrtimer_try_to_cancel(&timr->it.real.timer); |
---|
827 | 827 | } |
---|
828 | 828 | |
---|
| 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 | + |
---|
829 | 840 | /* Set a POSIX.1b interval timer. */ |
---|
830 | 841 | int common_timer_set(struct k_itimer *timr, int flags, |
---|
831 | 842 | struct itimerspec64 *new_setting, |
---|
.. | .. |
---|
891 | 902 | else |
---|
892 | 903 | error = kc->timer_set(timr, flags, new_spec64, old_spec64); |
---|
893 | 904 | |
---|
894 | | - unlock_timer(timr, flag); |
---|
895 | 905 | if (error == TIMER_RETRY) { |
---|
| 906 | + rcu_read_lock(); |
---|
| 907 | + unlock_timer(timr, flag); |
---|
| 908 | + timer_wait_for_callback(kc, timr); |
---|
| 909 | + rcu_read_unlock(); |
---|
896 | 910 | old_spec64 = NULL; // We already got the old time... |
---|
897 | 911 | goto retry; |
---|
898 | 912 | } |
---|
| 913 | + unlock_timer(timr, flag); |
---|
899 | 914 | |
---|
900 | 915 | return error; |
---|
901 | 916 | } |
---|
.. | .. |
---|
957 | 972 | return 0; |
---|
958 | 973 | } |
---|
959 | 974 | |
---|
960 | | -static inline int timer_delete_hook(struct k_itimer *timer) |
---|
| 975 | +static int timer_delete_hook(struct k_itimer *timer) |
---|
961 | 976 | { |
---|
962 | 977 | const struct k_clock *kc = timer->kclock; |
---|
| 978 | + int ret; |
---|
963 | 979 | |
---|
964 | 980 | if (WARN_ON_ONCE(!kc || !kc->timer_del)) |
---|
965 | 981 | 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; |
---|
967 | 990 | } |
---|
968 | 991 | |
---|
969 | 992 | /* Delete a POSIX.1b interval timer. */ |
---|
.. | .. |
---|
977 | 1000 | if (!timer) |
---|
978 | 1001 | return -EINVAL; |
---|
979 | 1002 | |
---|
980 | | - if (timer_delete_hook(timer) == TIMER_RETRY) { |
---|
981 | | - unlock_timer(timer, flags); |
---|
| 1003 | + if (timer_delete_hook(timer) == TIMER_RETRY) |
---|
982 | 1004 | goto retry_delete; |
---|
983 | | - } |
---|
984 | 1005 | |
---|
985 | 1006 | spin_lock(¤t->sighand->siglock); |
---|
986 | 1007 | list_del(&timer->list); |
---|
.. | .. |
---|
1006 | 1027 | retry_delete: |
---|
1007 | 1028 | spin_lock_irqsave(&timer->it_lock, flags); |
---|
1008 | 1029 | |
---|
1009 | | - if (timer_delete_hook(timer) == TIMER_RETRY) { |
---|
1010 | | - unlock_timer(timer, flags); |
---|
| 1030 | + if (timer_delete_hook(timer) == TIMER_RETRY) |
---|
1011 | 1031 | goto retry_delete; |
---|
1012 | | - } |
---|
| 1032 | + |
---|
1013 | 1033 | list_del(&timer->list); |
---|
1014 | 1034 | /* |
---|
1015 | 1035 | * This keeps any tasks waiting on the spin lock from thinking |
---|