Skip to content

Commit ccc319d

Browse files
Daniel Bristot de Oliveirarostedt
authored andcommitted
rv/monitor: Add the wwnr monitor
Per task wakeup while not running (wwnr) monitor. This model is broken, the reason is that a task can be running in the processor without being set as RUNNABLE. Think about a task about to sleep: 1: set_current_state(TASK_UNINTERRUPTIBLE); 2: schedule(); And then imagine an IRQ happening in between the lines one and two, waking the task up. BOOM, the wakeup will happen while the task is running. Q: Why do we need this model, so? A: To test the reactors. Link: https://lkml.kernel.org/r/473c0fc39967250fdebcff8b620311c11dccad30.1659052063.git.bristot@kernel.org Cc: Wim Van Sebroeck <[email protected]> Cc: Guenter Roeck <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Will Deacon <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Marco Elver <[email protected]> Cc: Dmitry Vyukov <[email protected]> Cc: "Paul E. McKenney" <[email protected]> Cc: Shuah Khan <[email protected]> Cc: Gabriele Paoloni <[email protected]> Cc: Juri Lelli <[email protected]> Cc: Clark Williams <[email protected]> Cc: Tao Zhou <[email protected]> Cc: Randy Dunlap <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Signed-off-by: Daniel Bristot de Oliveira <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent 10bde81 commit ccc319d

File tree

8 files changed

+220
-0
lines changed

8 files changed

+220
-0
lines changed

Documentation/trace/rv/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ Runtime Verification
1111
da_monitor_synthesis.rst
1212
da_monitor_instrumentation.rst
1313
monitor_wip.rst
14+
monitor_wwnr.rst
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
Monitor wwnr
2+
============
3+
4+
- Name: wwrn - wakeup while not running
5+
- Type: per-task deterministic automaton
6+
- Author: Daniel Bristot de Oliveira <[email protected]>
7+
8+
Description
9+
-----------
10+
11+
This is a per-task sample monitor, with the following
12+
definition::
13+
14+
|
15+
|
16+
v
17+
wakeup +-------------+
18+
+--------- | |
19+
| | not_running |
20+
+--------> | | <+
21+
+-------------+ |
22+
| |
23+
| switch_in | switch_out
24+
v |
25+
+-------------+ |
26+
| running | -+
27+
+-------------+
28+
29+
This model is borken, the reason is that a task can be running
30+
in the processor without being set as RUNNABLE. Think about a
31+
task about to sleep::
32+
33+
1: set_current_state(TASK_UNINTERRUPTIBLE);
34+
2: schedule();
35+
36+
And then imagine an IRQ happening in between the lines one and two,
37+
waking the task up. BOOM, the wakeup will happen while the task is
38+
running.
39+
40+
- Why do we need this model, so?
41+
- To test the reactors.
42+
43+
Specification
44+
-------------
45+
Grapviz Dot file in tools/verification/models/wwnr.dot

include/trace/events/rv.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,18 @@ DECLARE_EVENT_CLASS(error_da_monitor_id,
122122
__entry->event,
123123
__entry->state)
124124
);
125+
126+
#ifdef CONFIG_RV_MON_WWNR
127+
/* id is the pid of the task */
128+
DEFINE_EVENT(event_da_monitor_id, event_wwnr,
129+
TP_PROTO(int id, char *state, char *event, char *next_state, bool final_state),
130+
TP_ARGS(id, state, event, next_state, final_state));
131+
132+
DEFINE_EVENT(error_da_monitor_id, error_wwnr,
133+
TP_PROTO(int id, char *state, char *event),
134+
TP_ARGS(id, state, event));
135+
#endif /* CONFIG_RV_MON_WWNR */
136+
125137
#endif /* CONFIG_DA_MON_EVENTS_ID */
126138
#endif /* _TRACE_RV_H */
127139

kernel/trace/rv/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@ config RV_MON_WIP
3838
For further information, see:
3939
Documentation/trace/rv/monitor_wip.rst
4040

41+
config RV_MON_WWNR
42+
depends on RV
43+
select DA_MON_EVENTS_ID
44+
bool "wwnr monitor"
45+
help
46+
Enable wwnr (wakeup while not running) sample monitor, this is a
47+
sample monitor that illustrates the usage of per-task monitor.
48+
The model is borken on purpose: it serves to test reactors.
49+
50+
For further information, see:
51+
Documentation/trace/rv/monitor_wwnr.rst
52+
4153
config RV_REACTORS
4254
bool "Runtime verification reactors"
4355
default y

kernel/trace/rv/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
obj-$(CONFIG_RV) += rv.o
44
obj-$(CONFIG_RV_REACTORS) += rv_reactors.o
55
obj-$(CONFIG_RV_MON_WIP) += monitors/wip/wip.o
6+
obj-$(CONFIG_RV_MON_WWNR) += monitors/wwnr/wwnr.o

kernel/trace/rv/monitors/wwnr/wwnr.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <linux/ftrace.h>
3+
#include <linux/tracepoint.h>
4+
#include <linux/kernel.h>
5+
#include <linux/module.h>
6+
#include <linux/init.h>
7+
#include <linux/rv.h>
8+
#include <rv/instrumentation.h>
9+
#include <rv/da_monitor.h>
10+
11+
#define MODULE_NAME "wwnr"
12+
13+
#include <trace/events/rv.h>
14+
#include <trace/events/sched.h>
15+
16+
#include "wwnr.h"
17+
18+
struct rv_monitor rv_wwnr;
19+
DECLARE_DA_MON_PER_TASK(wwnr, unsigned char);
20+
21+
static void handle_switch(void *data, bool preempt, struct task_struct *p,
22+
struct task_struct *n, unsigned int prev_state)
23+
{
24+
/* start monitoring only after the first suspension */
25+
if (prev_state == TASK_INTERRUPTIBLE)
26+
da_handle_start_event_wwnr(p, switch_out_wwnr);
27+
else
28+
da_handle_event_wwnr(p, switch_out_wwnr);
29+
30+
da_handle_event_wwnr(n, switch_in_wwnr);
31+
}
32+
33+
static void handle_wakeup(void *data, struct task_struct *p)
34+
{
35+
da_handle_event_wwnr(p, wakeup_wwnr);
36+
}
37+
38+
static int enable_wwnr(void)
39+
{
40+
int retval;
41+
42+
retval = da_monitor_init_wwnr();
43+
if (retval)
44+
return retval;
45+
46+
rv_attach_trace_probe("wwnr", sched_switch, handle_switch);
47+
rv_attach_trace_probe("wwnr", sched_wakeup, handle_wakeup);
48+
49+
return 0;
50+
}
51+
52+
static void disable_wwnr(void)
53+
{
54+
rv_wwnr.enabled = 0;
55+
56+
rv_detach_trace_probe("wwnr", sched_switch, handle_switch);
57+
rv_detach_trace_probe("wwnr", sched_wakeup, handle_wakeup);
58+
59+
da_monitor_destroy_wwnr();
60+
}
61+
62+
struct rv_monitor rv_wwnr = {
63+
.name = "wwnr",
64+
.description = "wakeup while not running per-task testing model.",
65+
.enable = enable_wwnr,
66+
.disable = disable_wwnr,
67+
.reset = da_monitor_reset_all_wwnr,
68+
.enabled = 0,
69+
};
70+
71+
static int register_wwnr(void)
72+
{
73+
rv_register_monitor(&rv_wwnr);
74+
return 0;
75+
}
76+
77+
static void unregister_wwnr(void)
78+
{
79+
rv_unregister_monitor(&rv_wwnr);
80+
}
81+
82+
module_init(register_wwnr);
83+
module_exit(unregister_wwnr);
84+
85+
MODULE_LICENSE("GPL");
86+
MODULE_AUTHOR("Daniel Bristot de Oliveira <[email protected]>");
87+
MODULE_DESCRIPTION("wwnr: wakeup while not running monitor");

kernel/trace/rv/monitors/wwnr/wwnr.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Automatically generated C representation of wwnr automaton
3+
* For further information about this format, see kernel documentation:
4+
* Documentation/trace/rv/deterministic_automata.rst
5+
*/
6+
7+
enum states_wwnr {
8+
not_running_wwnr = 0,
9+
running_wwnr,
10+
state_max_wwnr
11+
};
12+
13+
#define INVALID_STATE state_max_wwnr
14+
15+
enum events_wwnr {
16+
switch_in_wwnr = 0,
17+
switch_out_wwnr,
18+
wakeup_wwnr,
19+
event_max_wwnr
20+
};
21+
22+
struct automaton_wwnr {
23+
char *state_names[state_max_wwnr];
24+
char *event_names[event_max_wwnr];
25+
unsigned char function[state_max_wwnr][event_max_wwnr];
26+
unsigned char initial_state;
27+
bool final_states[state_max_wwnr];
28+
};
29+
30+
struct automaton_wwnr automaton_wwnr = {
31+
.state_names = {
32+
"not_running",
33+
"running"
34+
},
35+
.event_names = {
36+
"switch_in",
37+
"switch_out",
38+
"wakeup"
39+
},
40+
.function = {
41+
{ running_wwnr, INVALID_STATE, not_running_wwnr },
42+
{ INVALID_STATE, not_running_wwnr, INVALID_STATE },
43+
},
44+
.initial_state = not_running_wwnr,
45+
.final_states = { 1, 0 },
46+
};

tools/verification/models/wwnr.dot

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
digraph state_automaton {
2+
{node [shape = plaintext, style=invis, label=""] "__init_not_running"};
3+
{node [shape = ellipse] "not_running"};
4+
{node [shape = plaintext] "not_running"};
5+
{node [shape = plaintext] "running"};
6+
"__init_not_running" -> "not_running";
7+
"not_running" [label = "not_running", color = green3];
8+
"not_running" -> "not_running" [ label = "wakeup" ];
9+
"not_running" -> "running" [ label = "switch_in" ];
10+
"running" [label = "running"];
11+
"running" -> "not_running" [ label = "switch_out" ];
12+
{ rank = min ;
13+
"__init_not_running";
14+
"not_running";
15+
}
16+
}

0 commit comments

Comments
 (0)