Contents Index Search Previous Next
9.5.3 Entry Calls
1
{entry call} [An
entry_call_statement (an
entry
call) can appear in various contexts.]
{simple
entry call} {entry
call (simple)} A
simple entry call
is a stand-alone statement that represents an unconditional call on an
entry of a target task or a protected object. [Entry calls can also appear
as part of
select_statements (see
9.7).]
Syntax
2
entry_call_statement
::= entry_name [
actual_parameter_part];
Name Resolution Rules
3
The
entry_name
given in an
entry_call_statement
shall resolve to denote an entry. The rules for parameter associations
are the same as for subprogram calls (see
6.4
and
6.4.1).
Static Semantics
4
[The
entry_name
of an
entry_call_statement specifies
(explicitly or implicitly) the target object of the call, the entry or
entry family, and the entry index, if any (see
9.5).]
Dynamic Semantics
5
{open
entry} {entry (open)}
{closed entry} {entry
(closed)} Under certain circumstances
(detailed below), an entry of a task or protected object is checked to
see whether it is
open or
closed:
6
- {open entry (of
a task)} {closed entry
(of a task)} An entry of a task is open
if the task is blocked on an accept_statement
that corresponds to the entry (see 9.5.2),
or on a selective_accept (see 9.7.1)
with an open accept_alternative
that corresponds to the entry; otherwise it is closed.
7
- {open entry (of
a protected object)} {closed
entry (of a protected object)} An entry
of a protected object is open if the condition
of the entry_barrier of the corresponding
entry_body evaluates to True; otherwise
it is closed. {Program_Error (raised by failure of
run-time check)} If the evaluation of
the condition propagates an exception,
the exception Program_Error is propagated to all current callers of all
entries of the protected object.
7.a
Reason: An exception
during barrier evaluation is considered essentially a fatal error. All
current entry callers are notified with a Program_Error. In a fault-tolerant
system, a protected object might provide a Reset protected procedure,
or equivalent, to support attempts to restore such a "broken"
protected object to a reasonable state.
7.b
Discussion: Note that
the definition of when a task entry is open is based on the state of
the (accepting) task, whereas the "openness" of a protected
entry is defined only when it is explicitly checked, since the barrier
expression needs to be evaluated. Implementation permissions are given
(below) to allow implementations to evaluate the barrier expression more
or less often than it is checked, but the basic semantic model presumes
it is evaluated at the times when it is checked.
8
{execution
(entry_call_statement) [partial]} For
the execution of an
entry_call_statement,
evaluation of the
name and of the
parameter associations is as for a subprogram call (see
6.4).
{issue (an entry call)} The
entry call is then
issued: For a call on an entry of a protected
object, a new protected action is started on the object (see
9.5.1).
The named entry is checked to see if it is open;
{select
an entry call (immediately)} if open,
the entry call is said to be
selected immediately, and the execution
of the call proceeds as follows:
9
- For a call on an open entry of a task,
the accepting task becomes ready and continues the execution of the corresponding
accept_statement (see 9.5.2).
10
- For a call on an open entry of a protected
object, the corresponding entry_body
is executed (see 9.5.2) as part of the protected
action.
11
If the
accept_statement
or
entry_body completes other than
by a requeue (see
9.5.4), return is made
to the caller (after servicing the entry queues -- see below); any necessary
assigning back of formal to actual parameters occurs, as for a subprogram
call (see
6.4.1); such assignments take place
outside of any protected action.
11.a
Ramification: The return
to the caller will generally not occur until the protected action completes,
unless some other thread of control is given the job of completing the
protected action and releasing the associated execution resource.
12
If the named entry is closed, the entry call
is added to an
entry queue (as part of the protected action, for
a call on a protected entry), and the call remains queued until it is
selected or cancelled;
{entry queue} there
is a separate (logical) entry queue for each entry of a given task or
protected object [(including each entry of an entry family)].
13
{service
(an entry queue)} {select
an entry call (from an entry queue)} When
a queued call is
selected, it is removed from its entry queue.
Selecting a queued call from a particular entry queue is called
servicing
the entry queue. An entry with queued calls can be serviced under the
following circumstances:
14
- When the associated task reaches a
corresponding accept_statement,
or a selective_accept with a corresponding
open accept_alternative;
15
- If after performing, as part of a
protected action on the associated protected object, an operation on
the object other than a call on a protected function, the entry is checked
and found to be open.
16
{select an entry call (from
an entry queue)} If there is at least
one call on a queue corresponding to an open entry, then one such call
is selected according to the
entry queuing policy in effect (see
below), and the corresponding
accept_statement
or
entry_body is executed as above
for an entry call that is selected immediately.
17
{entry queuing policy}
The entry queuing policy controls selection among
queued calls both for task and protected entry queues.
{default
entry queuing policy} {entry
queuing policy (default policy)} The default
entry queuing policy is to select calls on a given entry queue in order
of arrival. If calls from two or more queues are simultaneously eligible
for selection, the default entry queuing policy does not specify which
queue is serviced first. Other entry queuing policies can be specified
by
pragmas (see
D.4).
18
For a protected object, the above servicing of
entry queues continues until there are no open entries with queued calls,
at which point the protected action completes.
18.a
Discussion: While servicing
the entry queues of a protected object, no new calls can be added to
any entry queue of the object, except due to an internal requeue (see
9.5.4). This is because the first step of
a call on a protected entry is to start a new protected action, which
implies acquiring (for exclusive read-write access) the execution resource
associated with the protected object, which cannot be done while another
protected action is already in progress.
19
{blocked (during an entry
call) [partial]} For an entry call that
is added to a queue, and that is not the
triggering_statement
of an
asynchronous_select (see
9.7.4),
the calling task is blocked until the call is cancelled, or the call
is selected and a corresponding
accept_statement
or
entry_body completes without
requeuing. In addition, the calling task is blocked during a rendezvous.
19.a
Ramification: For a call
on a protected entry, the caller is not blocked if the call is selected
immediately, unless a requeue causes the call to be queued.
20
{cancellation (of an entry
call)} An attempt can be made to cancel
an entry call upon an abort (see
9.8) and as
part of certain forms of
select_statement
(see
9.7.2,
9.7.3,
and
9.7.4). The cancellation does not take
place until a point (if any) when the call is on some entry queue, and
not protected from cancellation as part of a requeue (see
9.5.4);
at such a point, the call is removed from the entry queue and the call
completes due to the cancellation. The cancellation of a call on an entry
of a protected object is a protected action[, and as such cannot take
place while any other protected action is occurring on the protected
object. Like any protected action, it includes servicing of the entry
queues (in case some entry barrier depends on a Count attribute).]
20.a
Implementation Note: In
the case of an attempted cancellation due to abort, this removal might
have to be performed by the calling task itself if the ceiling priority
of the protected object is lower than the task initiating the abort.
21
{Tasking_Error (raised by
failure of run-time check)} A call on
an entry of a task that has already completed its execution raises the
exception Tasking_Error at the point of the call; similarly, this exception
is raised at the point of the call if the called task completes its execution
or becomes abnormal before accepting the call or completing the rendezvous
(see
9.8). This applies equally to a simple
entry call and to an entry call as part of a
select_statement.
Implementation Permissions
22
An implementation may perform the sequence of
steps of a protected action using any thread of control; it need not
be that of the task that started the protected action. If an entry_body
completes without requeuing, then the corresponding calling task may
be made ready without waiting for the entire protected action to complete.
22.a
Reason: These permissions
are intended to allow flexibility for implementations on multiprocessors.
On a monoprocessor, which thread of control executes the protected action
is essentially invisible, since the thread is not abortable in any case,
and the "current_task" function is not guaranteed to work during
a protected action (see C.7).
23
When the entry of a protected object is checked
to see whether it is open, the implementation need not reevaluate the
condition of the corresponding entry_barrier
if no variable or attribute referenced by the condition
(directly or indirectly) has been altered by the execution (or cancellation)
of a protected procedure or entry call on the object since the condition
was last evaluated.
23.a
Ramification: Changes
to variables referenced by an entry barrier that result from actions
outside of a protected procedure or entry call on the protected object
need not be "noticed." For example, if a global variable is
referenced by an entry barrier, it should not be altered (except as part
of a protected action on the object) any time after the barrier is first
evaluated. In other words, globals can be used to "parameterize"
a protected object, but they cannot reliably be used to control it after
the first use of the protected object.
23.b
Implementation Note: Note
that even if a global variable is volatile, the implementation need only
reevaluate a barrier if the global is updated during a protected action
on the protected object. This ensures that an entry-open bit-vector implementation
approach is possible, where the bit-vector is computed at the end of
a protected action, rather than upon each entry call.
24
An implementation may evaluate the conditions
of all entry_barriers of a given
protected object any time any entry of the object is checked to see if
it is open.
24.a
Ramification: In other
words, any side-effects of evaluating an entry barrier should be innocuous,
since an entry barrier might be evaluated more or less often than is
implied by the "official" dynamic semantics.
24.b
Implementation Note: It
is anticipated that when the number of entries is known to be small,
all barriers will be evaluated any time one of them needs to be, to produce
an "entry-open bit-vector." The appropriate bit will be tested
when the entry is called, and only if the bit is false will a check be
made to see whether the bit-vector might need to be recomputed. This
should allow an implementation to maximize the performance of a call
on an open entry, which seems like the most important case.
24.c
In addition to the entry-open
bit-vector, an "is-valid" bit is needed per object, which indicates
whether the current bit-vector setting is valid. A "depends-on-Count-attribute"
bit is needed per type. The "is-valid" bit is set to false
(as are all the bits of the bit-vector) when the protected object is
first created, as well as any time an exception is propagated from computing
the bit-vector. Is-valid would also be set false any time the Count is
changed and "depends-on-Count-attribute" is true for the type,
or a protected procedure or entry returns indicating it might have updated
a variable referenced in some barrier.
24.d
A single procedure can be compiled
to evaluate all of the barriers, set the entry-open bit-vector accordingly,
and set the is-valid bit to true. It could have a "when others"
handler to set them all false, and call a routine to propagate Program_Error
to all queued callers.
24.e
For protected types where the
number of entries is not known to be small, it makes more sense to evaluate
a barrier only when the corresponding entry is checked to see if it is
open. It isn't worth saving the state of the entry between checks, because
of the space that would be required. Furthermore, the entry queues probably
want to take up space only when there is actually a caller on them, so
rather than an array of all entry queues, a linked list of nonempty entry
queues make the most sense in this case, with the first caller on each
entry queue acting as the queue header.
25
When an attempt is made to cancel an entry call,
the implementation need not make the attempt using the thread of control
of the task (or interrupt) that initiated the cancellation; in particular,
it may use the thread of control of the caller itself to attempt the
cancellation, even if this might allow the entry call to be selected
in the interim.
25.a
Reason: Because cancellation
of a protected entry call is a protected action (which helps make the
Count attribute of a protected entry meaningful), it might not be practical
to attempt the cancellation from the thread of control that initiated
the cancellation. For example, if the cancellation is due to the expiration
of a delay, it is unlikely that the handler of the timer interrupt could
perform the necessary protected action itself (due to being on the interrupt
level). Similarly, if the cancellation is due to an abort, it is possible
that the task initiating the abort has a priority higher than the ceiling
priority of the protected object (for implementations that support ceiling
priorities). Similar considerations could apply in a multiprocessor situation.
26
26 If an exception is raised
during the execution of an entry_body,
it is propagated to the corresponding caller (see 11.4).
27
27 For a call on a protected
entry, the entry is checked to see if it is open prior to queuing the
call, and again thereafter if its Count attribute (see 9.9)
is referenced in some entry barrier.
27.a
Ramification: Given this,
extra care is required if a reference to the Count attribute of an entry
appears in the entry's own barrier.
27.b
Reason: An entry is checked
to see if it is open prior to queuing to maximize the performance of
a call on an open entry.
28
28 In addition to simple
entry calls, the language permits timed, conditional, and asynchronous
entry calls (see 9.7.2, 9.7.3,
and see 9.7.4).
28.a
Ramification: A task
can call its own entries, but the task will deadlock if the call is a
simple entry call.
29
29 The condition
of an entry_barrier is allowed to
be evaluated by an implementation more often than strictly necessary,
even if the evaluation might have side effects. On the other hand, an
implementation need not reevaluate the condition
if nothing it references was updated by an intervening protected action
on the protected object, even if the condition
references some global variable that might have been updated by an action
performed from outside of a protected action.
Examples
30
Examples of
entry calls:
31
Agent.Shut_Down; -- see 9.1
Parser.Next_Lexeme(E); -- see 9.1
Pool(5).Read(Next_Char); -- see 9.1
Controller.Request(Low)(Some_Item); -- see 9.1
Flags(3).Seize; -- see 9.4
Contents Index Search Previous Next Legal