diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2005-06-23 03:09:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-23 12:45:17 -0400 |
commit | f972be33ce6a08b5f096ba013c7459a3a82f5f39 (patch) | |
tree | 5d495cdfc82dce1b8017244563f2f5437c395433 | |
parent | fd450b7318b75343fd76b3d95416853e34e72c95 (diff) |
[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: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | kernel/posix-timers.c | 34 |
1 files changed, 7 insertions, 27 deletions
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index cabb63fc9e16..5b7b4736d82b 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c | |||
@@ -89,23 +89,6 @@ static struct idr posix_timers_id; | |||
89 | static DEFINE_SPINLOCK(idr_lock); | 89 | static DEFINE_SPINLOCK(idr_lock); |
90 | 90 | ||
91 | /* | 91 | /* |
92 | * Just because the timer is not in the timer list does NOT mean it is | ||
93 | * inactive. It could be in the "fire" routine getting a new expire time. | ||
94 | */ | ||
95 | #define TIMER_INACTIVE 1 | ||
96 | |||
97 | #ifdef CONFIG_SMP | ||
98 | # define timer_active(tmr) \ | ||
99 | ((tmr)->it.real.timer.entry.prev != (void *)TIMER_INACTIVE) | ||
100 | # define set_timer_inactive(tmr) \ | ||
101 | do { \ | ||
102 | (tmr)->it.real.timer.entry.prev = (void *)TIMER_INACTIVE; \ | ||
103 | } while (0) | ||
104 | #else | ||
105 | # define timer_active(tmr) BARFY // error to use outside of SMP | ||
106 | # define set_timer_inactive(tmr) do { } while (0) | ||
107 | #endif | ||
108 | /* | ||
109 | * we assume that the new SIGEV_THREAD_ID shares no bits with the other | 92 | * we assume that the new SIGEV_THREAD_ID shares no bits with the other |
110 | * SIGEV values. Here we put out an error if this assumption fails. | 93 | * SIGEV values. Here we put out an error if this assumption fails. |
111 | */ | 94 | */ |
@@ -226,7 +209,6 @@ static inline int common_timer_create(struct k_itimer *new_timer) | |||
226 | init_timer(&new_timer->it.real.timer); | 209 | init_timer(&new_timer->it.real.timer); |
227 | new_timer->it.real.timer.data = (unsigned long) new_timer; | 210 | new_timer->it.real.timer.data = (unsigned long) new_timer; |
228 | new_timer->it.real.timer.function = posix_timer_fn; | 211 | new_timer->it.real.timer.function = posix_timer_fn; |
229 | set_timer_inactive(new_timer); | ||
230 | return 0; | 212 | return 0; |
231 | } | 213 | } |
232 | 214 | ||
@@ -480,7 +462,6 @@ static void posix_timer_fn(unsigned long __data) | |||
480 | int do_notify = 1; | 462 | int do_notify = 1; |
481 | 463 | ||
482 | spin_lock_irqsave(&timr->it_lock, flags); | 464 | spin_lock_irqsave(&timr->it_lock, flags); |
483 | set_timer_inactive(timr); | ||
484 | if (!list_empty(&timr->it.real.abs_timer_entry)) { | 465 | if (!list_empty(&timr->it.real.abs_timer_entry)) { |
485 | spin_lock(&abs_list.lock); | 466 | spin_lock(&abs_list.lock); |
486 | do { | 467 | do { |
@@ -983,8 +964,8 @@ common_timer_set(struct k_itimer *timr, int flags, | |||
983 | * careful here. If smp we could be in the "fire" routine which will | 964 | * careful here. If smp we could be in the "fire" routine which will |
984 | * be spinning as we hold the lock. But this is ONLY an SMP issue. | 965 | * be spinning as we hold the lock. But this is ONLY an SMP issue. |
985 | */ | 966 | */ |
967 | if (try_to_del_timer_sync(&timr->it.real.timer) < 0) { | ||
986 | #ifdef CONFIG_SMP | 968 | #ifdef CONFIG_SMP |
987 | if (timer_active(timr) && !del_timer(&timr->it.real.timer)) | ||
988 | /* | 969 | /* |
989 | * It can only be active if on an other cpu. Since | 970 | * It can only be active if on an other cpu. Since |
990 | * we have cleared the interval stuff above, it should | 971 | * we have cleared the interval stuff above, it should |
@@ -994,11 +975,9 @@ common_timer_set(struct k_itimer *timr, int flags, | |||
994 | * a "retry" exit status. | 975 | * a "retry" exit status. |
995 | */ | 976 | */ |
996 | return TIMER_RETRY; | 977 | return TIMER_RETRY; |
997 | |||
998 | set_timer_inactive(timr); | ||
999 | #else | ||
1000 | del_timer(&timr->it.real.timer); | ||
1001 | #endif | 978 | #endif |
979 | } | ||
980 | |||
1002 | remove_from_abslist(timr); | 981 | remove_from_abslist(timr); |
1003 | 982 | ||
1004 | timr->it_requeue_pending = (timr->it_requeue_pending + 2) & | 983 | timr->it_requeue_pending = (timr->it_requeue_pending + 2) & |
@@ -1083,8 +1062,9 @@ retry: | |||
1083 | static inline int common_timer_del(struct k_itimer *timer) | 1062 | static inline int common_timer_del(struct k_itimer *timer) |
1084 | { | 1063 | { |
1085 | timer->it.real.incr = 0; | 1064 | timer->it.real.incr = 0; |
1065 | |||
1066 | if (try_to_del_timer_sync(&timer->it.real.timer) < 0) { | ||
1086 | #ifdef CONFIG_SMP | 1067 | #ifdef CONFIG_SMP |
1087 | if (timer_active(timer) && !del_timer(&timer->it.real.timer)) | ||
1088 | /* | 1068 | /* |
1089 | * It can only be active if on an other cpu. Since | 1069 | * It can only be active if on an other cpu. Since |
1090 | * we have cleared the interval stuff above, it should | 1070 | * we have cleared the interval stuff above, it should |
@@ -1094,9 +1074,9 @@ static inline int common_timer_del(struct k_itimer *timer) | |||
1094 | * a "retry" exit status. | 1074 | * a "retry" exit status. |
1095 | */ | 1075 | */ |
1096 | return TIMER_RETRY; | 1076 | return TIMER_RETRY; |
1097 | #else | ||
1098 | del_timer(&timer->it.real.timer); | ||
1099 | #endif | 1077 | #endif |
1078 | } | ||
1079 | |||
1100 | remove_from_abslist(timer); | 1080 | remove_from_abslist(timer); |
1101 | 1081 | ||
1102 | return 0; | 1082 | return 0; |