Skip to content

Commit 530bfad

Browse files
Hao JiaPeter Zijlstra
authored andcommitted
sched/core: Avoid selecting the task that is throttled to run when core-sched enable
When {rt, cfs}_rq or dl task is throttled, since cookied tasks are not dequeued from the core tree, So sched_core_find() and sched_core_next() may return throttled task, which may cause throttled task to run on the CPU. So we add checks in sched_core_find() and sched_core_next() to make sure that the return is a runnable task that is not throttled. Co-developed-by: Cruz Zhao <CruzZhao@linux.alibaba.com> Signed-off-by: Cruz Zhao <CruzZhao@linux.alibaba.com> Signed-off-by: Hao Jia <jiahao.os@bytedance.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r/20230316081806.69544-1-jiahao.os@bytedance.com
1 parent d91e15a commit 530bfad

File tree

5 files changed

+90
-19
lines changed

5 files changed

+90
-19
lines changed

kernel/sched/core.c

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -261,36 +261,51 @@ void sched_core_dequeue(struct rq *rq, struct task_struct *p, int flags)
261261
resched_curr(rq);
262262
}
263263

264-
/*
265-
* Find left-most (aka, highest priority) task matching @cookie.
266-
*/
267-
static struct task_struct *sched_core_find(struct rq *rq, unsigned long cookie)
264+
static int sched_task_is_throttled(struct task_struct *p, int cpu)
268265
{
269-
struct rb_node *node;
270-
271-
node = rb_find_first((void *)cookie, &rq->core_tree, rb_sched_core_cmp);
272-
/*
273-
* The idle task always matches any cookie!
274-
*/
275-
if (!node)
276-
return idle_sched_class.pick_task(rq);
266+
if (p->sched_class->task_is_throttled)
267+
return p->sched_class->task_is_throttled(p, cpu);
277268

278-
return __node_2_sc(node);
269+
return 0;
279270
}
280271

281272
static struct task_struct *sched_core_next(struct task_struct *p, unsigned long cookie)
282273
{
283274
struct rb_node *node = &p->core_node;
275+
int cpu = task_cpu(p);
276+
277+
do {
278+
node = rb_next(node);
279+
if (!node)
280+
return NULL;
281+
282+
p = __node_2_sc(node);
283+
if (p->core_cookie != cookie)
284+
return NULL;
285+
286+
} while (sched_task_is_throttled(p, cpu));
287+
288+
return p;
289+
}
290+
291+
/*
292+
* Find left-most (aka, highest priority) and unthrottled task matching @cookie.
293+
* If no suitable task is found, NULL will be returned.
294+
*/
295+
static struct task_struct *sched_core_find(struct rq *rq, unsigned long cookie)
296+
{
297+
struct task_struct *p;
298+
struct rb_node *node;
284299

285-
node = rb_next(node);
300+
node = rb_find_first((void *)cookie, &rq->core_tree, rb_sched_core_cmp);
286301
if (!node)
287302
return NULL;
288303

289-
p = container_of(node, struct task_struct, core_node);
290-
if (p->core_cookie != cookie)
291-
return NULL;
304+
p = __node_2_sc(node);
305+
if (!sched_task_is_throttled(p, rq->cpu))
306+
return p;
292307

293-
return p;
308+
return sched_core_next(p, cookie);
294309
}
295310

296311
/*
@@ -6236,7 +6251,7 @@ static bool try_steal_cookie(int this, int that)
62366251
goto unlock;
62376252

62386253
p = sched_core_find(src, cookie);
6239-
if (p == src->idle)
6254+
if (!p)
62406255
goto unlock;
62416256

62426257
do {
@@ -6248,6 +6263,13 @@ static bool try_steal_cookie(int this, int that)
62486263

62496264
if (p->core_occupation > dst->idle->core_occupation)
62506265
goto next;
6266+
/*
6267+
* sched_core_find() and sched_core_next() will ensure that task @p
6268+
* is not throttled now, we also need to check whether the runqueue
6269+
* of the destination CPU is being throttled.
6270+
*/
6271+
if (sched_task_is_throttled(p, this))
6272+
goto next;
62516273

62526274
deactivate_task(src, p, 0);
62536275
set_task_cpu(p, this);

kernel/sched/deadline.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2704,6 +2704,13 @@ static void prio_changed_dl(struct rq *rq, struct task_struct *p,
27042704
#endif
27052705
}
27062706

2707+
#ifdef CONFIG_SCHED_CORE
2708+
static int task_is_throttled_dl(struct task_struct *p, int cpu)
2709+
{
2710+
return p->dl.dl_throttled;
2711+
}
2712+
#endif
2713+
27072714
DEFINE_SCHED_CLASS(dl) = {
27082715

27092716
.enqueue_task = enqueue_task_dl,
@@ -2736,6 +2743,9 @@ DEFINE_SCHED_CLASS(dl) = {
27362743
.switched_to = switched_to_dl,
27372744

27382745
.update_curr = update_curr_dl,
2746+
#ifdef CONFIG_SCHED_CORE
2747+
.task_is_throttled = task_is_throttled_dl,
2748+
#endif
27392749
};
27402750

27412751
/* Used for dl_bw check and update, used under sched_rt_handler()::mutex */

kernel/sched/fair.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11933,6 +11933,18 @@ bool cfs_prio_less(const struct task_struct *a, const struct task_struct *b,
1193311933

1193411934
return delta > 0;
1193511935
}
11936+
11937+
static int task_is_throttled_fair(struct task_struct *p, int cpu)
11938+
{
11939+
struct cfs_rq *cfs_rq;
11940+
11941+
#ifdef CONFIG_FAIR_GROUP_SCHED
11942+
cfs_rq = task_group(p)->cfs_rq[cpu];
11943+
#else
11944+
cfs_rq = &cpu_rq(cpu)->cfs;
11945+
#endif
11946+
return throttled_hierarchy(cfs_rq);
11947+
}
1193611948
#else
1193711949
static inline void task_tick_core(struct rq *rq, struct task_struct *curr) {}
1193811950
#endif
@@ -12559,6 +12571,10 @@ DEFINE_SCHED_CLASS(fair) = {
1255912571
.task_change_group = task_change_group_fair,
1256012572
#endif
1256112573

12574+
#ifdef CONFIG_SCHED_CORE
12575+
.task_is_throttled = task_is_throttled_fair,
12576+
#endif
12577+
1256212578
#ifdef CONFIG_UCLAMP_TASK
1256312579
.uclamp_enabled = 1,
1256412580
#endif

kernel/sched/rt.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2677,6 +2677,21 @@ static unsigned int get_rr_interval_rt(struct rq *rq, struct task_struct *task)
26772677
return 0;
26782678
}
26792679

2680+
#ifdef CONFIG_SCHED_CORE
2681+
static int task_is_throttled_rt(struct task_struct *p, int cpu)
2682+
{
2683+
struct rt_rq *rt_rq;
2684+
2685+
#ifdef CONFIG_RT_GROUP_SCHED
2686+
rt_rq = task_group(p)->rt_rq[cpu];
2687+
#else
2688+
rt_rq = &cpu_rq(cpu)->rt;
2689+
#endif
2690+
2691+
return rt_rq_throttled(rt_rq);
2692+
}
2693+
#endif
2694+
26802695
DEFINE_SCHED_CLASS(rt) = {
26812696

26822697
.enqueue_task = enqueue_task_rt,
@@ -2710,6 +2725,10 @@ DEFINE_SCHED_CLASS(rt) = {
27102725

27112726
.update_curr = update_curr_rt,
27122727

2728+
#ifdef CONFIG_SCHED_CORE
2729+
.task_is_throttled = task_is_throttled_rt,
2730+
#endif
2731+
27132732
#ifdef CONFIG_UCLAMP_TASK
27142733
.uclamp_enabled = 1,
27152734
#endif

kernel/sched/sched.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2224,6 +2224,10 @@ struct sched_class {
22242224
#ifdef CONFIG_FAIR_GROUP_SCHED
22252225
void (*task_change_group)(struct task_struct *p);
22262226
#endif
2227+
2228+
#ifdef CONFIG_SCHED_CORE
2229+
int (*task_is_throttled)(struct task_struct *p, int cpu);
2230+
#endif
22272231
};
22282232

22292233
static inline void put_prev_task(struct rq *rq, struct task_struct *prev)

0 commit comments

Comments
 (0)