cgroups: add cpu_relax() calls in css_tryget() and cgroup_clear_css_refs()
[safe/jmp/linux-2.6] / kernel / hrtimer.c
index 8010a67..f33afb0 100644 (file)
@@ -614,7 +614,9 @@ void clock_was_set(void)
  */
 void hres_timers_resume(void)
 {
-       /* Retrigger the CPU local events: */
+       WARN_ONCE(!irqs_disabled(),
+                 KERN_INFO "hres_timers_resume() called with IRQs enabled!");
+
        retrigger_next_event(NULL);
 }
 
@@ -634,7 +636,6 @@ static inline void hrtimer_init_timer_hres(struct hrtimer *timer)
 {
 }
 
-static void __run_hrtimer(struct hrtimer *timer);
 
 /*
  * When High resolution timers are active, try to reprogram. Note, that in case
@@ -646,13 +647,9 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
                                            struct hrtimer_clock_base *base)
 {
        if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) {
-               /*
-                * XXX: recursion check?
-                * hrtimer_forward() should round up with timer granularity
-                * so that we never get into inf recursion here,
-                * it doesn't do that though
-                */
-               __run_hrtimer(timer);
+               spin_unlock(&base->cpu_base->lock);
+               raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+               spin_lock(&base->cpu_base->lock);
                return 1;
        }
        return 0;
@@ -705,11 +702,6 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
 }
 static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { }
 static inline void hrtimer_init_timer_hres(struct hrtimer *timer) { }
-static inline int hrtimer_reprogram(struct hrtimer *timer,
-                                   struct hrtimer_clock_base *base)
-{
-       return 0;
-}
 
 #endif /* CONFIG_HIGH_RES_TIMERS */
 
@@ -780,9 +772,11 @@ EXPORT_SYMBOL_GPL(hrtimer_forward);
  *
  * The timer is inserted in expiry order. Insertion into the
  * red black tree is O(log(n)). Must hold the base lock.
+ *
+ * Returns 1 when the new timer is the leftmost timer in the tree.
  */
-static void enqueue_hrtimer(struct hrtimer *timer,
-                           struct hrtimer_clock_base *base, int reprogram)
+static int enqueue_hrtimer(struct hrtimer *timer,
+                          struct hrtimer_clock_base *base)
 {
        struct rb_node **link = &base->active.rb_node;
        struct rb_node *parent = NULL;
@@ -814,20 +808,8 @@ static void enqueue_hrtimer(struct hrtimer *timer,
         * Insert the timer to the rbtree and check whether it
         * replaces the first pending timer
         */
-       if (leftmost) {
-               /*
-                * Reprogram the clock event device. When the timer is already
-                * expired hrtimer_enqueue_reprogram has either called the
-                * callback or added it to the pending list and raised the
-                * softirq.
-                *
-                * This is a NOP for !HIGHRES
-                */
-               if (reprogram && hrtimer_enqueue_reprogram(timer, base))
-                       return;
-
+       if (leftmost)
                base->first = &timer->node;
-       }
 
        rb_link_node(&timer->node, parent, link);
        rb_insert_color(&timer->node, &base->active);
@@ -836,6 +818,8 @@ static void enqueue_hrtimer(struct hrtimer *timer,
         * state of a possibly running callback.
         */
        timer->state |= HRTIMER_STATE_ENQUEUED;
+
+       return leftmost;
 }
 
 /*
@@ -912,7 +896,7 @@ hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, unsigned long delta_n
 {
        struct hrtimer_clock_base *base, *new_base;
        unsigned long flags;
-       int ret;
+       int ret, leftmost;
 
        base = lock_hrtimer_base(timer, &flags);
 
@@ -940,12 +924,16 @@ hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, unsigned long delta_n
 
        timer_stats_hrtimer_set_start_info(timer);
 
+       leftmost = enqueue_hrtimer(timer, new_base);
+
        /*
         * Only allow reprogramming if the new base is on this CPU.
         * (it might still be on another CPU if the timer was pending)
+        *
+        * XXX send_remote_softirq() ?
         */
-       enqueue_hrtimer(timer, new_base,
-                       new_base->cpu_base == &__get_cpu_var(hrtimer_bases));
+       if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases))
+               hrtimer_enqueue_reprogram(timer, new_base);
 
        unlock_hrtimer_base(timer, &flags);
 
@@ -1157,13 +1145,13 @@ static void __run_hrtimer(struct hrtimer *timer)
        spin_lock(&cpu_base->lock);
 
        /*
-        * Note: We clear the CALLBACK bit after enqueue_hrtimer to avoid
-        * reprogramming of the event hardware. This happens at the end of this
-        * function anyway.
+        * Note: We clear the CALLBACK bit after enqueue_hrtimer and
+        * we do not reprogramm the event hardware. Happens either in
+        * hrtimer_start_range_ns() or in hrtimer_interrupt()
         */
        if (restart != HRTIMER_NORESTART) {
                BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
-               enqueue_hrtimer(timer, base, 0);
+               enqueue_hrtimer(timer, base);
        }
        timer->state &= ~HRTIMER_STATE_CALLBACK;
 }
@@ -1277,7 +1265,16 @@ void hrtimer_peek_ahead_timers(void)
        local_irq_restore(flags);
 }
 
-#endif /* CONFIG_HIGH_RES_TIMERS */
+static void run_hrtimer_softirq(struct softirq_action *h)
+{
+       hrtimer_peek_ahead_timers();
+}
+
+#else /* CONFIG_HIGH_RES_TIMERS */
+
+static inline void __hrtimer_peek_ahead_timers(void) { }
+
+#endif /* !CONFIG_HIGH_RES_TIMERS */
 
 /*
  * Called from timer softirq every jiffy, expire hrtimers:
@@ -1472,8 +1469,8 @@ out:
        return ret;
 }
 
-asmlinkage long
-sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
+SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
+               struct timespec __user *, rmtp)
 {
        struct timespec tu;
 
@@ -1523,16 +1520,14 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
                __remove_hrtimer(timer, old_base, HRTIMER_STATE_MIGRATE, 0);
                timer->base = new_base;
                /*
-                * Enqueue the timers on the new cpu, but do not reprogram 
-                * the timer as that would enable a deadlock between
-                * hrtimer_enqueue_reprogramm() running the timer and us still
-                * holding a nested base lock.
-                *
-                * Instead we tickle the hrtimer interrupt after the migration
-                * is done, which will run all expired timers and re-programm
-                * the timer device.
+                * Enqueue the timers on the new cpu. This does not
+                * reprogram the event device in case the timer
+                * expires before the earliest on this CPU, but we run
+                * hrtimer_interrupt after we migrated everything to
+                * sort out already expired timers and reprogram the
+                * event device.
                 */
-               enqueue_hrtimer(timer, new_base, 0);
+               enqueue_hrtimer(timer, new_base);
 
                /* Clear the migration state bit */
                timer->state &= ~HRTIMER_STATE_MIGRATE;
@@ -1610,6 +1605,9 @@ void __init hrtimers_init(void)
        hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
                          (void *)(long)smp_processor_id());
        register_cpu_notifier(&hrtimers_nb);
+#ifdef CONFIG_HIGH_RES_TIMERS
+       open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq);
+#endif
 }
 
 /**