Next: Thread components mapping, Previous: Data components mapping, Up: Components mapping rules
AADL subprograms are mapped to Ada procedures. In case of data-owned subprograms, they are managed in the related generated package, as seen in Data components mapping. The parameters of the procedure are mapped from the subprogram features with respect to the following rules:
The body of the mapped procedure depend on the nature of the
subprogram component. Subprogram components can be classified in many
kind depending on the value of the Source_Language
,
Source_Name
and Source_Text
standard AADL properties and
the existence or not of call sequences in the subprogram
implementation. There are four kinds of subprogram components:
Empty subprograms correspond to subprograms for which there is neither
Source_Language
nor Source_Name
nor Source_Text
values nor call sequences. Such kind of subprogram components has no
particular utility. For example:
subprogram sp features e : in parameter message; s : out parameter message; end sp;
is en empty subprogram. A possible Ada implementation for this subprogram could be:
procedure sp (e : in message; s : out message) is NYI : exception; begin raise NYI; end sp;
Opaque subprograms are the simplest “useful” subprogram components
(in code generation point of view). For these subprograms, the
Source_Language
property indicates the programming language of
the implementation (C or Ada95). The Source_Name
property indicates
the name of the subprogram implementing the subprogram:
Source_Name
property
is the fully qualified name of the subprogram
(e.g. My_Package.My_Spg
). If the package is stored in a file
named according to the GNAT Ada compiler conventions, there is no need
to give a Source_Text
property for Ada95 subprograms. Otherwise
the Source_Text
property is necessary for the compiler to fetch
the implementation files.
Source_Name
property is the
name of the C subprogram implementing the AADL subprogram. The
Source_Text
is mandatory for this kind of subprogram and it
must give one of the following information:
.c
source file that contains the implementation
of the subprogram.
.o
) that
implement the AADL subprogram.
C
library (.a
) that
implement the AADL subprogram.
C
source file that implements the AADL subprogram, an object
file that contains entities used by the C
file and a library
that is necessary to the C
sources or the objects.
In this case, the code generation consist of creating a shell for the implementation code. In the case of Ada subprograms, the generated subprogram renames the implementation subprogram (using the Ada95 renaming facility). Example:
subprogram sp features e : in parameter message; s : out parameter message; end sp; subprogram implementation sp.impl properties Source_Language => Ada95; Source_Name => "Repository.Sp_Impl"; end sp.impl;
The generated code for the sp.impl
component is:
with Repository; ... procedure sp_impl (e : in message; s : out message) renames Repository.Sp_Impl;
The code of the Repository.sp_impl
procedure is provided by the
architecture and must be conform with the sp.impl
signature. The
coherence between the two subprograms will be verified by the Ada95
compiler.
The fact that the hand-written code is not inserted in the generated shell allows this code to be written in a programming language other than Ada95. Thus, if the implementation code is C we have this situation:
subprogram sp features e : in parameter message; s : out parameter message; end sp; subprogram implementation sp.impl properties Source_Language => C; Source_Name => "implem"; end sp.impl;
The Source_Name
value is interpreted as the name of the C
subprogram implementing the AADL subprogram. The generated code for
the sp.impl
component is:
procedure sp_impl (e : in message; s : out message); pragma Import (C, sp_impl, "implem");
This approach will allow us to have a certain flexibility by separating the generated code and the hand-written code. We can modify the AADL description without affecting the hand-written code (the signature should not be modified of course).
In addition to the opaque approach which consist of delegating all the subprogram body writing to the user, AADL allows to model subprogram as a pure call sequence to other subprograms. Example:
subprogram spA features s : out parameter message; end spA; subprogram spB features s : out parameter message; end spA; subprogram spC features e : in parameter message; s : out parameter message; end spA; subprogram spA.impl calls { call1 : subprogram spB; call2 : subprogram spC;}; connections cnx1 : parameter call1.s -> call2.e; cnx2 : parameter call2.s -> s; end spA.impl;
In this case, the subprogram connects together a number of other
subprograms. In addition to the call sequence, the connections clause
completes the description by specifying the connections between
parameters. The pure sequence call model allows to generate complete
code : the calls in the call sequence corresponds to Ada95 procedure
calls and the connections between parameters correspond to eventual
intermediary variables. The Ada95 code generated for the subprogram
spA.impl
is:
procedure spA_impl (s : out message) is cnx1 : message; begin spB (cnx1); spC (cnx1, s); end spA_impl;
Note that in case of pure call sequence subprograms, the AADL subprogram must contain only one call sequence. If there are more than one call sequence, it's impossible - in this case - to determine the relation between them.
The two last kinds of subprogram components describe even an opaque implementation for which all the functional part is written by the user or a pure call sequence for which all the functional part is given by the AADL description. These two cases are relatively simple to implement. However, they don't offer much flexibility. In the general case we want to integrate the maximum of information within the AADL description in order to get an easy assembling of the distributed application components. However, AADL does not provide control structures (conditions, loops). The best way is to combine the opaque model and the pure call sequence model.
To illustrate the problem, let's consider the following example: A
subprogram spA
receives an input integer value . The subprogram
behavior depends on the a value:
spB
;
spA
calls a third subprogram called spC
which give its
return value to spB
In all cases, the return value of spB
is given to a forth
subprogram spD
; the return value of spD
is returned by
spA
.
The behavior of spA
is illustrated by this algorithm:
if a < 4 then b <- spB (a) else c <- spC () b <- spB (c) end if d <- spD (b) return d
We assume that the subprograms spB
, spC
and spD
are
correctly defined.
We have three call sequences. AADL allows only to describe the architectural aspects of the algorithm (the connections between the different subprograms). The AADL source corresponding to the last example is:
data int properties GAIA::Data_Type => Integer; end int; subprogram spA features a : in parameter int; d : out parameter int; end spA; subprogram spB features e : in parameter int; s : out parameter int; end spB; subprogram spC features s : out parameter int; end spC; subprogram spD features e : in parameter int; s : out parameter int; end spD; subprogram implementation spA.impl properties Source_Language => Ada95; Source_Name => "Repository.SpA_Impl" calls seq1 : {spB1 : subprogram spB;}; seq2 : {spC2 : subprogram spC; spB2 : subprogram spB;}; seq3 : {spD3 : subprogram spD;}; connections cnx1 : parameter a -> apB1.e; cnx2 : parameter spB1.s -> spD3.e; cnx3 : parameter spC2.s -> spB2.e; cnx4 : parameter spB2.s -> spD3.e; cnx5 : parameter spd3.s -> d; end spA.impl;
The first remark is that the subprogram implementation contains at the
same time the Source_[Language|Name]
(and a possible
Source_Text
) properties and call sequences. The hand-written
code describes the algorithm. This algorithm should be able to handle
each call sequence as being a block and must be as simple as possible:
the user should not know the content of the call sequence.
The generated code for each block (call sequence) is almost identical to the generated code for pure call sequence. For each block, a subprogram is generated. To make things simple for the user, these subprograms have the same signature (one parameter called Status):
type SpA_Impl_Status is record a, b, c, d : int; end record; procedure SpA_Seq1 (in out Status : spA_impl_Status) is begin spB (Status.a, Status.b); end SpA_Seq1; procedure SpA_Seq2 (in out Status : spA_impl_Status) is begin spC (Status.c); spB (Status.c, Status.b); end SpA_Seq2; procedure SpA_Seq3 (in out Status : spA_impl_Status) is begin spD (Status.b, d); end SpA_Seq3;
The generated code for the spA.impl
subprogram is very simple:
procedure SpA_Impl (a : in int; d : out int) is Status : spA_impl_Status; begin Status.a := a; Repository.SpA_Impl (Status, SpA_Seq1'Access, SpA_Seq2'Access, SpA_Seq3'Access); d := Status.d; end SpA_Impl;
The subprogram which describes the algorithm and which should be written by the user is relatively simple, and does not require any knowledge of the call sequences contents:
type SpA_Impl_Call_Sequence is access procedure (in out Status : spA_impl_Status); procedure SpA_Impl (Status : in out spA_impl_Status, seq1 : spA_impl_Call_Sequence, seq2 : spA_impl_Call_Sequence, seq3 : spA_impl_Call_Sequence) is begin if Status.a > 4 then seq1.all (Status); else seq2.all (Status); end if; seq3.all (Status); end SpA_Impl;
If a subprogram has a requires access
feature to a data, this
data is added to the parameters list, with the mode corresponding to
data access rights (i.e. read-only
=> in
,
write-only
=> out
and read-write
=> in
out
).
In the specific case of subprograms requiring protected data access, user should provides different data depending on subprograms' nature.
If the subprogram is a “method” of the protected object (i.e. if it
appears in its features
field), then the user should provides an
implementation of the subprogram which take the subprogram access as
the first parameter, with the mode chosen following the rule described
above. The parameter's name must always be this
. This parameter
type must always be of the protected data type internal type
(cf. Data components mapping).
If the subprogram is a not “method” of the protected object, user
work depends of the accessed data's Actual_Lock_Implementation
property, which defines shared variables update policy. This policy
could be either synchronous (synchronous_lock
) or asynchronous
(asynchronous_lock
). Default is asynchronous update policy.
The user must write a subprogram implementation complying to the following rules :
features
field) must always be parsed in the same order they are
declared in the AADL specification. In any case, mode is still chosen
accordingly to the rule describe above.
Note that only opaque subprograms currently support synchronous data update policy.
If synchronous policy is chosen for a data update policy, the user should be aware that access protection is ensured by the runtime code (cf. Thread components mapping).
Here is an example of data-owned specification of a protected object :
data internal_data properties ARAO::data_type => integer; end internal_data; data shared_data features method : subprogram update; properties Concurrency_Control_Protocol => Protected_Access; ARAO::Actual_Lock_Implementation => Synchronous_Lock; end shared_data; data implementation shared_data.i subcomponents Field : data internal_data; end shared_data.i; -- subprograms subprogram update features this : requires data access shared_data.i; properties source_language => Ada95; source_name => "Repository"; end update;
The user provides :
procedure Update (Field : in out Partition.Internal_Data; I : in Partition.message); ------------ -- Update -- ------------ procedure Update (Field : in out Partition.Internal_Data; I : in Partition.message) is use Partition; begin Field := Partition.Internal_Data (Integer (Field) + Integer (I)); end Update;
And Ocarina will generate the following implementation for the access-protected subprogram :
------------ -- update -- ------------ procedure Update (This : in out Partition.Shared_Data_I; I : Partition.Message) is begin PolyORB.Tasking.Mutexes.Enter (This.Mutex); Repository.Update (Field => This.Field, I => I); PolyORB.Tasking.Mutexes.Leave (This.Mutex); end Update;
Available properties for subprogram components can be found in SAE AS5506, in 5.2 page 56 and in Appendix A, pages 197-218.
Actual_Memory_Binding | Not Supported
|
Actual_Subprogram_Call | Not Supported
|
Client_Subprogram_Execution_Time | Not Supported
|
Compute_Deadline | Not Supported
|
Compute_Execution_Time | Not Supported
|
Concurrency_Control_Protocol | Not Supported
|
Queue_Processing_Protocol | Not Supported
|
Queue_Size | Not Supported
|
Recover_Deadline | Not Supported
|
Recover_Execution_Time | Not Supported
|
Server_Subprogram_Call_Binding | Not Supported
|
Source_Code_Size | Not Supported
|
Source_Data_Size | Not Supported
|
Source_Heap_Size | Not Supported
|
Source_Stack_Size | Not Supported
|
Source_Language | Supported (Ada)
|
Source_Name | Supported
|
Source_Text | Supported
|