Skip to content

Commit ebc0f83

Browse files
Peter Zijlstra (Intel)Ingo Molnar
authored andcommitted
timers/nohz: Update NOHZ load in remote tick
The way loadavg is tracked during nohz only pays attention to the load upon entering nohz. This can be particularly noticeable if full nohz is entered while non-idle, and then the cpu goes idle and stays that way for a long time. Use the remote tick to ensure that full nohz cpus report their deltas within a reasonable time. [ swood: Added changelog and removed recheck of stopped tick. ] Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Scott Wood <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 488603b commit ebc0f83

File tree

3 files changed

+28
-11
lines changed

3 files changed

+28
-11
lines changed

include/linux/sched/nohz.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ static inline void nohz_balance_enter_idle(int cpu) { }
1515

1616
#ifdef CONFIG_NO_HZ_COMMON
1717
void calc_load_nohz_start(void);
18+
void calc_load_nohz_remote(struct rq *rq);
1819
void calc_load_nohz_stop(void);
1920
#else
2021
static inline void calc_load_nohz_start(void) { }
22+
static inline void calc_load_nohz_remote(struct rq *rq) { }
2123
static inline void calc_load_nohz_stop(void) { }
2224
#endif /* CONFIG_NO_HZ_COMMON */
2325

kernel/sched/core.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3677,6 +3677,7 @@ static void sched_tick_remote(struct work_struct *work)
36773677
if (cpu_is_offline(cpu))
36783678
goto out_unlock;
36793679

3680+
curr = rq->curr;
36803681
update_rq_clock(rq);
36813682

36823683
if (!is_idle_task(curr)) {
@@ -3689,10 +3690,11 @@ static void sched_tick_remote(struct work_struct *work)
36893690
}
36903691
curr->sched_class->task_tick(rq, curr, 0);
36913692

3693+
calc_load_nohz_remote(rq);
36923694
out_unlock:
36933695
rq_unlock_irq(rq, &rf);
3694-
36953696
out_requeue:
3697+
36963698
/*
36973699
* Run the remote tick once per second (1Hz). This arbitrary
36983700
* frequency is large enough to avoid overload but short enough

kernel/sched/loadavg.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -231,23 +231,36 @@ static inline int calc_load_read_idx(void)
231231
return calc_load_idx & 1;
232232
}
233233

234-
void calc_load_nohz_start(void)
234+
static void calc_load_nohz_fold(struct rq *rq)
235235
{
236-
struct rq *this_rq = this_rq();
237236
long delta;
238237

239-
/*
240-
* We're going into NO_HZ mode, if there's any pending delta, fold it
241-
* into the pending NO_HZ delta.
242-
*/
243-
delta = calc_load_fold_active(this_rq, 0);
238+
delta = calc_load_fold_active(rq, 0);
244239
if (delta) {
245240
int idx = calc_load_write_idx();
246241

247242
atomic_long_add(delta, &calc_load_nohz[idx]);
248243
}
249244
}
250245

246+
void calc_load_nohz_start(void)
247+
{
248+
/*
249+
* We're going into NO_HZ mode, if there's any pending delta, fold it
250+
* into the pending NO_HZ delta.
251+
*/
252+
calc_load_nohz_fold(this_rq());
253+
}
254+
255+
/*
256+
* Keep track of the load for NOHZ_FULL, must be called between
257+
* calc_load_nohz_{start,stop}().
258+
*/
259+
void calc_load_nohz_remote(struct rq *rq)
260+
{
261+
calc_load_nohz_fold(rq);
262+
}
263+
251264
void calc_load_nohz_stop(void)
252265
{
253266
struct rq *this_rq = this_rq();
@@ -268,7 +281,7 @@ void calc_load_nohz_stop(void)
268281
this_rq->calc_load_update += LOAD_FREQ;
269282
}
270283

271-
static long calc_load_nohz_fold(void)
284+
static long calc_load_nohz_read(void)
272285
{
273286
int idx = calc_load_read_idx();
274287
long delta = 0;
@@ -323,7 +336,7 @@ static void calc_global_nohz(void)
323336
}
324337
#else /* !CONFIG_NO_HZ_COMMON */
325338

326-
static inline long calc_load_nohz_fold(void) { return 0; }
339+
static inline long calc_load_nohz_read(void) { return 0; }
327340
static inline void calc_global_nohz(void) { }
328341

329342
#endif /* CONFIG_NO_HZ_COMMON */
@@ -346,7 +359,7 @@ void calc_global_load(unsigned long ticks)
346359
/*
347360
* Fold the 'old' NO_HZ-delta to include all NO_HZ CPUs.
348361
*/
349-
delta = calc_load_nohz_fold();
362+
delta = calc_load_nohz_read();
350363
if (delta)
351364
atomic_long_add(delta, &calc_load_tasks);
352365

0 commit comments

Comments
 (0)