* [patch 1/3] nohz: only wakeup a single target cpu when kicking a task
2021-01-28 18:40 [patch 0/3] nohz_full: only wakeup target CPUs when notifying new tick dependency (v4) Marcelo Tosatti
@ 2021-01-28 18:40 ` Marcelo Tosatti
2021-01-28 18:40 ` [patch 2/3] nohz: change signal tick dependency to wakeup CPUs of member tasks Marcelo Tosatti
2021-01-28 18:40 ` [patch 3/3] nohz: tick_nohz_kick_task: only IPI if remote task is running Marcelo Tosatti
2 siblings, 0 replies; 4+ messages in thread
From: Marcelo Tosatti @ 2021-01-28 18:40 UTC (permalink / raw)
To: Peter Zijlstra, Frederic Weisbecker; +Cc: linux-kernel, Marcelo Tosatti
When adding a tick dependency to a task, its necessary to
wakeup 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.
From: Frederic Weisbecker <frederic@kernel.org>
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: linux-2.6/kernel/time/tick-sched.c
===================================================================
--- linux-2.6.orig/kernel/time/tick-sched.c
+++ linux-2.6/kernel/time/tick-sched.c
@@ -322,6 +322,31 @@ void tick_nohz_full_kick_cpu(int cpu)
irq_work_queue_on(&per_cpu(nohz_full_kick_work, cpu), cpu);
}
+static void tick_nohz_kick_task(struct task_struct *tsk)
+{
+ int cpu = task_cpu(tsk);
+
+ /*
+ * If the task concurrently migrates to another cpu,
+ * we guarantee it sees the new tick dependency upon
+ * schedule.
+ *
+ *
+ * set_task_cpu(p, cpu);
+ * STORE p->cpu = @cpu
+ * __schedule() (switch to task 'p')
+ * LOCK rq->lock
+ * smp_mb__after_spin_lock() STORE p->tick_dep_mask
+ * tick_nohz_task_switch() smp_mb() (atomic_fetch_or())
+ * LOAD p->tick_dep_mask LOAD p->cpu
+ */
+
+ preempt_disable();
+ if (cpu_online(cpu))
+ tick_nohz_full_kick_cpu(cpu);
+ preempt_enable();
+}
+
/*
* Kick all full dynticks CPUs in order to force these to re-evaluate
* their dependency on the tick and restart it if necessary.
@@ -404,19 +429,8 @@ EXPORT_SYMBOL_GPL(tick_nohz_dep_clear_cp
*/
void tick_nohz_dep_set_task(struct task_struct *tsk, enum tick_dep_bits bit)
{
- if (!atomic_fetch_or(BIT(bit), &tsk->tick_dep_mask)) {
- if (tsk == current) {
- preempt_disable();
- tick_nohz_full_kick();
- preempt_enable();
- } else {
- /*
- * Some future tick_nohz_full_kick_task()
- * should optimize this.
- */
- tick_nohz_full_kick_all();
- }
- }
+ if (!atomic_fetch_or(BIT(bit), &tsk->tick_dep_mask))
+ tick_nohz_kick_task(tsk);
}
EXPORT_SYMBOL_GPL(tick_nohz_dep_set_task);
^ permalink raw reply [flat|nested] 4+ messages in thread* [patch 2/3] nohz: change signal tick dependency to wakeup CPUs of member tasks
2021-01-28 18:40 [patch 0/3] nohz_full: only wakeup target CPUs when notifying new tick dependency (v4) Marcelo Tosatti
2021-01-28 18:40 ` [patch 1/3] nohz: only wakeup a single target cpu when kicking a task Marcelo Tosatti
@ 2021-01-28 18:40 ` Marcelo Tosatti
2021-01-28 18:40 ` [patch 3/3] nohz: tick_nohz_kick_task: only IPI if remote task is running Marcelo Tosatti
2 siblings, 0 replies; 4+ messages in thread
From: Marcelo Tosatti @ 2021-01-28 18:40 UTC (permalink / raw)
To: Peter Zijlstra, Frederic Weisbecker; +Cc: linux-kernel, Marcelo Tosatti
Rather than waking up all nohz_full CPUs on the system, only wakeup
the target CPUs of member threads of the signal.
Reduces interruptions to nohz_full CPUs.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: linux-2.6/kernel/time/tick-sched.c
===================================================================
--- linux-2.6.orig/kernel/time/tick-sched.c
+++ linux-2.6/kernel/time/tick-sched.c
@@ -446,7 +446,17 @@ EXPORT_SYMBOL_GPL(tick_nohz_dep_clear_ta
*/
void tick_nohz_dep_set_signal(struct signal_struct *sig, enum tick_dep_bits bit)
{
- tick_nohz_dep_set_all(&sig->tick_dep_mask, bit);
+ int prev;
+
+ prev = atomic_fetch_or(BIT(bit), &sig->tick_dep_mask);
+ if (!prev) {
+ struct task_struct *t;
+
+ rcu_read_lock();
+ __for_each_thread(sig, t)
+ tick_nohz_kick_task(t);
+ rcu_read_unlock();
+ }
}
void tick_nohz_dep_clear_signal(struct signal_struct *sig, enum tick_dep_bits bit)
^ permalink raw reply [flat|nested] 4+ messages in thread* [patch 3/3] nohz: tick_nohz_kick_task: only IPI if remote task is running
2021-01-28 18:40 [patch 0/3] nohz_full: only wakeup target CPUs when notifying new tick dependency (v4) Marcelo Tosatti
2021-01-28 18:40 ` [patch 1/3] nohz: only wakeup a single target cpu when kicking a task Marcelo Tosatti
2021-01-28 18:40 ` [patch 2/3] nohz: change signal tick dependency to wakeup CPUs of member tasks Marcelo Tosatti
@ 2021-01-28 18:40 ` Marcelo Tosatti
2 siblings, 0 replies; 4+ messages in thread
From: Marcelo Tosatti @ 2021-01-28 18:40 UTC (permalink / raw)
To: Peter Zijlstra, Frederic Weisbecker; +Cc: linux-kernel, Marcelo Tosatti
If the task is not running, run_posix_cpu_timers has nothing
to elapsed, so spare IPI in that case.
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: linux-2.6/kernel/sched/core.c
===================================================================
--- linux-2.6.orig/kernel/sched/core.c
+++ linux-2.6/kernel/sched/core.c
@@ -9182,3 +9182,9 @@ void call_trace_sched_update_nr_running(
{
trace_sched_update_nr_running_tp(rq, count);
}
+
+bool task_on_rq(struct task_struct *p)
+{
+ return p->on_rq == TASK_ON_RQ_QUEUED;
+}
+
Index: linux-2.6/include/linux/sched.h
===================================================================
--- linux-2.6.orig/include/linux/sched.h
+++ linux-2.6/include/linux/sched.h
@@ -232,6 +232,8 @@ extern void io_schedule_finish(int token
extern long io_schedule_timeout(long timeout);
extern void io_schedule(void);
+extern bool task_on_rq(struct task_struct *p);
+
/**
* struct prev_cputime - snapshot of system and user cputime
* @utime: time spent in user mode
Index: linux-2.6/kernel/time/tick-sched.c
===================================================================
--- linux-2.6.orig/kernel/time/tick-sched.c
+++ linux-2.6/kernel/time/tick-sched.c
@@ -324,8 +324,6 @@ void tick_nohz_full_kick_cpu(int cpu)
static void tick_nohz_kick_task(struct task_struct *tsk)
{
- int cpu = task_cpu(tsk);
-
/*
* If the task concurrently migrates to another cpu,
* we guarantee it sees the new tick dependency upon
@@ -340,6 +338,23 @@ static void tick_nohz_kick_task(struct t
* tick_nohz_task_switch() smp_mb() (atomic_fetch_or())
* LOAD p->tick_dep_mask LOAD p->cpu
*/
+ int cpu = task_cpu(tsk);
+
+ /*
+ * If the task is not running, run_posix_cpu_timers
+ * has nothing to elapsed, can spare IPI in that
+ * case.
+ *
+ * activate_task() STORE p->tick_dep_mask
+ * STORE p->task_on_rq
+ * __schedule() (switch to task 'p') smp_mb() (atomic_fetch_or())
+ * LOCK rq->lock LOAD p->task_on_rq
+ * smp_mb__after_spin_lock()
+ * tick_nohz_task_switch()
+ * LOAD p->tick_dep_mask
+ */
+ if (!task_on_rq(tsk))
+ return;
preempt_disable();
if (cpu_online(cpu))
^ permalink raw reply [flat|nested] 4+ messages in thread