From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out-174.mta0.migadu.com (out-174.mta0.migadu.com [91.218.175.174]) (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 53C442FD684 for ; Tue, 2 Dec 2025 05:52:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.174 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764654752; cv=none; b=ftNMwEIsDTSLgMLjVivvGnZh6ViB3JAPYSNeMxvpORzyiU1PyhSOK5I6HLI83xXMMFn6l5w9qNFYdRBqneoAHzmKlZGqOKF1Ee5zjmSQpl+wYin5EvLnGN5lgNaRnT/Y7DeHeiQcm7WQ5j83Ed2DcwqFUj5BhPZjcZrfCs3kMF4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764654752; c=relaxed/simple; bh=JdLxWzIKx6klWT9jsKYY7eouFzpO+96F7J+AeSmubsM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=VfrD2+lizm8lo2NcYAzUrNioTja4E2/WsJLWlIL/zD+Br/PIJWKxwl/k2vBx7sbz1Wxuj10Gq4BMU0BO3pRLp96SSQ8otDkWXPlvcdFpFIxxw9HoJq01V9XMKFHls7pedbDapFJwqKNZN/2X6spHYlllusczKnkaJgKpZjydiPk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=AQBw46c4; arc=none smtp.client-ip=91.218.175.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="AQBw46c4" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1764654748; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=gHWn95yEC3O3xQUzVt7rSHOANZ4Q1Csk0BTF+UdK244=; b=AQBw46c4fYDbskEP1LHgJo6YJh/xZxU+fTsqB34hMU7uOhjFzsiNrmhom6Y5HvZmHr5oMp qIcASz3kHsbjrGXaqvacy39izDc/+Mkm9tmmrwPZIAzIMDbgRIA48Xxe5m+TRvKVKGtMFc j1zlwox4PglUNDT+Zc3MlNDb6l2DEDs= From: wen.yang@linux.dev To: Ingo Molnar , Peter Zijlstra , Juri Lelli , Dietmar Eggemann , Steven Rostedt Cc: Wen Yang , Vincent Guittot , Ben Segall , Mel Gorman , Valentin Schneider , linux-kernel@vger.kernel.org Subject: [PATCH 2/2] sched/rt: add RT throttle statistics Date: Tue, 2 Dec 2025 13:51:19 +0800 Message-Id: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT From: Wen Yang A priority inversion scenario can occur when a CFS task is starved due to RT throttling. The scenario is as follows: 0. An rtmutex (e.g., softirq_ctrl.lock) is contended by both CFS tasks (e.g., ksoftirqd) and RT tasks (e.g., ktimer). 1. An RT task 'A' (e.g., ktimer) acquired the rtmutex. 2. A CFS task 'B' (e.g., ksoftirqd) attempts to acquire the same rtmutex and blocks. 3. A higher-priority RT task 'C' (e.g., stress-ng) runs for an extended period, preempting task 'A' and causing the RT runqueue to be throttled. 4. Once rt throttled, CFS task 'B' should run, but it remains blocked because the lock is still held by the non-running RT task 'A'. This can even lead to the CPU going idle. 5. When the rt throttle period ends, the high-priority RT task 'C' resumes execution, and the cycle repeats, leading to indefinite starvation of CFS task 'B'. A typical stack trace for the blocked ksoftirqd shows it in a 'D' (TASK_RTLOCK_WAIT) state, waiting on the lock: ksoftirqd/5-61 [005] d...211 58212.064160: sched_switch: prev_comm=ksoftirqd/5 prev_pid=61 prev_prio=120 prev_state=D ==> next_comm=swapper/5 next_pid=0 next_prio=120 ksoftirqd/5-61 [005] d...211 58212.064161: => __schedule => schedule_rtlock => rtlock_slowlock_locked => rt_spin_lock => __local_bh_disable_ip => run_ksoftirqd => smpboot_thread_fn => kthread => ret_from_fork This patch adds throttle_count to rt_rq, incremented on each throttling event and displayed in print_rt_rq for /proc/sched_debug. Thus user-space tools (e.g. stalld) can monitor throttle_comunt to detect the huge CPU consumption by RT processes and find tasks in the 'TASK_RTLOCK_WAIT' state to handle priority inversion. Signed-off-by: Wen Yang Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Juri Lelli Cc: Vincent Guittot Cc: Dietmar Eggemann Cc: Steven Rostedt Cc: Ben Segall Cc: Mel Gorman Cc: Valentin Schneider Cc: linux-kernel@vger.kernel.org --- kernel/sched/debug.c | 1 + kernel/sched/rt.c | 1 + kernel/sched/sched.h | 1 + 3 files changed, 3 insertions(+) diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c index 41caa22e0680..8ed33c74e5a5 100644 --- a/kernel/sched/debug.c +++ b/kernel/sched/debug.c @@ -894,6 +894,7 @@ void print_rt_rq(struct seq_file *m, int cpu, struct rt_rq *rt_rq) P(rt_throttled); PN(rt_time); PN(rt_runtime); + PU(throttle_count); #endif #undef PN diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index f1867fe8e5c5..88c659285c70 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -884,6 +884,7 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq) */ if (likely(rt_b->rt_runtime)) { rt_rq->rt_throttled = 1; + rt_rq->throttle_count++; printk_deferred_once("sched: RT throttling activated\n"); } else { /* diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index bbf513b3e76c..88119540e4d4 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -840,6 +840,7 @@ struct rt_rq { int rt_throttled; u64 rt_time; /* consumed RT time, goes up in update_curr_rt */ u64 rt_runtime; /* allotted RT time, "slice" from rt_bandwidth, RT sharing/balancing */ + u64 throttle_count; /* Nests inside the rq lock: */ raw_spinlock_t rt_runtime_lock; -- 2.25.1