mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Yuri Andriaccio <yurand2000@gmail.com>
To: Ingo Molnar <mingo@redhat.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Juri Lelli <juri.lelli@redhat.com>,
	Vincent Guittot <vincent.guittot@linaro.org>,
	Dietmar Eggemann <dietmar.eggemann@arm.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	Ben Segall <bsegall@google.com>, Mel Gorman <mgorman@suse.de>,
	Valentin Schneider <vschneid@redhat.com>
Cc: linux-kernel@vger.kernel.org,
	Luca Abeni <luca.abeni@santannapisa.it>,
	Yuri Andriaccio <yuri.andriaccio@santannapisa.it>
Subject: [RFC PATCH v4 22/28] sched/deadline: Introduce dl_server_try_pull_f
Date: Mon,  1 Dec 2025 13:41:55 +0100	[thread overview]
Message-ID: <20251201124205.11169-23-yurand2000@gmail.com> (raw)
In-Reply-To: <20251201124205.11169-1-yurand2000@gmail.com>

Introduce a new deadline server callback, dl_server_try_pull_f, that
attempts to pull some tasks from other runqueues and returns true if after
this operation the runqueue is not empty.
This function is needed by some scheduling algorithms to guarantee that
they are work-conserving (i.e. whenever there is an idle CPU and a ready
task, this must be immediately scheduled there) or to enforce some other
properties of the scheduling algorithm used on the served runqueue (for
example, for a fixed-priority scheduler the m highest-priority tasks must
be scheduled).

The function is called whenever the dl_server_timer (the runtime
replenishment timer) expires and the deadline server is recharged.
The idea behind this callback is that since the deadline server is being
unthrottled and is becoming able to serve its runqueue, it should
pull tasks from the other runqueues (if there are no runnable tasks on its
own runqueue, or if the tasks on its runqueue have low priority).

The interface of the function provides a sched_dl_entity pointer, i.e. the
deadline server and expects to return true if there are runnable tasks on
that server (also just pulled from other runqueues), false otherwise.

The replenishment timer callback, if there are no runnable tasks for a
given server, will replenish its bandwidth and then stop it.

This callback is not relevant for fair deadline servers.

This fixes the test case where a single hog process, in a cgroup with
reservation 10ms/100ms, runs (without this patch) on only one CPU, while
(with this patch), by definition of the global Fixed Priority scheduling
algorithm, it must run on all (up to a utilization of 100ms/100ms) the
CPUs of the machine.

Co-developed-by: luca abeni <luca.abeni@santannapisa.it>
Signed-off-by: luca abeni <luca.abeni@santannapisa.it>
Signed-off-by: Yuri Andriaccio <yurand2000@gmail.com>
---
 include/linux/sched.h   |  3 ++-
 kernel/sched/deadline.c | 12 ++++++++++++
 kernel/sched/fair.c     |  8 +++++++-
 kernel/sched/rt.c       | 13 ++++++++++++-
 kernel/sched/sched.h    |  6 ++++++
 5 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index 9ef7797983..62b8586d4f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -633,7 +633,7 @@ struct sched_rt_entity {
 #endif
 } __randomize_layout;
 
-typedef bool (*dl_server_has_tasks_f)(struct sched_dl_entity *);
+typedef bool (*dl_server_try_pull_f)(struct sched_dl_entity *);
 typedef struct task_struct *(*dl_server_pick_f)(struct sched_dl_entity *);
 
 struct sched_dl_entity {
@@ -734,6 +734,7 @@ struct sched_dl_entity {
 	struct dl_rq			*dl_rq;
 	struct rq			*my_q;
 	dl_server_pick_f		server_pick_task;
+	dl_server_try_pull_f		server_try_pull_task;
 
 #ifdef CONFIG_RT_MUTEXES
 	/*
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 082bccc30b..a588fe3bbf 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -1295,6 +1295,7 @@ static const u64 dl_server_min_res = 1 * NSEC_PER_MSEC;
 static enum hrtimer_restart dl_server_timer(struct hrtimer *timer, struct sched_dl_entity *dl_se)
 {
 	struct rq *rq = rq_of_dl_se(dl_se);
+	bool is_active;
 	u64 fw;
 
 	scoped_guard (rq_lock, rq) {
@@ -1309,6 +1310,15 @@ static enum hrtimer_restart dl_server_timer(struct hrtimer *timer, struct sched_
 		if (!dl_se->dl_runtime)
 			return HRTIMER_NORESTART;
 
+		rq_unpin_lock(rq, rf);
+		is_active = dl_se->server_try_pull_task(dl_se);
+		rq_repin_lock(rq, rf);
+		if (!is_active) {
+			replenish_dl_entity(dl_se);
+			dl_server_stop(dl_se);
+			return HRTIMER_NORESTART;
+		}
+
 		if (dl_se->dl_defer_armed) {
 			/*
 			 * First check if the server could consume runtime in background.
@@ -1712,10 +1722,12 @@ void dl_server_stop(struct sched_dl_entity *dl_se)
 
 void dl_server_init(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq,
 		    struct rq *served_rq,
+		    dl_server_try_pull_f try_pull_task,
 		    dl_server_pick_f pick_task)
 {
 	dl_se->dl_rq = dl_rq;
 	dl_se->my_q  = served_rq;
+	dl_se->server_try_pull_task = try_pull_task;
 	dl_se->server_pick_task = pick_task;
 }
 
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 9c724d8232..dad46f6bd4 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -8957,6 +8957,11 @@ static struct task_struct *__pick_next_task_fair(struct rq *rq, struct task_stru
 	return pick_next_task_fair(rq, prev, NULL);
 }
 
+static bool fair_server_try_pull_task(struct sched_dl_entity *dl_se)
+{
+	return true;
+}
+
 static struct task_struct *fair_server_pick_task(struct sched_dl_entity *dl_se)
 {
 	return pick_task_fair(dl_se->my_q);
@@ -8968,7 +8973,8 @@ void fair_server_init(struct rq *rq)
 
 	init_dl_entity(dl_se);
 
-	dl_server_init(dl_se, &rq->dl, rq, fair_server_pick_task);
+	dl_server_init(dl_se, &rq->dl, rq,
+		       fair_server_try_pull_task, fair_server_pick_task);
 }
 
 /*
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index e2b67f8309..80580b48ab 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -134,6 +134,16 @@ void free_rt_sched_group(struct task_group *tg)
 static struct sched_rt_entity *pick_next_rt_entity(struct rt_rq *rt_rq);
 static inline void set_next_task_rt(struct rq *rq, struct task_struct *p, bool first);
 
+static bool rt_server_try_pull(struct sched_dl_entity *dl_se)
+{
+	struct rt_rq *rt_rq = &dl_se->my_q->rt;
+
+	if (dl_se->my_q->rt.rt_nr_running == 0)
+		group_pull_rt_task(rt_rq);
+
+	return dl_se->my_q->rt.rt_nr_running > 0;
+}
+
 static struct task_struct *rt_server_pick(struct sched_dl_entity *dl_se)
 {
 	struct rt_rq *rt_rq = &dl_se->my_q->rt;
@@ -235,7 +245,8 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
 		dl_se->dl_density = to_ratio(dl_se->dl_period, dl_se->dl_runtime);
 		dl_se->dl_server = 1;
 
-		dl_server_init(dl_se, &cpu_rq(i)->dl, s_rq, rt_server_pick);
+		dl_server_init(dl_se, &cpu_rq(i)->dl, s_rq,
+			       rt_server_try_pull, rt_server_pick);
 	}
 
 	return 1;
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index c8eac719eb..c069f6fef0 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -363,6 +363,11 @@ extern s64 dl_scaled_delta_exec(struct rq *rq, struct sched_dl_entity *dl_se, s6
  *
  *   dl_se::rq -- runqueue we belong to.
  *
+ *   dl_se::server_try_pull() -- used on bandwidth enforcement; the server has a
+ *				 chance to pull tasks from the other runqueues,
+ *				 otherwise it is stopped if there is no task to
+ *				 run.
+ *
  *   dl_se::server_pick() -- nested pick_next_task(); we yield the period if this
  *                           returns NULL.
  *
@@ -408,6 +413,7 @@ extern void dl_server_start(struct sched_dl_entity *dl_se);
 extern void dl_server_stop(struct sched_dl_entity *dl_se);
 extern void dl_server_init(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq,
 		    struct rq *served_rq,
+		    dl_server_try_pull_f try_pull_task,
 		    dl_server_pick_f pick_task);
 extern void sched_init_dl_servers(void);
 extern int dl_check_tg(unsigned long total);
-- 
2.51.0


  parent reply	other threads:[~2025-12-01 12:42 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-01 12:41 [RFC PATCH v4 00/28] Hierarchical Constant Bandwidth Server Yuri Andriaccio
2025-12-01 12:41 ` [RFC PATCH v4 01/28] sched/deadline: Do not access dl_se->rq directly Yuri Andriaccio
2026-01-14 11:03   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 02/28] sched/deadline: Distinct between dl_rq and my_q Yuri Andriaccio
2026-01-14 16:10   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 03/28] sched/rt: Pass an rt_rq instead of an rq where needed Yuri Andriaccio
2026-01-15 14:33   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 04/28] sched/rt: Move some functions from rt.c to sched.h Yuri Andriaccio
2026-01-15 14:40   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 05/28] sched/rt: Disable RT_GROUP_SCHED Yuri Andriaccio
2026-01-15 15:56   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 06/28] sched/rt: Remove rq field in struct rt_rq Yuri Andriaccio
2026-01-15 16:12   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 07/28] sched/rt: Introduce HCBS specific structs in task_group Yuri Andriaccio
2026-01-16 13:50   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 08/28] sched/core: Initialize HCBS specific structures Yuri Andriaccio
2026-01-16 14:09   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 09/28] sched/deadline: Add dl_init_tg Yuri Andriaccio
2026-01-16 15:02   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 10/28] sched/rt: Add {alloc/free}_rt_sched_group Yuri Andriaccio
2026-01-19 13:49   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 11/28] sched/deadline: Account rt-cgroups bandwidth in deadline tasks schedulability tests Yuri Andriaccio
2026-01-19 14:00   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 12/28] sched/rt: Implement dl-server operations for rt-cgroups Yuri Andriaccio
2026-01-19 15:01   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 13/28] sched/rt: Update task event callbacks for HCBS scheduling Yuri Andriaccio
2026-01-21  9:46   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 14/28] sched/rt: Update rt-cgroup schedulability checks Yuri Andriaccio
2026-01-21 10:21   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 15/28] sched/rt: Allow zeroing the runtime of the root control group Yuri Andriaccio
2026-01-21 10:32   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 16/28] sched/rt: Remove old RT_GROUP_SCHED data structures Yuri Andriaccio
2026-01-21 10:41   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 17/28] sched/core: Cgroup v2 support Yuri Andriaccio
2026-01-21 10:51   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 18/28] sched/rt: Remove support for cgroups-v1 Yuri Andriaccio
2026-01-21 11:08   ` Juri Lelli
2025-12-01 12:41 ` [RFC PATCH v4 19/28] sched/deadline: Allow deeper hierarchies of RT cgroups Yuri Andriaccio
2025-12-01 12:41 ` [RFC PATCH v4 20/28] sched/rt: Add rt-cgroup migration Yuri Andriaccio
2025-12-01 12:41 ` [RFC PATCH v4 21/28] sched/rt: Add HCBS migration related checks and function calls Yuri Andriaccio
2025-12-01 12:41 ` Yuri Andriaccio [this message]
2025-12-01 12:41 ` [RFC PATCH v4 23/28] sched/deadline: Fix HCBS migrations on server stop Yuri Andriaccio
2025-12-01 12:41 ` [RFC PATCH v4 24/28] sched/core: Execute enqueued balance callbacks when changing allowed CPUs Yuri Andriaccio
2025-12-01 12:41 ` [RFC PATCH v4 25/28] sched/core: Execute enqueued balance callbacks when migrating task betweeen cgroups Yuri Andriaccio
2025-12-01 12:41 ` [RFC PATCH v4 26/28] Documentation: Update documentation for real-time cgroups Yuri Andriaccio
2025-12-01 12:42 ` [RFC PATCH v4 27/28] [DEBUG] sched/rt: Add debug BUG_ONs for pre-migration code Yuri Andriaccio
2025-12-01 12:42 ` [RFC PATCH v4 28/28] [DEBUG] sched/rt: Add debug BUG_ONs in migration code Yuri Andriaccio

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251201124205.11169-23-yurand2000@gmail.com \
    --to=yurand2000@gmail.com \
    --cc=bsegall@google.com \
    --cc=dietmar.eggemann@arm.com \
    --cc=juri.lelli@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luca.abeni@santannapisa.it \
    --cc=mgorman@suse.de \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=vincent.guittot@linaro.org \
    --cc=vschneid@redhat.com \
    --cc=yuri.andriaccio@santannapisa.it \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome