Version 1.2 of ai05s/ai05-0278-1.txt
!standard D.16.1(0) 11-11-12 AI05-0278-1/01
!class Amendment 11-11-12
!status Amendment 2012 11-11-12
!status ARG Approved 6-0-3 11-11-12
!status work item 11-11-12
!status received 11-09-19
!priority Low
!difficulty Medium
!qualifier Error
!subject Set_CPU called during a protected action
!summary
The effect of Set_CPU and Assign_Task is delayed until the next dispatching
point when either is called during a protected action.
!proposal
Set_CPU is and Assign_Task are both defined to be a task dispatching point.
Both can be called during a protected action. We don't want blocking operations
like task dispatching points inside of a protected action.
Thus we need to adopt a more complicated model; the effect should be delayed
until the protected action has ended, but no later than the next task
dispatching point.
!wording
Modify the last three sentences of D.16.1(26/3):
A call of Assign_Task is a task dispatching point for task T {unless T is inside
of a protected action, in which case the effect on task T is delayed until its
next task dispatching point}. If T is the Current_Task the effect is immediate{
if T is not inside a protected action}, otherwise the effect is as soon as
practical. Assigning a task to System_Dispatching_Domain that is already
assigned to that domain has no effect.
Modify the last two sentences of D.16.1(27/3):
A call of Set_CPU is a task dispatching point for task T {unless T is inside of
a protected action, in which case the effect on task T is delayed until its next
task dispatching point}. If T is the Current_Task the effect is immediate{ if T
is not inside a protected action}, otherwise the effect is as soon as practical.
!discussion
An alternative model that was considered is that the effect is immediate
as soon as T is not in a protected action. This, however, would require
distributed overhead to check for an event that is likely to be very rare
(at least compared to the number of protected actions). Specifically, part
of ending a protected action would have to be a check whether Set_CPU was
called during the execution of the protected action. Since the vast majority
of Ada programs will not use this package, but most execute protected actions,
this overhead is not acceptable.
[Editor's note: Given the emphasis on the task dispatching point, I wonder
if we shouldn't bound the "as soon as practical" time to the next task
dispatching point of T? But this is a question not asked, so no change there.
Also, the first sentence of this change (which says the CPU change occurs at the
next task dispatching point) seems to slightly conflict with the second, which
allows making the CPU change as soon as possible. It's not bad enough to
actually change, the intent seems clear.]
!corrigendum D.16.1(0)
Insert new clause:
Force a conflict; the real wording is found in the conflict file.
!ACATS Test
It might be possible to create an ACATS C-Test to check this, but it would
be difficult to write correctly. It would be more valuable to check that
the switch is not done too late, but that is unlikely to fail (even if wrong).
!ASIS
No change needed.
!appendix
From: Alan Burns
Sent: Monday, September 19, 2011 4:55 AM
We have just held IRTAW - lots of interesting stuff for post Ada2012!
But a couple of 'editorial' issues were noted with regard to D.16.1
[Editor's note: the first comment is addressed in AI05-0269-1, and is not
repeated here.]
Set_CPU (and Assign_Task) both say the effect is immediate if T is the current
task. It was felt that like Set_Priority this should be 'immediately at the
first point when T is outside the execution of a protected action.' Moving a
task that has a lock may course implementation difficulties.
I hope these can be considered during the current review
****************************************************************
From: Randy Brukardt
Sent: Monday, September 19, 2011 7:55 PM
...
> Set_CPU (and Assign_Task) both say the effect is immediate if T is the
> current task. It was felt that like Set_Priority this should be
> 'immediately at the first point when T is outside the execution of a
> protected action.' Moving a task that has a lock may course
> implementation difficulties.
This seems like overspecification to me. If "immediate" is a problem for some
implementations, we should bound the places where the effect can happen but not
prevent an implementation that can do it sooner. (It is quite complex to support
delaying the effect of one of these operations on a non-running task.)
The reason that Set_Priority is required to take after any protected action is
explained in the AARM; it might cause a protected action to be abandoned (by a
new ceiling priority violation), and that seems bad. OTOH, there is no such
effect for changing the CPU of a task; the semantics remain the same. So I don't
see any reason to *disallow* changing the CPU during a protected action (and
that is what the Set_Priority wording does).
It makes sense to me that some implementations might have trouble doing such a
change during a protected action (especially of a running task), but it also
seems likely that *not* doing such a change immediately for a non-running task
also would add complexity to no benefit. So I don't think we want exactly the
wording of Set_Priority, rather we would want something like "no later than the
completion of all protected actions". (But I don't think that is the right
wording.)
> I hope these can be considered during the current review
I think the second comment (the only one discussed here) needs more
consideration than we can give during an editorial review. As noted, it seems
wrong to me, and thus I think we'll need to discuss it as one of the first Ada
2012 AIs.
But this is not a change that I would feel comfortable making on my own, and it
seems better to me as it is than it would be requiring a delayed response (which
surely adds complexity to task operations, since the end of every protected
operation would have to check if a CPU change is needed). That is, we'd rather
have implementations bending over backwards to do "immediate" than to do
"delaying". So I think no immediate change is the best policy.
****************************************************************
From: Alan Burns
Sent: Tuesday, September 20, 2011 2:28 AM
OK - accept perhaps best to discuss this in a future AI - it is linked to the
need to do a number of things 'at the same time', ie change priority and CPU
(atomically).
I assume the first issue in my email - the pragma, is an edit change.
****************************************************************
From: Randy Brukardt
Sent: Tuesday, September 20, 2011 7:55 PM
> OK - accept perhaps best to discuss this in a future AI - it is linked
> to the need to do a number of things 'at the same time', ie change
> priority and CPU (atomically).
Right, but keep in mind we don't have any way currently to do that (CPU and
priority changes are made separately, and it would seem very wrong to me to
require them somehow to be done together when requested separately). Perhaps
there is some missing functionality??
> I assume the first issue in my email - the pragma, is an edit change.
Right.
****************************************************************
From: Steve Michell
Sent: Thursday, September 22, 2011 3:27 PM
The following sentence to 16.1(27) says that Set_CPU is a task dispatching
point. Clearly we do not want task dispatching points in the middle of a
protected object. If the task had been waiting on a protected entry, then the
actual task executing the code may be doing it for task T. I think that there
could be a binding interpretation here.
****************************************************************
From: Randy Brukardt
Sent: Thursday, September 22, 2011 6:35 PM
> The following sentence to 16.1(27) says that Set_CPU is a task
> dispatching point. Clearly we do not want task dispatching points in
> the middle of a protected object.
I agree, but I don't see any reason that Set_CPU should be *required* to be a
task dispatching point. (It should be *allowed* to be a task dispatching point,
but that's very different.) Depending on the implementation, Set_CPU may not
have any effect on task queuing or the like, and it would require distributed
overhead to support deferring it (a check at the ending of every protected
action to see if a Set_CPU was deferred). This isn't horribly expensive, but
still is a bad idea for something that almost never will be used.
> If the task had been waiting on a protected entry, then the actual
> task executing the code may be doing it for task T.
I agree that this is a possible implementation, but it is rather unlikely that
this capability would be used. (It's virtually impossible in practice, as it
would be require redirecting exceptions and finalizations during any "on behalf
of" execution. That would cause distributed overhead for those operations and
would probably eat up any savings from doing "on behalf of" execution. I'd much
prefer that the permission be completely removed from the language so that it is
not used to justify other overhead as above, especially as "as-if" optimizations
would allow it to be done anyway.)
> I think that there could be a binding interpretation here.
I agree, we need to discuss this properly, with a write-up. As noted above, I
think the current wording is wrong as it costs overhead for no reason. And the
current wording is also wrong in that it does not allow deferring (and that
surely needs to be allowed, at a minimum for implementations that have separate
queues for separate CPU groups). Net is that I think the current wording is way
overspecified (especially for something with few [no?] implementations).
Definitely not something we can decide now.
****************************************************************
Questions? Ask the ACAA Technical Agent