sched: Introduce sched_class::pick_task()
Because sched_class::pick_next_task() also implies sched_class::set_next_task() (and possibly put_prev_task() and newidle_balance) it is not state invariant. This makes it unsuitable for remote task selection. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> [Vineeth: folded fixes] Signed-off-by: Vineeth Remanan Pillai <viremana@linux.microsoft.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Tested-by: Don Hiatt <dhiatt@digitalocean.com> Tested-by: Hongyu Ning <hongyu.ning@linux.intel.com> Tested-by: Vincent Guittot <vincent.guittot@linaro.org> Link: https://lkml.kernel.org/r/20210422123308.437092775@infradead.org
This commit is contained in:
parent
875feb41fd
commit
21f56ffe44
@ -1852,7 +1852,7 @@ static struct sched_dl_entity *pick_next_dl_entity(struct rq *rq,
|
||||
return rb_entry(left, struct sched_dl_entity, rb_node);
|
||||
}
|
||||
|
||||
static struct task_struct *pick_next_task_dl(struct rq *rq)
|
||||
static struct task_struct *pick_task_dl(struct rq *rq)
|
||||
{
|
||||
struct sched_dl_entity *dl_se;
|
||||
struct dl_rq *dl_rq = &rq->dl;
|
||||
@ -1864,7 +1864,18 @@ static struct task_struct *pick_next_task_dl(struct rq *rq)
|
||||
dl_se = pick_next_dl_entity(rq, dl_rq);
|
||||
BUG_ON(!dl_se);
|
||||
p = dl_task_of(dl_se);
|
||||
set_next_task_dl(rq, p, true);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static struct task_struct *pick_next_task_dl(struct rq *rq)
|
||||
{
|
||||
struct task_struct *p;
|
||||
|
||||
p = pick_task_dl(rq);
|
||||
if (p)
|
||||
set_next_task_dl(rq, p, true);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -2539,6 +2550,7 @@ DEFINE_SCHED_CLASS(dl) = {
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
.balance = balance_dl,
|
||||
.pick_task = pick_task_dl,
|
||||
.select_task_rq = select_task_rq_dl,
|
||||
.migrate_task_rq = migrate_task_rq_dl,
|
||||
.set_cpus_allowed = set_cpus_allowed_dl,
|
||||
|
@ -4419,6 +4419,8 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
|
||||
static void
|
||||
set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
|
||||
{
|
||||
clear_buddies(cfs_rq, se);
|
||||
|
||||
/* 'current' is not kept within the tree. */
|
||||
if (se->on_rq) {
|
||||
/*
|
||||
@ -4478,7 +4480,7 @@ pick_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *curr)
|
||||
* Avoid running the skip buddy, if running something else can
|
||||
* be done without getting too unfair.
|
||||
*/
|
||||
if (cfs_rq->skip == se) {
|
||||
if (cfs_rq->skip && cfs_rq->skip == se) {
|
||||
struct sched_entity *second;
|
||||
|
||||
if (se == curr) {
|
||||
@ -4505,8 +4507,6 @@ pick_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *curr)
|
||||
se = cfs_rq->last;
|
||||
}
|
||||
|
||||
clear_buddies(cfs_rq, se);
|
||||
|
||||
return se;
|
||||
}
|
||||
|
||||
@ -7095,6 +7095,39 @@ preempt:
|
||||
set_last_buddy(se);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static struct task_struct *pick_task_fair(struct rq *rq)
|
||||
{
|
||||
struct sched_entity *se;
|
||||
struct cfs_rq *cfs_rq;
|
||||
|
||||
again:
|
||||
cfs_rq = &rq->cfs;
|
||||
if (!cfs_rq->nr_running)
|
||||
return NULL;
|
||||
|
||||
do {
|
||||
struct sched_entity *curr = cfs_rq->curr;
|
||||
|
||||
/* When we pick for a remote RQ, we'll not have done put_prev_entity() */
|
||||
if (curr) {
|
||||
if (curr->on_rq)
|
||||
update_curr(cfs_rq);
|
||||
else
|
||||
curr = NULL;
|
||||
|
||||
if (unlikely(check_cfs_rq_runtime(cfs_rq)))
|
||||
goto again;
|
||||
}
|
||||
|
||||
se = pick_next_entity(cfs_rq, curr);
|
||||
cfs_rq = group_cfs_rq(se);
|
||||
} while (cfs_rq);
|
||||
|
||||
return task_of(se);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct task_struct *
|
||||
pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
|
||||
{
|
||||
@ -11298,6 +11331,7 @@ DEFINE_SCHED_CLASS(fair) = {
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
.balance = balance_fair,
|
||||
.pick_task = pick_task_fair,
|
||||
.select_task_rq = select_task_rq_fair,
|
||||
.migrate_task_rq = migrate_task_rq_fair,
|
||||
|
||||
|
@ -439,6 +439,13 @@ static void set_next_task_idle(struct rq *rq, struct task_struct *next, bool fir
|
||||
schedstat_inc(rq->sched_goidle);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static struct task_struct *pick_task_idle(struct rq *rq)
|
||||
{
|
||||
return rq->idle;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct task_struct *pick_next_task_idle(struct rq *rq)
|
||||
{
|
||||
struct task_struct *next = rq->idle;
|
||||
@ -506,6 +513,7 @@ DEFINE_SCHED_CLASS(idle) = {
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
.balance = balance_idle,
|
||||
.pick_task = pick_task_idle,
|
||||
.select_task_rq = select_task_rq_idle,
|
||||
.set_cpus_allowed = set_cpus_allowed_common,
|
||||
#endif
|
||||
|
@ -1626,7 +1626,7 @@ static struct task_struct *_pick_next_task_rt(struct rq *rq)
|
||||
return rt_task_of(rt_se);
|
||||
}
|
||||
|
||||
static struct task_struct *pick_next_task_rt(struct rq *rq)
|
||||
static struct task_struct *pick_task_rt(struct rq *rq)
|
||||
{
|
||||
struct task_struct *p;
|
||||
|
||||
@ -1634,7 +1634,17 @@ static struct task_struct *pick_next_task_rt(struct rq *rq)
|
||||
return NULL;
|
||||
|
||||
p = _pick_next_task_rt(rq);
|
||||
set_next_task_rt(rq, p, true);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static struct task_struct *pick_next_task_rt(struct rq *rq)
|
||||
{
|
||||
struct task_struct *p = pick_task_rt(rq);
|
||||
|
||||
if (p)
|
||||
set_next_task_rt(rq, p, true);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -2483,6 +2493,7 @@ DEFINE_SCHED_CLASS(rt) = {
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
.balance = balance_rt,
|
||||
.pick_task = pick_task_rt,
|
||||
.select_task_rq = select_task_rq_rt,
|
||||
.set_cpus_allowed = set_cpus_allowed_common,
|
||||
.rq_online = rq_online_rt,
|
||||
|
@ -1953,6 +1953,9 @@ struct sched_class {
|
||||
#ifdef CONFIG_SMP
|
||||
int (*balance)(struct rq *rq, struct task_struct *prev, struct rq_flags *rf);
|
||||
int (*select_task_rq)(struct task_struct *p, int task_cpu, int flags);
|
||||
|
||||
struct task_struct * (*pick_task)(struct rq *rq);
|
||||
|
||||
void (*migrate_task_rq)(struct task_struct *p, int new_cpu);
|
||||
|
||||
void (*task_woken)(struct rq *this_rq, struct task_struct *task);
|
||||
|
@ -34,15 +34,24 @@ static void set_next_task_stop(struct rq *rq, struct task_struct *stop, bool fir
|
||||
stop->se.exec_start = rq_clock_task(rq);
|
||||
}
|
||||
|
||||
static struct task_struct *pick_next_task_stop(struct rq *rq)
|
||||
static struct task_struct *pick_task_stop(struct rq *rq)
|
||||
{
|
||||
if (!sched_stop_runnable(rq))
|
||||
return NULL;
|
||||
|
||||
set_next_task_stop(rq, rq->stop, true);
|
||||
return rq->stop;
|
||||
}
|
||||
|
||||
static struct task_struct *pick_next_task_stop(struct rq *rq)
|
||||
{
|
||||
struct task_struct *p = pick_task_stop(rq);
|
||||
|
||||
if (p)
|
||||
set_next_task_stop(rq, p, true);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
enqueue_task_stop(struct rq *rq, struct task_struct *p, int flags)
|
||||
{
|
||||
@ -123,6 +132,7 @@ DEFINE_SCHED_CLASS(stop) = {
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
.balance = balance_stop,
|
||||
.pick_task = pick_task_stop,
|
||||
.select_task_rq = select_task_rq_stop,
|
||||
.set_cpus_allowed = set_cpus_allowed_common,
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user