185 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			185 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| Deterministic Automata
 | |
| ======================
 | |
| 
 | |
| Formally, a deterministic automaton, denoted by G, is defined as a quintuple:
 | |
| 
 | |
|         *G* = { *X*, *E*, *f*, x\ :subscript:`0`, X\ :subscript:`m` }
 | |
| 
 | |
| where:
 | |
| 
 | |
| - *X* is the set of states;
 | |
| - *E* is the finite set of events;
 | |
| - x\ :subscript:`0` is the initial state;
 | |
| - X\ :subscript:`m` (subset of *X*) is the set of marked (or final) states.
 | |
| - *f* : *X* x *E* -> *X* $ is the transition function. It defines the state
 | |
|   transition in the occurrence of an event from *E* in the state *X*. In the
 | |
|   special case of deterministic automata, the occurrence of the event in *E*
 | |
|   in a state in *X* has a deterministic next state from *X*.
 | |
| 
 | |
| For example, a given automaton named 'wip' (wakeup in preemptive) can
 | |
| be defined as:
 | |
| 
 | |
| - *X* = { ``preemptive``, ``non_preemptive``}
 | |
| - *E* = { ``preempt_enable``, ``preempt_disable``, ``sched_waking``}
 | |
| - x\ :subscript:`0` = ``preemptive``
 | |
| - X\ :subscript:`m` = {``preemptive``}
 | |
| - *f* =
 | |
|    - *f*\ (``preemptive``, ``preempt_disable``) = ``non_preemptive``
 | |
|    - *f*\ (``non_preemptive``, ``sched_waking``) = ``non_preemptive``
 | |
|    - *f*\ (``non_preemptive``, ``preempt_enable``) = ``preemptive``
 | |
| 
 | |
| One of the benefits of this formal definition is that it can be presented
 | |
| in multiple formats. For example, using a *graphical representation*, using
 | |
| vertices (nodes) and edges, which is very intuitive for *operating system*
 | |
| practitioners, without any loss.
 | |
| 
 | |
| The previous 'wip' automaton can also be represented as::
 | |
| 
 | |
|                        preempt_enable
 | |
|           +---------------------------------+
 | |
|           v                                 |
 | |
|         #============#  preempt_disable   +------------------+
 | |
|     --> H preemptive H -----------------> |  non_preemptive  |
 | |
|         #============#                    +------------------+
 | |
|                                             ^              |
 | |
|                                             | sched_waking |
 | |
|                                             +--------------+
 | |
| 
 | |
| Deterministic Automaton in C
 | |
| ----------------------------
 | |
| 
 | |
| In the paper "Efficient formal verification for the Linux kernel",
 | |
| the authors present a simple way to represent an automaton in C that can
 | |
| be used as regular code in the Linux kernel.
 | |
| 
 | |
| For example, the 'wip' automata can be presented as (augmented with comments)::
 | |
| 
 | |
|   /* enum representation of X (set of states) to be used as index */
 | |
|   enum states {
 | |
| 	preemptive = 0,
 | |
| 	non_preemptive,
 | |
| 	state_max
 | |
|   };
 | |
| 
 | |
|   #define INVALID_STATE state_max
 | |
| 
 | |
|   /* enum representation of E (set of events) to be used as index */
 | |
|   enum events {
 | |
| 	preempt_disable = 0,
 | |
| 	preempt_enable,
 | |
| 	sched_waking,
 | |
| 	event_max
 | |
|   };
 | |
| 
 | |
|   struct automaton {
 | |
| 	char *state_names[state_max];                   // X: the set of states
 | |
| 	char *event_names[event_max];                   // E: the finite set of events
 | |
| 	unsigned char function[state_max][event_max];   // f: transition function
 | |
| 	unsigned char initial_state;                    // x_0: the initial state
 | |
| 	bool final_states[state_max];                   // X_m: the set of marked states
 | |
|   };
 | |
| 
 | |
|   struct automaton aut = {
 | |
| 	.state_names = {
 | |
| 		"preemptive",
 | |
| 		"non_preemptive"
 | |
| 	},
 | |
| 	.event_names = {
 | |
| 		"preempt_disable",
 | |
| 		"preempt_enable",
 | |
| 		"sched_waking"
 | |
| 	},
 | |
| 	.function = {
 | |
| 		{ non_preemptive,  INVALID_STATE,  INVALID_STATE },
 | |
| 		{  INVALID_STATE,     preemptive, non_preemptive },
 | |
| 	},
 | |
| 	.initial_state = preemptive,
 | |
| 	.final_states = { 1, 0 },
 | |
|   };
 | |
| 
 | |
| The *transition function* is represented as a matrix of states (lines) and
 | |
| events (columns), and so the function *f* : *X* x *E* -> *X* can be solved
 | |
| in O(1). For example::
 | |
| 
 | |
|   next_state = automaton_wip.function[curr_state][event];
 | |
| 
 | |
| Graphviz .dot format
 | |
| --------------------
 | |
| 
 | |
| The Graphviz open-source tool can produce the graphical representation
 | |
| of an automaton using the (textual) DOT language as the source code.
 | |
| The DOT format is widely used and can be converted to many other formats.
 | |
| 
 | |
| For example, this is the 'wip' model in DOT::
 | |
| 
 | |
|   digraph state_automaton {
 | |
|         {node [shape = circle] "non_preemptive"};
 | |
|         {node [shape = plaintext, style=invis, label=""] "__init_preemptive"};
 | |
|         {node [shape = doublecircle] "preemptive"};
 | |
|         {node [shape = circle] "preemptive"};
 | |
|         "__init_preemptive" -> "preemptive";
 | |
|         "non_preemptive" [label = "non_preemptive"];
 | |
|         "non_preemptive" -> "non_preemptive" [ label = "sched_waking" ];
 | |
|         "non_preemptive" -> "preemptive" [ label = "preempt_enable" ];
 | |
|         "preemptive" [label = "preemptive"];
 | |
|         "preemptive" -> "non_preemptive" [ label = "preempt_disable" ];
 | |
|         { rank = min ;
 | |
|                 "__init_preemptive";
 | |
|                 "preemptive";
 | |
|         }
 | |
|   }
 | |
| 
 | |
| This DOT format can be transformed into a bitmap or vectorial image
 | |
| using the dot utility, or into an ASCII art using graph-easy. For
 | |
| instance::
 | |
| 
 | |
|   $ dot -Tsvg -o wip.svg wip.dot
 | |
|   $ graph-easy wip.dot > wip.txt
 | |
| 
 | |
| dot2c
 | |
| -----
 | |
| 
 | |
| dot2c is a utility that can parse a .dot file containing an automaton as
 | |
| in the example above and automatically convert it to the C representation
 | |
| presented in [3].
 | |
| 
 | |
| For example, having the previous 'wip' model into a file named 'wip.dot',
 | |
| the following command will transform the .dot file into the C
 | |
| representation (previously shown) in the 'wip.h' file::
 | |
| 
 | |
|   $ dot2c wip.dot > wip.h
 | |
| 
 | |
| The 'wip.h' content is the code sample in section 'Deterministic Automaton
 | |
| in C'.
 | |
| 
 | |
| Remarks
 | |
| -------
 | |
| 
 | |
| The automata formalism allows modeling discrete event systems (DES) in
 | |
| multiple formats, suitable for different applications/users.
 | |
| 
 | |
| For example, the formal description using set theory is better suitable
 | |
| for automata operations, while the graphical format for human interpretation;
 | |
| and computer languages for machine execution.
 | |
| 
 | |
| References
 | |
| ----------
 | |
| 
 | |
| Many textbooks cover automata formalism. For a brief introduction see::
 | |
| 
 | |
|   O'Regan, Gerard. Concise guide to software engineering. Springer,
 | |
|   Cham, 2017.
 | |
| 
 | |
| For a detailed description, including operations, and application on Discrete
 | |
| Event Systems (DES), see::
 | |
| 
 | |
|   Cassandras, Christos G., and Stephane Lafortune, eds. Introduction to discrete
 | |
|   event systems. Boston, MA: Springer US, 2008.
 | |
| 
 | |
| For the C representation in kernel, see::
 | |
| 
 | |
|   De Oliveira, Daniel Bristot; Cucinotta, Tommaso; De Oliveira, Romulo
 | |
|   Silva. Efficient formal verification for the Linux kernel. In:
 | |
|   International Conference on Software Engineering and Formal Methods.
 | |
|   Springer, Cham, 2019. p. 315-332.
 |