diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-01-15 15:00:37 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-01-15 15:00:37 -0500 |
commit | a11ce3a4ac0ad78618cddb9ce16def7486f2707d (patch) | |
tree | 96f6f9b7f979dcfa94d036d7431fdd799b108638 | |
parent | 79078c53baabee12dfefb0cfe00ca94cb2c35570 (diff) | |
parent | 24b91e360ef521a2808771633d76ebc68bd5604b (diff) |
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull NOHZ fix from Ingo Molnar:
"This fixes an old NOHZ race where we incorrectly calculate the next
timer interrupt in certain circumstances where hrtimers are pending,
that can cause hard to reproduce stalled-values artifacts in
/proc/stat"
* 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
nohz: Fix collision between tick and other hrtimers
-rw-r--r-- | kernel/time/tick-sched.c | 9 | ||||
-rw-r--r-- | kernel/time/tick-sched.h | 2 |
2 files changed, 9 insertions, 2 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 2c115fdab397..74e0388cc88d 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -767,7 +767,7 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, | |||
767 | tick = expires; | 767 | tick = expires; |
768 | 768 | ||
769 | /* Skip reprogram of event if its not changed */ | 769 | /* Skip reprogram of event if its not changed */ |
770 | if (ts->tick_stopped && (expires == dev->next_event)) | 770 | if (ts->tick_stopped && (expires == ts->next_tick)) |
771 | goto out; | 771 | goto out; |
772 | 772 | ||
773 | /* | 773 | /* |
@@ -787,6 +787,8 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, | |||
787 | trace_tick_stop(1, TICK_DEP_MASK_NONE); | 787 | trace_tick_stop(1, TICK_DEP_MASK_NONE); |
788 | } | 788 | } |
789 | 789 | ||
790 | ts->next_tick = tick; | ||
791 | |||
790 | /* | 792 | /* |
791 | * If the expiration time == KTIME_MAX, then we simply stop | 793 | * If the expiration time == KTIME_MAX, then we simply stop |
792 | * the tick timer. | 794 | * the tick timer. |
@@ -802,7 +804,10 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, | |||
802 | else | 804 | else |
803 | tick_program_event(tick, 1); | 805 | tick_program_event(tick, 1); |
804 | out: | 806 | out: |
805 | /* Update the estimated sleep length */ | 807 | /* |
808 | * Update the estimated sleep length until the next timer | ||
809 | * (not only the tick). | ||
810 | */ | ||
806 | ts->sleep_length = ktime_sub(dev->next_event, now); | 811 | ts->sleep_length = ktime_sub(dev->next_event, now); |
807 | return tick; | 812 | return tick; |
808 | } | 813 | } |
diff --git a/kernel/time/tick-sched.h b/kernel/time/tick-sched.h index bf38226e5c17..075444e3d48e 100644 --- a/kernel/time/tick-sched.h +++ b/kernel/time/tick-sched.h | |||
@@ -27,6 +27,7 @@ enum tick_nohz_mode { | |||
27 | * timer is modified for nohz sleeps. This is necessary | 27 | * timer is modified for nohz sleeps. This is necessary |
28 | * to resume the tick timer operation in the timeline | 28 | * to resume the tick timer operation in the timeline |
29 | * when the CPU returns from nohz sleep. | 29 | * when the CPU returns from nohz sleep. |
30 | * @next_tick: Next tick to be fired when in dynticks mode. | ||
30 | * @tick_stopped: Indicator that the idle tick has been stopped | 31 | * @tick_stopped: Indicator that the idle tick has been stopped |
31 | * @idle_jiffies: jiffies at the entry to idle for idle time accounting | 32 | * @idle_jiffies: jiffies at the entry to idle for idle time accounting |
32 | * @idle_calls: Total number of idle calls | 33 | * @idle_calls: Total number of idle calls |
@@ -44,6 +45,7 @@ struct tick_sched { | |||
44 | unsigned long check_clocks; | 45 | unsigned long check_clocks; |
45 | enum tick_nohz_mode nohz_mode; | 46 | enum tick_nohz_mode nohz_mode; |
46 | ktime_t last_tick; | 47 | ktime_t last_tick; |
48 | ktime_t next_tick; | ||
47 | int inidle; | 49 | int inidle; |
48 | int tick_stopped; | 50 | int tick_stopped; |
49 | unsigned long idle_jiffies; | 51 | unsigned long idle_jiffies; |