CS222 Lecture: Interrupts, Exceptions, and the VAX Condition-Handling Facility
               and Unix signal facility
                                                        Revised 2/18/99

Materials: Transparency of VAX system control block
           Transparency of VAX/VMS condition handler argument arrays
           Example program illustrating use of a VAX/VMS condition handler
           Example program illustrating use of a MIPS/Unix signal catcher
Intro
-----

   A. In our discussion thus far, we have assumed that the flow of control
      within a program proceeds from instruction to successive instruction,
      except when explicitly altered by a branch or procedure call instruction.

   B. There are, however, two kinds of events that can cause the flow of
      execution to be altered apart from an explicit instruction in the
      currently running program.

      1. INTERRUPTS can be generated by external devices to indicate that they
         need service by the CPU.  Examples:

         a. When a disk controller has been asked to transfer a block of data
            between memory and the disk, it will issue an interrupt request
            when the transfer is complete.

         b. Many types of terminal controllers will issue an interrupt request
            every time a key is struck on the terminal they control.

         c. The system clock issues an interrupt request at regular intervals
            so that software can keep track of the time of day and can manage
            sharing of the CPU resources among different users (time-slicing.)

      2. EXCEPTIONS arise from the operation of the currently running program.
         They are usually (but not always) the result of some flaw in the
         program.

         a. The VAX documentation divides exceptions into two categories:

            i. Faults are exceptions that prevent the instruction that
               is executing from completing.

           ii. Traps are exceptions that indicate that the instruction that
               caused them completed with some kind of error.

         b. Examples:

            i. Memory access violations - attempting to access a region of 
               memory the program is not allowed to access (usually resulting 
               from an error in address computation or an infinite loop.)
               [FAULT]

           ii. Illegal instructions or invalid addressing modes - usually the
               result of bad code or attempting to execute data.  [FAULT]

          iii. Division by zero. [TRAP]

           iv. Overflow and/or floating point underflow may result in a trap.

               - Floating point overflow always results in a trap.

               - Floating point underflow and integer or decimal overflow will
                 result in a trap if the corresponding enable bit in the PSL
                 (FU, IV, DV) is set to 1.

               - The entry mask of a procedure specifies the setting of IV
                 and DV for that procedure.  FU must be set/cleared directly.

               - Example: ^M<R3,IV> would save R3 and enable integer overflow
                        exceptions

               [TRAP if enabled]

         Note: We have used VAX exceptions, but MIPS is similar.

      3. Interrupts and exceptions differ in that the former are ASYNCHRONOUS
         while the latter are SYNCHRONOUS.

         a. Interrupts arise from conditions outside the currently running
            program.  Thus, if the same program is run again, it is very
            unlikely that the same interrupt will occur at the same point in
            the program.

         b. Exceptions arise from the behavior of the currently running program.
            Ordinarily, if a given program gives rise to an exception, then it
            will generate that same exception at the same point in its execution
            every time it is run on the same input data.

   C. On most computers, dealing with interrupts and exceptions involves 
      features of both the hardware and the operating system.

      1. In response to an interrupt or exception, the hardware typically
         does a forced jump to an operating system routine that is designed to
         handle the specific condition detected.  In so doing, it saves
         enough information about the context in which the interrupt/exception
         occurred to allow a return to what was happening after the interrupt/
         exception has been dealt with.

      2. The operating system routine that is invoked must analyze the specific
         event and decide on an appropriate action, which may or may not alter
         the execution of the program that was running at the time the
         interrupt/exception occurred.

      3. In the remainder of this lecture, we will look at how two specific
         CPU/operating system combinations deal with interrupts/exceptions.
        
         a. VMS on the VAX

         b. Unix on MIPS

         c. Since VAXen are also capable of running Unix, we could look at
            this combination as well.  Since it is very similar to Unix on
            MIPS, we will not do so.  (Further, Unix on a VAX does not
            fully utilize the features of the VAX hardware, which were really
            designed to support VMS.)

I. VAX/VMS Interrupt Handling
-  ------- --------- --------

   A. Though interrupts and exceptions are very distinct in their origin, they
      are handled similarly by the hardware.

      1. The PSL and PC value currently in force is pushed on a special system
         stack (not the one ordinarily used by the currently running program.)

      2. The address of a SERVICE ROUTINE is looked up in a special data
         structure called the SYSTEM CONTROL BLOCK.  Each type of interrupt or
         exception maps to its own entry in this table.

         TRANSPARENCY - VAX SYSTEM CONTROL BLOCK

      3. The specified service routine - which is part of the operating system -
         is activated.  It then deals with the interrupt or exception in
         whatever way it needs to.

   B. As we have noted previously, the VMS operating system includes special
      code segments called DEVICE DRIVERS - one for each class of IO device
      configured on the system.

      1. The System Control Block entry for each kind of device interrupt
         contains the address of an interrupt handler routine that is part of
         the device driver for that device.

      2. Normally, an interrupt indicates the completion of the last request
         issued by the device driver to the device.  A typical action for the
         driver, then, would be to check to see if another request has been
         queued up (by the QIO system service) for the same device.

         a. If so, the request is removed from the queue and given to the
            device, and the device is left enabled to interrupt when that
            request is finished.

         b. If the queue is empty, then further interrupts from the device are
            disabled until a request arrives in the queue for it.

      3. Usually, an interrupt service routine ends with an REI instruction,
         that resumes the currently running process at the point where it
         left off.  The fact that an interrupt occurred should be entirely
         invisible to the program that was running.

   C. Certain kinds of interrupts can cause the currently running process to
      be put aside in favor of another.

      1. To support multiple users, VMS time-slices the CPU's time among all
         users that need to use the CPU.  A timer interrupt may indicate that
         the current process's time slice has expired, in which case it is time
         to give another user a turn.

      2. Various processes can have different priority levels associated with
         them.  If a high priority process is waiting for an IO request to
         complete, then when the interrupt arrives signalling the completion
         of that request the operating system may take the CPU away from the
         current process and give it to the higher priority one.

      3. However, when the process that was put aside does eventually regain the
         use of the CPU (its turn comes up again), control is restored to it
         in such away as to make the temporary loss of the CPU invisible -
         except for delays in getting results that the person running the
         program may notice.

II. VAX/VMS Exception Handling
--  ------- --------- --------

   A. As we noted previously, an exception usually means that something has
      gone wrong with the currently running program.  Though the hardware
      handles interrupts and exceptions the same way, the VMS operating
      system responds to them in quite different ways.

   B. The default action by VMS in the case of an exception is to print the 
      familiar "symbolic stack dump" and abort the current program.
      However, VMS provides a very sophisticated facility called the condition
      handling facility that allows a program to "catch" some or all exceptions
      and handle them in its own way, without terminating execution.

      1. This is a mechanism provided by the VMS operating system - not by the
         hardware.  It is found in the software that the SCB entries for the
         various exceptions point to.  (However, it does make use of a bit of
         hardware support.)

      2. Recall that the stack frame that is created when a procedure is called
         contains a slot reserved for a CONDITION HANDLER ADDRESS.

         a. This is the slot that FP points to.

         b. It is automatically initialized to zero by the hardware when a
            CALLG or CALLS instruction is executed.

      3. A procedure that wants to handle some or all exceptions arising from
         its execution (or the execution of procedures it calls) may place
         the address of the entry mask of a condition handling procedure in this
         slot in its stack frame.

         a. Example:

                .ENTRY  PROC ...
                MOVAB   MY_HANDLER,(FP)         ; Establish handler
                ...

        
                .ENTRY  MY_HANDLER,^M<>         ; This procedure will be called
                ...                             ; if any exception arises while
                ...                             ; PROC is executing


         b. The VMS exception handling software operates as follows:  When an
            exception occurs, it begins searching down the stack one frame at
            a time, starting with the procedure that was executing when the
            exception occurred.

            i. If a frame that contains a non-zero value in its condition
               handler slot is found, then the procedure whose address appears
               there is called.

           ii. The condition handler has several options available to it - one
               of which is to indicate successful handling of the condition.
               If the condition handler returns a success code, then execution
               resumes in the regular part of the program as if no exception had
               occurred - at the instruction AFTER the one that caused the
               exception.

          iii. Alternately, the condition handler may unwind one or more 
               intervening stack frames from the stack before returning a 
               success code.  This causes execution to return at a point in the
               program where some procedure was called that lay in the path
               leading to the point of the exception.  (Often, a condition
               handler unwinds back to the call to the routine that established
               it.)

           iv. Another option available to the handler is to resignal the
               condition (indicating that someone else should handle it.)  If 
               this happens, the search for a handler resumes at the next frame
               down in the stack.

         c. If no handler is found on the stack, or all those that are found
            resignal, then the default action of printing a stack dump and
            aborting is taken.

            i. Actually, this is handled using the same mechanism by having a
               traceback handler installed on the stack just below the main
               entry point to the user program.

           ii. If the stack becomes corrupted so the traceback handler can't
               be found, then a special default handler is invoked that prints
               the register dump some of you have seen.

   C. VMS Condition handling procedures must be written according to very 
      specific standards.

      1. As usual, they must save and restore any registers they use - which is
         normally done by listing them in their entry mask.

      2. They normally end with the usual RET instruction, and must return one 
         of the following status codes in R0:

         a. SS$_CONTINUE

         b. SS$_RESIGNAL

         c. Optionally, they can call the SYS$UNWIND system service to remove
            some number of stack frames from the stack before returning - thus
            forcing premature termination of one or more procedures.

         d. Instead of returning, a condition handler may call the $EXIT system
            service to terminate the program.

   D. The condition handling procedure obtains information about the specific
      exception that caused if to be called through the argument list passed to
      it by the VMS system software.  This argument list contains two arguments,
      each of which is an array that is passed by reference.

      1. The first array is called the SIGNAL ARGUMENTS (SIG_ARGS) array, and
         contains information about the exception that caused the handler to be
         called.  Its exact format varies from condition to condition.

         TRANSPARENCY - VAX/VMS Condition handler arguments

      2. The second array is called the MECHANISM ARGUMENTS (MCH_ARGS) array.
         It contains information about how the handler was found, as well as
         saved copies of the R0 and R1 values in effect when the exception
         occurred (since these are not normally saved by procedure calls.)
         Its format is always the same.

         TRANSPARENCY

   E. EXAMPLE PROGRAM: CONDITION_HANDLING.MAR

III. MIPS/Unix Interrupt/Exception Handling
---  --------- ------------------- --------

   A. In some ways, the MIPS hardware is similar to the VAX, in that interrupts
      and exceptions are handled the same way.  However, the mechanism that is
      used is a bit simpler.

      1. Two special CPU registers are loaded when an interrupt or exception
         occurs:

         EPC = PC value at time interrupt/exception occurred
         Cause = code indicating what happened

      2. Control goes to a fixed address in memory, which must contain a
         routine that deciphers the Cause and takes the appropriate action

   B. In the case of an interrupt, the operating system transfers control to
      an interrupt handler that is part of the device driver for the specific
      device that interrupted, which takes it from there.

   C. In the case of an exception, Unix converts the exception to a signal 
      which is delivered to the process through the Unix signal mechanism
      (discussed in the Unix manual pages under the heading signal.)

      1. In Unix, signals can be sent from a variety of sources.

         a. An exception within the current program, as discussed here.

         b. User action at the keyboard - e.g. typing ^C to terminate the
            program, or ^Z to suspend execution.

         c. Another program using the kill system service to send a signal.

      2. The default action for a signal is one of the following - depending
         on the specific signal:

         a. Terminate the program.

         b. Terminate the program with a core dump (a copy of the current
            state of the memory and registers contained in a file called
            core, which can then be analyzed by a debugger to determine the
            cause of the error.)

         c. Stop the program - with the possibility of resumption later.

         d. Ignore the signal.

   D. The default handling of a signal can be overridden by using the signal
      system service.  This system service takes two parameters - an integer
      that identifies the signal, and the address of a function that is to
      be called when that signal occurs.  Thereafter, any occurrence of that
      particular signal will be "caught" by the handler.

      HANDOUT - Quadratic equation solver extended to handle overflow
                (setup code that calls signal).

   E. While both VMS and Unix allow the user to install an exception handler 
      routine that is called when an exception occurs, there are two key
      differences:

      1. In VMS, a handler is associated with a SPECIFIC CALL FRAME, and
         handles ANY exception that occurs in that procedure, or a procedure
         it calls.  In Unix, a handler is associated with a SPECIFIC EXCEPTION,
         and handles an occurrence of that exception in ANY PROCEDURE.

      2. A VMS handler is cancelled when the procedure that established it
         exits (since the handler address is popped off the stack along with
         the rest of its call frame.)  A Unix handler must be explicitly
         cancelled.

         TRANSPARENCY - Exit protocol that calls signal to re-establish
                        previous handler.

   F. Since once a procedure establishes a handler it becomes possible for
      that handler to be invoked by an exception in any procedure that it
      calls (directly or indirectly), there is sometimes a need to unwind
      the stack of pending procedure calls to get back to the procedure that
      actually established the handler.  (This is what SYS$UNWIND does on VMS).
      On Unix, this is handled by a longjmp.

         TRANSPARENCY - setjmp in entry protocol and longjmp in handler

IV. Deliberately Caused Exceptions
--  ------------ ------ ----------

   A. Though exceptions normally arise due to program errors detected by the
      hardware, there are some times when it is useful for the software
      to be able to create an exception.  

   B. In the case of the VAX, we consider three distinct instances of this.

      1. The run-time library LIB$SIGNAL can be used to signal a condition.  It
         takes a single parameter, which may be either a hardware detected
         exception code or a software specified code.  This facility is used
         extensively by system software to report errors detected by software
         checks.  (E.g. many symbolic stack dumps that you have seen are
         actually initiated this way.)

      2. The BPT instruction causes a breakpoint trap exception. This is used by
         the debugger to implement the SET BREAK command.

      3. Four machine instructions - CHMK, CHME, CHMS, and CHMU - exist to 
         change the privilege level of the CPU.  They each go to a special 
         exception handler in VMS.  Each takes a single parameter called a 
         request code.

         a. CHMK goes to the system service dispatcher.  The request code is
            taken as identifying a particular system service to be executed.
            Most system service procedures are realized by using CHMK to get 
            into kernel mode.

         b. CHME is used internally by system software.

         c. CHMS goes to the DCL command interpreter.  The request code is taken
            as identifying a DCL service that can be called from within a 
            program.

         d. CHMU generates an exception through the usual channels to the user
            program.

   C. Similar facilities are present on the MIPS.

      1. The kill system service can be used to send a signal to any process,
         including (but not limited to) the one that invokes it.

      2. The break instruction causes a SIGTRAP signal.  Debuggers normally
         arrange to catch this signal, since the break instruction is used
         to set breakpoints in a program.

      3. The sycall instruction causes an exception, which is recognized by
         the operating system's handler as indicating a desire to call a
         system service routine (as specified by values placed in registers
         before the syscall.)

Copyright ©1999 - Russell C. Bjork