!standard C.3.1(13) 18-01-29 AI12-0252-1/02 !class binding interpretation 18-01-26 !status Amendment 1-2012 18-01-29 !status ARG Approved 10-0-1 18-01-29 !status work item 18-01-26 !status received 18-01-15 !priority Low !difficulty Easy !qualifier Omission !subject Duplicate interrupt handlers under Ravenscar !summary If restriction No_Dynamic_Attachment is in effect, a second attempt to attach an interrupt raises Program_Error. !question Suppose I have protected First_PO is ... private ... procedure Handler with Attach_Handler => Ada.Interrupts.Names.Foo_Interrupt; end First_PO; where Foo_Interrupt isn't reserved. What should happen if I also write in the same partition another PO attached to the same interrupt? (Raise Program_Error.) !recommendation (See Summary.) !wording Add after C.3.1(13): If restriction No_Dynamic_Attachment is in effect, then a check is made that the interrupt identified by an Attach_Handler aspect does not appear in any previously elaborated Attach_Handler aspect; Program_Error is raised if this check fails. !discussion The Ravenscar profile includes the two restrictions No_Dynamic_Attachment and No_Local_Protected_Objects. These require any interrupt handler to be attached using Attach_Handler, only at library level, and no operations from Ada.Interrupts to be used. The usual full Ada (no Ravenscar profile) intent is that a handler check if there is any previous handler before attaching itself, and call the previous handler appropriately. This model cannot be used in Ravenscar, as dynamic handler operations are not allowed. Moreover, since Ravenscar requires library-level attachment, there is no case where some other handler can be attached temporarily. Therefore, the only possible result is for one of the handlers to be attached, and the other to be ignored (because its effect was overwritten). This is just a program bug, and it doesn't make sense for the Ravenscar runtime to be required to completely ignore this error. Thus, we add a rule to require the raising of Program_Error in this case. --- We tie the rule to the single restriction No_Dynamic_Attachment. However, using this restriction without No_Local_Protected_Objects allows handlers to be declared in nested units. This would allow creating a temporary handler that would override a library-level handler and which then would automatically restore the original treatment when the nested unit is left. While this seems potentially useful, it also seems to be a form of dynamic attachment. Thus, we determined that it was not harmful to raise an exception in this case as well. Note that this view of No_Dynamic_Attachment does not completely ban dynamic attachment, as one still can attach a temporary handler so long as no other handler is currently in use. This combination (No_Dynamic_Attachment without No_Local_Protected_Objects seems unlikely enough not to worry about this. --- We can't use a Post-compilation Rule to check this since the interrupt number is not required to be static, even when the Ravenscar profile is in effect. !corrigendum C.3.1(13) @dinsa When a handler is attached to an interrupt, the interrupt is blocked [(subject to the Implementation Permission in C.3)] during the execution of every protected action on the protected object containing the handler. @dinst If restriction No_Dynamic_Attachment is in effect, then a check is made that the interrupt identified by an Attach_Handler aspect does not appear in any previously elaborated Attach_Handler aspect; Program_Error is raised if this check fails. !ASIS No ASIS effect. !ACATS test !appendix !topic Interrupt reservation under Ravenscar !reference Ada 2012 RMC.3.1 !from Simon Wright 18-01-15 !keywords interrupt attachment Ravenscar !discussion Under Ravenscar, the only way of specifying an interrupt handler is via aspect Attach_Handler in a library-level protected object: * D.13(6) Ravenscar restrictions include No_Dynamic_Attachment and No_Local_Protected_Objects * D.7(10) No_Dynamic_Attachment forbids use of Ada.Interrupts * D.7(10.2) No_Local_Protected_Objects requires library-level declaration of POs Suppose I have protected First_PO is ... private ... procedure Handler with Attach_Handler => Ada.Interrupts.Names.Foo_Interrupt; end First_PO; where Foo_Interrupt isn't reserved. What should happen if I also write in the same partition another PO attached to the same interrupt? protected Other_PO is ... private ... procedure Handler with Attach_Handler => Ada.Interrupts.Names.Foo_Interrupt; end Other_PO; If the implementation allows the attachment to go ahead, following the implication of C.3.1(14.1) that interrupt handlers can be stacked, we're in the position that the actions that were intended to be taken by one of the POs (the first to be elaborated) will never be taken. The meaning of the program depends on the chosen elaboration order, and this situation can't be recovered from at run time (because we can't use Ada.Interrupts). I found this because an AdaCore library had already declared a handler for a particular interrupt, and I needed to implement my own behaviour. In this case, I could probably have ensured that my handler was used by cunning use of elaboration pragmas. In other circumstances, e.g. attaching the wrong interrupt (where for example Other_PO should have been attached to Bar_Interrupt), there might be long and tedious debugging sessions. I would like to see PE being raised; would this be a suitable candidate for an implementation permission? e.g. C.3.1(17.1) If Ravenscar restrictions are in force, an implementation may extend the check specified in (10) so that once an interrupt has been attached it is treated as reserved. Even better, make this implementation advice (22), changing the word "may" to "should". **************************************************************** From: Randy Brukardt Sent: Friday, January 19, 2018 8:24 PM ... > What should happen if I also write in the same partition another PO > attached to the same interrupt? Something well-defined should happen, and that doesn't seem to be the case now. So this seems like a language bug. ... > I would like to see PE being raised; would this be a suitable > candidate for an implementation permission? e.g. > > C.3.1(17.1) If Ravenscar restrictions are in force, an implementation > may extend the check specified in (10) so that once an interrupt has > been attached it is treated as reserved. > > Even better, make this implementation advice (22), changing the word > "may" to "should". A profile like Ravenscar is completely defined out of other pragmas and attributes; it has no semantics of its own. Thus a paragraph like this is out-of-bounds for Ada. (They've been proposed and even once made it into the Standard, but they get crushed once that happens.) I also don't see any value to making it an option; I think a check should be mandated (much like Detect_Blocking mandates checks). Finally, Standard can't refer to paragraph numbers, so the wording has to identify the check in question more specifically. To turn positive: We need to tie some defined behavior to some restriction or aspect. You noted that the original restriction invoked by Ravenscar includes No_Dynamic_Attachment. Since No_Dynamic_Attachment prevents the use of Ada.Interrupts, there is no way for a handler in that environment to call any previous handler. Thus calling the previous handler is impossible. When No_Local_Protected_Objects is also in effect, only one handler can be usefully attached. So I would suggest a Dynamic Semantics rule something like: If both restriction No_Dynamic_Attachment and restriction No_Local_Protected_Objects are in effect, then a check is made that the interrupt identified by an Attach_Handler aspect does not appear in any previously elaborated Attach_Handler aspect; Program_Error is raised if this check fails. It's a bit unfortunate that the interrupt number is not required to be static; otherwise I would suggest using a Post-Compilation Check instead. (Restrictions often cause post-compilation checks, adding another is not likely to be a big deal.) In any case, I think this is a necessary bug fix, and thus it ought to apply to Ada 2012 and Ada 2005 as well as any future Ada. The situation you ran into shouldn't happen in a "safe" language. **************************************************************** From: Randy Brukardt Sent: Friday, January 26, 2018 1:57 AM Here is an AI to fix a problem a user encountered using interrupts with Ravenscar. [This is version /01 of the AI - RLB] It seems like a bug to silently ignore an extra interrupt handler for an interrupt (and to the reporter as well). But the language rules clearly require that. So I've proposed a rule to fix it. Comments welcome, especially from our real-time people. **************************************************************** From: Jeffrey Cousins Sent: Friday, January 26, 2018 8:36 AM Personally I think No_Dynamic_Attachment should ban the temporary attachment too. **************************************************************** From: Tullio Vardanega Sent: Friday, January 26, 2018 9:06 AM Useful fix, completely in line with the Ravenscar Profile intent. I am with Jeff on the view that No_Dynamic_Attachment should disallow attaching handlers in nested units (because leaving them would cause dynamic detachment :) If one wanted the notion that Randy evokes near the bottom of the AI, then they should use dynamic attachments. **************************************************************** From: Gary Dismukes Sent: Friday, January 26, 2018 11:05 AM > Personally I think No_Dynamic_Attachment should ban the temporary attachment > too. I agree with Jeff. **************************************************************** From: Randy Brukardt Sent: Friday, January 26, 2018 10:01 PM I almost convinced myself of that writing the AI discussion, but as it was really late I didn't want to go back and rewrite the entire AI for that. It's an easy enough change to do if we want (just delete some words from the wording and rewrite the discussion). So this version is good enough for discussion during the call. (But did want to hear the opinion of those that aren't going to be able to attend the meeting.) ***************************************************************