From nobody Mon May 25 02:56:16 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 320CB3DD847; Tue, 19 May 2026 07:49:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779176998; cv=none; b=Oq544hOtmR4G8qVYKqU+UBxEgisijfgn2Y8qb4Pm4lRqylkbm542tCEv56WTB7TTOJpE9ydRJ79sRHqY65VQ8RNkG34CfovQxYp1gNbJBdpnoUkycx+Y+Yar1qv+8Glqcj61pDPr9Sz54MYmcznOGlgmBW3v01liEnys9VfHEP8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779176998; c=relaxed/simple; bh=mgCpvKA1Z8lP7MIk4JH67/fuLeGUyUtS1SEIdFGylLo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gua9ZQrFH0xwEIK7+8wbxegDYu+CpUZlS0YWMlYqA6AGGax1UV44o8tsANL0zoIVcevbGwRZvzbrP150NT2Ne/P/VIy9XvoB3aG7O3n1vNPXanE5Ak+WjfyxVtadPWW6XL05M3HJo72GpqKejXdNU2IuTqkU2WXl2H10Mn9X4lI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=AtRSeb0X; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=YjR/uvaD; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="AtRSeb0X"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="YjR/uvaD" From: Nam Cao DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1779176989; 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=dsOE7YC2GreJsc6/lCfnO7P4YYGxLfwkbP8mSrCEJ3E=; b=AtRSeb0XTn3k1YFb7IqdjqtZpgZWhve37/RW3Z9rn0iHpoFJMSfvqqwuQfmPD13+OXFHBZ 4LY73WFcHN82k3eBpNUyvlWRjjxoxVgwmD4CR44tNZ9eFyCWwuefBMJjUQk/00Dg0gO7fs 40b5yiga8HINLlEU/KWgPodR4hBWPm+IXkGgW3rdr/8tkdehWTC3yMhKDbPQLmg0d7w0pk 2x2HHJyHNPU5FO32LMi1T/VRbfp5j7H9KtaBGsGa4mmssgqoq36j29jeB3ozBbbAdYJRR8 72Mz4m8w92hpE2fZid6BGm+3lV/zW3SSQd+nPwMd9XtSbUNPHFPLwQDsoK3mCw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1779176989; 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=dsOE7YC2GreJsc6/lCfnO7P4YYGxLfwkbP8mSrCEJ3E=; b=YjR/uvaDKKfogHOdgUXs0+vS91/Cyw99Jsbd0KavYdsXmtCiESkZS5EFdFtdIjb6DuHecY Bi+HQVStC9nW+NAQ== To: Gabriele Monaco , Steven Rostedt , linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Nam Cao Subject: [PATCH 1/3] rv/rtapp/sleep: Make the error more informative for user Date: Tue, 19 May 2026 09:49:33 +0200 Message-ID: <14242f444f7d2396c0c5a345f0099665d09a0ec5.1779176466.git.namcao@linutronix.de> 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: quoted-printable Content-Type: text/plain; charset="utf-8" The rtapp/sleep monitor detects real-time tasks which go to sleep in an real-time-unsafe manner. If this happen, the monitor triggers a trace event in the sched_wakeup tracepoint's handler. However, the invoking context of that trace event is not the most informative, because of the stack trace of that event is the wakeup's code path which is not very helpful: 74.669317: rv:error_sleep: condvar[254]: violation detected ltl_validate+0x345 ([kernel.kallsyms]) handle_sched_wakeup+0x34 ([kernel.kallsyms]) ttwu_do_activate+0xff ([kernel.kallsyms]) sched_ttwu_pending+0x104 ([kernel.kallsyms]) __flush_smp_call_function_queue+0x15b ([kernel.kallsyms]) __sysvec_call_function_single+0x18 ([kernel.kallsyms]) sysvec_call_function_single+0x66 ([kernel.kallsyms]) asm_sysvec_call_function_single+0x1a ([kernel.kallsyms]) pv_native_safe_halt+0xf ([kernel.kallsyms]) default_idle+0x9 ([kernel.kallsyms]) default_idle_call+0x33 ([kernel.kallsyms]) do_idle+0x234 ([kernel.kallsyms]) cpu_startup_entry+0x24 ([kernel.kallsyms]) start_secondary+0xf8 ([kernel.kallsyms]) common_startup_64+0x13e ([kernel.kallsyms]) What would be much more valuable is the stack trace of the task itself. Change the update of WAKEUP from being in sched_wakeup trace point's handler to sched_exit trace point's handler. This makes the event happen in the task's context, making the stack trace far more informative for user: rv:error_sleep: condvar[254]: violation detected ltl_validate+0x345 ([kernel.kallsyms]) handle_sched_exit+0x39 ([kernel.kallsyms]) __schedule+0x80f ([kernel.kallsyms]) schedule+0x22 ([kernel.kallsyms]) futex_do_wait+0x33 ([kernel.kallsyms]) __futex_wait+0x8c ([kernel.kallsyms]) futex_wait+0x73 ([kernel.kallsyms]) do_futex+0xc6 ([kernel.kallsyms]) __x64_sys_futex+0x121 ([kernel.kallsyms]) do_syscall_64+0xf3 ([kernel.kallsyms]) entry_SYSCALL_64_after_hwframe+0x77 ([kernel.kallsyms]) __futex_abstimed_wait_common64+0xc6 (inlined) __futex_abstimed_wait_common+0xc6 (/usr/lib/x86_64-linux-gnu/libc.so.6) Signed-off-by: Nam Cao --- kernel/trace/rv/monitors/sleep/sleep.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/trace/rv/monitors/sleep/sleep.c b/kernel/trace/rv/monit= ors/sleep/sleep.c index 8dfe5ec13e19..0a36f5519e6b 100644 --- a/kernel/trace/rv/monitors/sleep/sleep.c +++ b/kernel/trace/rv/monitors/sleep/sleep.c @@ -92,9 +92,9 @@ static void handle_sched_set_state(void *data, struct tas= k_struct *task, int sta ltl_atom_pulse(task, LTL_ABORT_SLEEP, true); } =20 -static void handle_sched_wakeup(void *data, struct task_struct *task) +static void handle_sched_exit(void *data, bool is_switch) { - ltl_atom_pulse(task, LTL_WAKE, true); + ltl_atom_pulse(current, LTL_WAKE, true); } =20 static void handle_sched_waking(void *data, struct task_struct *task) @@ -200,7 +200,7 @@ static int enable_sleep(void) return retval; =20 rv_attach_trace_probe("rtapp_sleep", sched_waking, handle_sched_waking); - rv_attach_trace_probe("rtapp_sleep", sched_wakeup, handle_sched_wakeup); + rv_attach_trace_probe("rtapp_sleep", sched_exit_tp, handle_sched_exit); rv_attach_trace_probe("rtapp_sleep", sched_set_state_tp, handle_sched_set= _state); rv_attach_trace_probe("rtapp_sleep", contention_begin, handle_contention_= begin); rv_attach_trace_probe("rtapp_sleep", contention_end, handle_contention_en= d); @@ -213,7 +213,7 @@ static int enable_sleep(void) static void disable_sleep(void) { rv_detach_trace_probe("rtapp_sleep", sched_waking, handle_sched_waking); - rv_detach_trace_probe("rtapp_sleep", sched_wakeup, handle_sched_wakeup); + rv_detach_trace_probe("rtapp_sleep", sched_exit_tp, handle_sched_exit); rv_detach_trace_probe("rtapp_sleep", sched_set_state_tp, handle_sched_set= _state); rv_detach_trace_probe("rtapp_sleep", contention_begin, handle_contention_= begin); rv_detach_trace_probe("rtapp_sleep", contention_end, handle_contention_en= d); --=20 2.47.3 From nobody Mon May 25 02:56:16 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 054123DB641; Tue, 19 May 2026 07:49:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779177002; cv=none; b=a08+9OtSpontIqYNkKIK5r0KRRxgHo1U8Q4fCaoX2AalcnIf0ZTsOXZRqE2u2rQXuApL3gjmzzvYZD1RNapg4AbDSxNJJZuR8pX9+k1b0cBO0WMdqtcShpwPaZKgu9B6lwByz7lL/rUtFJjAgdBPEQWqVCXcyqLhWN3JNcE2lZQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779177002; c=relaxed/simple; bh=qB14ZcRjNUseOaH4fxbgwngfB0pNuavqGWlXPb9fYeo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bTV8jvHjTLEbMelDF4nBijvNAR7tXLywqb9L/W81/sYOeiNcoUlEuTjjWKmmMr5Yx5hQwpoUpYFqvg4uru5w+KvdxUQ9IGJSfmpEfKBa63Pw+Ubfr15Sh7sWbt7D2tA69YL4SVY3bQM9Ew/FQcCCNgLyY9hwfj8lLw0tF37Qqo0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=vWopdMRm; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=CtCQg2hb; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="vWopdMRm"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="CtCQg2hb" From: Nam Cao DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1779176990; 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=2YAFz3/nEoV68jxh3U+BQ79tHP/jhnfEHV3OQmZJeY0=; b=vWopdMRmOcFkuCkxGIo/rOq1XPg2YCTaUCU9Xmog0M2lQYzOcZPC+vHw8mXoh5l6sRRYkb gbddZFAfoAmN3Z486X7xpQnAIlzy9XKvnxzp5C5viqMXQH0jxJUWBF3MtElDzXv0xfyG7c 5polVzZyBmQfJ1+SXRyjzHSLjjuKmhxomtIkSAGn8RoiDj3gJ8O648SVxINxVS5jLjDp6G FeDhKA5uCZvyt3JE5V+2mPflj3Pzv9AJ7rrcYGzgLiV16EPhH9vbdeSTxknIqt+oltxbW7 3sXufTqC64/35zmCGWG07ec5fOnQOv2Q5S22D14ZlmSQj9ca8Cj/GHdDYzI55g== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1779176990; 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=2YAFz3/nEoV68jxh3U+BQ79tHP/jhnfEHV3OQmZJeY0=; b=CtCQg2hbsUiF5sIef5HPURj3bjUZhBCAEpOuL4cPnRQU98y0odOzx/6Wotpmrfs0tDqjYX a7PIrbHVpA71+kAw== To: Gabriele Monaco , Steven Rostedt , linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Nam Cao Subject: [PATCH 2/3] rv/rtapp/sleep: Update nanosleep rule Date: Tue, 19 May 2026 09:49:34 +0200 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: quoted-printable Content-Type: text/plain; charset="utf-8" CLOCK_REALTIME is the only clock that often is misused in real-time applications. The other clocks either are safe for real-time uses (CLOCK_TAI, CLOCK_MONOTONIC, CLOCK_BOOTTIME) or are unlikely to be misused (CLOCK_AUX, CLOCK_PROCESS_CPUTIME_ID). The rtapp monitor's purpose is warning people about common mistakes with real-time design. However, warning about all clock types generates too much false positives. Update the monitor to only warn about CLOCK_REALTIME. Signed-off-by: Nam Cao --- kernel/trace/rv/monitors/sleep/sleep.c | 10 ++--- kernel/trace/rv/monitors/sleep/sleep.h | 52 +++++++++++------------ tools/verification/models/rtapp/sleep.ltl | 2 +- 3 files changed, 28 insertions(+), 36 deletions(-) diff --git a/kernel/trace/rv/monitors/sleep/sleep.c b/kernel/trace/rv/monit= ors/sleep/sleep.c index 0a36f5519e6b..e01ac56b3f4a 100644 --- a/kernel/trace/rv/monitors/sleep/sleep.c +++ b/kernel/trace/rv/monitors/sleep/sleep.c @@ -43,9 +43,7 @@ static void ltl_atoms_init(struct task_struct *task, stru= ct ltl_monitor *mon, bo ltl_atom_set(mon, LTL_WOKEN_BY_EQUAL_OR_HIGHER_PRIO, false); =20 if (task_creation) { - ltl_atom_set(mon, LTL_KTHREAD_SHOULD_STOP, false); - ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_MONOTONIC, false); - ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_TAI, false); + ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_REALTIME, false); ltl_atom_set(mon, LTL_NANOSLEEP_TIMER_ABSTIME, false); ltl_atom_set(mon, LTL_CLOCK_NANOSLEEP, false); ltl_atom_set(mon, LTL_FUTEX_WAIT, false); @@ -136,8 +134,7 @@ static void handle_sys_enter(void *data, struct pt_regs= *regs, long id) case __NR_clock_nanosleep_time64: #endif syscall_get_arguments(current, regs, args); - ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_MONOTONIC, args[0] =3D=3D CLOCK_MO= NOTONIC); - ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_TAI, args[0] =3D=3D CLOCK_TAI); + ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_REALTIME, args[0] =3D=3D CLOCK_REA= LTIME); ltl_atom_set(mon, LTL_NANOSLEEP_TIMER_ABSTIME, args[1] =3D=3D TIMER_ABST= IME); ltl_atom_update(current, LTL_CLOCK_NANOSLEEP, true); break; @@ -178,8 +175,7 @@ static void handle_sys_exit(void *data, struct pt_regs = *regs, long ret) =20 ltl_atom_set(mon, LTL_FUTEX_LOCK_PI, false); ltl_atom_set(mon, LTL_FUTEX_WAIT, false); - ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_MONOTONIC, false); - ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_TAI, false); + ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_REALTIME, false); ltl_atom_set(mon, LTL_NANOSLEEP_TIMER_ABSTIME, false); ltl_atom_set(mon, LTL_EPOLL_WAIT, false); ltl_atom_update(current, LTL_CLOCK_NANOSLEEP, false); diff --git a/kernel/trace/rv/monitors/sleep/sleep.h b/kernel/trace/rv/monit= ors/sleep/sleep.h index 95dc2727c059..ed1ac7ad008e 100644 --- a/kernel/trace/rv/monitors/sleep/sleep.h +++ b/kernel/trace/rv/monitors/sleep/sleep.h @@ -20,8 +20,7 @@ enum ltl_atom { LTL_FUTEX_WAIT, LTL_KERNEL_THREAD, LTL_KTHREAD_SHOULD_STOP, - LTL_NANOSLEEP_CLOCK_MONOTONIC, - LTL_NANOSLEEP_CLOCK_TAI, + LTL_NANOSLEEP_CLOCK_REALTIME, LTL_NANOSLEEP_TIMER_ABSTIME, LTL_RT, LTL_SLEEP, @@ -46,8 +45,7 @@ static const char *ltl_atom_str(enum ltl_atom atom) "fu_wa", "ker_th", "kth_sh_st", - "na_cl_mo", - "na_cl_ta", + "na_cl_re", "na_ti_ab", "rt", "sl", @@ -87,8 +85,7 @@ static void ltl_start(struct task_struct *task, struct lt= l_monitor *mon) bool sleep =3D test_bit(LTL_SLEEP, mon->atoms); bool rt =3D test_bit(LTL_RT, mon->atoms); bool nanosleep_timer_abstime =3D test_bit(LTL_NANOSLEEP_TIMER_ABSTIME, mo= n->atoms); - bool nanosleep_clock_tai =3D test_bit(LTL_NANOSLEEP_CLOCK_TAI, mon->atoms= ); - bool nanosleep_clock_monotonic =3D test_bit(LTL_NANOSLEEP_CLOCK_MONOTONIC= , mon->atoms); + bool nanosleep_clock_realtime =3D test_bit(LTL_NANOSLEEP_CLOCK_REALTIME, = mon->atoms); bool kthread_should_stop =3D test_bit(LTL_KTHREAD_SHOULD_STOP, mon->atoms= ); bool kernel_thread =3D test_bit(LTL_KERNEL_THREAD, mon->atoms); bool futex_wait =3D test_bit(LTL_FUTEX_WAIT, mon->atoms); @@ -97,17 +94,17 @@ static void ltl_start(struct task_struct *task, struct = ltl_monitor *mon) bool clock_nanosleep =3D test_bit(LTL_CLOCK_NANOSLEEP, mon->atoms); bool block_on_rt_mutex =3D test_bit(LTL_BLOCK_ON_RT_MUTEX, mon->atoms); bool abort_sleep =3D test_bit(LTL_ABORT_SLEEP, mon->atoms); - bool val42 =3D task_is_rcu || task_is_migration; - bool val43 =3D futex_lock_pi || val42; - bool val5 =3D block_on_rt_mutex || val43; - bool val34 =3D abort_sleep || kthread_should_stop; - bool val35 =3D woken_by_nmi || val34; - bool val36 =3D woken_by_hardirq || val35; - bool val14 =3D woken_by_equal_or_higher_prio || val36; + bool val41 =3D task_is_rcu || task_is_migration; + bool val42 =3D futex_lock_pi || val41; + bool val5 =3D block_on_rt_mutex || val42; + bool val33 =3D abort_sleep || kthread_should_stop; + bool val34 =3D woken_by_nmi || val33; + bool val35 =3D woken_by_hardirq || val34; + bool val14 =3D woken_by_equal_or_higher_prio || val35; bool val13 =3D !wake; - bool val26 =3D nanosleep_clock_monotonic || nanosleep_clock_tai; - bool val27 =3D nanosleep_timer_abstime && val26; - bool val18 =3D clock_nanosleep && val27; + bool val25 =3D !nanosleep_clock_realtime; + bool val26 =3D nanosleep_timer_abstime && val25; + bool val18 =3D clock_nanosleep && val26; bool val20 =3D val18 || epoll_wait; bool val9 =3D futex_wait || val20; bool val11 =3D val9 || kernel_thread; @@ -138,8 +135,7 @@ ltl_possible_next_states(struct ltl_monitor *mon, unsig= ned int state, unsigned l bool sleep =3D test_bit(LTL_SLEEP, mon->atoms); bool rt =3D test_bit(LTL_RT, mon->atoms); bool nanosleep_timer_abstime =3D test_bit(LTL_NANOSLEEP_TIMER_ABSTIME, mo= n->atoms); - bool nanosleep_clock_tai =3D test_bit(LTL_NANOSLEEP_CLOCK_TAI, mon->atoms= ); - bool nanosleep_clock_monotonic =3D test_bit(LTL_NANOSLEEP_CLOCK_MONOTONIC= , mon->atoms); + bool nanosleep_clock_realtime =3D test_bit(LTL_NANOSLEEP_CLOCK_REALTIME, = mon->atoms); bool kthread_should_stop =3D test_bit(LTL_KTHREAD_SHOULD_STOP, mon->atoms= ); bool kernel_thread =3D test_bit(LTL_KERNEL_THREAD, mon->atoms); bool futex_wait =3D test_bit(LTL_FUTEX_WAIT, mon->atoms); @@ -148,17 +144,17 @@ ltl_possible_next_states(struct ltl_monitor *mon, uns= igned int state, unsigned l bool clock_nanosleep =3D test_bit(LTL_CLOCK_NANOSLEEP, mon->atoms); bool block_on_rt_mutex =3D test_bit(LTL_BLOCK_ON_RT_MUTEX, mon->atoms); bool abort_sleep =3D test_bit(LTL_ABORT_SLEEP, mon->atoms); - bool val42 =3D task_is_rcu || task_is_migration; - bool val43 =3D futex_lock_pi || val42; - bool val5 =3D block_on_rt_mutex || val43; - bool val34 =3D abort_sleep || kthread_should_stop; - bool val35 =3D woken_by_nmi || val34; - bool val36 =3D woken_by_hardirq || val35; - bool val14 =3D woken_by_equal_or_higher_prio || val36; + bool val41 =3D task_is_rcu || task_is_migration; + bool val42 =3D futex_lock_pi || val41; + bool val5 =3D block_on_rt_mutex || val42; + bool val33 =3D abort_sleep || kthread_should_stop; + bool val34 =3D woken_by_nmi || val33; + bool val35 =3D woken_by_hardirq || val34; + bool val14 =3D woken_by_equal_or_higher_prio || val35; bool val13 =3D !wake; - bool val26 =3D nanosleep_clock_monotonic || nanosleep_clock_tai; - bool val27 =3D nanosleep_timer_abstime && val26; - bool val18 =3D clock_nanosleep && val27; + bool val25 =3D !nanosleep_clock_realtime; + bool val26 =3D nanosleep_timer_abstime && val25; + bool val18 =3D clock_nanosleep && val26; bool val20 =3D val18 || epoll_wait; bool val9 =3D futex_wait || val20; bool val11 =3D val9 || kernel_thread; diff --git a/tools/verification/models/rtapp/sleep.ltl b/tools/verification= /models/rtapp/sleep.ltl index 6f26c4810f78..2637bc48a620 100644 --- a/tools/verification/models/rtapp/sleep.ltl +++ b/tools/verification/models/rtapp/sleep.ltl @@ -9,7 +9,7 @@ RT_VALID_SLEEP_REASON =3D FUTEX_WAIT =20 RT_FRIENDLY_NANOSLEEP =3D CLOCK_NANOSLEEP and NANOSLEEP_TIMER_ABSTIME - and (NANOSLEEP_CLOCK_MONOTONIC or NANOSLEEP_CLOCK_TAI) + and not NANOSLEEP_CLOCK_REALTIME =20 RT_FRIENDLY_WAKE =3D WOKEN_BY_EQUAL_OR_HIGHER_PRIO or WOKEN_BY_HARDIRQ --=20 2.47.3 From nobody Mon May 25 02:56:16 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 054AE3DD53A; Tue, 19 May 2026 07:49:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779177005; cv=none; b=kuup7UAQCn7CpBgCNNINqFAWyxaHaCHczUIKSEPpg83rOHZbK9rHN+H4Le5/38EfjH103Fjx59pqFVnwTFkD/BDBSWnu5NkZwOQN2gyZqwSfBlxmBcPglcAYsUzuKL/0LCgx77aCs3SpmMlomfMUD85/e8XB3FiPxI2AfCcnVi0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779177005; c=relaxed/simple; bh=l0UqfrqySwK1qte+CD+uj3feyLXsornN+qkltAYeX74=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PpWy4hiho5GWijLAZu85xe6GP8onhqydF9APt9PskcgraJbOj5BdVsBLClhXqMszhAzLOrl91+SacxxKC5knSS99DcudbR7BFj9IE/XP+gAHqDLkXJ6y2NjAp08px2+J2qrjRliRyQiMhyQl/qmbXKx6IJXEc6N23l9vJcVcHcw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=YJizzzV5; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=9cHD6S3F; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="YJizzzV5"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="9cHD6S3F" From: Nam Cao DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1779176990; 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=lWgbrEvpcQITqXlQwIDTRiP3OVyn/NsE8cID6HfD6R8=; b=YJizzzV5fWD1oRLhIB54W/5YG2ouezdJ/3zGpTs89WlM3hir1RgQt19Ibj3fmRPf8GiYOj XJ4exM4ZEqVeHpzZ+ECRTcOd86GA/CXX3wq0FLPwrkR6XayT/yMarm4guyfkvjrEYtsb7A /b5dEeTnV/ACCexx5QEoJ6ZNtCXJNAEOuV1WXx61inES9VwmB57DkiKkJInGGP3tPBCoMs 67DkG8LQmDn+Nv1eGSvaCWBAI14C8vVYJt5/mFRENoTAM09abo8jwrOTa4xja4vdTSWp2O hGIEawSPFUqDvy9+kSxoWsdbUoPmauLq/Ku5dCvPiqDEREi+W4K49ZUdMh4EYA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1779176990; 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=lWgbrEvpcQITqXlQwIDTRiP3OVyn/NsE8cID6HfD6R8=; b=9cHD6S3FK1NjcrCLqGFnQdnasaD/xStUpCD9uBqnmX9sySbe2xZXHo/4s5tN71S64oNKLC XsnzYg+A5FGNaMDw== To: Gabriele Monaco , Steven Rostedt , linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Nam Cao Subject: [PATCH 3/3] rv/rtapp: Add wakeup monitor Date: Tue, 19 May 2026 09:49:35 +0200 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: quoted-printable Content-Type: text/plain; charset="utf-8" Add a wakeup monitor to detect a lower-priority task waking up a higher-priority task. The rtapp/sleep monitor already detects this. However, that monitor triggers an error in the context of the woken task and user only gets the stacktrace of that task. It is also extremely useful to get the stacktrace of the waking task, which this monitor offers. In other words, this monitor complements the rtapp/sleep monitor. Signed-off-by: Nam Cao --- kernel/trace/rv/Kconfig | 1 + kernel/trace/rv/Makefile | 1 + kernel/trace/rv/monitors/wakeup/Kconfig | 17 ++ kernel/trace/rv/monitors/wakeup/wakeup.c | 155 ++++++++++++++++++ kernel/trace/rv/monitors/wakeup/wakeup.h | 92 +++++++++++ .../trace/rv/monitors/wakeup/wakeup_trace.h | 14 ++ kernel/trace/rv/rv_trace.h | 1 + tools/verification/models/rtapp/wakeup.ltl | 5 + 8 files changed, 286 insertions(+) create mode 100644 kernel/trace/rv/monitors/wakeup/Kconfig create mode 100644 kernel/trace/rv/monitors/wakeup/wakeup.c create mode 100644 kernel/trace/rv/monitors/wakeup/wakeup.h create mode 100644 kernel/trace/rv/monitors/wakeup/wakeup_trace.h create mode 100644 tools/verification/models/rtapp/wakeup.ltl diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig index 3884b14df375..4d3a14a0bac2 100644 --- a/kernel/trace/rv/Kconfig +++ b/kernel/trace/rv/Kconfig @@ -76,6 +76,7 @@ source "kernel/trace/rv/monitors/opid/Kconfig" source "kernel/trace/rv/monitors/rtapp/Kconfig" source "kernel/trace/rv/monitors/pagefault/Kconfig" source "kernel/trace/rv/monitors/sleep/Kconfig" +source "kernel/trace/rv/monitors/wakeup/Kconfig" # Add new rtapp monitors here =20 source "kernel/trace/rv/monitors/stall/Kconfig" diff --git a/kernel/trace/rv/Makefile b/kernel/trace/rv/Makefile index 94498da35b37..c2c0e4142eb4 100644 --- a/kernel/trace/rv/Makefile +++ b/kernel/trace/rv/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_RV_MON_OPID) +=3D monitors/opid/opid.o obj-$(CONFIG_RV_MON_STALL) +=3D monitors/stall/stall.o obj-$(CONFIG_RV_MON_DEADLINE) +=3D monitors/deadline/deadline.o obj-$(CONFIG_RV_MON_NOMISS) +=3D monitors/nomiss/nomiss.o +obj-$(CONFIG_RV_MON_WAKEUP) +=3D monitors/wakeup/wakeup.o # Add new monitors here obj-$(CONFIG_RV_REACTORS) +=3D rv_reactors.o obj-$(CONFIG_RV_REACT_PRINTK) +=3D reactor_printk.o diff --git a/kernel/trace/rv/monitors/wakeup/Kconfig b/kernel/trace/rv/moni= tors/wakeup/Kconfig new file mode 100644 index 000000000000..3cf11c5cd5f7 --- /dev/null +++ b/kernel/trace/rv/monitors/wakeup/Kconfig @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_WAKEUP + depends on RV + depends on RV_MON_RTAPP + depends on HAVE_SYSCALL_TRACEPOINTS + select TRACE_IRQFLAGS + default y + select LTL_MON_EVENTS_ID + bool "wakeup monitor" + help + This monitor detects a lower-priority task waking up a + higher-priority task. The RV_MON_SLEEP monitor already + detects this case, but this monitor detects in the context + of the waking task instead. This and RV_MON_SLEEP can be + enabled together to get the stacktrace of both the waking + task and the woken task. diff --git a/kernel/trace/rv/monitors/wakeup/wakeup.c b/kernel/trace/rv/mon= itors/wakeup/wakeup.c new file mode 100644 index 000000000000..534997a7b45c --- /dev/null +++ b/kernel/trace/rv/monitors/wakeup/wakeup.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "wakeup" + +#include +#include +#include +#include + +#include +#include + + +#ifndef __NR_futex +#define __NR_futex (-__COUNTER__) +#endif +#ifndef __NR_futex_time64 +#define __NR_futex_time64 (-__COUNTER__) +#endif + +#include "wakeup.h" +#include + +static void ltl_atoms_fetch(struct task_struct *task, struct ltl_monitor *= mon) +{ + /* + * This includes "actual" real-time tasks and also PI-boosted + * tasks. A task being PI-boosted means it is blocking an "actual" + * real-task, therefore it should also obey the monitor's rule, + * otherwise the "actual" real-task may be delayed. + */ + ltl_atom_set(mon, LTL_RT, rt_or_dl_task(task)); +} + +static void ltl_atoms_init(struct task_struct *task, struct ltl_monitor *m= on, bool task_creation) +{ + ltl_atom_set(mon, LTL_WOKEN_BY_LOWER_PRIO, false); + ltl_atom_set(mon, LTL_WOKEN_BY_SOFTIRQ, false); + + if (task_creation) { + ltl_atom_set(mon, LTL_BLOCK_ON_RT_MUTEX, false); + ltl_atom_set(mon, LTL_FUTEX_LOCK_PI, false); + } + + ltl_atom_set(mon, LTL_USER_THREAD, !(task->flags & PF_KTHREAD)); +} + +static void handle_sched_waking(void *data, struct task_struct *task) +{ + if (this_cpu_read(hardirq_context)) { + return; + } else if (in_task()) { + if (current->prio > task->prio) + ltl_atom_pulse(task, LTL_WOKEN_BY_LOWER_PRIO, true); + } else if (in_serving_softirq()) { + ltl_atom_pulse(task, LTL_WOKEN_BY_SOFTIRQ, true); + } +} + +static void handle_contention_begin(void *data, void *lock, unsigned int f= lags) +{ + if (flags & LCB_F_RT) + ltl_atom_update(current, LTL_BLOCK_ON_RT_MUTEX, true); +} + +static void handle_contention_end(void *data, void *lock, int ret) +{ + ltl_atom_update(current, LTL_BLOCK_ON_RT_MUTEX, false); +} + +static void handle_sys_enter(void *data, struct pt_regs *regs, long id) +{ + unsigned long args[6]; + int op, cmd; + + switch (id) { + case __NR_futex: + case __NR_futex_time64: + syscall_get_arguments(current, regs, args); + op =3D args[1]; + cmd =3D op & FUTEX_CMD_MASK; + + switch (cmd) { + case FUTEX_LOCK_PI: + case FUTEX_LOCK_PI2: + ltl_atom_update(current, LTL_FUTEX_LOCK_PI, true); + break; + } + break; + } +} + +static void handle_sys_exit(void *data, struct pt_regs *regs, long ret) +{ + ltl_atom_update(current, LTL_FUTEX_LOCK_PI, false); +} + +static int enable_wakeup(void) +{ + int retval; + + retval =3D ltl_monitor_init(); + if (retval) + return retval; + + rv_attach_trace_probe("rtapp_wakeup", sched_waking, handle_sched_waking); + rv_attach_trace_probe("rtapp_wakeup", contention_begin, handle_contention= _begin); + rv_attach_trace_probe("rtapp_wakeup", contention_end, handle_contention_e= nd); + rv_attach_trace_probe("rtapp_wakeup", sys_enter, handle_sys_enter); + rv_attach_trace_probe("rtapp_wakeup", sys_exit, handle_sys_exit); + + return 0; +} + +static void disable_wakeup(void) +{ + rv_detach_trace_probe("rtapp_wakeup", sched_waking, handle_sched_waking); + rv_detach_trace_probe("rtapp_wakeup", contention_begin, handle_contention= _begin); + rv_detach_trace_probe("rtapp_wakeup", contention_end, handle_contention_e= nd); + rv_detach_trace_probe("rtapp_wakeup", sys_enter, handle_sys_enter); + rv_detach_trace_probe("rtapp_wakeup", sys_exit, handle_sys_exit); + + ltl_monitor_destroy(); +} + +static struct rv_monitor rv_wakeup =3D { + .name =3D "wakeup", + .description =3D "Monitor that real-time tasks are not woken by lower-pri= ority tasks", + .enable =3D enable_wakeup, + .disable =3D disable_wakeup, +}; + +static int __init register_wakeup(void) +{ + return rv_register_monitor(&rv_wakeup, &rv_rtapp); +} + +static void __exit unregister_wakeup(void) +{ + rv_unregister_monitor(&rv_wakeup); +} + +module_init(register_wakeup); +module_exit(unregister_wakeup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Nam Cao "); +MODULE_DESCRIPTION("Monitor that real-time tasks are not woken by lower-pr= iority tasks"); diff --git a/kernel/trace/rv/monitors/wakeup/wakeup.h b/kernel/trace/rv/mon= itors/wakeup/wakeup.h new file mode 100644 index 000000000000..6f80da64e0e1 --- /dev/null +++ b/kernel/trace/rv/monitors/wakeup/wakeup.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * C implementation of Buchi automaton, automatically generated by + * tools/verification/rvgen from the linear temporal logic specification. + * For further information, see kernel documentation: + * Documentation/trace/rv/linear_temporal_logic.rst + */ + +#include + +#define MONITOR_NAME wakeup + +enum ltl_atom { + LTL_BLOCK_ON_RT_MUTEX, + LTL_FUTEX_LOCK_PI, + LTL_RT, + LTL_USER_THREAD, + LTL_WOKEN_BY_LOWER_PRIO, + LTL_WOKEN_BY_SOFTIRQ, + LTL_NUM_ATOM +}; +static_assert(LTL_NUM_ATOM <=3D RV_MAX_LTL_ATOM); + +static const char *ltl_atom_str(enum ltl_atom atom) +{ + static const char *const names[] =3D { + "bl_on_rt_mu", + "fu_lo_pi", + "rt", + "us_th", + "wo_lo_pr", + "wo_so", + }; + + return names[atom]; +} + +enum ltl_buchi_state { + S0, + RV_NUM_BA_STATES +}; +static_assert(RV_NUM_BA_STATES <=3D RV_MAX_BA_STATES); + +static void ltl_start(struct task_struct *task, struct ltl_monitor *mon) +{ + bool woken_by_softirq =3D test_bit(LTL_WOKEN_BY_SOFTIRQ, mon->atoms); + bool woken_by_lower_prio =3D test_bit(LTL_WOKEN_BY_LOWER_PRIO, mon->atoms= ); + bool user_thread =3D test_bit(LTL_USER_THREAD, mon->atoms); + bool rt =3D test_bit(LTL_RT, mon->atoms); + bool futex_lock_pi =3D test_bit(LTL_FUTEX_LOCK_PI, mon->atoms); + bool block_on_rt_mutex =3D test_bit(LTL_BLOCK_ON_RT_MUTEX, mon->atoms); + bool val9 =3D block_on_rt_mutex || futex_lock_pi; + bool val6 =3D !woken_by_softirq; + bool val5 =3D !woken_by_lower_prio; + bool val8 =3D val5 && val6; + bool val10 =3D val8 || val9; + bool val3 =3D !user_thread; + bool val2 =3D !rt; + bool val4 =3D val2 || val3; + bool val11 =3D val4 || val10; + + if (val11) + __set_bit(S0, mon->states); +} + +static void +ltl_possible_next_states(struct ltl_monitor *mon, unsigned int state, unsi= gned long *next) +{ + bool woken_by_softirq =3D test_bit(LTL_WOKEN_BY_SOFTIRQ, mon->atoms); + bool woken_by_lower_prio =3D test_bit(LTL_WOKEN_BY_LOWER_PRIO, mon->atoms= ); + bool user_thread =3D test_bit(LTL_USER_THREAD, mon->atoms); + bool rt =3D test_bit(LTL_RT, mon->atoms); + bool futex_lock_pi =3D test_bit(LTL_FUTEX_LOCK_PI, mon->atoms); + bool block_on_rt_mutex =3D test_bit(LTL_BLOCK_ON_RT_MUTEX, mon->atoms); + bool val9 =3D block_on_rt_mutex || futex_lock_pi; + bool val6 =3D !woken_by_softirq; + bool val5 =3D !woken_by_lower_prio; + bool val8 =3D val5 && val6; + bool val10 =3D val8 || val9; + bool val3 =3D !user_thread; + bool val2 =3D !rt; + bool val4 =3D val2 || val3; + bool val11 =3D val4 || val10; + + switch (state) { + case S0: + if (val11) + __set_bit(S0, next); + break; + } +} diff --git a/kernel/trace/rv/monitors/wakeup/wakeup_trace.h b/kernel/trace/= rv/monitors/wakeup/wakeup_trace.h new file mode 100644 index 000000000000..7e056183f920 --- /dev/null +++ b/kernel/trace/rv/monitors/wakeup/wakeup_trace.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_WAKEUP +DEFINE_EVENT(event_ltl_monitor_id, event_wakeup, + TP_PROTO(struct task_struct *task, char *states, char *atoms, char *= next), + TP_ARGS(task, states, atoms, next)); +DEFINE_EVENT(error_ltl_monitor_id, error_wakeup, + TP_PROTO(struct task_struct *task), + TP_ARGS(task)); +#endif /* CONFIG_RV_MON_WAKEUP */ diff --git a/kernel/trace/rv/rv_trace.h b/kernel/trace/rv/rv_trace.h index 9622c269789c..2f8a932432c9 100644 --- a/kernel/trace/rv/rv_trace.h +++ b/kernel/trace/rv/rv_trace.h @@ -241,6 +241,7 @@ DECLARE_EVENT_CLASS(error_ltl_monitor_id, ); #include #include +#include // Add new monitors based on CONFIG_LTL_MON_EVENTS_ID here #endif /* CONFIG_LTL_MON_EVENTS_ID */ =20 diff --git a/tools/verification/models/rtapp/wakeup.ltl b/tools/verificatio= n/models/rtapp/wakeup.ltl new file mode 100644 index 000000000000..a5d63ca0811a --- /dev/null +++ b/tools/verification/models/rtapp/wakeup.ltl @@ -0,0 +1,5 @@ +RULE =3D always (((RT and USER_THREAD) imply + (not (WOKEN_BY_LOWER_PRIO or WOKEN_BY_SOFTIRQ)) or ALLOWLIST)) + +ALLOWLIST =3D BLOCK_ON_RT_MUTEX + or FUTEX_LOCK_PI --=20 2.47.3