xref: /linux/Documentation/trace/rv/hybrid_automata.rst (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
1*708340c2SGabriele MonacoHybrid Automata
2*708340c2SGabriele Monaco===============
3*708340c2SGabriele Monaco
4*708340c2SGabriele MonacoHybrid automata are an extension of deterministic automata, there are several
5*708340c2SGabriele Monacodefinitions of hybrid automata in the literature. The adaptation implemented
6*708340c2SGabriele Monacohere is formally denoted by G and defined as a 7-tuple:
7*708340c2SGabriele Monaco
8*708340c2SGabriele Monaco        *G* = { *X*, *E*, *V*, *f*, x\ :subscript:`0`, X\ :subscript:`m`, *i* }
9*708340c2SGabriele Monaco
10*708340c2SGabriele Monaco- *X* is the set of states;
11*708340c2SGabriele Monaco- *E* is the finite set of events;
12*708340c2SGabriele Monaco- *V* is the finite set of environment variables;
13*708340c2SGabriele Monaco- x\ :subscript:`0` is the initial state;
14*708340c2SGabriele Monaco- X\ :subscript:`m` (subset of *X*) is the set of marked (or final) states.
15*708340c2SGabriele Monaco- *f* : *X* x *E* x *C(V)* -> *X* is the transition function.
16*708340c2SGabriele Monaco  It defines the state transition in the occurrence of an event from *E* in the
17*708340c2SGabriele Monaco  state *X*. Unlike deterministic automata, the transition function also
18*708340c2SGabriele Monaco  includes guards from the set of all possible constraints (defined as *C(V)*).
19*708340c2SGabriele Monaco  Guards can be true or false with the valuation of *V* when the event occurs,
20*708340c2SGabriele Monaco  and the transition is possible only when constraints are true. Similarly to
21*708340c2SGabriele Monaco  deterministic automata, the occurrence of the event in *E* in a state in *X*
22*708340c2SGabriele Monaco  has a deterministic next state from *X*, if the guard is true.
23*708340c2SGabriele Monaco- *i* : *X* -> *C'(V)* is the invariant assignment function, this is a
24*708340c2SGabriele Monaco  constraint assigned to each state in *X*, every state in *X* must be left
25*708340c2SGabriele Monaco  before the invariant turns to false. We can omit the representation of
26*708340c2SGabriele Monaco  invariants whose value is true regardless of the valuation of *V*.
27*708340c2SGabriele Monaco
28*708340c2SGabriele MonacoThe set of all possible constraints *C(V)* is defined according to the
29*708340c2SGabriele Monacofollowing grammar:
30*708340c2SGabriele Monaco
31*708340c2SGabriele Monaco        g = v < c | v > c | v <= c | v >= c | v == c | v != c | g && g | true
32*708340c2SGabriele Monaco
33*708340c2SGabriele MonacoWith v a variable in *V* and c a numerical value.
34*708340c2SGabriele Monaco
35*708340c2SGabriele MonacoWe define the special case of hybrid automata whose variables grow with uniform
36*708340c2SGabriele Monacorates as timed automata. In this case, the variables are called clocks.
37*708340c2SGabriele MonacoAs the name implies, timed automata can be used to describe real time.
38*708340c2SGabriele MonacoAdditionally, clocks support another type of guard which always evaluates to true:
39*708340c2SGabriele Monaco
40*708340c2SGabriele Monaco        reset(v)
41*708340c2SGabriele Monaco
42*708340c2SGabriele MonacoThe reset constraint is used to set the value of a clock to 0.
43*708340c2SGabriele Monaco
44*708340c2SGabriele MonacoThe set of invariant constraints *C'(V)* is a subset of *C(V)* including only
45*708340c2SGabriele Monacoconstraint of the form:
46*708340c2SGabriele Monaco
47*708340c2SGabriele Monaco        g = v < c | true
48*708340c2SGabriele Monaco
49*708340c2SGabriele MonacoThis simplifies the implementation as a clock expiration is a necessary and
50*708340c2SGabriele Monacosufficient condition for the violation of invariants while still allowing more
51*708340c2SGabriele Monacocomplex constraints to be specified as guards.
52*708340c2SGabriele Monaco
53*708340c2SGabriele MonacoIt is important to note that any hybrid automaton is a valid deterministic
54*708340c2SGabriele Monacoautomaton with additional guards and invariants. Those can only further
55*708340c2SGabriele Monacoconstrain what transitions are valid but it is not possible to define
56*708340c2SGabriele Monacotransition functions starting from the same state in *X* and the same event in
57*708340c2SGabriele Monaco*E* but ending up in different states in *X* based on the valuation of *V*.
58*708340c2SGabriele Monaco
59*708340c2SGabriele MonacoExamples
60*708340c2SGabriele Monaco--------
61*708340c2SGabriele Monaco
62*708340c2SGabriele MonacoWip as hybrid automaton
63*708340c2SGabriele Monaco~~~~~~~~~~~~~~~~~~~~~~~
64*708340c2SGabriele Monaco
65*708340c2SGabriele MonacoThe 'wip' (wakeup in preemptive) example introduced as a deterministic automaton
66*708340c2SGabriele Monacocan also be described as:
67*708340c2SGabriele Monaco
68*708340c2SGabriele Monaco- *X* = { ``any_thread_running`` }
69*708340c2SGabriele Monaco- *E* = { ``sched_waking`` }
70*708340c2SGabriele Monaco- *V* = { ``preemptive`` }
71*708340c2SGabriele Monaco- x\ :subscript:`0` = ``any_thread_running``
72*708340c2SGabriele Monaco- X\ :subscript:`m` = {``any_thread_running``}
73*708340c2SGabriele Monaco- *f* =
74*708340c2SGabriele Monaco   - *f*\ (``any_thread_running``, ``sched_waking``, ``preemptive==0``) = ``any_thread_running``
75*708340c2SGabriele Monaco- *i* =
76*708340c2SGabriele Monaco   - *i*\ (``any_thread_running``) = ``true``
77*708340c2SGabriele Monaco
78*708340c2SGabriele MonacoWhich can be represented graphically as::
79*708340c2SGabriele Monaco
80*708340c2SGabriele Monaco     |
81*708340c2SGabriele Monaco     |
82*708340c2SGabriele Monaco     v
83*708340c2SGabriele Monaco   #====================#   sched_waking;preemptive==0
84*708340c2SGabriele Monaco   H                    H ------------------------------+
85*708340c2SGabriele Monaco   H any_thread_running H                               |
86*708340c2SGabriele Monaco   H                    H <-----------------------------+
87*708340c2SGabriele Monaco   #====================#
88*708340c2SGabriele Monaco
89*708340c2SGabriele MonacoIn this example, by using the preemptive state of the system as an environment
90*708340c2SGabriele Monacovariable, we can assert this constraint on ``sched_waking`` without requiring
91*708340c2SGabriele Monacopreemption events (as we would in a deterministic automaton), which can be
92*708340c2SGabriele Monacouseful in case those events are not available or not reliable on the system.
93*708340c2SGabriele Monaco
94*708340c2SGabriele MonacoSince all the invariants in *i* are true, we can omit them from the representation.
95*708340c2SGabriele Monaco
96*708340c2SGabriele MonacoStall model with guards (iteration 1)
97*708340c2SGabriele Monaco~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
98*708340c2SGabriele Monaco
99*708340c2SGabriele MonacoAs a sample timed automaton we can define 'stall' as:
100*708340c2SGabriele Monaco
101*708340c2SGabriele Monaco- *X* = { ``dequeued``, ``enqueued``, ``running``}
102*708340c2SGabriele Monaco- *E* = { ``enqueue``, ``dequeue``, ``switch_in``}
103*708340c2SGabriele Monaco- *V* = { ``clk`` }
104*708340c2SGabriele Monaco- x\ :subscript:`0` = ``dequeue``
105*708340c2SGabriele Monaco- X\ :subscript:`m` = {``dequeue``}
106*708340c2SGabriele Monaco- *f* =
107*708340c2SGabriele Monaco   - *f*\ (``enqueued``, ``switch_in``, ``clk < threshold``) = ``running``
108*708340c2SGabriele Monaco   - *f*\ (``running``, ``dequeue``) = ``dequeued``
109*708340c2SGabriele Monaco   - *f*\ (``dequeued``, ``enqueue``, ``reset(clk)``) = ``enqueued``
110*708340c2SGabriele Monaco- *i* = *omitted as all true*
111*708340c2SGabriele Monaco
112*708340c2SGabriele MonacoGraphically represented as::
113*708340c2SGabriele Monaco
114*708340c2SGabriele Monaco       |
115*708340c2SGabriele Monaco       |
116*708340c2SGabriele Monaco       v
117*708340c2SGabriele Monaco     #============================#
118*708340c2SGabriele Monaco     H          dequeued          H <+
119*708340c2SGabriele Monaco     #============================#  |
120*708340c2SGabriele Monaco       |                             |
121*708340c2SGabriele Monaco       | enqueue; reset(clk)         |
122*708340c2SGabriele Monaco       v                             |
123*708340c2SGabriele Monaco     +----------------------------+  |
124*708340c2SGabriele Monaco     |          enqueued          |  | dequeue
125*708340c2SGabriele Monaco     +----------------------------+  |
126*708340c2SGabriele Monaco       |                             |
127*708340c2SGabriele Monaco       | switch_in; clk < threshold  |
128*708340c2SGabriele Monaco       v                             |
129*708340c2SGabriele Monaco     +----------------------------+  |
130*708340c2SGabriele Monaco     |          running           | -+
131*708340c2SGabriele Monaco     +----------------------------+
132*708340c2SGabriele Monaco
133*708340c2SGabriele MonacoThis model imposes that the time between when a task is enqueued (it becomes
134*708340c2SGabriele Monacorunnable) and when the task gets to run must be lower than a certain threshold.
135*708340c2SGabriele MonacoA failure in this model means that the task is starving.
136*708340c2SGabriele MonacoOne problem in using guards on the edges in this case is that the model will
137*708340c2SGabriele Monaconot report a failure until the ``switch_in`` event occurs. This means that,
138*708340c2SGabriele Monacoaccording to the model, it is valid for the task never to run.
139*708340c2SGabriele Monaco
140*708340c2SGabriele MonacoStall model with invariants (iteration 2)
141*708340c2SGabriele Monaco~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
142*708340c2SGabriele Monaco
143*708340c2SGabriele MonacoThe first iteration isn't exactly what was intended, we can change the model as:
144*708340c2SGabriele Monaco
145*708340c2SGabriele Monaco- *X* = { ``dequeued``, ``enqueued``, ``running``}
146*708340c2SGabriele Monaco- *E* = { ``enqueue``, ``dequeue``, ``switch_in``}
147*708340c2SGabriele Monaco- *V* = { ``clk`` }
148*708340c2SGabriele Monaco- x\ :subscript:`0` = ``dequeue``
149*708340c2SGabriele Monaco- X\ :subscript:`m` = {``dequeue``}
150*708340c2SGabriele Monaco- *f* =
151*708340c2SGabriele Monaco   - *f*\ (``enqueued``, ``switch_in``) = ``running``
152*708340c2SGabriele Monaco   - *f*\ (``running``, ``dequeue``) = ``dequeued``
153*708340c2SGabriele Monaco   - *f*\ (``dequeued``, ``enqueue``, ``reset(clk)``) = ``enqueued``
154*708340c2SGabriele Monaco- *i* =
155*708340c2SGabriele Monaco   - *i*\ (``enqueued``) = ``clk < threshold``
156*708340c2SGabriele Monaco
157*708340c2SGabriele MonacoGraphically::
158*708340c2SGabriele Monaco
159*708340c2SGabriele Monaco    |
160*708340c2SGabriele Monaco    |
161*708340c2SGabriele Monaco    v
162*708340c2SGabriele Monaco  #=========================#
163*708340c2SGabriele Monaco  H        dequeued         H <+
164*708340c2SGabriele Monaco  #=========================#  |
165*708340c2SGabriele Monaco    |                          |
166*708340c2SGabriele Monaco    | enqueue; reset(clk)      |
167*708340c2SGabriele Monaco    v                          |
168*708340c2SGabriele Monaco  +-------------------------+  |
169*708340c2SGabriele Monaco  |        enqueued         |  |
170*708340c2SGabriele Monaco  |    clk < threshold      |  | dequeue
171*708340c2SGabriele Monaco  +-------------------------+  |
172*708340c2SGabriele Monaco    |                          |
173*708340c2SGabriele Monaco    | switch_in                |
174*708340c2SGabriele Monaco    v                          |
175*708340c2SGabriele Monaco  +-------------------------+  |
176*708340c2SGabriele Monaco  |         running         | -+
177*708340c2SGabriele Monaco  +-------------------------+
178*708340c2SGabriele Monaco
179*708340c2SGabriele MonacoIn this case, we moved the guard as an invariant to the ``enqueued`` state,
180*708340c2SGabriele Monacothis means we not only forbid the occurrence of ``switch_in`` when ``clk`` is
181*708340c2SGabriele Monacopast the threshold but also mark as invalid in case we are *still* in
182*708340c2SGabriele Monaco``enqueued`` after the threshold. This model is effectively in an invalid state
183*708340c2SGabriele Monacoas soon as a task is starving, rather than when the starving task finally runs.
184*708340c2SGabriele Monaco
185*708340c2SGabriele MonacoHybrid Automaton in C
186*708340c2SGabriele Monaco---------------------
187*708340c2SGabriele Monaco
188*708340c2SGabriele MonacoThe definition of hybrid automata in C is heavily based on the deterministic
189*708340c2SGabriele Monacoautomata one. Specifically, we add the set of environment variables and the
190*708340c2SGabriele Monacoconstraints (both guards on transitions and invariants on states) as follows.
191*708340c2SGabriele MonacoThis is a combination of both iterations of the stall example::
192*708340c2SGabriele Monaco
193*708340c2SGabriele Monaco  /* enum representation of X (set of states) to be used as index */
194*708340c2SGabriele Monaco  enum states {
195*708340c2SGabriele Monaco	dequeued,
196*708340c2SGabriele Monaco	enqueued,
197*708340c2SGabriele Monaco	running,
198*708340c2SGabriele Monaco	state_max,
199*708340c2SGabriele Monaco  };
200*708340c2SGabriele Monaco
201*708340c2SGabriele Monaco  #define INVALID_STATE state_max
202*708340c2SGabriele Monaco
203*708340c2SGabriele Monaco  /* enum representation of E (set of events) to be used as index */
204*708340c2SGabriele Monaco  enum events {
205*708340c2SGabriele Monaco	dequeue,
206*708340c2SGabriele Monaco	enqueue,
207*708340c2SGabriele Monaco	switch_in,
208*708340c2SGabriele Monaco	event_max,
209*708340c2SGabriele Monaco  };
210*708340c2SGabriele Monaco
211*708340c2SGabriele Monaco  /* enum representation of V (set of environment variables) to be used as index */
212*708340c2SGabriele Monaco  enum envs {
213*708340c2SGabriele Monaco	clk,
214*708340c2SGabriele Monaco	env_max,
215*708340c2SGabriele Monaco	env_max_stored = env_max,
216*708340c2SGabriele Monaco  };
217*708340c2SGabriele Monaco
218*708340c2SGabriele Monaco  struct automaton {
219*708340c2SGabriele Monaco	char *state_names[state_max];                  // X: the set of states
220*708340c2SGabriele Monaco	char *event_names[event_max];                  // E: the finite set of events
221*708340c2SGabriele Monaco	char *env_names[env_max];                      // V: the finite set of env vars
222*708340c2SGabriele Monaco	unsigned char function[state_max][event_max];  // f: transition function
223*708340c2SGabriele Monaco	unsigned char initial_state;                   // x_0: the initial state
224*708340c2SGabriele Monaco	bool final_states[state_max];                  // X_m: the set of marked states
225*708340c2SGabriele Monaco  };
226*708340c2SGabriele Monaco
227*708340c2SGabriele Monaco  struct automaton aut = {
228*708340c2SGabriele Monaco	.state_names = {
229*708340c2SGabriele Monaco		"dequeued",
230*708340c2SGabriele Monaco		"enqueued",
231*708340c2SGabriele Monaco		"running",
232*708340c2SGabriele Monaco	},
233*708340c2SGabriele Monaco	.event_names = {
234*708340c2SGabriele Monaco		"dequeue",
235*708340c2SGabriele Monaco		"enqueue",
236*708340c2SGabriele Monaco		"switch_in",
237*708340c2SGabriele Monaco	},
238*708340c2SGabriele Monaco	.env_names = {
239*708340c2SGabriele Monaco		"clk",
240*708340c2SGabriele Monaco	},
241*708340c2SGabriele Monaco	.function = {
242*708340c2SGabriele Monaco		{ INVALID_STATE,      enqueued, INVALID_STATE },
243*708340c2SGabriele Monaco		{ INVALID_STATE, INVALID_STATE,       running },
244*708340c2SGabriele Monaco		{      dequeued, INVALID_STATE, INVALID_STATE },
245*708340c2SGabriele Monaco	},
246*708340c2SGabriele Monaco	.initial_state = dequeued,
247*708340c2SGabriele Monaco	.final_states = { 1, 0, 0 },
248*708340c2SGabriele Monaco  };
249*708340c2SGabriele Monaco
250*708340c2SGabriele Monaco  static bool verify_constraint(enum states curr_state, enum events event,
251*708340c2SGabriele Monaco                                enum states next_state)
252*708340c2SGabriele Monaco  {
253*708340c2SGabriele Monaco	bool res = true;
254*708340c2SGabriele Monaco
255*708340c2SGabriele Monaco	/* Validate guards as part of f */
256*708340c2SGabriele Monaco	if (curr_state == enqueued && event == switch_in)
257*708340c2SGabriele Monaco		res = get_env(clk) < threshold;
258*708340c2SGabriele Monaco	else if (curr_state == dequeued && event == enqueue)
259*708340c2SGabriele Monaco		reset_env(clk);
260*708340c2SGabriele Monaco
261*708340c2SGabriele Monaco	/* Validate invariants in i */
262*708340c2SGabriele Monaco	if (next_state == curr_state || !res)
263*708340c2SGabriele Monaco		return res;
264*708340c2SGabriele Monaco	if (next_state == enqueued)
265*708340c2SGabriele Monaco		ha_start_timer_jiffy(ha_mon, clk, threshold_jiffies);
266*708340c2SGabriele Monaco	else if (curr_state == enqueued)
267*708340c2SGabriele Monaco		res = !ha_cancel_timer(ha_mon);
268*708340c2SGabriele Monaco	return res;
269*708340c2SGabriele Monaco  }
270*708340c2SGabriele Monaco
271*708340c2SGabriele MonacoThe function ``verify_constraint``, here reported as simplified, checks guards,
272*708340c2SGabriele Monacoperforms resets and starts timers to validate invariants according to
273*708340c2SGabriele Monacospecification, those cannot easily be represented in the automaton struct.
274*708340c2SGabriele MonacoDue to the complex nature of environment variables, the user needs to provide
275*708340c2SGabriele Monacofunctions to get and reset environment variables that are not common clocks
276*708340c2SGabriele Monaco(e.g. clocks with ns or jiffy granularity).
277*708340c2SGabriele MonacoSince invariants are only defined as clock expirations (e.g. *clk <
278*708340c2SGabriele Monacothreshold*), reaching the expiration of a timer armed when entering the state
279*708340c2SGabriele Monacois in fact a failure in the model and triggers a reaction. Leaving the state
280*708340c2SGabriele Monacostops the timer.
281*708340c2SGabriele Monaco
282*708340c2SGabriele MonacoIt is important to note that timers implemented with hrtimers introduce
283*708340c2SGabriele Monacooverhead, if the monitor has several instances (e.g. all tasks) this can become
284*708340c2SGabriele Monacoan issue. The impact can be decreased using the timer wheel (``HA_TIMER_TYPE``
285*708340c2SGabriele Monacoset to ``HA_TIMER_WHEEL``), this lowers the responsiveness of the timer without
286*708340c2SGabriele Monacodamaging the accuracy of the model, since the invariant condition is checked
287*708340c2SGabriele Monacobefore disabling the timer in case the callback is late.
288*708340c2SGabriele MonacoAlternatively, if the monitor is guaranteed to *eventually* leave the state and
289*708340c2SGabriele Monacothe incurred delay to wait for the next event is acceptable, guards can be used
290*708340c2SGabriele Monacoin place of invariants, as seen in the stall example.
291*708340c2SGabriele Monaco
292*708340c2SGabriele MonacoGraphviz .dot format
293*708340c2SGabriele Monaco--------------------
294*708340c2SGabriele Monaco
295*708340c2SGabriele MonacoAlso the Graphviz representation of hybrid automata is an extension of the
296*708340c2SGabriele Monacodeterministic automata one. Specifically, guards can be provided in the event
297*708340c2SGabriele Monaconame separated by ``;``::
298*708340c2SGabriele Monaco
299*708340c2SGabriele Monaco    "state_start" -> "state_dest" [ label = "sched_waking;preemptible==0;reset(clk)" ];
300*708340c2SGabriele Monaco
301*708340c2SGabriele MonacoInvariant can be specified in the state label (not the node name!) separated by ``\n``::
302*708340c2SGabriele Monaco
303*708340c2SGabriele Monaco    "enqueued" [label = "enqueued\nclk < threshold_jiffies"];
304*708340c2SGabriele Monaco
305*708340c2SGabriele MonacoConstraints can be specified as valid C comparisons and allow spaces, the first
306*708340c2SGabriele Monacoelement of the comparison must be the clock while the second is a numerical or
307*708340c2SGabriele Monacoparametrised value. Guards allow comparisons to be combined with boolean
308*708340c2SGabriele Monacooperations (``&&`` and ``||``), resets must be separated from other constraints.
309*708340c2SGabriele Monaco
310*708340c2SGabriele MonacoThis is the full example of the last version of the 'stall' model in DOT::
311*708340c2SGabriele Monaco
312*708340c2SGabriele Monaco  digraph state_automaton {
313*708340c2SGabriele Monaco      {node [shape = circle] "enqueued"};
314*708340c2SGabriele Monaco      {node [shape = plaintext, style=invis, label=""] "__init_dequeued"};
315*708340c2SGabriele Monaco      {node [shape = doublecircle] "dequeued"};
316*708340c2SGabriele Monaco      {node [shape = circle] "running"};
317*708340c2SGabriele Monaco      "__init_dequeued" -> "dequeued";
318*708340c2SGabriele Monaco      "enqueued" [label = "enqueued\nclk < threshold_jiffies"];
319*708340c2SGabriele Monaco      "running" [label = "running"];
320*708340c2SGabriele Monaco      "dequeued" [label = "dequeued"];
321*708340c2SGabriele Monaco      "enqueued" -> "running" [ label = "switch_in" ];
322*708340c2SGabriele Monaco      "running" -> "dequeued" [ label = "dequeue" ];
323*708340c2SGabriele Monaco      "dequeued" -> "enqueued" [ label = "enqueue;reset(clk)" ];
324*708340c2SGabriele Monaco      { rank = min ;
325*708340c2SGabriele Monaco          "__init_dequeued";
326*708340c2SGabriele Monaco          "dequeued";
327*708340c2SGabriele Monaco      }
328*708340c2SGabriele Monaco  }
329*708340c2SGabriele Monaco
330*708340c2SGabriele MonacoReferences
331*708340c2SGabriele Monaco----------
332*708340c2SGabriele Monaco
333*708340c2SGabriele MonacoOne book covering model checking and timed automata is::
334*708340c2SGabriele Monaco
335*708340c2SGabriele Monaco  Christel Baier and Joost-Pieter Katoen: Principles of Model Checking,
336*708340c2SGabriele Monaco  The MIT Press, 2008.
337*708340c2SGabriele Monaco
338*708340c2SGabriele MonacoHybrid automata are described in detail in::
339*708340c2SGabriele Monaco
340*708340c2SGabriele Monaco  Thomas Henzinger: The theory of hybrid automata,
341*708340c2SGabriele Monaco  Proceedings 11th Annual IEEE Symposium on Logic in Computer Science, 1996.
342