aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/timer.h4
-rw-r--r--kernel/timer.c53
2 files changed, 36 insertions, 21 deletions
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 2e78fedfc069..221f81ac2002 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -76,9 +76,11 @@ static inline void add_timer(struct timer_list * timer)
76} 76}
77 77
78#ifdef CONFIG_SMP 78#ifdef CONFIG_SMP
79 extern int try_to_del_timer_sync(struct timer_list *timer);
79 extern int del_timer_sync(struct timer_list *timer); 80 extern int del_timer_sync(struct timer_list *timer);
80#else 81#else
81# define del_timer_sync(t) del_timer(t) 82# define try_to_del_timer_sync(t) del_timer(t)
83# define del_timer_sync(t) del_timer(t)
82#endif 84#endif
83 85
84#define del_singleshot_timer_sync(t) del_timer_sync(t) 86#define del_singleshot_timer_sync(t) del_timer_sync(t)
diff --git a/kernel/timer.c b/kernel/timer.c
index 8aadc62efd65..1f986c16d89f 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -365,6 +365,34 @@ int del_timer(struct timer_list *timer)
365EXPORT_SYMBOL(del_timer); 365EXPORT_SYMBOL(del_timer);
366 366
367#ifdef CONFIG_SMP 367#ifdef CONFIG_SMP
368/*
369 * This function tries to deactivate a timer. Upon successful (ret >= 0)
370 * exit the timer is not queued and the handler is not running on any CPU.
371 *
372 * It must not be called from interrupt contexts.
373 */
374int try_to_del_timer_sync(struct timer_list *timer)
375{
376 timer_base_t *base;
377 unsigned long flags;
378 int ret = -1;
379
380 base = lock_timer_base(timer, &flags);
381
382 if (base->running_timer == timer)
383 goto out;
384
385 ret = 0;
386 if (timer_pending(timer)) {
387 detach_timer(timer, 1);
388 ret = 1;
389 }
390out:
391 spin_unlock_irqrestore(&base->lock, flags);
392
393 return ret;
394}
395
368/*** 396/***
369 * del_timer_sync - deactivate a timer and wait for the handler to finish. 397 * del_timer_sync - deactivate a timer and wait for the handler to finish.
370 * @timer: the timer to be deactivated 398 * @timer: the timer to be deactivated
@@ -384,28 +412,13 @@ EXPORT_SYMBOL(del_timer);
384 */ 412 */
385int del_timer_sync(struct timer_list *timer) 413int del_timer_sync(struct timer_list *timer)
386{ 414{
387 timer_base_t *base;
388 unsigned long flags;
389 int ret = -1;
390
391 check_timer(timer); 415 check_timer(timer);
392 416
393 do { 417 for (;;) {
394 base = lock_timer_base(timer, &flags); 418 int ret = try_to_del_timer_sync(timer);
395 419 if (ret >= 0)
396 if (base->running_timer == timer) 420 return ret;
397 goto unlock; 421 }
398
399 ret = 0;
400 if (timer_pending(timer)) {
401 detach_timer(timer, 1);
402 ret = 1;
403 }
404unlock:
405 spin_unlock_irqrestore(&base->lock, flags);
406 } while (ret < 0);
407
408 return ret;
409} 422}
410 423
411EXPORT_SYMBOL(del_timer_sync); 424EXPORT_SYMBOL(del_timer_sync);