|
The IF-language was proposed in order to model asynchronous communicating
real-time systems.
For full details of IF see
here.
It is also the common model description language of the
ADVANCE
project.
We show the main concepts of IF by showing how
Dekker's mutex algorithm can be specified in IF.
In [RAY86]
Dekker's mutex algorithm is described as follows:
var flag: array[0..1] of boolean;
var turn: 0..1;
flag is initialized to false, and turn has the value 0 or 1.
The protocol for process i then becomes:
flag[i] := true;
while flag[j] do if turn = j then
begin
flag[i] := false;
while turn = j do nothing enddo;
flag[i] := true;
end;
endif;
enddo;
[critical section];
turn := j;
flag[i] := false;
The corresponding IF specification looks like:
Now one can check the mutex property like this:
check if:pep-reach
dekker.if
mutex.if_form
The following output should be printed on your screen:
Time needed: 0.350000 seconds
Result: NO.
This is the expected result. There exists no execution sequence so that the
program control stays at the labelled control points at the same time.
We have implemented an interface between the common description language (IF)
and the Kit. It includes a a compiler from IF into safe Petri Nets (the basic
model of the Kit), a formula converter which translates properties of the
original model into Petri net properties, and a trace interpreter which
translates error traces of the Petri net back into traces of the original
model. The fragment covered by the compiler excludes the real-time features
of the language and is limited to finite data types (since these cannot be
modeled in the target language), but includes important features like dynamic
process creation or different signal delivery disciplines.
More precisely, the list of supported features is as follows:
- Systems consist of multiple processes running in parallel; multiple
instances of a process can exist simultaneously, but the maximum number of
concurrently active instances has to be fixed a priori.
- Processes
can communicate by exchanging signals or through shared variables. Signals
(which may take arguments) can pass either through signalroutes or through
direct communication between processes. Incoming signals are stored in a
message queue. A limitation is that the capacity of the message queue has to
be fixed a priori.
- Signalroute can have different delivery
disciplines in the common language most of which are supported by the
compiler: FIFO and multiset queueing, reliable and lossy transmission,
peer-to-peer, unicast, and multicast delivery. Moreover, the common language
provides for urgent (immediate) and delayed delivery. In the case of delayed
delivery, the language allows to place temporal constraints on the amount of
delay and the transmission rate. These temporal restrictions are not
supported by the compiler, but distinction is made between immediate and
delayed delivery where signals are stored in a buffer (of fixed size).
- The following data types are supported by the compiler:
- finite integer fragments
- process/signalroute ids
- booleans
- enum and range types
The following types are not supported
- floats, clocks and unbounded integer types
- arrays and records (though these could be added if necessary)
- strings and abstract types
- Procedures (which are used to import C code into the system) are not
supported.
- Of the guards that control entry into a state transition,
we support the input and the provided guards.
The temporal guards tpc, deadline, or when are not supported.
Save sets are not currently supported, but can be considered
for implementation if needed.
- Of the actions available inside state transitions,
we support manipulation of variables (task), sending of signals (output),
and the dynamic creation of processes (complete with the passing of arguments)
and signalroutes, as well as process/signalroute destruction (kill).
Actions to do with clocks (set/reset) are not supported.
We give the atomic propositions in Backus-Naur notation.
- AtomicProposition:
- ProcessInstance.signals ArithOp Value
- | SignalrouteInstance.signals ArithOp Value
- | ProcessIdent.instances ArithOp Value
- | SignalrouteIdent.instances ArithOp Value
- | ProcessInstance.VariableIdent ArithOp Value
- | ProcessInstance.state = StateName
- | ProcessInstance.queue[Value].signal =
SignalName
- | SignalrouteInstance.queue[Value].signal =
SignalName
- | SignalrouteInstance.queue[Value].receiver =
ProcessValue
- | ProcessInstance.overflow
- | SignalrouteInstance.overflow
- | ProcessInstance.active
- ProcessInstance:
- ProcessIdent
- | ProcessIdent[z]
(z in N)
- | ProcessIdent[VariableIdent]
- SignalrouteInstance:
- SignalrouteIdent
- | SignalrouteIdent[z]
(z in N)
- | SignalrouteIdent[VariableIdent]
- ArithOp:
- = | # | < | <= | > | >=
|
|