From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792733114; b=v6HIqEx5EfwDsMQeafds/wuBDCnfX52j/mOXAnr4w2zNuUzcMmZFaju6W2sLdQqkWScu b1bLDTPHJozFe8eSidIk1XP5A3b52T8UBDFopbP6mqAZKAUz3jjaRy3WRQnIsaT3oltNJ 23dPcuqJf5PIMIlCVWim6A9w5KL45EnnwvSQrWEcqQia1JPqRmD5fupr3DYcwJFnxzLvP 4U993WddpfYoO3NdXyEpjXZNaIAIuC89qHatTwyTDqYHUi7UMLHM1tdl4+c0M0hF+L2TH Z98ymRFJHVqT1Vdqx93gokFt/lSQbitfzLpMa6IolKcXjoYyrdb68zLXE3on2vJ1Fvg== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792733114; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=FftEjJeFJ/W17MfTGrQ7oYkwpecy2Hl+HZ5sm8SFOJA=; b=WBtFWc3ZSfn/hwLhGNBJ8M9ig0olpmpQnWhHuoAA91bglD7Z+KuYQSclThpujNLUhACu JusnxKSwWlCvo4wBa13qd/Xmrh+z4OqStJ36skgFRIAx9n1kcqwDU8B1ndBSbHFKkyuwp ThZw0RVTbXu/Psuv1GHr+DdGNP1ZX7DIA3yNhPs6itcK0k94UOjC3fkytd+MuQ/MlwjXV BnvkYFKz2jtuxYMDC6nwLH7hTwsMFm2TjWpg2Zw36SbXd2CJFbVJXlboJdsKxP/UzBD6R 42eyaP8VQRDTVBVxmNygOvckLJwZDfxhhF/69DKqGr+tCg0V/d4CDZZa4CXT8UYSRcw== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=mJ1MwJIV; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C17F660A2607; Fri, 23 Oct 2026 05:24:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=mJ1MwJIV Received: by smtp.kernel.org (Postfix) with ESMTPSA id CB3781F031E1; Fri, 23 Oct 2026 05:24:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1792733099; bh=FftEjJeFJ/W17MfTGrQ7oYkwpecy2Hl+HZ5sm8SFOJA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=mJ1MwJIVhThWjuw7D6i9rYOKIIE7WjGo5XRxxOo96qbwiqIM8vWwd9MZGWqSEXLz+ 9ak2/c9fuJPAp3jfQ1OZ8ulzafJEd0O401G8f4Sd650x6g8Vu2D3ItftXYsTfFY7KW eR8NxJqG9HNPc4rvD3gOC9r/1anOsAWsNRwoYOX3VFIEnS0131juRcQYJZSJrF+mNb hUhw54FILwDVqCJIqTPXMaID0yEMR37n2Q21XwGtNdm8J6It2FG1NOQRikl/rMD/vf u+55ouHHwEYsoDrwS1J9h4wrb7Z1QqJuOonkXG5LNLEYrrvHqG6eSP3O5vIF3cLg3c ayoNp0m1agbFg== From: Tejun Heo To: sched-ext@lists.linux.dev Cc: David Vernet , Andrea Righi , Changwoo Min , Emil Tsalapatis , David Dai , linux-kernel@vger.kernel.org, Tejun Heo Subject: [PATCH 05/15] sched_ext: Restore a rescuee's slice after ops.stopping() Date: Thu, 22 Oct 2026 19:24:42 -1000 Message-ID: <20261023052452.2889061-6-tj@kernel.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261023052452.2889061-1-tj@kernel.org> References: <20261023052452.2889061-1-tj@kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit put_prev_task_scx() restores a preempted rescuee's unserved slice through scx_rescue_keep() before it calls ops.stopping(). A rescuee whose slice the scheduler zeroes there is left to the reinsert instead: 1. ops.stopping() zeroes the rescuee's slice 2. the reinsert condition special-cases the rescuee and keeps it on the local DSQ with a zero slice 3. the pick's default refill supplies a slice, or the task runs on a zero slice until the tick when its scheduler lacks BASE Move the keep after the stopping call so that scx_rescue_keep() restores the remainder whether a preemption or ops.stopping() zeroed the slice, and drop the special case from the reinsert condition as a rescuee reaching it always has a slice. A rescuee whose slice ops.stopping() zeroed now goes to the tail of the local DSQ with its remainder restored, behind what the scheduler wanted to run first, instead of staying at the head on a zero slice. The slice end in the same block moves with it, so a protected task's protection outlasts ops.stopping() and a slice write from there is refused. The scheduler has to be able to handle the refusal anyway, as a write on a protected task is refused whenever it is made, and ops.stopping() is too late to extend a slice as the next task is already picked by the time it runs. Signed-off-by: Tejun Heo --- kernel/sched/ext/ext.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c index 065ecdf3e3bf..4b976beb2f6d 100644 --- a/kernel/sched/ext/ext.c +++ b/kernel/sched/ext/ext.c @@ -3558,17 +3558,6 @@ static void put_prev_task_scx(struct rq *rq, struct task_struct *p, update_curr_scx(rq); - /* - * If the slice is consumed, protection ends with it. A rescuee - * preempted beforehand keeps going, see scx_rescue_keep(). - */ - if (!p->scx.slice) { - if (unlikely(p == scx_rescuee(rq))) - rescue_keep = scx_rescue_keep(rq, p); - if (!rescue_keep) - scx_task_slice_ended(rq, p); - } - /* * Preserve the running session when proxy execution refreshes the same * donor around an execution-context switch on this rq. @@ -3581,6 +3570,18 @@ static void put_prev_task_scx(struct rq *rq, struct task_struct *p, p->scx.flags &= ~SCX_TASK_RUN_TRACKED; } + /* + * If the slice is consumed, protection ends with it. A rescuee keeps + * going when a preemption or ops.stopping() zeroed its slice, see + * scx_rescue_keep(). + */ + if (!p->scx.slice) { + if (unlikely(p == scx_rescuee(rq))) + rescue_keep = scx_rescue_keep(rq, p); + if (!rescue_keep) + scx_task_slice_ended(rq, p); + } + if (p->scx.flags & SCX_TASK_QUEUED) { if (proxy_block) goto switch_class; @@ -3605,12 +3606,8 @@ static void put_prev_task_scx(struct rq *rq, struct task_struct *p, * The exception is an IMMED donor put by proxy_resched_idle(): * the CPU isn't busy, proxy resolution is only retrying through * idle, so keep the donor where it can be picked again. - * - * An open rescue must keep @p on the local DSQ even if the - * scheduler zeroed the slice in ops.stopping() above. */ - if ((p->scx.slice || unlikely(p == scx_rescuee(rq))) && - !scx_bypassing(sch, cpu_of(rq))) { + if (p->scx.slice && !scx_bypassing(sch, cpu_of(rq))) { if ((p->scx.flags & SCX_TASK_IMMED) && !proxy_put) { p->scx.flags |= SCX_TASK_REENQ_PREEMPTED; scx_do_enqueue_task(rq, p, SCX_ENQ_REENQ, -1); -- 2.56.0