North-Holland Microprocessingand Microprogramming21 (1987) 301-310
PERFORMANCE
301
ASPECTS OF Ada TASKING IN EMBEDDED SYSTEMS
R.D. Huijsman,
J. van Katwijk, W.J. Toetenel
Faculty of Mathematics and Computer Science, Delft University of Technology, P.O. Box 356 2600 AJ Delft, The Netherlands
The authors discuss performance aspects of Ada tasking and report about experiments carried out to investigate the real-time behaviour of their own Ada tasking supervisor.
i. Introduction A common feature of embedded systems is their need for both parallel processing and real-time control. In conformance with the requirements laid down in the IRONMAN report [IRONMAN-77], the Ada [i] Language has been designed for the embedded computer systems domain and as such contains constructs supporting concurrent execution of sequential processes with or without real-time constraints. As part of a r e s e a r c h project at Delft University of Technology, a compiler has been designed and implemented for almost the complete Ada programming language. The implemented language excludes fixed point and floating point types, but includes the full Ada tasking semantics. Problem Definition Support of the full Ada tasking semantics makes it necessary for a run-time environment to provide services like storage allocation for tasks, task scheduling and intertask communication. Unfortunately, operating systems usually cannot furnish directly the specific services needed for Ada tasking, and embedded systems mostly perform without an underlying resident operating system. As a consequence the run-time environment providing these services must be supplied by an Ada implementation itself. A crucial issue, however, remains the efficiency of the implemented services: it seems that currently one of the major problems with the use of the Ada tasking model is the overhead incurred by the run-time system of an implementation. Various complaints have been heard in this respect: it seems e.g. that on the average an empty rendezvous is executed in no less than about 1 msec. Since such figures are obtained for rather powerful architectures like VAX 11/750 and M68000 [Burns-85], the overhead on smaller microprocessors will most likely be unacceptable.
Therefore, in order to enable successful large scale application of the Ada language on microprocessor architectures, it seems essential to find a way of decreasing the overhead by •
identifying the origins of the overhead, subsequently,
•
trying to improve areas involved.
the run-time
and,
system in the
Our Work Using our Ada implementation we have analyzed Ada tasking performance problems and their possible solutions. We have also actually experimented with a number of solutions expected to incur less overhead in a uni-processor context. Furthermore we have tried to assess the way the overhead induced by our implementation might be affected by choosing other implementation models or by adapting our implementation for multi-processor target configurations. Remainder of the Paper The remainder of the paper is made up of 4 sections presenting, in order of appearance: (i) an overview of the Ada tasking semantics, (ii) a description of both interface and structure of our tasking support kernel, (iii) a description of the experiments and measurements carried out, together with the obtained results and their analysis, and (iv) the conclusions drawn from the results, followed by a brief account of ongoing and planned work. 2. Ada Tasking Semantics General The model used in the Ada language for support of concurrent programming is that of sequential processes (tasks) which operate in parallel to achieve a common goal and, if necessary, interact by first synchronizing and then exchanging information (an integral activity
R.D. Huijsman et al. / Ada Tasking in Embedded Systems
302
called rendezvous). In the Ada tasking model a rendezvous always takes place between two tasks. A task can possess one or more synchronization and communication points called entries, which can be parameterized like procedures. Interaction between tasks consists of one task calling an entry of another task and the latter accepting the entry call. As more tasks may call the same entry, possibly at the same time, a queue of pending, unprocessed requests for communication is associated with each entry. Requests are added to these queues in order of arrival and processed on a strict FIFO basis. This model is basically the same as Hoare's CSP [Hoare-78], but exhibits some notable differences: •
information transfer during vous can be bidirectional;
•
in Ada the called task can do processing during a rendezvous and deliver results to the calling task, which remains suspended during these actions;
•
an Ada rendez-
Ada tasks can use shared variables.
Finally, Ada tasks do not exist independently from each other, but have a hierarchical relationship as described in the next subsection. Creation, Activation,
Termination
Every task is an object, possessing both a specification defining its entry points and a body defining its execution. As such, a task can be created either automatically, as part of the creation of a local referencing environment, or dynamically, by evaluation of an aZZocato~. In the latter case the task is anonymous and its entries can be called only via use of the access value delivered as result of evaluation of the allocator. Each task, whether created automatically or dynamically, depends directly on a so-called master, i.e. the entity responsible for its creation. A master can be either another task, a subprogram, a library package or a block (i.e. a sequence of actions possessing a local environment of its own). In case of automatic creation this master is the entity whose local referencing environment is considered to contain the task object. For a dynamically created task its master is the entity whose local referencing environment defines the type of the access value delivered by the creating allocator's evaluation. Activation and termination of created tasks is subject to strict rules which are part of the Ada language definition. A task's activation is the initial part of its execution and consists of the creation of its local referencing environment. Activation of all tasks created automatically as part of a specific referencing environment takes place, in parallel, after creation of this
referencing environment and immediately preceding execution of the considered master's first action to follow this creation. Activation of a dynamically created task on the other hand is triggered by evaluation of the pertinent allocator, the thread of control containing the allocator remaining suspended until the end of the activation. The termination rules for tasks reflect the dependency relations resulting from the way they are created. Task termination is an event that concludes a task's life and as such is different from task completion. A task has completed execution when it has reached the end of the sequence of actions in its body. A task is in the terminated state, however, when it has stopped execution and has become unavailable for further communication and synchronization. Transition to this state will, apart from abnormal termination, occur only in one of the following situations: i. the task has completed are no dependent tasks;
execution
2. the task has completed execution dependent tasks are terminated;
and there and all its
3. the task is an acting task, waiting for a selective rendezvous and having expressed its willingness to terminate (as explained in the next paragraph), and: •
it depends on a completed master, and
•
all other tasks depending on its master are terminated or waiting for a selective rendezvous while being willing to terminate.
Likewise, a task's master which is a block or a subprogram can only be left when all of its dependent tasks have terminated. Co,m~unication and Synchronization Synchronization and communication between tasks can be selective, both at the actor and the server side. Selective rendezvousing at the acting task's side can take two forms, called timed entry call and conditional entry call respectively. A timed entry call is an entry call having a delay attached to it. Expiration of the delay before the entry call has been accepted causes immediate withdrawal of the call from the corresponding entry queue and makes the issuing task continue its processing. An entry call is called conditional if the acting task specifies that the call must be cancelled in case no immediate rendezvous is possible and some other processing be done instead. In a serving context, a task can specify a non-deterministic selection to be made from a set of one or more accept alternatives. The eligibility for selection of any alternative can in this case be dependent on a condition, called
R.D. Hui/sman et aL / Ada Taskingin EmbeddedSystems
guard, attached to the alternative. Evaluation of such conditions will be done only once for a specific selection, in un undefined order, and results in a set of eligible alternatives which must not be empty. If no entry calls for eligible accepts are outstanding the serving task is suspended until the first such entry call arriving. Suspension of a server task in such a case can be made subject to time-out by attaching one or more delays to the selection. Effectiveness of these delays can be controlled by attached conditions which are evaluated at the same time as those attached to accept alternatives. If it turns out after evaluation that more than one delay is in effect, the one with the shortest duration will be used for timeout of the selection. Instead of being timed, a wait for selection can be conditional. In this case the serving task specifies that the selection be cancelled if no immediate rendezvous is possible and some other processing be done instead (as in the case of a conditional entry call). Finally, a task can indicate its willingness to terminate during a wait for selection, although this cannot be done in combination with timed or conditional selection. Attributes
and Priorities
Ada defines a number of task specific attributes which can be interrogated during execution to either obtain representation information or information which can be used in the control of task interaction, in particular for scheduling purposes. More specifically the latter attributes enable a task to inquire whether another task is callable or terminated, and to obtain the number of calls queued to a specific entry of itself. Every task in Ada may have a static priority assigned to it, indicating its urgence relative to other tasks. Its only effect, however, is to provide preference in resource allocation to higher-priority tasks. Ongoing rendezvous have the higher of the priorities of the participating tasks, an undefined priority being considered as lower than a defined priority. 5. The architecture
and implementation
303
In this paragraph the architecture of the Delft Ada Tasking Supervisor (DATS) is briefly discussed. Due to the limited amount of space the discussion is not complete; for a complete discussion the reader is referred to [vKatwijk-87]. In the tasking supervisor a large number of design decisions has been made. From an architectural point of view the most important decision is to keep the interface simple and to only implement a message passing oriented supervisor. Task management For each elaboration of a task type a task type descriptor is constructed. The task type descriptor contains data to allow a task object to be created. Task objects are implemented as objects of an anonymous type; They are identified by objects of a private type tdp (task description pointer). For the creation of a task object the tasking supervisor provides a procedure create. type tdp is private; procedure create (m : master; c : in out tdp; tt : task_type; t : out tdp); The out parameter t yields the identification for the newly created task object, m identifies the master of the task object, c points to a chain of tasks to be activated all at the same time. tt is the descriptor of the task type. The supervisor provides a procedure activate for the activation of a collection of subtasks. procedure activate (c : tdp; s : boolean); On the entry of a non-trivial master a function enter master is called. The function returns a value of the private type master. This return value is used to identify the current master within the current thread of control. type master is private; null master: constant master;
-- null element
function enter_master (old_master : master) return master;
of DATS
Different from other simpler languages as e.g. Modula II, the in-line encoding of task management functions and task communication functions in a translated program is not sensible. The amount of code involved is far too large. Therefore, task management and task communication are supported by a tasking supervisor. A simple and clean supervisor interface has definitely advantages; customized run-time support systems can be made without any knowledge of the compiler structure. On the other hand, a potential drawback is the incurred overhead. Any extra layer of software causes overhead, thereby decreasing the real-time capabilities of the implementation.
On exit from a master the function emit master is called. On a call to this function the tasking supervisor suspends the current thread of control until all dependent tasks are terminated. function exit master return master; As soon as the thread of control reaches the end of the executable code (it gets completed), the supervisor procedure terminate is called to take care of task termination. procedure terminate; Consider the example of the following and an outline of its translated form.
task body
R.D. Huijsman et aL / Ada Taskingin EmbeddedSystems
304
value indicating whether taken place or not.
task body A is -- declarations
begin end; The translated form of a task body takes the form of a procedure body. procedure task_body is chain: tdp; -- chain ol sub tasks m: master; -- maintaining current master dummy: master;
begin m := enter_master (null_master); -- now for the declarations -- and the statements of the task body
declare -- local declarations -- elaborate them
-- notify tasking supervisor of arrival -- activate subtasks i f r e q u i r e d activate (chain, TRUE); -- sequence of statements
end; dummy := ezlt_master terminate;
(m);
end; Handling task communication Rosen [Rosen-83] describes a very small supervisor interface for the support of task communication. The interface consists of only three procedures. In the design and implementation of our supervisor we followed this approach. All forms of the entry call are mapped onto a timed entry call, which is then translated to a call to a supervisor procedure. Similarly, all forms of selective wait constructions, including the stand-alone accept statement are mapped onto calls of another single tasking supervisor procedure. the
example
of
an ordinary
entry
E
(n: integer; d: entry_vector; c: out integer; p: out system, address)
The first two parameters describe the alternatives. For each alternative a description is contained in a description vector, an entry_vector. The third parameter returns the order number of the selected alternative. The fourth parameter yields the address of a parameter block of the caller. of the selective
wait
select accept rdul do $1; end; or accept rdu2 do B. rdv3; end; -- B. rdu3 is an entry call to -- entry rdu3 in task object B or delay T1; $3; or delay T2; $4; end select; The code that is generated by our compiler contains explicit initializations of the alternative descriptor. The structure of the remaining code is start_rdv (4, alternatlve_desc, c, p); case c is when 1 => S1 ; end_rdu; when 2 => dumm := call rdu (B, rdu3, INFINITE, end_rdu; when 3 => $3; when 4 => $4; end case;
0);
The execution of a rendezvous is terminated by a call to the procedure end rdu. procedure end_rdu;
This call is mapped onto
The implementation
select E; or delay INFINITE; null; end select; Entry calls are implemented supervisor function call_rdv. function call e: d: p:
has
procedure start_rdu
Consider the example construction
begin
Consider call
rendezvous
Selective wait constructions are always mapped onto a call to a single supervisor procedure.
-- statements
... ...
the
rdu (t: tdp; entry_desc; duration; system, address)
of DATS
A detailed description of the structure of the implementation of DATS is omitted, due to space constraints. The interested reader is referred to [vKatwijk-87]. by
the
tasking
return boolean;
The entry to be called is identified by the pair (t, e) (task object, entry identification), d defines the delay, the time out within which the rendezvous must take place, p is the address of a parameter block. The function returns a boolean
The implementation of our tasking supervisor uses events and time slices. Low-level scheduling is implemented by a signal~waft mechanism. The procedure signal sends a specified signal to a task object. procedure signal (t: tdp; s: signal); The procedure wait causes the current thread of control to be suspended until either one of a specified set of signals is received or a time out has expired.
procedure wait (t: delay; am: signal_mask);
R.D. Huijsman et aL / A da Tasking in EmbeddedSystems
The procedure wait is in fact the dispatcher. Each task is kept in a variety of lists and queues during its lifetime. Each task is kept in a list owned by the master for that task. Furthermore, each task waiting for a time out is kept in a clock queue. Tasks that are ready to run are entered into one (of eight) priority based run queue. Finally, each task calling for a rendezvous is entered into a queue private to the entry that is being called. A task can reside in more than just one queue at the same time. Consider the case where a task issues a timed entry call: the task is put into two queues, namely in the clock queue for the implementation of the time out and in an entry queue. Given a number of low-level primitives, the implementation of most tasking supervisor procedures is relatively straightforward. Consider the example of the function emit master. function exit master return master is begin for i in the number o I dependent tasks loop wait (INFINITE, terminate); -- wait for the -- termination signal of aZl children end loop;
complexity of the implementation as well as on the overall efficiency. Secondly, another important factor is the chosen strategy to implement the tasking primitives. Various strategies can be applied to implement low-level features as e.g. task switching, critical regions or monitors. A choice must be made for the implementation of high-level tasking supervisor operations such as e.g. task creation, task activation and rendezvous management. Whatever choice is made, it will affect the efficiency of the tasking supervisor. The remaining part of this section is used to describe some experiments with our tasking supervisor. The purposes of the experiments are (i) to show the behaviour of the implementation on various tasking paradigms and (ii) to relate chosen implementation strategies with performance aspects. Results of the experiments are given in terms of pie charts, indicating the relative efficiency of the high-level and the low-level components of the tasking supervisor on some well-chosen tasking examples. The tasking examples are chosen such that: •
It would be possible to measure the effect of specific operations. In particular, a distinction is made between the amount of time spent in (i) life-time management, and (ii) tasking communication. For this purpose we timed two programs: one in which a large number of tasks (with empty bodies) is created, and another one in which a large amount of rendezvous (with empty accept body) is executed.
•
General statements could be made about the overall efficiency of the tasking supervisor. For this purpose we relate two solutions of the classical N queens problem to each other: a procedure based implementation and a tasking based implementation.
f o r t i n all d e p e n d e n t t a s k s loop signal (t, kill_signaZ); - - s e n d them a s i g n a l end l o o p ; end; 4. Efficiency
issues
One of the important issues when looking to Ada tasking is the real-time capability of the Ada tasking supervisor. The first impression of the real-time capabilities of our tasking supervisor was not encouraging; the maximum number of rendezvous per second that seemed to be possible was less than 300 (on a M68000 based UNIX [2] system). It was felt striking that results reported in literature were of the same magnitude ([Burns-85] [Burger-87]). To allow the implementation to be used for real-time embedded applications, significant improvements on the efficiency had to be achieved. It is difficult to find some metrics to measure the efficiency of Ada tasking primitives. Many hardware and software factors play a part in the efficiency of the implementation. In general these factors are not independent from each other. First, hardware support for tasking primitives on a low level may be found in the ability of some cpu's to support task switches and to dedicate memory to tasks ensuring private access. On a high level support is evident by using more than one cpu, dedicating tasks to different cpu's. Both possibilities have their influence on the
305
The programs were run as a single task on a Dutch brand M68000 based machine (12 Mhz) under the UNIX operating system. To reduce the overhead of the operating system, the programs were run on a system with only a single user logged on. For each program we measured the timepercentage spent on specific high-level and low-level operations. The resulting data is presented below. Experiment
I : life-time measurement
The purpose of this experiment is (i) the measurement of the overhead involved in taskcreation, activation and termination, and (ii) the measurement of costs related to mastermanagement. To this end we implemented the Ada program below. The experiment consisted of three tests, each test involved an increasing number of created tasks. The number of created tasks depends on
R.D. Hui/sman et aL / Ada Tasking in Embedded Systems
306
the value of the constant number_of_chflds, which is applied within the loop statement inside the procedure clusters. The actual values of the constant were i, lOand i00.
activation of the tasks in task array, (iii) creation, actions by the supervisor to create the tasks, and (iv), termfnat, actions that sup)oft the termination of tasks.
procedure l ~ e t l m e is number_o~IteratZons : constant := 1000; number_of_chZld8 : constant :.... ; task type chZId; task body child is begin null; end; procedure clusters (number: in fnteger) is begin f o r f in 1 .. number_o/_fterat~on8 loop declare task_array : array (I .. number) of child; begin null; end; end loop; end clusters; begin Clusters (number_of_chflds); end;
Low level anatomy lifetime management
The results of the experiment are shown in the following table and 2 pie charts. The table summerizes the average execution time of the program for i, 10, and i00 child tasks.
I
,' I
E x e c u t i o n t£me Experiment I
,number
I
ch~Ids
lO1 1oo
I tfme ~n seconds
II
7.s2
56.62
I
567.90
]
1I I
I
The pie charts present the distribution of time spent on high- and low level operations performed by the supervisor. The pie charts are related to the number_o~chfld8 i.
High level anatomy lifetime management
=dgnal8.9% walt 16.8%
swap 6.2%
specific= 4.5%
bit 29.0% ~ ~....[.?...[.
k:,cklng 29.5%
FIGURE4~
The segment labels denote (i) speciffcs, the specific operations related to the life-time management of tasks, (ii) queuing, queue and dequeue actions involved with task scheduling and dispatching, ( i i i ) 8wuTrping, the actual switching of tasks, (iv) sfgnal and (v) wait, the basic inter-task communication mechanism, (vi) fnft, the actions related to memory allocation for task descriptors and the initialization of the various fields of the descriptor and finally (vii) locking, locking various data access operations on internal datastructures, implementing monitors, and implementing critical regions within supervisor code. Analysis of these results shows that: •
The average time per task spent on life-time management and master administration is 5.6 milliseconds.
•
Only 34.5 percent of the time is spent on activities directly involved with life-time issues and master management. The rest is due to low-level task communication and context switching.
Experiment II: Measuring rendezvous efficiency
actlvat 20.4%
The purpose of this experiment is to investigate the time characteristics of the rendezvous implementation. The following Ada program contains two tasks. Both tasks, a server task and a caller are involved in a rendezvous. The code of the corresponding accept body is empty.
creatio~ 29.3%
tetmlnat 31.5%
FIGURE 4.1
The segment figures give the relative amount of time ( in percentages) spent on the actions denoted by the segment labels which are: (i) masters, actions involved in entering and leaving a non trivial master, ( i i ) actluat,
p r o c e d u r e rendezuou8 is task seruer is entry e; end server; task body seruer is begin for ~ in 1 .. I0000 loop accept e do null;
307
R.D. Huijsman et aL / Ada Tasking in Embedded Systems
end;
end loop; end server; task caller; task body caller is begin for i in 1 .. 10000
Low level Anatomy Rendezvous
q~mei9.ng2% server t3.3%~
~
=k~J8.2% c.haln6.~3% e~d~4.9%5.2%
loop
server, e; end loop; end caller; begin
walt
~6.3%
null; end; The results, depicted below, were obtained averaging the results of i0 program runs. A complete rendezvous
involving:
1 start rdv / end_rdv operation, 1 call ~dv call, 2 context switches, was measured to cost 4.06 msec. The time percentages spent by the high-level and low-level operations are given in the following 2 pie charts.
High level anatomy Rendezvous
c.$wttch 39.7% ~
RGURE 4.4
by
calle15. r 6%
sorvor 44.7% FIGURE4~ The segments denote: (i) calker, starting and finishing an entry-call, (ii) c.switch, context switching between the server and the caller tasks, (iii) server, initialization and termination of a rendezvous.
Here the segments display the rendezvousspecific operations (i) server, caller and chaining, together with the low-level details of a context-switch comprising (ii) swap, signal, queueing, wait and locking. An analysis of the results gives: •
The rendezvous specific actions (ii) caller, (iii) chaining and (vii) server take together only 24.8 % of the total amount of time;
•
A rather ing.
•
The fi~n~res illustrate the asymetrie semantics of the rendezvous. Significantly more time is spent on the server side of the rendezvous.
large segment
is occupied
by lock-
Experiment lll: Overall performance As a general test we implemented an algorithm that computes the solutions for the problem of placing N queens on a chess board. [Wirth-76] gives a Pascal implementation, which, slightly modified, was used to gather the desired statistics. Results on the same problem are reported in [Clapp-86]. We studied 2 different approaches: a procedural approach, without any tasks, and a tasking approach where we choose to maximize the amount of concurrency. In the tasking solution a task is created each time a queen must be placed on the board. Initially N tasks are created. The next table summarizes the execution times of experiments for some values for N. The second column gives the number of recursive calls made by the sequential solution, which equals the number of tasks created in the concurrent solution. The difference between the execution times for the sequential and the concurrent solution exemplifies the overhead induced by the use of tasks in our tasking supervisor.
N 6 ? 8 To
# calls~tasks 149 512 1965 picture
the
N QUEENS Sequential 0.31 1.50 5.68 number
of
] Concurrent~ 1.62 6.18 29.77
concurrent
i I ] tasks
R.D. Huijsman et aL / Ada Taskingin EmbeddedSystems
308
executing we gathered following figure.
,.....
Another important issue is the applied tasking paradigm. Created tasks, performing their actions within endless loops without applying semantics that allow termination, do not incur life-time and master management overhead.
m
5. Concerning the rendezvous. Here the time characteristics are strongly depending on the number of context switches caused by the applied tasking paradigm and the chosen implementation strategy. Here improvement can be achieved by a n o p t i m a l choice of paradigm (see e.g. [Gehani-84]) and possibly by improved implementation strategies (see e.g. [Stevenson-SOl).
the statistics
•
shown the
N queens solution 8 quow~
7 ¢lu~
--o--
6 ¢tuu~
~
m" of concurrent tasks
~oo 900
s"
'I
6~o 300
I
~D
•
7
O
m
=
•
II
•
•
•
n
•
time In =econds
Our current work is related to finding answers to the following general questions: i. Is it possible to identify for a given functionality of a n A d a tasking supervisor inefficiencies in implementation strategies?
Analysis of these results leads to the following statements. •
The overhead involved in using tasks is about 5 times as much as the overhead involved in working with sequential procedures,
2. Is it possible to clearly define a metrics for the (in)efficiency of the Ada language constructions related to tasking?
•
The tasking overhead is more or less independent of the total number of tasks involved.
Giving a full answer to both questions requires a fair amount of research. Not only several architectural models for a tasking supervisor have to be investigated, but also for each architecture various implementations have to be made.
5. Conclusions The experiments sions:
and further work leads to the following
conclu-
I. General issues. The overall picture shows a rather large overhead on low-level operations such as ~ockfng, 8fgna~/waft communf-
catfonand contemt-swftchfng. Although fine tuning of the prototype supervisor by inline coding of all lock and unlock actions, optimization of operations involved with task scheduling and in line coding of appropiate operations results in a more favourable behaviour (average time spent on a n e m p t y rendezvous is reduced with a factor 0.7 to 2.8 milliseconds on a MC68000, on a faster MC68020 we measured values under 1 milisecond), the fact remains that the overhead incurred by the chosen implementation strategy remains substantial. 2. Concerning life-time management. A rather large time-segment was consumed by the acquisition and initialization of task storage. Acquisition is performed by the resident operating system. Life-time management time consumption is substantial. Reduction can be achieved as is illustrated by the following remarks. •
Leaving the rather heavy semantics of Ada, (the master concept in combination with termination issues may be applied in a less strict fashion), results in a considarable reduction of supervisor overhead.
A second approach in our current research is the question as to whether the full semantics of the Ada language is required to fulfill the needs of an embedded application. It may be advantageous to reduce the functionality of the tasking supervisor, to enhance the overall performance. Another interesting topic is the degree of dedication of a supervisor implementation to a specific target architecture. Modern cpu's are often equipped with capabilities that enable multitasking. Using these capabilities may reduce the overhead incurred by the usage of tasking operations as context switching and scheduling. These low-level operations can be executed by the cpu itself. Nevertheless, the Ada semantics involved in synchronization of tasks and communication put severe demands on the capabilities of any cpu. The overall problem of engineering a highly efficient tasking supervisor can be perceived as finding a optimum on a multi-dimensional plane of implementations, where the spanning axes could have the following dimensions •
Semantic issues. A dimension showing the amount of implemented Ada semantics, ranging from the basics of tasking to the full Ada semantics.
•
High level issues. A dimension expressing the strategies chosen to implement the tasking supervisor, in particular the high level synchronisation feature of Ada tasking, the rendezuous. Three techniques are described in literature
R.D. Huijsman et aL / Ada Tasking in EmbeddedSystems
for the implementation of a rendezvous, (i), the message passing strategy, the most natural way to implement a rendezvous, (ii) a method called "the procedure call interface" in which the caller may execute a server's body by proxy, and (iii) a scheme where any task that can immediately execute a rendezvous may do so. This last technique is known as the "order of arrival scheme". See e.g. [Stevenson 80]. •
Low level issues. A dimension depicting the optimization of the implementation, taking into account the degree of hardware support.
Another subject is the apparent scarcity of Ada implementations for distributed applications. As targets will, most probably, not be limited to uni-processor configurations, it will be necessary to develop Ada implementations for support of a wide spectrum of multi-processor configurations. As part of our ongoing research we are in the process of adapting the current, above described implementation of our supervisor for use on a tightly coupled multi-processor configuration. Although we are convinced, till evidence of the contrary, that this adaptation can be done while keeping the interface essentially unchanged, changes in the implementation structure cannot be avoided. These changes in their turn will inevitably affect the real-time characteristics of the supervisor, be it in a up to now non-quantifiable way. On the high level of Ada tasking semantics e.g., activation elapsed time will go down on the average, as referencing environment creation for child tasks will be physically parallelized to the degree to which processors are available. On the low level of implementation on the other hand, context switching will e.g. take longer on the average than in a uni-processor context, as all processors will need exclusive access to a.o. shared data structures. The latter requires locking not only to protect against clock interrupts, but also to safeguard against interference from other processors than the one accessing these structures. This extended locking will add to the already significant overhead cost of locking in the uni-processor case. However, a definitive judgement regarding the performance characteristics of our implementation model in a multi-processor situation must wait till measurements like the ones described in section 4 can be carried out. 6. Notes and Bibliografy [i]
A d a i s atrademark of U.S. dept. of Defence
[2]
Unix is a trademark of AT&T Bell Labs.
[Burns-85] A review of Ada tasking, A. Burns, A.M. Lister, A.J. Wellings
309
University of York, Dept of Computer Science YCS-78, 1985 [Burger-87] An assesment of the overhead associated with tasking facilities and task paradigms in Ada T.M. Burger, K.W. Nielsen ACM Ada Letters Vol VII, #i, February 1987 [Clapp-86] Solutions to the N queens Problem Using Tasking in Ada R. M. Clapp, T. N. Mudge, R. A. Volz SigplanNotices Vol 21 #12, December 1986 [Gehani-84] Ada - Concurrent Programming, Prentice Hall 1984 [Hoare-78] Communicating sequential processes, C.A.B. Hoare, CACM 21 (8), pp 666-677 1978 [IRONMAN-77] Requirements for High Order Programming Languages. Department of Defence, Washington, D.C., January 1977. [vKatwijk-87] The Design and Implementation of an Ada Language Compiler, J. van Katwijk, Delft University of Technology, Dept. of Computer Science 1987. [Rosen-83] A kernel for tasks and rendezvous management in Ada, J.P. Rosen Ada-Europe/AdaTec joint conference on Ada, Brussels March 1983. [Stevenson-80] Algorithms for Translating Ada tasking D.R. Stevenson SigplanNotices Vol 15 #ii, 1980
Multi-
[Wirth-76] Algorithms + Datastructures = Programs Prentice Hall 1976