Skip to content

Commit 29721b8

Browse files
Frederic Weisbeckeringomolnar
authored andcommitted
tick/nohz: Only wake up a single target cpu when kicking a task
When adding a tick dependency to a task, its necessary to wake up the CPU where the task resides to reevaluate tick dependencies on that CPU. However the current code wakes up all nohz_full CPUs, which is unnecessary. Switch to waking up a single CPU, by using ordering of writes to task->cpu and task->tick_dep_mask. [ mingo: Minor readability edit. ] Suggested-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Frederic Weisbecker <frederic@kernel.org> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Acked-by: Peter Zijlstra <peterz@infradead.org> Link: https://lore.kernel.org/r/20210512232924.150322-7-frederic@kernel.org
1 parent 176b890 commit 29721b8

1 file changed

Lines changed: 27 additions & 13 deletions

File tree

kernel/time/tick-sched.c

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,31 @@ void tick_nohz_full_kick_cpu(int cpu)
322322
irq_work_queue_on(&per_cpu(nohz_full_kick_work, cpu), cpu);
323323
}
324324

325+
static void tick_nohz_kick_task(struct task_struct *tsk)
326+
{
327+
int cpu = task_cpu(tsk);
328+
329+
/*
330+
* If the task concurrently migrates to another CPU,
331+
* we guarantee it sees the new tick dependency upon
332+
* schedule.
333+
*
334+
*
335+
* set_task_cpu(p, cpu);
336+
* STORE p->cpu = @cpu
337+
* __schedule() (switch to task 'p')
338+
* LOCK rq->lock
339+
* smp_mb__after_spin_lock() STORE p->tick_dep_mask
340+
* tick_nohz_task_switch() smp_mb() (atomic_fetch_or())
341+
* LOAD p->tick_dep_mask LOAD p->cpu
342+
*/
343+
344+
preempt_disable();
345+
if (cpu_online(cpu))
346+
tick_nohz_full_kick_cpu(cpu);
347+
preempt_enable();
348+
}
349+
325350
/*
326351
* Kick all full dynticks CPUs in order to force these to re-evaluate
327352
* their dependency on the tick and restart it if necessary.
@@ -404,19 +429,8 @@ EXPORT_SYMBOL_GPL(tick_nohz_dep_clear_cpu);
404429
*/
405430
void tick_nohz_dep_set_task(struct task_struct *tsk, enum tick_dep_bits bit)
406431
{
407-
if (!atomic_fetch_or(BIT(bit), &tsk->tick_dep_mask)) {
408-
if (tsk == current) {
409-
preempt_disable();
410-
tick_nohz_full_kick();
411-
preempt_enable();
412-
} else {
413-
/*
414-
* Some future tick_nohz_full_kick_task()
415-
* should optimize this.
416-
*/
417-
tick_nohz_full_kick_all();
418-
}
419-
}
432+
if (!atomic_fetch_or(BIT(bit), &tsk->tick_dep_mask))
433+
tick_nohz_kick_task(tsk);
420434
}
421435
EXPORT_SYMBOL_GPL(tick_nohz_dep_set_task);
422436

0 commit comments

Comments
 (0)