All of lore.kernel.org
 help / color / mirror / Atom feed
* sched/deadline: Server stops while fair tasks are still runnable
@ 2026-01-12  9:02 Gabriele Monaco
  2026-01-12 14:45 ` Juri Lelli
  0 siblings, 1 reply; 8+ messages in thread
From: Gabriele Monaco @ 2026-01-12  9:02 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra, Juri Lelli; +Cc: Clark Williams

The boost model in [1] spotted cases with fair tasks running after the server
stopped. I believe this means that it's equally possible for those tasks to
starve without the server even trying to start.

There are 2 related situation that can result in this:

1. dl_server_idle is set to true when the CPU is really idle
2. a fair task wakes up (nothing happens since the server is still active)
3. dl_server_timer stops the server since it's idle, although it isn't really

```
    <idle>-0    d.h3.  2.521220: event_boost:     -12: idle x dl_replenish -> idle
    <idle>-0    d.h3.  2.521227: event_laxity:    -12: zero_laxity_wait x dl_replenish_idle -> idle_wait
 thread3-3-580  d..4.  3.338067: event_boost:     -12: idle x dl_server_resume_throttled -> throttled
 thread3-3-580  d..3.  3.338076: sched_wakeup:    ksoftirqd/12:118 [120] CPU:012
 thread5-5-582  d.h2.  3.471237: event_boost:     -12: throttled x dl_server_stop -> stopped (final)
 thread5-5-582  d.h2.  3.471240: event_laxity:    -12: idle_wait x dl_server_stop -> stopped (final)
ktimers/12-117  d..3.  3.538088: error_boost:     -12: event sched_switch_in not expected in the state stopped
ktimers/12-117  d..2.  3.538089: sched_switch:    ktimers/12:117 [98] S ==> ksoftirqd/12:118 [120]
```


1. dl_server_timer runs when the CPU is idle but after a fair task wakes up
2. the call to update_curr sets dl_server_idle since it's only checking rq->curr
(which is indeed idle)
3. the server is stopped within the same timer call although a fair task just
woke up

```
ktimers/13-125  d.s52  7.309878: event_boost:    -12: stopped x dl_server_start -> ready
ktimers/13-125  d.s52  7.309878: event_laxity:   -12: stopped x dl_server_start -> zero_laxity_wait
ktimers/13-125  d.s42  7.309879: sched_wakeup:   kworker/u519:2:5559 [120] CPU:012
    <idle>-0    d.h3.  7.309889: event_boost:    -12: ready x dl_replenish -> ready
    <idle>-0    d.h3.  7.309889: event_laxity:   -12: zero_laxity_wait x dl_replenish_idle -> idle_wait
    <idle>-0    d.h3.  7.309890: event_boost:    -12: ready x dl_server_stop -> stopped (final)
    <idle>-0    d.h3.  7.309891: event_laxity:   -12: idle_wait x dl_server_stop -> stopped (final)
    <idle>-0    d..3.  7.309895: error_boost:    -12: event sched_switch_in not expected in the state stopped
    <idle>-0    d..2.  7.309896: sched_switch:   swapper/12:0 [120] R ==> kworker/u519:2:5559 [120]

```

In both cases, if no new fair task wakes up, the one that woke up right before
stopping the server could starve. That's a problem isn't it?

I tried a quick solution to the first case by clearing dl_server_idle every time
the server started (even if it's still active, that is at every fair wakeup) and
I think the second case could be avoided by relying on idle_cpu() instead of
looking only on rq->curr, taking also waking tasks into account (not tried).

Is this a real issue or is the monitor just too sensitive?

Thanks,
Gabriele

[1] - https://lore.kernel.org/lkml/20251205131621.135513-1-gmonaco@redhat.com


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: sched/deadline: Server stops while fair tasks are still runnable
  2026-01-12  9:02 sched/deadline: Server stops while fair tasks are still runnable Gabriele Monaco
@ 2026-01-12 14:45 ` Juri Lelli
  2026-01-13  8:52   ` [PATCH] sched/deadline: Fix server stopping with runnable tasks Gabriele Monaco
  0 siblings, 1 reply; 8+ messages in thread
From: Juri Lelli @ 2026-01-12 14:45 UTC (permalink / raw)
  To: Gabriele Monaco; +Cc: linux-kernel, Peter Zijlstra, Juri Lelli, Clark Williams

Hi Gabriele,

On 12/01/26 10:02, Gabriele Monaco wrote:
> The boost model in [1] spotted cases with fair tasks running after the server
> stopped. I believe this means that it's equally possible for those tasks to
> starve without the server even trying to start.
> 
> There are 2 related situation that can result in this:
> 
> 1. dl_server_idle is set to true when the CPU is really idle
> 2. a fair task wakes up (nothing happens since the server is still active)
> 3. dl_server_timer stops the server since it's idle, although it isn't really
> 
> ```
>     <idle>-0    d.h3.  2.521220: event_boost:     -12: idle x dl_replenish -> idle
>     <idle>-0    d.h3.  2.521227: event_laxity:    -12: zero_laxity_wait x dl_replenish_idle -> idle_wait
>  thread3-3-580  d..4.  3.338067: event_boost:     -12: idle x dl_server_resume_throttled -> throttled
>  thread3-3-580  d..3.  3.338076: sched_wakeup:    ksoftirqd/12:118 [120] CPU:012
>  thread5-5-582  d.h2.  3.471237: event_boost:     -12: throttled x dl_server_stop -> stopped (final)
>  thread5-5-582  d.h2.  3.471240: event_laxity:    -12: idle_wait x dl_server_stop -> stopped (final)
> ktimers/12-117  d..3.  3.538088: error_boost:     -12: event sched_switch_in not expected in the state stopped
> ktimers/12-117  d..2.  3.538089: sched_switch:    ktimers/12:117 [98] S ==> ksoftirqd/12:118 [120]
> ```
> 
> 
> 1. dl_server_timer runs when the CPU is idle but after a fair task wakes up
> 2. the call to update_curr sets dl_server_idle since it's only checking rq->curr
> (which is indeed idle)
> 3. the server is stopped within the same timer call although a fair task just
> woke up
> 
> ```
> ktimers/13-125  d.s52  7.309878: event_boost:    -12: stopped x dl_server_start -> ready
> ktimers/13-125  d.s52  7.309878: event_laxity:   -12: stopped x dl_server_start -> zero_laxity_wait
> ktimers/13-125  d.s42  7.309879: sched_wakeup:   kworker/u519:2:5559 [120] CPU:012
>     <idle>-0    d.h3.  7.309889: event_boost:    -12: ready x dl_replenish -> ready
>     <idle>-0    d.h3.  7.309889: event_laxity:   -12: zero_laxity_wait x dl_replenish_idle -> idle_wait
>     <idle>-0    d.h3.  7.309890: event_boost:    -12: ready x dl_server_stop -> stopped (final)
>     <idle>-0    d.h3.  7.309891: event_laxity:   -12: idle_wait x dl_server_stop -> stopped (final)
>     <idle>-0    d..3.  7.309895: error_boost:    -12: event sched_switch_in not expected in the state stopped
>     <idle>-0    d..2.  7.309896: sched_switch:   swapper/12:0 [120] R ==> kworker/u519:2:5559 [120]
> 
> ```
> 
> In both cases, if no new fair task wakes up, the one that woke up right before
> stopping the server could starve. That's a problem isn't it?

Yeah, think so. :/

Looks like we clear dl_defer_idle only while updating the fair task
entity (which didn't happen yet in both cases above).

> I tried a quick solution to the first case by clearing dl_server_idle every time
> the server started (even if it's still active, that is at every fair wakeup) and
> I think the second case could be avoided by relying on idle_cpu() instead of
> looking only on rq->curr, taking also waking tasks into account (not tried).

Not sure if you want to wait for Peter to chime in, but if you have
patches we can definitely take a look. :)

Thanks,
Juri


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] sched/deadline: Fix server stopping with runnable tasks
  2026-01-12 14:45 ` Juri Lelli
@ 2026-01-13  8:52   ` Gabriele Monaco
  2026-01-13  9:37     ` Peter Zijlstra
  2026-01-13 10:43     ` [tip: sched/urgent] " tip-bot2 for Gabriele Monaco
  0 siblings, 2 replies; 8+ messages in thread
From: Gabriele Monaco @ 2026-01-13  8:52 UTC (permalink / raw)
  To: juri.lelli, peterz, Ingo Molnar, linux-kernel; +Cc: williams, Gabriele Monaco

The deadline server can currently stop due to idle although fair tasks
are runnable. This happens essentially when:

* the server is set to idle, a task wakes up, the server stops
* a task wakes up, the server sets itself to idle and stops right away

Address both cases by clearing the server idle flag whenever a fair task
wakes up and accounting also for pending tasks in the definition of idle.

Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
---

This is really quick and dirty but seems to fix it according to the
models. I also updated the chart to show what is happening here.
I added the same event (server_resume) to the model.

 kernel/sched/deadline.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 138136742871..1070e93350df 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -1376,7 +1376,7 @@ update_stats_dequeue_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se, int
 
 static void update_curr_dl_se(struct rq *rq, struct sched_dl_entity *dl_se, s64 delta_exec)
 {
-	bool idle = rq->curr == rq->idle;
+	bool idle = rq->curr == rq->idle && !rq->nr_running && !rq->ttwu_pending;
 	s64 scaled_delta_exec;
 
 	if (unlikely(delta_exec <= 0)) {
@@ -1560,8 +1560,8 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
  * | 8 |       B:zero_laxity-wait       |     |    |
  * |   |                                | <---+    |
  * |   +--------------------------------+          |
- * |     |              ^     ^           2        |
- * |     | 7            | 2   +--------------------+
+ * |     |              ^         ^       2        |
+ * |     | 7            | 2, 1    +----------------+
  * |     v              |
  * |   +-------------+  |
  * +-- | C:idle-wait | -+
@@ -1606,8 +1606,11 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
  *   dl_defer_idle = 0
  *
  *
- * [1] A->B, A->D
+ * [1] A->B, A->D, C->B
  * dl_server_start()
+ *   dl_defer_idle = 0;
+ *   if (dl_server_active)
+ *     return; // [B]
  *   dl_server_active = 1;
  *   enqueue_dl_entity()
  *     update_dl_entity(WAKEUP)
@@ -1741,6 +1744,7 @@ void dl_server_start(struct sched_dl_entity *dl_se)
 {
 	struct rq *rq = dl_se->rq;
 
+	dl_se->dl_defer_idle = 0;
 	if (!dl_server(dl_se) || dl_se->dl_server_active)
 		return;
 

base-commit: 0f61b1860cc3f52aef9036d7235ed1f017632193
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] sched/deadline: Fix server stopping with runnable tasks
  2026-01-13  8:52   ` [PATCH] sched/deadline: Fix server stopping with runnable tasks Gabriele Monaco
@ 2026-01-13  9:37     ` Peter Zijlstra
  2026-01-13  9:42       ` Gabriele Monaco
  2026-01-13 10:43     ` [tip: sched/urgent] " tip-bot2 for Gabriele Monaco
  1 sibling, 1 reply; 8+ messages in thread
From: Peter Zijlstra @ 2026-01-13  9:37 UTC (permalink / raw)
  To: Gabriele Monaco; +Cc: juri.lelli, Ingo Molnar, linux-kernel, williams

On Tue, Jan 13, 2026 at 09:52:01AM +0100, Gabriele Monaco wrote:
> The deadline server can currently stop due to idle although fair tasks
> are runnable. This happens essentially when:
> 
> * the server is set to idle, a task wakes up, the server stops
> * a task wakes up, the server sets itself to idle and stops right away
> 
> Address both cases by clearing the server idle flag whenever a fair task
> wakes up and accounting also for pending tasks in the definition of idle.
> 
> Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
> ---
> 
> This is really quick and dirty but seems to fix it according to the
> models. I also updated the chart to show what is happening here.
> I added the same event (server_resume) to the model.
> 
>  kernel/sched/deadline.c | 12 ++++++++----
>  1 file changed, 8 insertions(+), 4 deletions(-)
> 
> diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
> index 138136742871..1070e93350df 100644
> --- a/kernel/sched/deadline.c
> +++ b/kernel/sched/deadline.c
> @@ -1376,7 +1376,7 @@ update_stats_dequeue_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se, int
>  
>  static void update_curr_dl_se(struct rq *rq, struct sched_dl_entity *dl_se, s64 delta_exec)
>  {
> -	bool idle = rq->curr == rq->idle;
> +	bool idle = rq->curr == rq->idle && !rq->nr_running && !rq->ttwu_pending;

This is idle_cpu(), perhaps we can lift that thing into sched.h or so.

>  	s64 scaled_delta_exec;
>  
>  	if (unlikely(delta_exec <= 0)) {
> @@ -1560,8 +1560,8 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
>   * | 8 |       B:zero_laxity-wait       |     |    |
>   * |   |                                | <---+    |
>   * |   +--------------------------------+          |
> - * |     |              ^     ^           2        |
> - * |     | 7            | 2   +--------------------+
> + * |     |              ^         ^       2        |
> + * |     | 7            | 2, 1    +----------------+
>   * |     v              |
>   * |   +-------------+  |
>   * +-- | C:idle-wait | -+
> @@ -1606,8 +1606,11 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
>   *   dl_defer_idle = 0
>   *
>   *
> - * [1] A->B, A->D
> + * [1] A->B, A->D, C->B
>   * dl_server_start()
> + *   dl_defer_idle = 0;
> + *   if (dl_server_active)
> + *     return; // [B]
>   *   dl_server_active = 1;
>   *   enqueue_dl_entity()
>   *     update_dl_entity(WAKEUP)
> @@ -1741,6 +1744,7 @@ void dl_server_start(struct sched_dl_entity *dl_se)
>  {
>  	struct rq *rq = dl_se->rq;
>  
> +	dl_se->dl_defer_idle = 0;
>  	if (!dl_server(dl_se) || dl_se->dl_server_active)
>  		return;

Yeah, this seems sensible.

Let me pick it up and do that idle_cpu() thing.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] sched/deadline: Fix server stopping with runnable tasks
  2026-01-13  9:37     ` Peter Zijlstra
@ 2026-01-13  9:42       ` Gabriele Monaco
  2026-01-13  9:48         ` Peter Zijlstra
  2026-01-13  9:50         ` Juri Lelli
  0 siblings, 2 replies; 8+ messages in thread
From: Gabriele Monaco @ 2026-01-13  9:42 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: juri.lelli, Ingo Molnar, linux-kernel, williams

On Tue, 2026-01-13 at 10:37 +0100, Peter Zijlstra wrote:
> >  static void update_curr_dl_se(struct rq *rq, struct sched_dl_entity *dl_se,
> > s64 delta_exec)
> >  {
> > -	bool idle = rq->curr == rq->idle;
> > +	bool idle = rq->curr == rq->idle && !rq->nr_running && !rq-
> > >ttwu_pending;
> 
> This is idle_cpu(), perhaps we can lift that thing into sched.h or so.
> 

Yeah, that's what I meant by quick and dirty.. I have idle_cpu() on the model
side (and have them matching simplifies a lot of things).

I just wasn't sure if we wanted a function call in there. But we can probably do
something nicer without it too.

Thanks,
Gabriele


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] sched/deadline: Fix server stopping with runnable tasks
  2026-01-13  9:42       ` Gabriele Monaco
@ 2026-01-13  9:48         ` Peter Zijlstra
  2026-01-13  9:50         ` Juri Lelli
  1 sibling, 0 replies; 8+ messages in thread
From: Peter Zijlstra @ 2026-01-13  9:48 UTC (permalink / raw)
  To: Gabriele Monaco; +Cc: juri.lelli, Ingo Molnar, linux-kernel, williams

On Tue, Jan 13, 2026 at 10:42:02AM +0100, Gabriele Monaco wrote:
> On Tue, 2026-01-13 at 10:37 +0100, Peter Zijlstra wrote:
> > >  static void update_curr_dl_se(struct rq *rq, struct sched_dl_entity *dl_se,
> > > s64 delta_exec)
> > >  {
> > > -	bool idle = rq->curr == rq->idle;
> > > +	bool idle = rq->curr == rq->idle && !rq->nr_running && !rq-
> > > >ttwu_pending;
> > 
> > This is idle_cpu(), perhaps we can lift that thing into sched.h or so.
> > 
> 
> Yeah, that's what I meant by quick and dirty.. I have idle_cpu() on the model
> side (and have them matching simplifies a lot of things).
> 
> I just wasn't sure if we wanted a function call in there. But we can probably do
> something nicer without it too.

I'm test building this...

---
diff --git a/include/linux/sched.h b/include/linux/sched.h
index bf96a7d595e2..524bdc0ca53f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1869,7 +1869,6 @@ static inline int task_nice(const struct task_struct *p)
 extern int can_nice(const struct task_struct *p, const int nice);
 extern int task_curr(const struct task_struct *p);
 extern int idle_cpu(int cpu);
-extern int available_idle_cpu(int cpu);
 extern int sched_setscheduler(struct task_struct *, int, const struct sched_param *);
 extern int sched_setscheduler_nocheck(struct task_struct *, int, const struct sched_param *);
 extern void sched_set_fifo(struct task_struct *p);
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 80c9559a3e30..d06b29ae961e 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -1420,7 +1420,7 @@ update_stats_dequeue_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se, int
 
 static void update_curr_dl_se(struct rq *rq, struct sched_dl_entity *dl_se, s64 delta_exec)
 {
-	bool idle = rq->curr == rq->idle;
+	bool idle = idle_rq(rq);
 	s64 scaled_delta_exec;
 
 	if (unlikely(delta_exec <= 0)) {
@@ -1603,8 +1603,8 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
  * | 8 |       B:zero_laxity-wait       |     |    |
  * |   |                                | <---+    |
  * |   +--------------------------------+          |
- * |     |              ^     ^           2        |
- * |     | 7            | 2   +--------------------+
+ * |     |              ^         ^       2        |
+ * |     | 7            | 2, 1    +----------------+
  * |     v              |
  * |   +-------------+  |
  * +-- | C:idle-wait | -+
@@ -1649,8 +1649,11 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
  *   dl_defer_idle = 0
  *
  *
- * [1] A->B, A->D
+ * [1] A->B, A->D, C->B
  * dl_server_start()
+ *   dl_defer_idle = 0;
+ *   if (dl_server_active)
+ *     return; // [B]
  *   dl_server_active = 1;
  *   enqueue_dl_entity()
  *     update_dl_entity(WAKEUP)
@@ -1784,6 +1787,7 @@ void dl_server_start(struct sched_dl_entity *dl_se)
 {
 	struct rq *rq = dl_se->rq;
 
+	dl_se->dl_defer_idle = 0;
 	if (!dl_server(dl_se) || dl_se->dl_server_active)
 		return;
 
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 58c9d244f12b..ea791550af0e 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1380,6 +1380,28 @@ static inline u32 sched_rng(void)
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 #define raw_rq()		raw_cpu_ptr(&runqueues)
 
+static inline bool idle_rq(struct rq *rq)
+{
+	return rq->curr == rq->idle && !rq->nr_running && !rq->ttwu_pending;
+}
+
+/**
+ * available_idle_cpu - is a given CPU idle for enqueuing work.
+ * @cpu: the CPU in question.
+ *
+ * Return: 1 if the CPU is currently idle. 0 otherwise.
+ */
+static inline bool available_idle_cpu(int cpu)
+{
+	if (!idle_rq(cpu_rq(cpu)))
+		return 0;
+
+	if (vcpu_is_preempted(cpu))
+		return 0;
+
+	return 1;
+}
+
 #ifdef CONFIG_SCHED_PROXY_EXEC
 static inline void rq_set_donor(struct rq *rq, struct task_struct *t)
 {
diff --git a/kernel/sched/syscalls.c b/kernel/sched/syscalls.c
index 0496dc29ed0f..cb337de679b8 100644
--- a/kernel/sched/syscalls.c
+++ b/kernel/sched/syscalls.c
@@ -180,35 +180,7 @@ int task_prio(const struct task_struct *p)
  */
 int idle_cpu(int cpu)
 {
-	struct rq *rq = cpu_rq(cpu);
-
-	if (rq->curr != rq->idle)
-		return 0;
-
-	if (rq->nr_running)
-		return 0;
-
-	if (rq->ttwu_pending)
-		return 0;
-
-	return 1;
-}
-
-/**
- * available_idle_cpu - is a given CPU idle for enqueuing work.
- * @cpu: the CPU in question.
- *
- * Return: 1 if the CPU is currently idle. 0 otherwise.
- */
-int available_idle_cpu(int cpu)
-{
-	if (!idle_cpu(cpu))
-		return 0;
-
-	if (vcpu_is_preempted(cpu))
-		return 0;
-
-	return 1;
+	return idle_rq(cpu_rq(cpu));
 }
 
 /**

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] sched/deadline: Fix server stopping with runnable tasks
  2026-01-13  9:42       ` Gabriele Monaco
  2026-01-13  9:48         ` Peter Zijlstra
@ 2026-01-13  9:50         ` Juri Lelli
  1 sibling, 0 replies; 8+ messages in thread
From: Juri Lelli @ 2026-01-13  9:50 UTC (permalink / raw)
  To: Gabriele Monaco; +Cc: Peter Zijlstra, Ingo Molnar, linux-kernel, williams

On 13/01/26 10:42, Gabriele Monaco wrote:
> On Tue, 2026-01-13 at 10:37 +0100, Peter Zijlstra wrote:
> > >  static void update_curr_dl_se(struct rq *rq, struct sched_dl_entity *dl_se,
> > > s64 delta_exec)
> > >  {
> > > -	bool idle = rq->curr == rq->idle;
> > > +	bool idle = rq->curr == rq->idle && !rq->nr_running && !rq-
> > > >ttwu_pending;
> > 
> > This is idle_cpu(), perhaps we can lift that thing into sched.h or so.
> > 
> 
> Yeah, that's what I meant by quick and dirty.. I have idle_cpu() on the model
> side (and have them matching simplifies a lot of things).
> 
> I just wasn't sure if we wanted a function call in there. But we can probably do
> something nicer without it too.

Thanks for the patch (looks sensible to me too) and nice catch from the
model!


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [tip: sched/urgent] sched/deadline: Fix server stopping with runnable tasks
  2026-01-13  8:52   ` [PATCH] sched/deadline: Fix server stopping with runnable tasks Gabriele Monaco
  2026-01-13  9:37     ` Peter Zijlstra
@ 2026-01-13 10:43     ` tip-bot2 for Gabriele Monaco
  1 sibling, 0 replies; 8+ messages in thread
From: tip-bot2 for Gabriele Monaco @ 2026-01-13 10:43 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Gabriele Monaco, Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the sched/urgent branch of tip:

Commit-ID:     ca1e8eede4fc68ce85a9fdce1a6c13ad64933318
Gitweb:        https://git.kernel.org/tip/ca1e8eede4fc68ce85a9fdce1a6c13ad64933318
Author:        Gabriele Monaco <gmonaco@redhat.com>
AuthorDate:    Tue, 13 Jan 2026 09:52:01 +01:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Tue, 13 Jan 2026 11:37:52 +01:00

sched/deadline: Fix server stopping with runnable tasks

The deadline server can currently stop due to idle although fair tasks
are runnable. This happens essentially when:

 * the server is set to idle, a task wakes up, the server stops
 * a task wakes up, the server sets itself to idle and stops right away

Address both cases by clearing the server idle flag whenever a fair task
wakes up and accounting also for pending tasks in the definition of idle.

Fixes: f5a538c07df2 ("sched/deadline: Fix dl_server stop condition")
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260113085159.114226-3-gmonaco@redhat.com
---
 kernel/sched/deadline.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index e3efc40..b5c19b1 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -1420,7 +1420,7 @@ update_stats_dequeue_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se, int 
 
 static void update_curr_dl_se(struct rq *rq, struct sched_dl_entity *dl_se, s64 delta_exec)
 {
-	bool idle = rq->curr == rq->idle;
+	bool idle = idle_rq(rq);
 	s64 scaled_delta_exec;
 
 	if (unlikely(delta_exec <= 0)) {
@@ -1603,8 +1603,8 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
  * | 8 |       B:zero_laxity-wait       |     |    |
  * |   |                                | <---+    |
  * |   +--------------------------------+          |
- * |     |              ^     ^           2        |
- * |     | 7            | 2   +--------------------+
+ * |     |              ^         ^       2        |
+ * |     | 7            | 2, 1    +----------------+
  * |     v              |
  * |   +-------------+  |
  * +-- | C:idle-wait | -+
@@ -1649,8 +1649,11 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
  *   dl_defer_idle = 0
  *
  *
- * [1] A->B, A->D
+ * [1] A->B, A->D, C->B
  * dl_server_start()
+ *   dl_defer_idle = 0;
+ *   if (dl_server_active)
+ *     return; // [B]
  *   dl_server_active = 1;
  *   enqueue_dl_entity()
  *     update_dl_entity(WAKEUP)
@@ -1759,6 +1762,7 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
  *   "B:zero_laxity-wait" -> "C:idle-wait"        [label="7:dl_server_update_idle"]
  *   "B:zero_laxity-wait" -> "D:running"          [label="3:dl_server_timer"]
  *   "C:idle-wait" -> "A:init"                    [label="8:dl_server_timer"]
+ *   "C:idle-wait" -> "B:zero_laxity-wait"        [label="1:dl_server_start"]
  *   "C:idle-wait" -> "B:zero_laxity-wait"        [label="2:dl_server_update"]
  *   "C:idle-wait" -> "C:idle-wait"               [label="7:dl_server_update_idle"]
  *   "D:running" -> "A:init"                      [label="4:pick_task_dl"]
@@ -1784,6 +1788,7 @@ void dl_server_start(struct sched_dl_entity *dl_se)
 {
 	struct rq *rq = dl_se->rq;
 
+	dl_se->dl_defer_idle = 0;
 	if (!dl_server(dl_se) || dl_se->dl_server_active)
 		return;
 

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-01-13 10:43 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-12  9:02 sched/deadline: Server stops while fair tasks are still runnable Gabriele Monaco
2026-01-12 14:45 ` Juri Lelli
2026-01-13  8:52   ` [PATCH] sched/deadline: Fix server stopping with runnable tasks Gabriele Monaco
2026-01-13  9:37     ` Peter Zijlstra
2026-01-13  9:42       ` Gabriele Monaco
2026-01-13  9:48         ` Peter Zijlstra
2026-01-13  9:50         ` Juri Lelli
2026-01-13 10:43     ` [tip: sched/urgent] " tip-bot2 for Gabriele Monaco

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.