Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
Linus Torvalds [Thu, 24 Jul 2008 19:55:01 +0000 (12:55 -0700)]
* 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  nohz: adjust tick_nohz_stop_sched_tick() call of s390 as well
  nohz: prevent tick stop outside of the idle loop

15 files changed:
arch/arm/kernel/process.c
arch/avr32/kernel/process.c
arch/blackfin/kernel/process.c
arch/mips/kernel/process.c
arch/powerpc/kernel/idle.c
arch/powerpc/platforms/iseries/setup.c
arch/s390/kernel/process.c
arch/sh/kernel/process_32.c
arch/sparc64/kernel/process.c
arch/um/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
include/linux/tick.h
kernel/softirq.c
kernel/time/tick-sched.c

index 199b368..89bfded 100644 (file)
@@ -162,7 +162,7 @@ void cpu_idle(void)
                if (!idle)
                        idle = default_idle;
                leds_event(led_idle_start);
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched())
                        idle();
                leds_event(led_idle_end);
index 6cf9df1..ff820a9 100644 (file)
@@ -31,7 +31,7 @@ void cpu_idle(void)
 {
        /* endless idle loop with no priority at all */
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched())
                        cpu_idle_sleep();
                tick_nohz_restart_sched_tick();
index 53c2cd2..77800dd 100644 (file)
@@ -105,7 +105,7 @@ void cpu_idle(void)
 #endif
                if (!idle)
                        idle = default_idle;
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched())
                        idle();
                tick_nohz_restart_sched_tick();
index c06f5b5..b16facd 100644 (file)
@@ -53,7 +53,7 @@ void __noreturn cpu_idle(void)
 {
        /* endless idle loop with no priority at all */
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched()) {
 #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
                        extern void smtc_idle_loop_hook(void);
index c3cf0e8..d308a9f 100644 (file)
@@ -60,7 +60,7 @@ void cpu_idle(void)
 
        set_thread_flag(TIF_POLLING_NRFLAG);
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched() && !cpu_should_die()) {
                        ppc64_runlatch_off();
 
index b721207..70b688c 100644 (file)
@@ -561,7 +561,7 @@ static void yield_shared_processor(void)
 static void iseries_shared_idle(void)
 {
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched() && !hvlpevent_is_pending()) {
                        local_irq_disable();
                        ppc64_runlatch_off();
@@ -591,7 +591,7 @@ static void iseries_dedicated_idle(void)
        set_thread_flag(TIF_POLLING_NRFLAG);
 
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                if (!need_resched()) {
                        while (!need_resched()) {
                                ppc64_runlatch_off();
index 85defd0..9839767 100644 (file)
@@ -142,7 +142,7 @@ static void default_idle(void)
 void cpu_idle(void)
 {
        for (;;) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched())
                        default_idle();
                tick_nohz_restart_sched_tick();
index b98e37a..921892c 100644 (file)
@@ -86,7 +86,7 @@ void cpu_idle(void)
                if (!idle)
                        idle = default_idle;
 
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched())
                        idle();
                tick_nohz_restart_sched_tick();
index 31ea752..8a9cd3e 100644 (file)
@@ -96,7 +96,7 @@ void cpu_idle(void)
        set_thread_flag(TIF_POLLING_NRFLAG);
 
        while(1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
 
                while (!need_resched() && !cpu_is_offline(cpu))
                        sparc64_yield(cpu);
index 83603cf..a1c6d07 100644 (file)
@@ -243,7 +243,7 @@ void default_idle(void)
                if (need_resched())
                        schedule();
 
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                nsecs = disable_timer();
                idle_sleep(nsecs);
                tick_nohz_restart_sched_tick();
index 0c3927a..53bc653 100644 (file)
@@ -128,7 +128,7 @@ void cpu_idle(void)
 
        /* endless idle loop with no priority at all */
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched()) {
 
                        check_pgt_cache();
index e8a8e1b..3fb62a7 100644 (file)
@@ -120,7 +120,7 @@ void cpu_idle(void)
        current_thread_info()->status |= TS_POLLING;
        /* endless idle loop with no priority at all */
        while (1) {
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(1);
                while (!need_resched()) {
 
                        rmb();
index a881c65..d3c0269 100644 (file)
@@ -49,6 +49,7 @@ struct tick_sched {
        unsigned long                   check_clocks;
        enum tick_nohz_mode             nohz_mode;
        ktime_t                         idle_tick;
+       int                             inidle;
        int                             tick_stopped;
        unsigned long                   idle_jiffies;
        unsigned long                   idle_calls;
@@ -105,14 +106,14 @@ static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 # ifdef CONFIG_NO_HZ
-extern void tick_nohz_stop_sched_tick(void);
+extern void tick_nohz_stop_sched_tick(int inidle);
 extern void tick_nohz_restart_sched_tick(void);
 extern void tick_nohz_update_jiffies(void);
 extern ktime_t tick_nohz_get_sleep_length(void);
 extern void tick_nohz_stop_idle(int cpu);
 extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time);
 # else
-static inline void tick_nohz_stop_sched_tick(void) { }
+static inline void tick_nohz_stop_sched_tick(int inidle) { }
 static inline void tick_nohz_restart_sched_tick(void) { }
 static inline void tick_nohz_update_jiffies(void) { }
 static inline ktime_t tick_nohz_get_sleep_length(void)
index 81e2fe0..f6b03d5 100644 (file)
@@ -286,7 +286,7 @@ void irq_exit(void)
 #ifdef CONFIG_NO_HZ
        /* Make sure that timer wheel updates are propagated */
        if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched())
-               tick_nohz_stop_sched_tick();
+               tick_nohz_stop_sched_tick(0);
        rcu_irq_exit();
 #endif
        preempt_enable_no_resched();
index 942fc7c..825b4c0 100644 (file)
@@ -195,7 +195,7 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
  * Called either from the idle loop or from irq_exit() when an idle period was
  * just interrupted by an interrupt which did not cause a reschedule.
  */
-void tick_nohz_stop_sched_tick(void)
+void tick_nohz_stop_sched_tick(int inidle)
 {
        unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags;
        struct tick_sched *ts;
@@ -224,6 +224,11 @@ void tick_nohz_stop_sched_tick(void)
        if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
                goto end;
 
+       if (!inidle && !ts->inidle)
+               goto end;
+
+       ts->inidle = 1;
+
        if (need_resched())
                goto end;
 
@@ -373,11 +378,14 @@ void tick_nohz_restart_sched_tick(void)
        local_irq_disable();
        tick_nohz_stop_idle(cpu);
 
-       if (!ts->tick_stopped) {
+       if (!ts->inidle || !ts->tick_stopped) {
+               ts->inidle = 0;
                local_irq_enable();
                return;
        }
 
+       ts->inidle = 0;
+
        rcu_exit_nohz();
 
        /* Update jiffies first */