* Compiler Optimizations of Ada Tasking
@ 1986-08-09 21:40 Litvintchouk
0 siblings, 0 replies; only message in thread
From: Litvintchouk @ 1986-08-09 21:40 UTC (permalink / raw)
Some time ago, I sent a query to this mailing list regarding available
compiler optimizations of Ada tasking. Following is a summary of the
replies I received.
[From Ed Falis, speaking in "unofficial" capacity re: Alsys compilers]
For rendezvous, both the 68K and 8086 based compilers do not perform any
context switching when an accept statement has an empty body.
Additionally, the 68K based compiler (Sun , Apollo) use the "order of
arrival" scheme that Dave Stevenson (at Rational?) developed several
years ago. In this scheme, the later of the two tasks to request the
rendezvous executes the accept body code in its own stack. Assuming an
even distribution of caller / acceptor arrival at the request point,
there's a 25% reduction in context switches under this scheme. (Note
that the Habermann Nassi optimization does not reduce the number of
context switches since it is exactly symmetrical to the "naive"
implementation). However, HN does facilitate more sophisticated
optimizations like task thread elimination (ie turning a task into a
monitor package), because the default mechanism is to have the caller
execute the accept body code. It can also simplify the implemnetation
of interupt entries for the same reason.
Another issue of interest is related to storage reclamation of task
stacks and heap objects whose lifetime is associated with a frame
internal to a task body. Rather than scheduling a terminating task to
perform its deallocations, we allow the task which triggers passage from
completion to termination to perform the cleanups for other tasks. This
reduces context switching at termination, and becomes particularly
noticeable when there are cascades of task selecting terminate
alternative of selective wait statements.
[From Tom Quiggle, re: Telesoft compilers]
At TeleSoft we are implementing a number of tasking optimizations. Some
of them are supported by our current Second-Generation Ada compiler, and
some will be implemented in future releases.
The optimizations we currently have in place are all interrupt related:
* If the accept for an interrupt entry (LRM 13.5.1:1) contains no
sequence of statements, we will defer the execution of the interrupt
task to the next synchronization point; thus eliminating two context
shifts. This optimization is applicable to situations where data is
arriving at a rate less than the longest expected sequential code
sequence in a task (e.g. a keyboard driver or a monitoring device
generating samples a few times a second). This optimization is
automatically applied.
* If the accept for an interrupt entry contains no scheduling events
(nested accepts, entry calls, delays), the body of the interrupt
entry may be executed in the context of the task which was executing
when the interrupt occurred. The compiler will generate code for
such an interrupt entry as a subprogram which will be called at the
point of interruption. The interrupt task (i.e. the task containing
the interrupt entry) must still be scheduled to allow it to execute the
sequence of statements following the accept, but the interrupt latency
is greatly reduced. With this optimization, the overhead of getting to
the user's interrupt handler is reduced to a few instructions. The
expensive full context shift is deferred to after executing the
(presumably time critical) accept body for the interrupt entry. This
optimization is triggered by a pragma.
* For accept statements for interrupt entries of the form:
while <boolean-expression> loop
accept interrupt_entry do
sequence_of_statements; -- must not contain scheduling events.
end interrupt_entry;
end loop;
more_statements;
we can apply the same optimization as mentioned above, but avoid the
expense of a context shift after the interrupt accept body as long as
the precondition holds true. In this case, the compiler will again
generate the code for the interrupt entry's accept body as a subprogram,
but will fold in the evaluation of the precondition, and return this
information to the run-time system. The run-time will only effect a
context shift to the interrupt task when the precondition is no longer
met.
This construct occurs most frequently in the form:
loop
while not buffer_full loop
accept interrupt_entry do
buffer(interrupt_related_data);
end interrupt_entry;
end loop;
accept flush_buffer(consumer_buff : out buffer_type) do
consumer_buff := local_buffer;
end flush_buffer;
end loop
in which case there is only a context shift to the interrupt task when
the buffer fills. When the buffer does fill, the task executing at
the point of the interrupt will be preempted, and the interrupt task
will be allowed to execute down to the accept to flush the buffer.
In the absence of a user-specified priority, the implementation can
also raise the priority of this task to insure that it gets back to
the accept for the interrupt entry without scheduling intervening tasks
(excluding another interrupt at a higher priority). This optimization
is triggered by a pragma.
Optimizations we intend to implement over the next year or so (my marketing
guys will kill me if I suggest any specific dates) include:
* Monitor tasks: Tasks intended to provide exclusive access to shared
data need not generate separate, schedulable, entities. Such tasks
may be replaced with a simple semaphore-like monitor, and entry calls
to these tasks become P/V operations surrounding subprogram calls.
* Messingers tasks: Dynamically allocated tasks whose sole purpose is
to pass data from a producer to a consumer in a non-blocking fashion
can also be optimized away. Again, no separate schedulable entity
need be created. Instead, a "special" task control block containing
a pointer to a data block is placed on the consumer's entry queue.
When the consumer accepts the entry call, it merely dequeues the
special TCB, dereferences the data pointer, and returns the TCB
to a pool of available messinger tasks.
Both of these optimizations will probably require a pragma, and may
place some restrictions on tasks using these optimizations.
Finally, I know of at least one compiler that will implement the
Habermann-Nassi optimization: the Intermetrics compiler.
Steven Litvintchouk
MITRE Corporation
Burlington Road
Bedford, MA 01730
(617)271-7753
ARPA: sdl@mitre-bedford
UUCP: ...{cbosgd,decvax,genrad,ll-xn,philabs,security,utzoo}!linus!sdl
(all the usual disclaimers about all this not representing MITRE
policy go here.)
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~1986-08-09 21:40 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1986-08-09 21:40 Compiler Optimizations of Ada Tasking Litvintchouk
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox