lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ