From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from casper.infradead.org (casper.infradead.org [90.155.50.34]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CC9E024DCE5 for ; Tue, 13 Jan 2026 09:48:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=90.155.50.34 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768297728; cv=none; b=AZJv5Ts/whYVm7Tjso9j+v/vIo9W+AS7DxL3shFIV/U6SJl4ntsw3BlP/p+pls3LXkxyyjJcBhA2Bz7cCcJ2f15qrwr0NLN5hJMSjrPgn1LhVHiTpGgH4kQM6eFCKO8qu2UPoHOXCk3BsIpW+6gb5fhdeIHmnCYzrFR9JtsXg/Y= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768297728; c=relaxed/simple; bh=5p4maE9fRzbdU7/18yS306HMamDcioC50MfCmLKRgO0=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=WBy5qX4QJjS9doDt9P+53SyR/JbVrWrb5zab4HNSECakeQUTPhgPFZ8lVQJqo0M05/Dsz7RV30dA3QyxO1/bzlQO0pxhayPnVfN5dcu7K4sdSEtA6TxcSaks6UpQx+mbhj+sBWSrPh4M+xgKDvU29v+r6RKvDSSeOI1L0bk1L4g= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org; spf=none smtp.mailfrom=infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=eYZXusqW; arc=none smtp.client-ip=90.155.50.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="eYZXusqW" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=In-Reply-To:Content-Transfer-Encoding: Content-Type:MIME-Version:References:Message-ID:Subject:Cc:To:From:Date: Sender:Reply-To:Content-ID:Content-Description; bh=ECxN8CDzyuCEecMdVJhtGzMpmHkZh+eLzSd2xXjUT0w=; b=eYZXusqWJO7rgI6MgayQBA3jCV H7jhAAs/gzW9/DnqEGDhRgLmwPLvGCRGOT/dLG95y3i03NiJWRy9VqsuigrY2SyuZJ0JB57PYUlYy nAnKPv8El0mmwn3GIiS+GH6hP8v1IciSOD/IKpC2iAIyKiWgQjjxEEnJ8zHXcVPIXVkk96TWu7WHZ cF1054v9UXmxFi+HwGsXhnAzbIuDNbfQUIuTSsPe43TlycKWK04ksLKEyMn0afy2asa+r9wtNwBUR EO18TU1t0O7OhsZQHBRRD6bupQUkcoY0bpqHgTRaJ+QciAldAd4fIyZh2KZzDyvacv+Otl+vYJZ+5 KzszPGEQ==; Received: from 77-249-17-252.cable.dynamic.v4.ziggo.nl ([77.249.17.252] helo=noisy.programming.kicks-ass.net) by casper.infradead.org with esmtpsa (Exim 4.98.2 #2 (Red Hat Linux)) id 1vfb12-00000004XMC-1M5K; Tue, 13 Jan 2026 09:48:44 +0000 Received: by noisy.programming.kicks-ass.net (Postfix, from userid 1000) id 47EC8302FA1; Tue, 13 Jan 2026 10:48:43 +0100 (CET) Date: Tue, 13 Jan 2026 10:48:43 +0100 From: Peter Zijlstra To: Gabriele Monaco Cc: juri.lelli@redhat.com, Ingo Molnar , linux-kernel@vger.kernel.org, williams@redhat.com Subject: Re: [PATCH] sched/deadline: Fix server stopping with runnable tasks Message-ID: <20260113094843.GU830755@noisy.programming.kicks-ass.net> References: <20260113085159.114226-3-gmonaco@redhat.com> <20260113093706.GT830755@noisy.programming.kicks-ass.net> <9366bb54fa7529e79608b56a394d375789d28aa5.camel@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <9366bb54fa7529e79608b56a394d375789d28aa5.camel@redhat.com> 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)); } /**