提交 f972be33 编写于 作者: O Oleg Nesterov 提交者: Linus Torvalds

[PATCH] posix-timers: use try_to_del_timer_sync()

sys_timer_settime/sys_timer_delete needs to delete k_itimer->real.timer
synchronously while holding ->it_lock, which is also locked in
posix_timer_fn.

This patch removes timer_active/set_timer_inactive which plays with
timer_list's internals in favour of using try_to_del_timer_sync(), which
was introduced in the previous patch.
Signed-off-by: NOleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: NAndrew Morton <akpm@osdl.org>
Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
上级 fd450b73
...@@ -88,23 +88,6 @@ static kmem_cache_t *posix_timers_cache; ...@@ -88,23 +88,6 @@ static kmem_cache_t *posix_timers_cache;
static struct idr posix_timers_id; static struct idr posix_timers_id;
static DEFINE_SPINLOCK(idr_lock); static DEFINE_SPINLOCK(idr_lock);
/*
* Just because the timer is not in the timer list does NOT mean it is
* inactive. It could be in the "fire" routine getting a new expire time.
*/
#define TIMER_INACTIVE 1
#ifdef CONFIG_SMP
# define timer_active(tmr) \
((tmr)->it.real.timer.entry.prev != (void *)TIMER_INACTIVE)
# define set_timer_inactive(tmr) \
do { \
(tmr)->it.real.timer.entry.prev = (void *)TIMER_INACTIVE; \
} while (0)
#else
# define timer_active(tmr) BARFY // error to use outside of SMP
# define set_timer_inactive(tmr) do { } while (0)
#endif
/* /*
* we assume that the new SIGEV_THREAD_ID shares no bits with the other * we assume that the new SIGEV_THREAD_ID shares no bits with the other
* SIGEV values. Here we put out an error if this assumption fails. * SIGEV values. Here we put out an error if this assumption fails.
...@@ -226,7 +209,6 @@ static inline int common_timer_create(struct k_itimer *new_timer) ...@@ -226,7 +209,6 @@ static inline int common_timer_create(struct k_itimer *new_timer)
init_timer(&new_timer->it.real.timer); init_timer(&new_timer->it.real.timer);
new_timer->it.real.timer.data = (unsigned long) new_timer; new_timer->it.real.timer.data = (unsigned long) new_timer;
new_timer->it.real.timer.function = posix_timer_fn; new_timer->it.real.timer.function = posix_timer_fn;
set_timer_inactive(new_timer);
return 0; return 0;
} }
...@@ -480,7 +462,6 @@ static void posix_timer_fn(unsigned long __data) ...@@ -480,7 +462,6 @@ static void posix_timer_fn(unsigned long __data)
int do_notify = 1; int do_notify = 1;
spin_lock_irqsave(&timr->it_lock, flags); spin_lock_irqsave(&timr->it_lock, flags);
set_timer_inactive(timr);
if (!list_empty(&timr->it.real.abs_timer_entry)) { if (!list_empty(&timr->it.real.abs_timer_entry)) {
spin_lock(&abs_list.lock); spin_lock(&abs_list.lock);
do { do {
...@@ -983,8 +964,8 @@ common_timer_set(struct k_itimer *timr, int flags, ...@@ -983,8 +964,8 @@ common_timer_set(struct k_itimer *timr, int flags,
* careful here. If smp we could be in the "fire" routine which will * careful here. If smp we could be in the "fire" routine which will
* be spinning as we hold the lock. But this is ONLY an SMP issue. * be spinning as we hold the lock. But this is ONLY an SMP issue.
*/ */
if (try_to_del_timer_sync(&timr->it.real.timer) < 0) {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
if (timer_active(timr) && !del_timer(&timr->it.real.timer))
/* /*
* It can only be active if on an other cpu. Since * It can only be active if on an other cpu. Since
* we have cleared the interval stuff above, it should * we have cleared the interval stuff above, it should
...@@ -994,11 +975,9 @@ common_timer_set(struct k_itimer *timr, int flags, ...@@ -994,11 +975,9 @@ common_timer_set(struct k_itimer *timr, int flags,
* a "retry" exit status. * a "retry" exit status.
*/ */
return TIMER_RETRY; return TIMER_RETRY;
set_timer_inactive(timr);
#else
del_timer(&timr->it.real.timer);
#endif #endif
}
remove_from_abslist(timr); remove_from_abslist(timr);
timr->it_requeue_pending = (timr->it_requeue_pending + 2) & timr->it_requeue_pending = (timr->it_requeue_pending + 2) &
...@@ -1083,8 +1062,9 @@ sys_timer_settime(timer_t timer_id, int flags, ...@@ -1083,8 +1062,9 @@ sys_timer_settime(timer_t timer_id, int flags,
static inline int common_timer_del(struct k_itimer *timer) static inline int common_timer_del(struct k_itimer *timer)
{ {
timer->it.real.incr = 0; timer->it.real.incr = 0;
if (try_to_del_timer_sync(&timer->it.real.timer) < 0) {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
if (timer_active(timer) && !del_timer(&timer->it.real.timer))
/* /*
* It can only be active if on an other cpu. Since * It can only be active if on an other cpu. Since
* we have cleared the interval stuff above, it should * we have cleared the interval stuff above, it should
...@@ -1094,9 +1074,9 @@ static inline int common_timer_del(struct k_itimer *timer) ...@@ -1094,9 +1074,9 @@ static inline int common_timer_del(struct k_itimer *timer)
* a "retry" exit status. * a "retry" exit status.
*/ */
return TIMER_RETRY; return TIMER_RETRY;
#else
del_timer(&timer->it.real.timer);
#endif #endif
}
remove_from_abslist(timer); remove_from_abslist(timer);
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册