]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/time/tick-sched.c
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/cooloney...
[linux-2.6-omap-h63xx.git] / kernel / time / tick-sched.c
index 3483e6cb9549c26e17d1985c2700737914871779..b416995b975727ca8b6dbf8b331de5351a1ef7f5 100644 (file)
@@ -167,9 +167,15 @@ void tick_nohz_stop_sched_tick(void)
                goto end;
 
        cpu = smp_processor_id();
-       if (unlikely(local_softirq_pending()))
-               printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
-                      local_softirq_pending());
+       if (unlikely(local_softirq_pending())) {
+               static int ratelimit;
+
+               if (ratelimit < 10) {
+                       printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
+                              local_softirq_pending());
+                       ratelimit++;
+               }
+       }
 
        now = ktime_get();
        /*
@@ -241,6 +247,21 @@ void tick_nohz_stop_sched_tick(void)
                if (cpu == tick_do_timer_cpu)
                        tick_do_timer_cpu = -1;
 
+               ts->idle_sleeps++;
+
+               /*
+                * delta_jiffies >= NEXT_TIMER_MAX_DELTA signals that
+                * there is no timer pending or at least extremly far
+                * into the future (12 days for HZ=1000). In this case
+                * we simply stop the tick timer:
+                */
+               if (unlikely(delta_jiffies >= NEXT_TIMER_MAX_DELTA)) {
+                       ts->idle_expires.tv64 = KTIME_MAX;
+                       if (ts->nohz_mode == NOHZ_MODE_HIGHRES)
+                               hrtimer_cancel(&ts->sched_timer);
+                       goto out;
+               }
+
                /*
                 * calculate the expiry time for the next timer wheel
                 * timer
@@ -248,7 +269,6 @@ void tick_nohz_stop_sched_tick(void)
                expires = ktime_add_ns(last_update, tick_period.tv64 *
                                       delta_jiffies);
                ts->idle_expires = expires;
-               ts->idle_sleeps++;
 
                if (ts->nohz_mode == NOHZ_MODE_HIGHRES) {
                        hrtimer_start(&ts->sched_timer, expires,
@@ -526,6 +546,7 @@ void tick_setup_sched_timer(void)
 {
        struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
        ktime_t now = ktime_get();
+       u64 offset;
 
        /*
         * Emulate tick processing via per-CPU hrtimers:
@@ -534,8 +555,12 @@ void tick_setup_sched_timer(void)
        ts->sched_timer.function = tick_sched_timer;
        ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
 
-       /* Get the next period */
+       /* Get the next period (per cpu) */
        ts->sched_timer.expires = tick_init_jiffy_update();
+       offset = ktime_to_ns(tick_period) >> 1;
+       do_div(offset, NR_CPUS);
+       offset *= smp_processor_id();
+       ts->sched_timer.expires = ktime_add_ns(ts->sched_timer.expires, offset);
 
        for (;;) {
                hrtimer_forward(&ts->sched_timer, now, tick_period);