[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20230821094927.51079-3-jiahao.os@bytedance.com>
Date: Mon, 21 Aug 2023 17:49:27 +0800
From: Hao Jia <jiahao.os@...edance.com>
To: mingo@...hat.com, peterz@...radead.org, mingo@...nel.org,
juri.lelli@...hat.com, vincent.guittot@...aro.org,
dietmar.eggemann@....com, rostedt@...dmis.org, bsegall@...gle.com,
mgorman@...e.de, bristot@...hat.com, vschneid@...hat.com,
pauld@...hat.com
Cc: linux-kernel@...r.kernel.org, Hao Jia <jiahao.os@...edance.com>
Subject: [PATCH 2/2] sched/rt: Block nohz tick_stop when rt bandwidth in use
The commit 88c56cfeaec4 ("sched/fair: Block nohz tick_stop
when cfs bandwidth in use") has been merged. It can handle
conflicts between NOHZ full and cfs_bandwidth, and the
scheduler feature HZ_BW allows us to choose which one to prefer.
This problem also exists between NOHZ full and rt_bandwidth.
Now when there is only one RR task or only FIFO tasks on
the NOHZ full cpu, NOHZ full will stop tick even though
those tasks are constrained by rt_bandwidth. This makes It
very easy for RT tasks to run longer than the rt_bandwidth
runtime limit. This may cause rt bandwidth limit not timely
and CFS task starvation for a long time.
Similar to the commit above, we also add a check in
pick_next_task_rt(), which updates the tick dependency
status according to whether the task to be run is
constrained by rt_bandwidth.
Add check in sched_can_stop_tick() to cover some
edge cases such as rq nr_running going from 2->1 without
going through pick_next_task_rt() and the 1 remains
the running RT task.
Signed-off-by: Hao Jia <jiahao.os@...edance.com>
---
kernel/sched/rt.c | 61 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 57 insertions(+), 4 deletions(-)
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 0b9e9467ef61..f55ce6935a80 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1741,7 +1741,31 @@ static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flag
}
#ifdef CONFIG_NO_HZ_FULL
-static bool can_stop_tick_rt(struct rq *rq, int *stop_next)
+/*
+ * If the scheduler feature HZ_BW is enabled, we need to further
+ * check whether task @p is constrained by RT bandwidth to decide
+ * whether to stop tick.
+ */
+static inline bool rt_task_bw_constrained(struct task_struct *p)
+{
+ struct rt_rq *rt_rq;
+
+ if (!sched_feat(HZ_BW))
+ return false;
+
+ if (rt_bandwidth_enabled())
+ return true;
+
+ if (p->sched_class == &rt_sched_class && task_on_rq_queued(p)) {
+ rt_rq = rt_rq_of_se(&p->rt);
+ if (sched_rt_runtime(rt_rq) != RUNTIME_INF)
+ return true;
+ }
+
+ return false;
+}
+
+static bool __can_stop_tick_rt(struct rq *rq, struct task_struct *p, int *stop_next)
{
int fifo_nr_running;
@@ -1751,7 +1775,7 @@ static bool can_stop_tick_rt(struct rq *rq, int *stop_next)
*/
if (rq->rt.rr_nr_running) {
*stop_next = 1;
- if (rq->rt.rr_nr_running == 1)
+ if (rq->rt.rr_nr_running == 1 && !rt_task_bw_constrained(p))
return true;
else
return false;
@@ -1764,11 +1788,38 @@ static bool can_stop_tick_rt(struct rq *rq, int *stop_next)
fifo_nr_running = rq->rt.rt_nr_running - rq->rt.rr_nr_running;
if (fifo_nr_running) {
*stop_next = 1;
- return true;
+ if (!rt_task_bw_constrained(p))
+ return true;
+ else
+ return false;
}
return true;
}
+
+static bool can_stop_tick_rt(struct rq *rq, int *stop_next)
+{
+ bool ret;
+
+ ret = __can_stop_tick_rt(rq, rq->curr, stop_next);
+ if (stop_next)
+ return ret;
+
+ return true;
+}
+static void sched_rt_update_stop_tick(struct rq *rq, struct task_struct *p)
+{
+ int cpu = cpu_of(rq);
+ int unused;
+
+ if (!sched_feat(HZ_BW) || !tick_nohz_full_cpu(cpu))
+ return;
+
+ if (!__can_stop_tick_rt(rq, p, &unused))
+ tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_SCHED);
+}
+#else /* CONFIG_NO_HZ_FULL */
+static inline void sched_rt_update_stop_tick(struct rq *rq, struct task_struct *p) {}
#endif
static inline void set_next_task_rt(struct rq *rq, struct task_struct *p, bool first)
@@ -1846,8 +1897,10 @@ static struct task_struct *pick_next_task_rt(struct rq *rq)
{
struct task_struct *p = pick_task_rt(rq);
- if (p)
+ if (p) {
+ sched_rt_update_stop_tick(rq, p);
set_next_task_rt(rq, p, true);
+ }
return p;
}
--
2.39.2
Powered by blists - more mailing lists