!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-11-12 !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) @dinsc 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. ****************************************************************