Skip to content

Commit a1ff03c

Browse files
author
Frederic Weisbecker
committed
tick: Detect and fix jiffies update stall
On some rare cases, the timekeeper CPU may be delaying its jiffies update duty for a while. Known causes include: * The timekeeper is waiting on stop_machine in a MULTI_STOP_DISABLE_IRQ or MULTI_STOP_RUN state. Disabled interrupts prevent from timekeeping updates while waiting for the target CPU to complete its stop_machine() callback. * The timekeeper vcpu has VMEXIT'ed for a long while due to some overload on the host. Detect and fix these situations with emergency timekeeping catchups. Original-patch-by: Paul E. McKenney <[email protected]> Signed-off-by: Frederic Weisbecker <[email protected]> Cc: Thomas Gleixner <[email protected]>
1 parent 58dedf0 commit a1ff03c

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

kernel/time/tick-sched.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ static ktime_t tick_init_jiffy_update(void)
169169
return period;
170170
}
171171

172+
#define MAX_STALLED_JIFFIES 5
173+
172174
static void tick_sched_do_timer(struct tick_sched *ts, ktime_t now)
173175
{
174176
int cpu = smp_processor_id();
@@ -196,6 +198,21 @@ static void tick_sched_do_timer(struct tick_sched *ts, ktime_t now)
196198
if (tick_do_timer_cpu == cpu)
197199
tick_do_update_jiffies64(now);
198200

201+
/*
202+
* If jiffies update stalled for too long (timekeeper in stop_machine()
203+
* or VMEXIT'ed for several msecs), force an update.
204+
*/
205+
if (ts->last_tick_jiffies != jiffies) {
206+
ts->stalled_jiffies = 0;
207+
ts->last_tick_jiffies = READ_ONCE(jiffies);
208+
} else {
209+
if (++ts->stalled_jiffies == MAX_STALLED_JIFFIES) {
210+
tick_do_update_jiffies64(now);
211+
ts->stalled_jiffies = 0;
212+
ts->last_tick_jiffies = READ_ONCE(jiffies);
213+
}
214+
}
215+
199216
if (ts->inidle)
200217
ts->got_idle_tick = 1;
201218
}

kernel/time/tick-sched.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ enum tick_nohz_mode {
4949
* @timer_expires_base: Base time clock monotonic for @timer_expires
5050
* @next_timer: Expiry time of next expiring timer for debugging purpose only
5151
* @tick_dep_mask: Tick dependency mask - is set, if someone needs the tick
52+
* @last_tick_jiffies: Value of jiffies seen on last tick
53+
* @stalled_jiffies: Number of stalled jiffies detected across ticks
5254
*/
5355
struct tick_sched {
5456
struct hrtimer sched_timer;
@@ -77,6 +79,8 @@ struct tick_sched {
7779
u64 next_timer;
7880
ktime_t idle_expires;
7981
atomic_t tick_dep_mask;
82+
unsigned long last_tick_jiffies;
83+
unsigned int stalled_jiffies;
8084
};
8185

8286
extern struct tick_sched *tick_get_tick_sched(int cpu);

0 commit comments

Comments
 (0)