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