linux/kernel/trace/rv/monitors/wakeup/wakeup.h
Nam Cao 6fdaab4e16 rv/rtapp: Add wakeup monitor
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 wakee task and user only gets
the stacktrace of that task. It is also extremely useful to get the
stacktrace of the waker task, which this monitor offers. In other
words, this monitor complements the rtapp/sleep monitor.

Signed-off-by: Nam Cao <namcao@linutronix.de>
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
Link: https://lore.kernel.org/r/ba5658fa13e49ada466b84a2c211f233037180b5.1781852967.git.namcao@linutronix.de
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
2026-07-24 09:01:10 +02:00

93 lines
2.4 KiB
C

/* 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 <linux/rv.h>
#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 <= RV_MAX_LTL_ATOM);
static const char *ltl_atom_str(enum ltl_atom atom)
{
static const char *const names[] = {
"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 <= RV_MAX_BA_STATES);
static void ltl_start(struct task_struct *task, struct ltl_monitor *mon)
{
bool woken_by_softirq = test_bit(LTL_WOKEN_BY_SOFTIRQ, mon->atoms);
bool woken_by_lower_prio = test_bit(LTL_WOKEN_BY_LOWER_PRIO, mon->atoms);
bool user_thread = test_bit(LTL_USER_THREAD, mon->atoms);
bool rt = test_bit(LTL_RT, mon->atoms);
bool futex_lock_pi = test_bit(LTL_FUTEX_LOCK_PI, mon->atoms);
bool block_on_rt_mutex = test_bit(LTL_BLOCK_ON_RT_MUTEX, mon->atoms);
bool val9 = block_on_rt_mutex || futex_lock_pi;
bool val6 = !woken_by_softirq;
bool val5 = !woken_by_lower_prio;
bool val8 = val5 && val6;
bool val10 = val8 || val9;
bool val3 = !user_thread;
bool val2 = !rt;
bool val4 = val2 || val3;
bool val11 = val4 || val10;
if (val11)
__set_bit(S0, mon->states);
}
static void
ltl_possible_next_states(struct ltl_monitor *mon, unsigned int state, unsigned long *next)
{
bool woken_by_softirq = test_bit(LTL_WOKEN_BY_SOFTIRQ, mon->atoms);
bool woken_by_lower_prio = test_bit(LTL_WOKEN_BY_LOWER_PRIO, mon->atoms);
bool user_thread = test_bit(LTL_USER_THREAD, mon->atoms);
bool rt = test_bit(LTL_RT, mon->atoms);
bool futex_lock_pi = test_bit(LTL_FUTEX_LOCK_PI, mon->atoms);
bool block_on_rt_mutex = test_bit(LTL_BLOCK_ON_RT_MUTEX, mon->atoms);
bool val9 = block_on_rt_mutex || futex_lock_pi;
bool val6 = !woken_by_softirq;
bool val5 = !woken_by_lower_prio;
bool val8 = val5 && val6;
bool val10 = val8 || val9;
bool val3 = !user_thread;
bool val2 = !rt;
bool val4 = val2 || val3;
bool val11 = val4 || val10;
switch (state) {
case S0:
if (val11)
__set_bit(S0, next);
break;
}
}