Version 1.1 of ai12s/ai12-0299-1.txt

Unformatted version of ai12s/ai12-0299-1.txt version 1.1
Other versions for file ai12s/ai12-0299-1.txt

!standard D.2.1(10.1/2)          19-01-04 AI12-0299-1/01
!class binding interpretation 19-01-04
!status work item 18-11-27
!status received 18-11-27
!priority Low
!difficulty Easy
!qualifier Clarification
!subject The permission of D.2.1(10.1/2) allows too much
!summary
An implementation can add new task dispatching points, but not alter language-defined task dispatching points.
!question
The Implementation Permission in D.2.1(10.1/2) reads:
[For optimization purposes,] an implementation may alter the points at which task dispatching occurs, in an implementation-defined manner. However, a delay_statement always corresponds to at least one task dispatching point.
This seems to allow pretty much any rules for task dispatching points to be conforming, overriding all of the rules in the following subclauses. For instance, an implementation could just say that no preemption occurs for the FIFO_Within_Priorities policy, and that would seem to be allowed by this permission. Is this intended? (No.)
!recommendation
(See Summary.)
!wording
Modify D.2.1(7/5):
A call of Yield is {always} a task dispatching point.{ A delay_statement is always a task dispatching point.}
AARM Ramification: This is true for any task dispatching policy, including an implementation-defined policy. A programmer can always use a delay_statement or a call to Yield to get task dispatching, regardless of which policy is in effect.
Replacing D.2.1(10.1/2) with:
Unless otherwise specified for a task dispatching policy, an implementation may add additional points at which task dispatching may occur, in an implementation-defined manner.
AARM Reason: This permission is intended to allow the implementation of Ada tasks in terms of target system threads, which may have additional conditions that cause task dispatching. For instance, for Linux threads, page faults are task dispatching points.
AARM Discussion: The Non_Preemptive_FIFO_Within_Priorities task dispatching policy (see D.2.4) does not allow additional task dispatching points.
Add after D.2.4(9/3):
AARM Ramification: This rule supersedes the Implementation Permission of D.2.1; an implementation that adds additional task dispatching points to this policy is incorrect.
!discussion
The original permission goes back to early Ada 95, and the reason for it is lost to the mists of time.
The only purpose that has been suggested is to allow implementation of Ada tasking policies on top of existing target facilities. In particular, Linux threads consider a page fault a task dispatching policy, so without some sort of permission, Annex D could not be implemented using those.
However, that only requires adding task dispatching points. There seems to be no need to "alter" existing task dispatching points, and allowing that would make analysis much harder. If an implementation really wants to "alter" some existing task dispatching points, it can define an implementation-defined policy to do whatever they want.
Additionally, the non-preemptive policy means just that, and we don't want any additional points at all in that policy. So we write the permission so that it does not apply to the non-preemptive policy.
!ASIS
No ASIS effect.
!ACATS test
This permission isn't directly testable, but it does make the rest of Annex D more testable. (With the original permission, requiring virtually anything about task dispatching could have been invalid because of this permission.)
!appendix

From: Randy Brukardt
Sent: Tuesday, November 27, 2018  2:03 AM

IRTAW people, here is a question for you:

There is an Implementation Permission in D.2.1(10.1/2):

   [For optimization purposes,] an implementation may alter the points
   at which task dispatching occurs, in an implementation-defined manner.
   However, a delay_statement always corresponds to at least one task 
   dispatching point.

The only effect of a call to Yield (explicitly or implicitly by the new aspect 
Yield) is to insert a task dispatching point. According to this Implementation 
Permission, an implementation would be allowed to completely ignore calls to 
Yield, and still be a conforming implementation of Ada. Note that this 
permission isn't limited by dispatching policies or anything else.

This permission comes from original Ada 95 (it was moved unchanged by Ada 
2005), so it existed before Yield was added. Before Yield, delay 0.0 was the
way to get a task dispatching point into a program.

Should this permission be updated to include Yield? 

P.S. I find this permission overly broad anyway, it seems to have almost no 
limitations on what an implementation could do and be conforming. I would have
expected it to be overridden by various dispatching policies, but that's not
the case -- it seems to override any policies. For instance, by this 
permission, an implementation that ignored D.2.3(9/2) [the preemption rule] 
in any case other than a delay_statement would seem to be within the 
language's requirements. I doubt that any real-time user of Ada would be happy
with that, though. So perhaps realities of the market are sufficient here. (Or
should I start claiming Annex D support for Janus/Ada?? ;-)

***************************************************************

From: Alan Burns
Sent: Tuesday, November 27, 2018  2:59 AM

Yes I think Yield does need adding to 10.1.

I am not totally sure what the purpose of 10.1 is, as you say it has been in 
Ada for a long time. The note says 'alter', not 'ignore' - but with no bound 
on what 'alter' means then it could, as
you say, undermine preemption rules etc. Should 10.1 be rewritten?

But to come back to your question, Yield is synonymous with delay 0.0, so yes 
it must be a task dispatching point.

***************************************************************

From: Tullio Vardanega
Sent: Tuesday, November 27, 2018  4:32 AM

Just to chime in.
Alan has given the "IRTAW answer" to your question, Randy.
As for D2.1.2(10.1/2), the current text was trying to make a very fine point,
which -- back then -- was implicitly referring to document requirements on the
alterations. A rewrite that bounds the admissible extent of alteration would
be good, I think.

***************************************************************

From: Tucker Taft
Sent: Tuesday, November 27, 2018  9:22 AM

OK, but then someone in the RT community will have to provide this rewrite.
It does say "implementation-defined" so that does imply some documentation of
the new rules, which is a fair amount of effort.

For now, I think we should add "Yield" to the paragraph.

***************************************************************

From: Randy Brukardt
Sent: Tuesday, November 27, 2018  5:45 PM

...
> OK, but then someone in the RT community will have to provide this 
> rewrite.  It does say "implementation-defined" so that does imply some 
> documentation of the new rules, which is a fair amount of effort.

Not that much. For Janus/Ada, it would be:
   A task dispatching point occurs whenever there is a language-defined 
   interaction between tasks (such as an accept statement), a delay_statement
   or Yield call, when a task is created, completed, terminated, or aborted,
   when a potentially blocking call to a protected entry is made, when 
   barriers are serviced for a protected object, and when a protected object
   is finalized. No other events are task dispatching points, regardless of 
   what the RM says.

Not that most real-time users would find this useful, but it would meet the 
letter of the Standard (by using this permission literally). Moreover, if you
would be willing to follow the old AdaCore conceit (read the source code if 
you want to know what happens in some case), it would be even easier.

> For now, I think we should add "Yield" to the paragraph.

In the absence of knowing precisely what this permission is for, that's 
probably all we can do. Unless we're willing to get radical with it. In that 
case, I'd suggest that the permission be completely deleted. In the case where
the RM defines a dispatching policy, it seems bad to allow implementations to
alter the meaning of that policy (by altering the definition of task 
dispatching points) -- if that's allowed, it becomes much harder to analyze 
Ada code for any tasking properties even when a policy is specified. And when 
there is no policy (or more accurately, an implementation-defined policy), 
it's implementation-defined for heavens sake. We don't need a permission to 
make it *more* implementation-defined! So there doesn't seem to be any 
positive value to this permission.

But of course I know just enough about RT to be dangerous. :-) So I think it 
is necessary for the RT community to think about if there are any cases where
it makes sense to allow flexibility for each policy, and if so, craft an 
individual permission for that policy. And in any case, give the blanket 
permission the heave-ho.

I say this as mainly a starting point for discussion within the RT community, 
and not as any sort of certain answer. In the meantime (since time is short 
for Ada 2020), we should add Yield to the exclusions to the permission -- at
least something can be counted on.

***************************************************************

From: Alan Burns
Sent: Wednesday, December 5, 2018  5:11 AM

IRTAW folk have discussed this, and are of the unanimous opinion that the 
permission refereed to in D.2.1(10.1/2) is at best useless and at worst 
undermining of the various dispatching policies defined elsewhere in Annex D.

We would recommend that this permission is deleted (unless there is evidence 
that some implementation somewhere is sensibly using it - we are collectively
not aware of any).

Perhaps it would be useful not to loose the statement that "a delay_statement 
always corresponds to ... a task dispatching point".  We feel this could be 
added to D.2.1(7/3).

In terms of the original question, if D.2.1(10.1/2) remains then Yield should 
be added.

***************************************************************

From: Erhard Ploedereder
Sent: Wednesday, December 5, 2018  8:12 AM

I would guess that D.2.1 (10.1/2) is the concession needed to implement Ada 
threads in terms of Linux threads. As for as I know, page faults are 
dispatching points for Linux threads and are not under the Ada model.

(As such, it is pretty badly worded, since it is an "anything goes" rule that 
allows ignoring dispatching points, which seems really bad.)

The question becomes whether Annex D policies want to preclude such an 
implementation on Linux/Unix and friends (or whether there are respective
loopholes elsewhere in the RM).

***************************************************************

From: Alan Burns
Sent: Wednesday, December 5, 2018  9:31 AM

So the permission required for Linux-based implementations is that an 
implementation can add extra dispatching points. This is different from
'altering' existing points.

The addition of extra dispatching points is only a problem for non-preemptive 
dispatching. Para D.2.4 (9.3) makes it clear that there is only a well 
defined set of dispatching points for this policy. So if we retain some form 
of D.2.1 (10.1/2) it must be made clear that D.2.4 (9.3) takes precedence.

***************************************************************

From: Randy Brukardt
Sent: Wednesday, December 5, 2018  4:45 PM

It seems possible to eliminate the effect of extra dispatching points (use
one thread per core, each locked to that core, and use those to execute the 
Ada code as needed), presuming you are not concerned about preemption of the
entire Ada program by the OS to let unrelated things run. (I don't see any 
way to avoid allowing that outside of running only on bare machines, which is
often not practical.)

Still, that would not really use the target OS's facilities (which I 
personally think is an advantage, but others obviously disagree). So I tend to
agree that some permission is needed.

So, how about replacing D.2.1(10.1/2) with the following:

Unless otherwise specified for a task dispatching policy, an implementation 
add additional points at which task dispatching may occur, in an 
implementation-defined manner. 

AARM Reason: This permission is intended to allow the implementation of Ada 
tasks in terms of target system threads, which may have additional conditions
that cause task dispatching. For instance, in Linux threads, page faults are 
task dispatching points.

AARM Discussion: The Non_Preemptive_FIFO_Within_Priorities task dispatching 
policy (see D.2.4) does not allow additional task dispatching points.

And probably add an AARM note after D.2.4(9/3):

AARM Ramification: This rule supersedes the Implementation Permission of D.2.1; 
an implementation that adds additional task dispatching points to this policy 
is incorrect.

You also wanted to add the delay_statement remark to D.2.1(7/5), which would
give:

A call of Yield is a task dispatching point. A delay_statement is always a task
dispatching point.

Is this sufficient? If this wording is what is needed, I can write up an AI to 
that effect (probably not for Monday's call, but we'll have another call in 
January).

***************************************************************

From: Jeff Cousins
Sent: Thursday, December 6, 2018  12:27 PM

Just a typo:

Unless otherwise specified for a task dispatching policy, an implementation
{may} add additional points at which task dispatching may occur, in an
implementation-defined manner. 

***************************************************************

From: Alan Burns
Sent: Friday, December 7, 2018  3:24 AM

I think this is sufficient and useful - so an AI would be good

**************************************************************


Questions? Ask the ACAA Technical Agent