Commit ecc8b655 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'timers-fixes-for-linus' of...

Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* '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
parents 2528ce32 e338125b
...@@ -162,7 +162,7 @@ void cpu_idle(void) ...@@ -162,7 +162,7 @@ void cpu_idle(void)
if (!idle) if (!idle)
idle = default_idle; idle = default_idle;
leds_event(led_idle_start); leds_event(led_idle_start);
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(1);
while (!need_resched()) while (!need_resched())
idle(); idle();
leds_event(led_idle_end); leds_event(led_idle_end);
......
...@@ -31,7 +31,7 @@ void cpu_idle(void) ...@@ -31,7 +31,7 @@ void cpu_idle(void)
{ {
/* endless idle loop with no priority at all */ /* endless idle loop with no priority at all */
while (1) { while (1) {
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(1);
while (!need_resched()) while (!need_resched())
cpu_idle_sleep(); cpu_idle_sleep();
tick_nohz_restart_sched_tick(); tick_nohz_restart_sched_tick();
......
...@@ -105,7 +105,7 @@ void cpu_idle(void) ...@@ -105,7 +105,7 @@ void cpu_idle(void)
#endif #endif
if (!idle) if (!idle)
idle = default_idle; idle = default_idle;
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(1);
while (!need_resched()) while (!need_resched())
idle(); idle();
tick_nohz_restart_sched_tick(); tick_nohz_restart_sched_tick();
......
...@@ -53,7 +53,7 @@ void __noreturn cpu_idle(void) ...@@ -53,7 +53,7 @@ void __noreturn cpu_idle(void)
{ {
/* endless idle loop with no priority at all */ /* endless idle loop with no priority at all */
while (1) { while (1) {
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(1);
while (!need_resched()) { while (!need_resched()) {
#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
extern void smtc_idle_loop_hook(void); extern void smtc_idle_loop_hook(void);
......
...@@ -60,7 +60,7 @@ void cpu_idle(void) ...@@ -60,7 +60,7 @@ void cpu_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG); set_thread_flag(TIF_POLLING_NRFLAG);
while (1) { while (1) {
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(1);
while (!need_resched() && !cpu_should_die()) { while (!need_resched() && !cpu_should_die()) {
ppc64_runlatch_off(); ppc64_runlatch_off();
......
...@@ -561,7 +561,7 @@ static void yield_shared_processor(void) ...@@ -561,7 +561,7 @@ static void yield_shared_processor(void)
static void iseries_shared_idle(void) static void iseries_shared_idle(void)
{ {
while (1) { while (1) {
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(1);
while (!need_resched() && !hvlpevent_is_pending()) { while (!need_resched() && !hvlpevent_is_pending()) {
local_irq_disable(); local_irq_disable();
ppc64_runlatch_off(); ppc64_runlatch_off();
...@@ -591,7 +591,7 @@ static void iseries_dedicated_idle(void) ...@@ -591,7 +591,7 @@ static void iseries_dedicated_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG); set_thread_flag(TIF_POLLING_NRFLAG);
while (1) { while (1) {
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(1);
if (!need_resched()) { if (!need_resched()) {
while (!need_resched()) { while (!need_resched()) {
ppc64_runlatch_off(); ppc64_runlatch_off();
......
...@@ -142,7 +142,7 @@ static void default_idle(void) ...@@ -142,7 +142,7 @@ static void default_idle(void)
void cpu_idle(void) void cpu_idle(void)
{ {
for (;;) { for (;;) {
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(1);
while (!need_resched()) while (!need_resched())
default_idle(); default_idle();
tick_nohz_restart_sched_tick(); tick_nohz_restart_sched_tick();
......
...@@ -86,7 +86,7 @@ void cpu_idle(void) ...@@ -86,7 +86,7 @@ void cpu_idle(void)
if (!idle) if (!idle)
idle = default_idle; idle = default_idle;
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(1);
while (!need_resched()) while (!need_resched())
idle(); idle();
tick_nohz_restart_sched_tick(); tick_nohz_restart_sched_tick();
......
...@@ -96,7 +96,7 @@ void cpu_idle(void) ...@@ -96,7 +96,7 @@ void cpu_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG); set_thread_flag(TIF_POLLING_NRFLAG);
while(1) { while(1) {
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(1);
while (!need_resched() && !cpu_is_offline(cpu)) while (!need_resched() && !cpu_is_offline(cpu))
sparc64_yield(cpu); sparc64_yield(cpu);
......
...@@ -243,7 +243,7 @@ void default_idle(void) ...@@ -243,7 +243,7 @@ void default_idle(void)
if (need_resched()) if (need_resched())
schedule(); schedule();
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(1);
nsecs = disable_timer(); nsecs = disable_timer();
idle_sleep(nsecs); idle_sleep(nsecs);
tick_nohz_restart_sched_tick(); tick_nohz_restart_sched_tick();
......
...@@ -128,7 +128,7 @@ void cpu_idle(void) ...@@ -128,7 +128,7 @@ void cpu_idle(void)
/* endless idle loop with no priority at all */ /* endless idle loop with no priority at all */
while (1) { while (1) {
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(1);
while (!need_resched()) { while (!need_resched()) {
check_pgt_cache(); check_pgt_cache();
......
...@@ -120,7 +120,7 @@ void cpu_idle(void) ...@@ -120,7 +120,7 @@ void cpu_idle(void)
current_thread_info()->status |= TS_POLLING; current_thread_info()->status |= TS_POLLING;
/* endless idle loop with no priority at all */ /* endless idle loop with no priority at all */
while (1) { while (1) {
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(1);
while (!need_resched()) { while (!need_resched()) {
rmb(); rmb();
......
...@@ -49,6 +49,7 @@ struct tick_sched { ...@@ -49,6 +49,7 @@ struct tick_sched {
unsigned long check_clocks; unsigned long check_clocks;
enum tick_nohz_mode nohz_mode; enum tick_nohz_mode nohz_mode;
ktime_t idle_tick; ktime_t idle_tick;
int inidle;
int tick_stopped; int tick_stopped;
unsigned long idle_jiffies; unsigned long idle_jiffies;
unsigned long idle_calls; unsigned long idle_calls;
...@@ -105,14 +106,14 @@ static inline int tick_check_oneshot_change(int allow_nohz) { return 0; } ...@@ -105,14 +106,14 @@ static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
#endif /* !CONFIG_GENERIC_CLOCKEVENTS */ #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
# ifdef CONFIG_NO_HZ # 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_restart_sched_tick(void);
extern void tick_nohz_update_jiffies(void); extern void tick_nohz_update_jiffies(void);
extern ktime_t tick_nohz_get_sleep_length(void); extern ktime_t tick_nohz_get_sleep_length(void);
extern void tick_nohz_stop_idle(int cpu); extern void tick_nohz_stop_idle(int cpu);
extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time); extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time);
# else # 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_restart_sched_tick(void) { }
static inline void tick_nohz_update_jiffies(void) { } static inline void tick_nohz_update_jiffies(void) { }
static inline ktime_t tick_nohz_get_sleep_length(void) static inline ktime_t tick_nohz_get_sleep_length(void)
......
...@@ -286,7 +286,7 @@ void irq_exit(void) ...@@ -286,7 +286,7 @@ void irq_exit(void)
#ifdef CONFIG_NO_HZ #ifdef CONFIG_NO_HZ
/* Make sure that timer wheel updates are propagated */ /* Make sure that timer wheel updates are propagated */
if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched()) if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched())
tick_nohz_stop_sched_tick(); tick_nohz_stop_sched_tick(0);
rcu_irq_exit(); rcu_irq_exit();
#endif #endif
preempt_enable_no_resched(); preempt_enable_no_resched();
......
...@@ -195,7 +195,7 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time) ...@@ -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 * 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. * 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; unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags;
struct tick_sched *ts; struct tick_sched *ts;
...@@ -224,6 +224,11 @@ void tick_nohz_stop_sched_tick(void) ...@@ -224,6 +224,11 @@ void tick_nohz_stop_sched_tick(void)
if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE)) if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
goto end; goto end;
if (!inidle && !ts->inidle)
goto end;
ts->inidle = 1;
if (need_resched()) if (need_resched())
goto end; goto end;
...@@ -373,11 +378,14 @@ void tick_nohz_restart_sched_tick(void) ...@@ -373,11 +378,14 @@ void tick_nohz_restart_sched_tick(void)
local_irq_disable(); local_irq_disable();
tick_nohz_stop_idle(cpu); tick_nohz_stop_idle(cpu);
if (!ts->tick_stopped) { if (!ts->inidle || !ts->tick_stopped) {
ts->inidle = 0;
local_irq_enable(); local_irq_enable();
return; return;
} }
ts->inidle = 0;
rcu_exit_nohz(); rcu_exit_nohz();
/* Update jiffies first */ /* Update jiffies first */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment