D.3 Priority Ceiling Locking
1
[This clause specifies the interactions between priority
task scheduling and protected object ceilings. This interaction is based
on the concept of the ceiling priority of a protected object.]
Syntax
2
The form of a
pragma
Locking_Policy is as follows:
3
Legality Rules
4
4.a
Implementation defined: Implementation-defined
policy_identifiers
allowed in a
pragma
Locking_Policy.
Post-Compilation Rules
5
A Locking_Policy
pragma is a configuration pragma.
Dynamic Semantics
6/2
{
8652/0073}
{
AI95-00091-01}
{
AI95-00327-01}
[A locking policy specifies the details of protected
object locking.
All protected objects have a priority.
The locking policy specifies the meaning of the priority of a These
rules specify whether or not protected
object objects
have priorities, and the relationships between these priorities
and task priorities. In addition, the policy specifies the state of a
task when it executes a protected action, and how its active priority
is affected by the locking.] The
locking policy is specified by
a Locking_Policy pragma. For implementation-defined locking policies,
the
meaning of the priority of effect
of a Priority or Interrupt_Priority pragma on a protected object
is implementation defined. If no Locking_Policy pragma
applies
to appears in any of the program
units comprising a partition, the locking policy for that partition,
as well as the
meaning of the priority of effect
of specifying either a Priority or Interrupt_Priority pragma for
a protected object, are implementation defined.
6.a/2
Implementation defined:
The locking policy if no Locking_Policy
pragma applies to any unit of a partition.
6.1/3
{
AI95-00327-01}
{
AI05-0229-1}
The expression
specified for the of
a Priority or Interrupt_Priority
aspect pragma (see D.1) is evaluated as part of the creation
of the corresponding protected object and converted to the subtype System.Any_Priority
or System.Interrupt_Priority, respectively. The value of the expression
is the initial priority of the corresponding protected object. If no
Priority or Interrupt_Priority aspect is
specified for pragma
applies to a protected object, the
initial priority is specified by the locking policy.
7
There is one predefined
locking policy, Ceiling_Locking; this policy is defined as follows:
8/3
{
AI95-00327-01}
{
AI05-0229-1}
Every protected object has a
ceiling priority,
which is determined by either a Priority or Interrupt_Priority
aspect pragma
as defined in
D.1, or
by assignment to the Priority attribute as described in D.5.2.
The ceiling priority of a protected object (or ceiling, for short) is
an upper bound on the active priority a task can have when it calls protected
operations of that protected object.
9/2
{
AI95-00327-01}
The
initial ceiling priority of a expression
of a Priority or Interrupt_Priority pragma is evaluated as part of the
creation of the corresponding protected object
is
equal to the initial priority for that object. and
converted to the subtype System.Any_Priority or System.Interrupt_Priority,
respectively. The value of the expression
is the ceiling priority of the corresponding protected object.
10/3
{
AI95-00327-01}
{
AI05-0229-1}
If an Interrupt_Handler or Attach_Handler
aspect pragma
(see
C.3.1)
is specified
for a protected subprogram of a protected type that does not have the
appears in a protected_definition
without an Interrupt_Priority
aspect specified pragma,
the
initial ceiling
priority of protected objects of that type is implementation defined,
but in the range of the subtype System.Interrupt_Priority.
10.a
Implementation defined: Default ceiling
priorities.
11/3
{
AI95-00327-01}
{
AI05-0229-1}
If
neither aspect no
pragma
Priority
nor,
Interrupt_Priority
, Interrupt_Handler, or Attach_Handler
is specified
for a protected type, and no protected
subprogram of the type has aspect Interrupt_Handler or Attach_Handler
specified in the protected_definition,
then the
initial ceiling
priority of the corresponding protected object is System.Priority'Last.
12
While a task executes a protected action, it inherits
the ceiling priority of the corresponding protected object.
13
When
a task calls a protected operation, a check is made that its active priority
is not higher than the ceiling of the corresponding protected object;
Program_Error is raised if this check fails.
Bounded (Run-Time) Errors
13.1/2
{
AI95-00327-01}
Following any change of priority, it is a bounded
error for the active priority of any task with a call queued on an entry
of a protected object to be higher than the ceiling priority of the protected
object. In this case one of the following applies:
13.2/2
at any time prior to executing
the entry body Program_Error is raised in the calling task;
13.3/2
when the entry is open the
entry body is executed at the ceiling priority of the protected object;
13.4/2
when the entry is open the
entry body is executed at the ceiling priority of the protected object
and then Program_Error is raised in the calling task; or
13.5/2
when the entry is open the
entry body is executed at the ceiling priority of the protected object
that was in effect when the entry call was queued.
13.a.1/2
Ramification: Note
that the error is “blamed” on the task that did the entry
call, not the task that changed the priority of the task or protected
object. This seems to make sense for the case of changing the priority
of a task blocked on a call, since if the Set_Priority had happened a
little bit sooner, before the task queued a call, the entry-calling task
would get the error. Similarly, there is no reason not to raise the priority
of a task that is executing in an abortable_part,
so long as its priority is lowered before it gets to the end and needs
to cancel the call. The priority might need to be lowered to allow it
to remove the call from the entry queue, in order to avoid violating
the ceiling. This seems relatively harmless, since there is an error,
and the task is about to start raising an exception anyway.
Implementation Permissions
14
The implementation is allowed to round all ceilings
in a certain subrange of System.Priority or System.Interrupt_Priority
up to the top of that subrange, uniformly.
14.a
Discussion: For example, an implementation
might use Priority'Last for all ceilings in Priority, and Interrupt_Priority'Last
for all ceilings in Interrupt_Priority. This would be equivalent to having
two ceiling priorities for protected objects, “nonpreemptible”
and “noninterruptible”, and is an allowed behavior.
14.b
Note that the implementation cannot choose a
subrange that crosses the boundary between normal and interrupt priorities.
15/2
{
AI95-00256-01}
Implementations are allowed to define other locking policies, but need
not support more than one
locking such
policy per partition.
16
[Since implementations are allowed to place restrictions
on code that runs at an interrupt-level active priority (see
C.3.1
and
D.2.1), the implementation may implement
a language feature in terms of a protected object with an implementation-defined
ceiling, but the ceiling shall be no less than Priority'Last.]
16.a
Implementation defined: The ceiling of
any protected object used internally by the implementation.
16.b
Proof: This permission follows from the
fact that the implementation can place restrictions on interrupt handlers
and on any other code that runs at an interrupt-level active priority.
16.c
The implementation might protect a storage pool
with a protected object whose ceiling is Priority'Last, which would cause
allocators
to fail when evaluated at interrupt priority. Note that the ceiling of
such an object has to be at least Priority'Last, since there is no permission
for
allocators
to fail when evaluated at a non-interrupt priority.
Implementation Advice
17
The implementation should use names that end with
“_Locking” for implementation-defined locking policies.
17.a/2
Implementation Advice:
Names that end with “_Locking”
should be used for implementation-defined locking policies.
18
23 While a task executes in a protected
action, it can be preempted only by tasks whose active priorities are
higher than the ceiling priority of the protected object.
19
24 If a protected object has a ceiling
priority in the range of Interrupt_Priority, certain interrupts are blocked
while protected actions of that object execute. In the extreme, if the
ceiling is Interrupt_Priority'Last, all blockable interrupts are blocked
during that time.
20
25 The ceiling priority of a protected
object has to be in the Interrupt_Priority range if one of its procedures
is to be used as an interrupt handler (see
C.3).
21
26 When specifying the ceiling of a protected
object, one should choose a value that is at least as high as the highest
active priority at which tasks can be executing when they call protected
operations of that object. In determining this value the following factors,
which can affect active priority, should be considered: the effect of
Set_Priority, nested protected operations, entry calls, task activation,
and other implementation-defined factors.
22
27 Attaching a protected procedure whose
ceiling is below the interrupt hardware priority to an interrupt causes
the execution of the program to be erroneous (see
C.3.1).
23
28 On a single processor implementation,
the ceiling priority rules guarantee that there is no possibility of
deadlock involving only protected subprograms (excluding the case where
a protected operation calls another protected operation on the same protected
object).
Extensions to Ada 95
23.a/2
{
AI95-00327-01}
All protected objects now have
a priority, which is the value of the Priority attribute of D.5.2.
How this value is interpreted depends on the locking policy; for instance,
the ceiling priority is derived from this value when the locking policy
is Ceiling_Locking.
Wording Changes from Ada 95
23.b/2
{
8652/0073}
{
AI95-00091-01}
Corrigendum: Corrected the wording to reflect
that pragma Locking_Policy cannot be inside of a program unit.
23.c/2
{
AI95-00256-01}
Clarified that an implementation need support only
one locking policy (of any kind, language-defined or otherwise) per partition.
23.d/2
{
AI95-00327-01}
The bounded error for the priority of a task being
higher than the ceiling of an object it is currently in was moved here
from D.5, so that it applies no matter how
the situation arises.
Wording Changes from Ada 2005
23.e/3
{
AI05-0229-1}
Revised to use aspects Priority and Interrupt_Priority
as pragmas
Priority and Interrupt_Priority are now obsolescent.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe