Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[sfrench/cifs-2.6.git] / kernel / timer.c
index 8aadc62efd65379dff44fcc08cc57e3c0fd90bbf..f2a11887a72680605bc9af158132a4fd104fbe24 100644 (file)
@@ -365,6 +365,34 @@ int del_timer(struct timer_list *timer)
 EXPORT_SYMBOL(del_timer);
 
 #ifdef CONFIG_SMP
+/*
+ * This function tries to deactivate a timer. Upon successful (ret >= 0)
+ * exit the timer is not queued and the handler is not running on any CPU.
+ *
+ * It must not be called from interrupt contexts.
+ */
+int try_to_del_timer_sync(struct timer_list *timer)
+{
+       timer_base_t *base;
+       unsigned long flags;
+       int ret = -1;
+
+       base = lock_timer_base(timer, &flags);
+
+       if (base->running_timer == timer)
+               goto out;
+
+       ret = 0;
+       if (timer_pending(timer)) {
+               detach_timer(timer, 1);
+               ret = 1;
+       }
+out:
+       spin_unlock_irqrestore(&base->lock, flags);
+
+       return ret;
+}
+
 /***
  * del_timer_sync - deactivate a timer and wait for the handler to finish.
  * @timer: the timer to be deactivated
@@ -384,28 +412,13 @@ EXPORT_SYMBOL(del_timer);
  */
 int del_timer_sync(struct timer_list *timer)
 {
-       timer_base_t *base;
-       unsigned long flags;
-       int ret = -1;
-
        check_timer(timer);
 
-       do {
-               base = lock_timer_base(timer, &flags);
-
-               if (base->running_timer == timer)
-                       goto unlock;
-
-               ret = 0;
-               if (timer_pending(timer)) {
-                       detach_timer(timer, 1);
-                       ret = 1;
-               }
-unlock:
-               spin_unlock_irqrestore(&base->lock, flags);
-       } while (ret < 0);
-
-       return ret;
+       for (;;) {
+               int ret = try_to_del_timer_sync(timer);
+               if (ret >= 0)
+                       return ret;
+       }
 }
 
 EXPORT_SYMBOL(del_timer_sync);
@@ -476,10 +489,14 @@ static inline void __run_timers(tvec_base_t *base)
                        detach_timer(timer, 1);
                        spin_unlock_irq(&base->t_base.lock);
                        {
-                               u32 preempt_count = preempt_count();
+                               int preempt_count = preempt_count();
                                fn(data);
                                if (preempt_count != preempt_count()) {
-                                       printk("huh, entered %p with %08x, exited with %08x?\n", fn, preempt_count, preempt_count());
+                                       printk(KERN_WARNING "huh, entered %p "
+                                              "with preempt_count %08x, exited"
+                                              " with %08x?\n",
+                                              fn, preempt_count,
+                                              preempt_count());
                                        BUG();
                                }
                        }
@@ -1580,7 +1597,7 @@ void msleep(unsigned int msecs)
 EXPORT_SYMBOL(msleep);
 
 /**
- * msleep_interruptible - sleep waiting for waitqueue interruptions
+ * msleep_interruptible - sleep waiting for signals
  * @msecs: Time in milliseconds to sleep for
  */
 unsigned long msleep_interruptible(unsigned int msecs)