ANDROID: sched: Add find_exec_ctx helper

Add a helper to find the runnable owner down a chain of blocked waiters

This patch was broken out from a larger chain migration
patch originally by Connor O'Brien.

Cc: Joel Fernandes <joelaf@google.com>
Cc: Qais Yousef <qyousef@layalina.io>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
Cc: Valentin Schneider <vschneid@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Ben Segall <bsegall@google.com>
Cc: Zimuzo Ezeozue <zezeozue@google.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Will Deacon <will@kernel.org>
Cc: Waiman Long <longman@redhat.com>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: "Paul E. McKenney" <paulmck@kernel.org>
Cc: Metin Kaya <Metin.Kaya@arm.com>
Cc: Xuewen Yan <xuewen.yan94@gmail.com>
Cc: K Prateek Nayak <kprateek.nayak@amd.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: kernel-team@android.com
Change-Id: I0d490e9360b1e3e12498c7d05cc7f335e9c2c296
Signed-off-by: Connor O'Brien <connoro@google.com>
[jstultz: split out from larger chain migration patch]
Signed-off-by: John Stultz <jstultz@google.com>
Bug: 306081722
---
v8
* Minor formatting changes suggested by Metin Kaya
* Fix for null owner case, uncovered by enabling optimistic
  spinning
* Add null exec_ctx check to this patch from an earlier patch,
  as suggested by Metin
v10:
* Cleanup suggested by Metin to go directly to mutex owner
* Simplify logic to task_queued_on_rq suggested by Metin
This commit is contained in:
Connor O'Brien
2023-11-08 07:00:23 +00:00
committed by John Stultz
parent eb7630f95f
commit a70dd21329
4 changed files with 76 additions and 6 deletions
+43
View File
@@ -3952,6 +3952,49 @@ static void activate_blocked_waiters(struct rq *target_rq,
raw_spin_unlock_irqrestore(&owner->blocked_lock, flags);
}
}
/* XXX: Add detailed comment! */
static inline bool task_queued_on_rq(struct rq *rq, struct task_struct *task)
{
if (!task_on_rq_queued(task))
return false;
smp_rmb();
if (task_rq(task) != rq)
return false;
smp_rmb();
return task_on_rq_queued(task);
}
/*
* Returns the unblocked task at the end of the blocked chain starting with p
* if that chain is composed entirely of tasks enqueued on rq, or NULL otherwise.
*/
struct task_struct *find_exec_ctx(struct rq *rq, struct task_struct *p)
{
struct task_struct *exec_ctx, *owner;
if (!sched_proxy_exec())
return p;
lockdep_assert_rq_held(rq);
for (exec_ctx = p; task_is_blocked(exec_ctx) && !task_on_cpu(rq, exec_ctx);
exec_ctx = owner) {
owner = __mutex_owner(exec_ctx->blocked_on);
if (!owner || owner == exec_ctx)
break;
if (!task_queued_on_rq(rq, owner) || task_current_donor(rq, owner)) {
exec_ctx = NULL;
break;
}
}
return exec_ctx;
}
#else /* !CONFIG_SCHED_PROXY_EXEC */
static inline void proxy_remove_from_sleeping_owner(struct task_struct *p)
{
+13 -3
View File
@@ -2298,6 +2298,8 @@ static void migrate_task_rq_dl(struct task_struct *p, int new_cpu __maybe_unused
static void check_preempt_equal_dl(struct rq *rq, struct task_struct *p)
{
struct task_struct *exec_ctx;
/*
* Current can't be migrated, useless to reschedule,
* let's hope p can move out.
@@ -2306,12 +2308,16 @@ static void check_preempt_equal_dl(struct rq *rq, struct task_struct *p)
!cpudl_find(&rq->rd->cpudl, rq->donor, rq->curr, NULL))
return;
exec_ctx = find_exec_ctx(rq, p);
if (task_current(rq, exec_ctx))
return;
/*
* p is migratable, so let's not schedule it and
* see if it is pushed or pulled somewhere else.
*/
if (p->nr_cpus_allowed != 1 &&
cpudl_find(&rq->rd->cpudl, p, p, NULL))
cpudl_find(&rq->rd->cpudl, p, exec_ctx, NULL))
return;
resched_curr(rq);
@@ -2532,7 +2538,7 @@ static int find_later_rq(struct task_struct *sched_ctx, struct task_struct *exec
if (unlikely(!later_mask))
return -1;
if (exec_ctx->nr_cpus_allowed == 1)
if (exec_ctx && exec_ctx->nr_cpus_allowed == 1)
return -1;
/*
@@ -2611,12 +2617,16 @@ static int find_later_rq(struct task_struct *sched_ctx, struct task_struct *exec
/* Locks the rq it finds */
static struct rq *find_lock_later_rq(struct task_struct *task, struct rq *rq)
{
struct task_struct *exec_ctx;
struct rq *later_rq = NULL;
int tries;
int cpu;
for (tries = 0; tries < DL_MAX_TRIES; tries++) {
cpu = find_later_rq(task, task);
exec_ctx = find_exec_ctx(rq, task);
if (!exec_ctx)
break;
cpu = find_later_rq(task, exec_ctx);
if ((cpu == -1) || (cpu == rq->cpu))
break;
+9 -2
View File
@@ -1709,6 +1709,11 @@ static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)
!cpupri_find(&rq->rd->cpupri, rq->donor, rq->curr, NULL))
return;
/* No reason to preempt since rq->curr wouldn't change anyway */
exec_ctx = find_exec_ctx(rq, p);
if (task_current(rq, exec_ctx))
return;
/*
* p is migratable, so let's not schedule it and
* see if it is pushed or pulled somewhere else.
@@ -1911,7 +1916,7 @@ static int find_lowest_rq(struct task_struct *sched_ctx, struct task_struct *exe
if (unlikely(!lowest_mask))
return -1;
if (exec_ctx->nr_cpus_allowed == 1)
if (exec_ctx && exec_ctx->nr_cpus_allowed == 1)
return -1; /* No other targets possible */
/*
@@ -2002,12 +2007,14 @@ static int find_lowest_rq(struct task_struct *sched_ctx, struct task_struct *exe
/* Will lock the rq it finds */
static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq)
{
struct task_struct *exec_ctx;
struct rq *lowest_rq = NULL;
int tries;
int cpu;
for (tries = 0; tries < RT_MAX_TRIES; tries++) {
cpu = find_lowest_rq(task, task);
exec_ctx = find_exec_ctx(rq, task);
cpu = find_lowest_rq(task, exec_ctx);
if ((cpu == -1) || (cpu == rq->cpu))
break;
+11 -1
View File
@@ -3888,7 +3888,17 @@ bool task_is_pushable(struct rq *rq, struct task_struct *p, int cpu)
return false;
}
#endif
#ifdef CONFIG_SCHED_PROXY_EXEC
struct task_struct *find_exec_ctx(struct rq *rq, struct task_struct *p);
#else /* !CONFIG_SCHED_PROXY_EXEC */
static inline
struct task_struct *find_exec_ctx(struct rq *rq, struct task_struct *p)
{
return p;
}
#endif /* CONFIG_SCHED_PROXY_EXEC */
#endif /* CONFIG_SMP */
#ifdef CONFIG_RT_MUTEXES