[comp.lang.ada] "Terminate but stay resident" interrupt handlers

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).