NCOHEN@IBM.COM (Norman COHEN) (11/15/87)
Dave Emery was looking for a way to write a "terminate but stay resident" interrupt handler in Ada. Actually, the rules of Ada make this straightforward, given appropriate implementation support. The key is to declare the interrupt-handler task not in the main program, but in a library package: PACKAGE Interrupt_Handler_Package IS TASK Interrupt_Handler IS ENTRY Interrupt_Entry; FOR Interrupt_Entry USE AT ...; END Interrupt_Handler; END Interrupt_Handler_Package; PACKAGE BODY Interrupt_Handler_Package IS TASK BODY Interrupt_Handler IS ... BEGIN LOOP ACCEPT Interrupt_Entry; ... -- Service the interrupt END LOOP; END Interrupt_Handler; END Interrupt_Handler_Package; WITH Interrupt_Handler_Package; PRAGMA Stay_Resident (Interrupt_Handler_Package); -- Hypothetical implementation-defined pragma (see text below) PROCEDURE Install_Handler IS ... BEGIN NULL; -- Alternatively, as Dave Emery put it, "Do something for a -- while, then finish up." END Install_Handler; The library package Interrupt_Handler_Package is elaborated, thus activating the Interrupt_Handler task, before the main program Install_Handler begins execution. Then the note in paragraph 9.14(13) of the Reference Manual comes into play: On the other hand, termination of the main program does not await termination of tasks that depend on library packages; the language does not define whether such tasks are required to terminate. Thus the main program terminates. Under an implementation in which all Ada tasks are interleaved in a single operating-system task, the Interrupt_Handler task would probably also terminate at this point; but under a system supporting the terminate-but-stay-resident concept, the Interrupt_Handler task could continue to execute. The example above supposes an implementation-defined pragma to tell the run-time system to keep resident all tasks in a given library package, but an implementation could conceivably do this by default. An implementation could also conceivably restrict the stay-resident semantics to tasks whose bodies have a particular structure--for example, a single loop beginning with a simple accept statement for an interrupt entry, since such a task could be made to "continue executing" simply by installing an interrupt handler, with no need to maintain task control blocks or perform explicit scheduling. Since we want the Interrupt_Handler task to execute forever, its body does not contain a terminate alternative. Indeed, a terminate alternative in a task dependent on a library package is always useless because it cannot be selected. See RM paragraph 9.4(8).