]> err.no Git - linux-2.6/blobdiff - kernel/hrtimer.c
simplify cpu_hotplug_begin()/put_online_cpus()
[linux-2.6] / kernel / hrtimer.c
index e379ef0e9c20c5e77b0003398e46eb859c6399e3..dea4c9124ac808b872d43a3dd83c15fc7cbb38a9 100644 (file)
@@ -590,7 +590,6 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
                        list_add_tail(&timer->cb_entry,
                                      &base->cpu_base->cb_pending);
                        timer->state = HRTIMER_STATE_PENDING;
-                       raise_softirq(HRTIMER_SOFTIRQ);
                        return 1;
                default:
                        BUG();
@@ -633,6 +632,11 @@ static int hrtimer_switch_to_hres(void)
        return 1;
 }
 
+static inline void hrtimer_raise_softirq(void)
+{
+       raise_softirq(HRTIMER_SOFTIRQ);
+}
+
 #else
 
 static inline int hrtimer_hres_active(void) { return 0; }
@@ -651,6 +655,7 @@ static inline int hrtimer_reprogram(struct hrtimer *timer,
 {
        return 0;
 }
+static inline void hrtimer_raise_softirq(void) { }
 
 #endif /* CONFIG_HIGH_RES_TIMERS */
 
@@ -850,7 +855,7 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
 {
        struct hrtimer_clock_base *base, *new_base;
        unsigned long flags;
-       int ret;
+       int ret, raise;
 
        base = lock_hrtimer_base(timer, &flags);
 
@@ -884,8 +889,18 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
        enqueue_hrtimer(timer, new_base,
                        new_base->cpu_base == &__get_cpu_var(hrtimer_bases));
 
+       /*
+        * The timer may be expired and moved to the cb_pending
+        * list. We can not raise the softirq with base lock held due
+        * to a possible deadlock with runqueue lock.
+        */
+       raise = timer->state == HRTIMER_STATE_PENDING;
+
        unlock_hrtimer_base(timer, &flags);
 
+       if (raise)
+               hrtimer_raise_softirq();
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(hrtimer_start);