Skip to content

Commit 2e0199d

Browse files
author
Peter Zijlstra
committed
sched/fair: Prepare exit/cleanup paths for delayed_dequeue
When dequeue_task() is delayed it becomes possible to exit a task (or cgroup) that is still enqueued. Ensure things are dequeued before freeing. Thanks to Valentin for asking the obvious questions and making switched_from_fair() less weird. Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Valentin Schneider <[email protected]> Tested-by: Valentin Schneider <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent e28b5f8 commit 2e0199d

File tree

1 file changed

+46
-13
lines changed

1 file changed

+46
-13
lines changed

kernel/sched/fair.c

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8342,7 +8342,21 @@ static void migrate_task_rq_fair(struct task_struct *p, int new_cpu)
83428342

83438343
static void task_dead_fair(struct task_struct *p)
83448344
{
8345-
remove_entity_load_avg(&p->se);
8345+
struct sched_entity *se = &p->se;
8346+
8347+
if (se->sched_delayed) {
8348+
struct rq_flags rf;
8349+
struct rq *rq;
8350+
8351+
rq = task_rq_lock(p, &rf);
8352+
if (se->sched_delayed) {
8353+
update_rq_clock(rq);
8354+
dequeue_entities(rq, se, DEQUEUE_SLEEP | DEQUEUE_DELAYED);
8355+
}
8356+
task_rq_unlock(rq, p, &rf);
8357+
}
8358+
8359+
remove_entity_load_avg(se);
83468360
}
83478361

83488362
/*
@@ -12854,10 +12868,22 @@ static void attach_task_cfs_rq(struct task_struct *p)
1285412868
static void switched_from_fair(struct rq *rq, struct task_struct *p)
1285512869
{
1285612870
detach_task_cfs_rq(p);
12871+
/*
12872+
* Since this is called after changing class, this is a little weird
12873+
* and we cannot use DEQUEUE_DELAYED.
12874+
*/
12875+
if (p->se.sched_delayed) {
12876+
dequeue_task(rq, p, DEQUEUE_NOCLOCK | DEQUEUE_SLEEP);
12877+
p->se.sched_delayed = 0;
12878+
if (sched_feat(DELAY_ZERO) && p->se.vlag > 0)
12879+
p->se.vlag = 0;
12880+
}
1285712881
}
1285812882

1285912883
static void switched_to_fair(struct rq *rq, struct task_struct *p)
1286012884
{
12885+
SCHED_WARN_ON(p->se.sched_delayed);
12886+
1286112887
attach_task_cfs_rq(p);
1286212888

1286312889
set_task_max_allowed_capacity(p);
@@ -13008,28 +13034,35 @@ void online_fair_sched_group(struct task_group *tg)
1300813034

1300913035
void unregister_fair_sched_group(struct task_group *tg)
1301013036
{
13011-
unsigned long flags;
13012-
struct rq *rq;
1301313037
int cpu;
1301413038

1301513039
destroy_cfs_bandwidth(tg_cfs_bandwidth(tg));
1301613040

1301713041
for_each_possible_cpu(cpu) {
13018-
if (tg->se[cpu])
13019-
remove_entity_load_avg(tg->se[cpu]);
13042+
struct cfs_rq *cfs_rq = tg->cfs_rq[cpu];
13043+
struct sched_entity *se = tg->se[cpu];
13044+
struct rq *rq = cpu_rq(cpu);
13045+
13046+
if (se) {
13047+
if (se->sched_delayed) {
13048+
guard(rq_lock_irqsave)(rq);
13049+
if (se->sched_delayed) {
13050+
update_rq_clock(rq);
13051+
dequeue_entities(rq, se, DEQUEUE_SLEEP | DEQUEUE_DELAYED);
13052+
}
13053+
list_del_leaf_cfs_rq(cfs_rq);
13054+
}
13055+
remove_entity_load_avg(se);
13056+
}
1302013057

1302113058
/*
1302213059
* Only empty task groups can be destroyed; so we can speculatively
1302313060
* check on_list without danger of it being re-added.
1302413061
*/
13025-
if (!tg->cfs_rq[cpu]->on_list)
13026-
continue;
13027-
13028-
rq = cpu_rq(cpu);
13029-
13030-
raw_spin_rq_lock_irqsave(rq, flags);
13031-
list_del_leaf_cfs_rq(tg->cfs_rq[cpu]);
13032-
raw_spin_rq_unlock_irqrestore(rq, flags);
13062+
if (cfs_rq->on_list) {
13063+
guard(rq_lock_irqsave)(rq);
13064+
list_del_leaf_cfs_rq(cfs_rq);
13065+
}
1303313066
}
1303413067
}
1303513068

0 commit comments

Comments
 (0)