linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 0/3] nohz_full: only wakeup target CPUs when notifying new tick dependency (v4)
@ 2021-01-28 18:40 Marcelo Tosatti
  2021-01-28 18:40 ` [patch 1/3] nohz: only wakeup a single target cpu when kicking a task Marcelo Tosatti
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Marcelo Tosatti @ 2021-01-28 18:40 UTC (permalink / raw)
  To: Peter Zijlstra, Frederic Weisbecker; +Cc: linux-kernel

When enabling per-CPU posix timers, an IPI to nohz_full CPUs might be
performed (to re-read the dependencies and possibly not re-enter
nohz_full on a given CPU).

A common case is for applications that run on nohz_full= CPUs
to not use POSIX timers (eg DPDK). This patch changes the notification
to only IPI the target CPUs where the task(s) whose tick dependencies
are being updated are executing.

This reduces interruptions to nohz_full= CPUs.

v4: only IPI if the remote task is on the remote runqueue (PeterZ/Frederic)
v3: replace superfluous rcu_read_lock with lockdep_assert (PeterZ)



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [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

end of thread, other threads:[~2021-01-28 19:30 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [patch 3/3] nohz: tick_nohz_kick_task: only IPI if remote task is running Marcelo Tosatti

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).