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.

Instead of using the sched_wakeup tracepoint, use the sched_exit
tracepoint. 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 <[email protected]>
---
 Documentation/trace/rv/monitor_rtapp.rst  |  2 +-
 kernel/trace/rv/monitors/sleep/sleep.c    | 10 +++++-----
 kernel/trace/rv/monitors/sleep/sleep.h    | 14 +++++++-------
 tools/verification/models/rtapp/sleep.ltl |  2 +-
 4 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/Documentation/trace/rv/monitor_rtapp.rst 
b/Documentation/trace/rv/monitor_rtapp.rst
index c8104eda924a..01656bf7080a 100644
--- a/Documentation/trace/rv/monitor_rtapp.rst
+++ b/Documentation/trace/rv/monitor_rtapp.rst
@@ -95,7 +95,7 @@ The monitor's specification is::
   RULE = always ((RT and SLEEP) imply (RT_FRIENDLY_SLEEP or ALLOWLIST))
 
   RT_FRIENDLY_SLEEP = (RT_VALID_SLEEP_REASON or KERNEL_THREAD)
-                  and ((not WAKE) until RT_FRIENDLY_WAKE)
+                  and ((not SCHEDULE_IN) until RT_FRIENDLY_WAKE)
 
   RT_VALID_SLEEP_REASON = FUTEX_WAIT
                        or RT_FRIENDLY_NANOSLEEP
diff --git a/kernel/trace/rv/monitors/sleep/sleep.c 
b/kernel/trace/rv/monitors/sleep/sleep.c
index 8dfe5ec13e19..d6b677fab8f8 100644
--- a/kernel/trace/rv/monitors/sleep/sleep.c
+++ b/kernel/trace/rv/monitors/sleep/sleep.c
@@ -36,7 +36,7 @@ static void ltl_atoms_fetch(struct task_struct *task, struct 
ltl_monitor *mon)
 static void ltl_atoms_init(struct task_struct *task, struct ltl_monitor *mon, 
bool task_creation)
 {
        ltl_atom_set(mon, LTL_SLEEP, false);
-       ltl_atom_set(mon, LTL_WAKE, false);
+       ltl_atom_set(mon, LTL_SCHEDULE_IN, false);
        ltl_atom_set(mon, LTL_ABORT_SLEEP, false);
        ltl_atom_set(mon, LTL_WOKEN_BY_HARDIRQ, false);
        ltl_atom_set(mon, LTL_WOKEN_BY_NMI, false);
@@ -92,9 +92,9 @@ static void handle_sched_set_state(void *data, struct 
task_struct *task, int sta
                ltl_atom_pulse(task, LTL_ABORT_SLEEP, true);
 }
 
-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_SCHEDULE_IN, true);
 }
 
 static void handle_sched_waking(void *data, struct task_struct *task)
@@ -200,7 +200,7 @@ static int enable_sleep(void)
                return retval;
 
        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_end);
@@ -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_end);
diff --git a/kernel/trace/rv/monitors/sleep/sleep.h 
b/kernel/trace/rv/monitors/sleep/sleep.h
index 95dc2727c059..403dc2852c52 100644
--- a/kernel/trace/rv/monitors/sleep/sleep.h
+++ b/kernel/trace/rv/monitors/sleep/sleep.h
@@ -24,10 +24,10 @@ enum ltl_atom {
        LTL_NANOSLEEP_CLOCK_TAI,
        LTL_NANOSLEEP_TIMER_ABSTIME,
        LTL_RT,
+       LTL_SCHEDULE_IN,
        LTL_SLEEP,
        LTL_TASK_IS_MIGRATION,
        LTL_TASK_IS_RCU,
-       LTL_WAKE,
        LTL_WOKEN_BY_EQUAL_OR_HIGHER_PRIO,
        LTL_WOKEN_BY_HARDIRQ,
        LTL_WOKEN_BY_NMI,
@@ -50,10 +50,10 @@ static const char *ltl_atom_str(enum ltl_atom atom)
                "na_cl_ta",
                "na_ti_ab",
                "rt",
-               "sl",
+               "sch_in",
+               "sle",
                "ta_mi",
                "ta_rc",
-               "wak",
                "wo_eq_hi_pr",
                "wo_ha",
                "wo_nm",
@@ -81,10 +81,10 @@ static void ltl_start(struct task_struct *task, struct 
ltl_monitor *mon)
        bool woken_by_hardirq = test_bit(LTL_WOKEN_BY_HARDIRQ, mon->atoms);
        bool woken_by_equal_or_higher_prio = 
test_bit(LTL_WOKEN_BY_EQUAL_OR_HIGHER_PRIO,
             mon->atoms);
-       bool wake = test_bit(LTL_WAKE, mon->atoms);
        bool task_is_rcu = test_bit(LTL_TASK_IS_RCU, mon->atoms);
        bool task_is_migration = test_bit(LTL_TASK_IS_MIGRATION, mon->atoms);
        bool sleep = test_bit(LTL_SLEEP, mon->atoms);
+       bool schedule_in = test_bit(LTL_SCHEDULE_IN, mon->atoms);
        bool rt = test_bit(LTL_RT, mon->atoms);
        bool nanosleep_timer_abstime = test_bit(LTL_NANOSLEEP_TIMER_ABSTIME, 
mon->atoms);
        bool nanosleep_clock_tai = test_bit(LTL_NANOSLEEP_CLOCK_TAI, 
mon->atoms);
@@ -104,7 +104,7 @@ static void ltl_start(struct task_struct *task, struct 
ltl_monitor *mon)
        bool val35 = woken_by_nmi || val34;
        bool val36 = woken_by_hardirq || val35;
        bool val14 = woken_by_equal_or_higher_prio || val36;
-       bool val13 = !wake;
+       bool val13 = !schedule_in;
        bool val26 = nanosleep_clock_monotonic || nanosleep_clock_tai;
        bool val27 = nanosleep_timer_abstime && val26;
        bool val18 = clock_nanosleep && val27;
@@ -132,10 +132,10 @@ ltl_possible_next_states(struct ltl_monitor *mon, 
unsigned int state, unsigned l
        bool woken_by_hardirq = test_bit(LTL_WOKEN_BY_HARDIRQ, mon->atoms);
        bool woken_by_equal_or_higher_prio = 
test_bit(LTL_WOKEN_BY_EQUAL_OR_HIGHER_PRIO,
             mon->atoms);
-       bool wake = test_bit(LTL_WAKE, mon->atoms);
        bool task_is_rcu = test_bit(LTL_TASK_IS_RCU, mon->atoms);
        bool task_is_migration = test_bit(LTL_TASK_IS_MIGRATION, mon->atoms);
        bool sleep = test_bit(LTL_SLEEP, mon->atoms);
+       bool schedule_in = test_bit(LTL_SCHEDULE_IN, mon->atoms);
        bool rt = test_bit(LTL_RT, mon->atoms);
        bool nanosleep_timer_abstime = test_bit(LTL_NANOSLEEP_TIMER_ABSTIME, 
mon->atoms);
        bool nanosleep_clock_tai = test_bit(LTL_NANOSLEEP_CLOCK_TAI, 
mon->atoms);
@@ -155,7 +155,7 @@ ltl_possible_next_states(struct ltl_monitor *mon, unsigned 
int state, unsigned l
        bool val35 = woken_by_nmi || val34;
        bool val36 = woken_by_hardirq || val35;
        bool val14 = woken_by_equal_or_higher_prio || val36;
-       bool val13 = !wake;
+       bool val13 = !schedule_in;
        bool val26 = nanosleep_clock_monotonic || nanosleep_clock_tai;
        bool val27 = nanosleep_timer_abstime && val26;
        bool val18 = clock_nanosleep && val27;
diff --git a/tools/verification/models/rtapp/sleep.ltl 
b/tools/verification/models/rtapp/sleep.ltl
index 6f26c4810f78..464c84b9df87 100644
--- a/tools/verification/models/rtapp/sleep.ltl
+++ b/tools/verification/models/rtapp/sleep.ltl
@@ -1,7 +1,7 @@
 RULE = always ((RT and SLEEP) imply (RT_FRIENDLY_SLEEP or ALLOWLIST))
 
 RT_FRIENDLY_SLEEP = (RT_VALID_SLEEP_REASON or KERNEL_THREAD)
-                and ((not WAKE) until RT_FRIENDLY_WAKE)
+                and ((not SCHEDULE_IN) until RT_FRIENDLY_WAKE)
 
 RT_VALID_SLEEP_REASON = FUTEX_WAIT
                      or RT_FRIENDLY_NANOSLEEP
-- 
2.47.3


Reply via email to