  | 
		
OpenVMS Programming Concepts Manual
 
 
9.8.4 Alpha Mechanism Argument Vector (Alpha Only)
On Alpha systems, the mechanism array returns much the same data as it
does on VAX systems, though its format is changed. The mechanism array
returned on Alpha systems preserves the contents of a larger set of
integer scratch registers as well as the Alpha floating-point scratch
registers. In addition, because Alpha registers are 64 bits long, the
mechanism array is constructed of quadwords (64 bits), not longwords
(32 bits) as it is on VAX systems. Figure 9-10 shows the format of
the mechanism array on Alpha systems.
 
Figure 9-10 Mechanism Array on Alpha Systems
  
 
Table 9-11 describes the arguments in the mechanism array.  
 
  Table 9-11 Fields in the Alpha Mechanism Array
  
    | Argument  | 
    Description  | 
   
  
    | 
      CHF$IS_MCH_ARGS
     | 
    
       Represents the number of quadwords in the mechanism array, not counting
       the argument count quadword. (The value contained in this argument is
       always 43.)
     | 
   
  
    | 
      CHF$IS_MCH_FLAGS
     | 
    
      Flag bits <63:0> for related argument mechanism information
      defined as follows for CHF$V_FPREGS:
        Bit <0>: When set, the process has already performed a
      floating-point operation and the floating-point registers stored in
      this structure are valid.
        If this bit is clear, the process has not yet performed any
      floating-point operations, and the values in the floating-point
      register slots in this structure are unpredictable.
      | 
   
  
    | 
      CHF$PH_MCH_FRAME
     | 
    
      The frame pointer (FP) in the procedure context of the establisher.
     | 
   
  
    | 
      CHF$IS_MCH_DEPTH
     | 
    
      Positive count of the number of procedure activation stack frames
      between the frame in which the exception occurred and the frame depth
      that established the handler being called.
     | 
   
  
    | 
      CHF$PS_MCH_DADDR
     | 
    
      Address of the handler data quadword if the exception handler data
      field is present (as indicated by PDSC.FLAGS.HANDLER_DATA_VALID);
      otherwise, contains zero.
     | 
   
  
    | 
      CHF$PH_MCH_ESF_ADDR
     | 
    
      Address of the exception stack frame (see the Alpha Architecture Reference Manual).
     | 
   
  
    | 
      CHF$PH_MCH_SIG_ADDR
     | 
    
      Address of the signal array. The signal array is a 32-bit (longword)
      array.
     | 
   
  
    | 
      CHF$IH_MCH_SAVR
      nn
     | 
    
      A copy of the saved integer registers at the time of the exception. The
      following registers are saved: R0, R1, and R16--R28. Registers R2--R15
      are implicitly saved in the call chain.
     | 
   
  
    | 
      CHF$FM_MCH_SAVF
      nn
     | 
    
      A copy of the saved floating-point registers at the time of the
      exception or may have unpredictable data as described in
      CHF$IS_MCH_FLAGS. If the floating-point register fields are valid, the
      following registers are saved: F0, F1, and F10--F30. Registers F2--F9
      are implicitly saved in the call chain.
     | 
   
 
For more information and recommendations about using the mechanism
argument vector on Alpha systems, see Migrating to an OpenVMS AXP System:  Recompiling and Relinking Applications. Note that this
manual has been archived but is available on the OpenVMS Documentation
CD-ROM.
9.8.5 Multiple Active Signals
 
A signal is said to be active until the routine that signaled regains
control or until the stack is unwound or the image exits. A second
signal can occur while a condition handler or a routine it has called
is executing. This situation is called multiple active
signals or multiple exception conditions.
When this situation occurs, the stack scan is not performed in the
usual way. Instead, the frames that were searched while processing all
of the previous exception conditions are skipped when the current
exception condition is processed. This is done in order to avoid
recursively reentering a routine that is not reentrant. For example,
Fortran code typically is not recursively reentrant. If a Fortran
handler were called while another activation of that handler was still
going, the results would be unpredictable.
 
A second exception may occur while a condition handler or a procedure
that it has called is still executing. In this case, when the exception
dispatcher searches for a condition handler, it skips the frames that
were searched to locate the first handler.
 
The search for a second handler terminates in the same manner as the
initial search, as described in Section 9.6.
 
If the SYS$UNWIND system service is issued by the second active
condition handler, the depth of the unwind is determined according to
the same rules followed in the exception dispatcher's search of the
stack: all frames that were searched for the first condition handler
are skipped.
 
Primary and secondary vectored handlers, on the other hand, are always
entered when an exception occurs.
 
If an exception occurs during the execution of a handler that was
established in the primary or secondary exception vector, that handler
must handle the additional condition. Failure to do so correctly might
result in a recursive exception loop in which the vectored handler is
repeatedly called until the user stack is exhausted.
 
The modified search routine is best illustrated with an example. Assume
the following calling sequence:
 
  - Routine A calls routine B, which calls routine C.
  
 - Routine C signals an exception condition (signal S), and the
  handler for routine C (CH) resignals.
  
 - Control passes to BH, the handler for routine B. The call frame for
  handler BH is located on top of the signal and mechanism arrays for
  signal S. The saved frame pointer in the call frame for BH points to
  the frame for routine C.
  
 - BH calls routine X; routine X calls routine Y.
  
 - Routine Y signals a second exception condition (signal T).
  Figure 9-11 illustrates the stack contents after the second exception
  condition is signaled.
Figure 9-11 Stack After Second Exception Condition Is
Signaled
  
 
     Normally, the OpenVMS Condition Handling facility (CHF) searches
    all currently active frames for condition handlers, including B and C.
    If this happens, however, BH is called again. At this point, you skip
    the condition handlers that have already been called. Thus, the search
    for condition handlers should proceed in the following order:
  
    YH
     XH
     BHH (the handler for routine B's handler)
     AH
   
   - The search now continues in its usual fashion. The CHF examines the
  primary and secondary exception vectors, then frames Y, X, and BH.
  Thus, handlers YH, XH, and BHH are called. Assume that these handlers
  resignal.
  
 - The CHF now skips the frames that have already been searched and
  resumes the search for condition handlers in routine A's frame. The
  depths that are passed to handlers as a result of this modified search
  are 0 for YH, 1 for XH, 2 for BHH, and 3 for AH.
  
Because of the possibility of multiple active signals, you should be
careful if you use an exception vector to establish a condition
handler. Vectored handlers are called, not skipped, each time an
exception occurs.
9.9 Types of Condition Handlers
 
On VAX systems, when a routine is activated, the first longword in its
stack frame is set to 0. This longword is reserved to contain an
address pointing to another routine called the condition handler. If an
exception condition is signaled during the execution of the routine,
the OpenVMS Condition Handling Facility uses the address in the first
longword of the frame to call the associated condition handler.
 
On Alpha systems, each procedure, other than a null frame procedure,
can have a condition handler potentially associated with it, identified
by the HANDLER_VALID, STACK_HANDLER, or REG_HANDLER field of the
associated procedure descriptor. You establish a handler by including
the procedure value of the handler procedure in that field.
 
The arguments passed to the condition-handling routine are the signal
and mechanism argument vectors, described in Section 9.8.2,
Section 9.8.3, and Section 9.8.4.
 
Various types of condition handlers can be called for a given routine:
 
  - User-supplied condition handlers 
 You can write your own
  condition handler and set up its address in the stack frame of your
  routine using the run-time library routine LIB$ESTABLISH or the
  mechanism supplied by your language.  On Alpha systems,
  LIB$ESTABLISH is not supported, though high-level languages may support
  it for compatibility.
   - Language-supplied condition handlers
    
 Many high-level languages provide a means for setting up handlers
    that are global to a single routine. If your language provides a
    condition-handling mechanism, you should always use it. If you also try
    to establish a condition handler using LIB$ESTABLISH, the two methods
    of handling exception conditions conflict, and the results are
    unpredictable.
   - System default condition handlers 
 The operating system provides
  a set of default condition handlers. These take over if there are no
  other condition handler addresses on the stack, or if all the previous
  condition handlers have passed on (resignaled) the indication of the
  exception condition.
  
9.9.1 Default Condition Handlers
The operating system establishes the following default condition
handlers each time a new image is started. The default handlers are
shown in the order they are encountered when the operating system
processes a signal. These three handlers are the only handlers that
output error messages.
 
  - Traceback handler 
 The traceback handler is established on the
  stack after the catchall handler. This enables the traceback handler to
  get control first. This handler performs three functions in the
  following order:
  
    - Outputs an error message using the Put Message (SYS$PUTMSG) system
    service. SYS$PUTMSG formats the message using the Formatted ASCII
    Output (SYS$FAO) system service and sends the message to the devices
    identified by the logical names SYS$ERROR and SYS$OUTPUT (if it differs
    from SYS$ERROR). That is, it displays the message associated with the
    signaled condition code, the traceback message, the program unit name
    and line number of the statement that signaled the condition code, and
    the relative and absolute program counter values. (On a warning or
    error, the number of the next statement to be executed is displayed.)
    
 - Issues a symbolic traceback, which shows the state of the routine
    stack at the time of the exception condition. That is, it displays the
    names of the program units in the calling hierarchy and the line
    numbers of the invocation statements.
      - Decides whether to continue executing the image or to force an exit
    based on the severity field of the condition value:
  
    | Severity  | 
    Error Type  | 
    Action  | 
   
  
    | 
      1
     | 
    
      Success
     | 
    
      Continue
     | 
   
  
    | 
      3
     | 
    
      Information
     | 
    
      Continue
     | 
   
  
    | 
      0
     | 
    
      Warning
     | 
    
      Continue
     | 
   
  
    | 
      2
     | 
    
      Error
     | 
    
      Continue
     | 
   
  
    | 
      4
     | 
    
      Severe
     | 
    
      Exit
     | 
   
 
       The traceback handler is in effect if you link your program with
      the /TRACEBACK qualifier of the LINK command (the default). Once you
      have completed program development, you generally link your program
      with the /NOTRACEBACK qualifier and use the catchall handler.
    
   - Catchall handler 
 The operating system establishes the catchall
  handler in the first stack frame and thus calls it last. This handler
  performs the same functions as the traceback handler except for the
  stack traceback. That is, it issues an error message and decides
  whether to continue execution. The catchall is called only if you link
  with the /NOTRACEBACK qualifier. It displays the message associated
  with the condition code and then continues program execution or, if the
  error is severe, terminates execution.
   - Last-chance handler 
 The operating system establishes the
  last-chance handler with a system exception vector. In most cases, this
  vector contains the address of the catchall handler, so that these two
  handlers are actually the same. The last-chance handler is called only
  if the stack is invalid or all the handlers on the stack have
  resignaled. If the debugger is present, the debugger's own last-chance
  handler replaces the system last-chance handler.
  
Displays the message associated with the condition code and then
continues program execution or, if the error is severe, terminates
execution. The catchall handler is not invoked if the traceback handler
is enabled.
 
In the following example, if the condition code INCOME_LINELOST is
signaled at line 496 of GET_STATS, regardless of which default handler
is in effect, the following message is displayed:
 
 
  
    
       
      
%INCOME-W-LINELOST, Statistics on last line lost due to CTRL/Z
 
 |   
If the traceback handler is in effect, the following text is also
displayed:
 
 
  
    
       
      
%TRACE-W-TRACEBACK, symbolic stack dump follows
module name     routine name       line      rel PC    abs PC
GET_STATS       GET_STATS           497     00000306  00008DA2
INCOME          INCOME              148     0000015A  0000875A
                                            0000A5BC  0000A5BC
                                            00009BDB  00009BDB
                                            0000A599  0000A599
 |   
Because INCOME_LINELOST is a warning, the line number of the next
statement to be executed (497), rather than the line number of the
statement that signaled the condition code, is displayed. Line 148 of
the program unit INCOME invoked GET_STATS.
9.9.2 Interaction Between Default and User-Supplied Handlers  
 
Several results are possible after a routine signals, depending on a
number of factors, such as the severity of the error, the method of
generating the signal, and the action of the condition handlers you
have defined and the default handlers. Given the severity of the
condition and the method of signaling, Figure 9-12 lists all
combinations of interaction between user condition handlers and default
condition handlers.
 
Figure 9-12 Interaction Between Handlers and Default
Handlers
  
 
9.10 Types of Actions Performed by Condition Handlers  
When a condition handler returns control to the OpenVMS Condition
Handling facility (CHF), the facility takes one of the following types
of actions, depending on the value returned by the condition handler:
 
  - Signal a condition 
 
Signaling a condition initiates the search for an established condition
handler.
   - Continue
    
 The condition handler may or may not be able to fix the problem,
    but the program can attempt to continue execution. The handler places
    the return status value SS$_CONTINUE in R0 and issues a RET instruction
    to return control to the dispatcher. If the exception was a fault, the
    instruction that caused it is reexecuted; if the exception was a trap,
    control is returned at the instruction following the one that caused
    it. A condition handler cannot continue if the exception condition was
    signaled by calling LIB$STOP.
      Section 9.12.1 contains more information about continuing.
   - Resignal 
 The handler cannot fix the problem, or this condition
  is one that it does not handle. It places the return status value
  SS$_RESIGNAL in R0 and issues a RET instruction to return control to
  the exception dispatcher. The dispatcher resumes its search for a
  condition handler. If it finds another condition handler, it passes
  control to that routine. A handler can alter the severity of the signal
  before resignaling.   Section 9.12.2 contains more information about
  resignaling.
   - Unwind 
 The condition handler cannot fix the problem, and
  execution cannot continue while using the current flow. The handler
  issues the Unwind Call Stack (SYS$UNWIND) system service to unwind the
  call stack. Call frames can then be removed from the stack and the flow
  of execution modified, depending on the arguments to the SYS$UNWIND
  service.  When a condition handler has already called SYS$UNWIND,
  any return status from the condition handler is ignored by the CHF. The
  CHF now unwinds the stack.  Unwinding the routine call stack first
  removes call frames, starting with the frame in which the condition
  occurred, and then returns control to an earlier routine in the calling
  sequence. You can unwind the stack whether the condition was detected
  by hardware or signaled using LIB$SIGNAL or LIB$STOP. Unwinding is the
  only way to continue execution after a call to LIB$STOP.
    Section 9.12.3 describes how to write a condition handler that
  unwinds the call stack.
   - Perform a nonlocal GOTO unwind 
 On Alpha systems, a GOTO unwind
  operation is a transfer of control that leaves one procedure invocation
  and continues execution in a prior (currently active) procedure. This
  unified GOTO operation gives unterminated procedure invocations the
  opportunity to clean up in an orderly way. See Section 9.10.2 for more
  information about GOTO unwind operations.
  
9.10.1 Unwinding the Call Stack
One type of action a condition handler can take is to unwind the
procedure call stack. The unwind operation is complex and should be
used only when control must be restored to an earlier procedure in the
calling sequence. Moreover, use of the SYS$UNWIND system service
requires the calling condition handler to be aware of the calling
sequence and of the exact point to which control is to return.
 
SYS$UNWIND accepts two optional arguments:
 
  - The depth to which the unwind is to occur. If the depth is 1, the
  call stack is unwound to the caller of the procedure that incurred the
  exception. If the depth is 2, the call stack is unwound to the caller's
  caller, and so on. By specifying the depth in the mechanism array, the
  handler can unwind to the procedure that established the handler.
  
 - The address of a location to receive control when the unwind
  operation is complete, that is, a PC to replace the current PC in the
  call frame of the procedure that will receive control when all
  specified frames have been removed from the stack.
  
If no argument is supplied to SYS$UNWIND, the unwind is performed to
the caller of the procedure that established the condition handler that
is issuing the SYS$UNWIND service. Control is returned to the address
specified in the return PC for that procedure. Note that this is the
default and the normal case for unwinding.
 
Another common case of unwinding is to unwind to the procedure that
declared the handler. On VAX systems, this is done by using the depth
value from the exception mechanism array (CHF$L_MCH_DEPTH) as the depth
argument to SYS$UNWIND. On Alpha systems, this is done by using the
depth value from the exception mechanism array (CHF$IS_MCH_DEPTH) as
the depth argument to SYS$UNWIND.
 
Therefore, it follows that the default unwind (no depth specified) is
equivalent to specifying CHF$L_MCH_DEPTH plus 1 on VAX systems. On
Alpha systems, the default unwind (no depth specified) is equivalent to
specifying CHF$IS_MCH_DEPTH plus 1. In certain instances of nested
exceptions, however, this is not the case. Compaq recommends that you
omit the depth argument when unwinding to the caller of the routine
that established the condition handler.
 
Figure 9-13 illustrates an unwind situation and describes some of the
possible results.
 
The unwind operation consists of two parts:
 
  - In the call to SYS$UNWIND, the return PCs saved in the stack are
  modified to point into a routine within the SYS$UNWIND service, but the
  entire stack remains present.
  
 - When the handler returns, control is directed to this routine by
  the modified PCs. It proceeds to return to itself, removing the
  modified stack frames, until the stack has been unwound to the proper
  depth.
  
For this reason, the stack is in an intermediate state directly after
calling SYS$UNWIND. Handlers should, in general, return immediately
after calling SYS$UNWIND.
 
During the actual unwinding of the call stack, the unwind routine
examines each frame in the call stack to see whether a condition
handler has been declared. If a handler has been declared, the unwind
routine calls the handler with the status value SS$_UNWIND (indicating
that the call stack is being unwound) in the condition name argument of
the signal array. When a condition handler is called with this status
value, it can perform any procedure-specific cleanup operations
required. For example, the handler should deallocate any processwide
resources that have been allocated. Then, the handler returns control
to the OpenVMS Condition Handling facility. After the handler returns,
the call frame is removed from the stack.
 
When a condition handler is called during the unwinding operation, the
condition handler must not generate a new signal. A new signal would
result in unpredictable behavior.
 
Thus, in Figure 9-13, handler B can be called a second time, during
the unwind operation. Note that handler B does not have to be able to
interpret the SS$_UNWIND status value specifically; the RET instruction
merely returns control to the unwind procedure, which does not check
any status values.
 
Handlers established by the primary, secondary, or last-chance vector
are not called, because they are not removed during an unwind operation.
 
While it is unwinding the stack, the OpenVMS Condition Handling
facility ignores any function value returned by a condition handler.
For this reason, a handler cannot both resignal and unwind. Thus, the
only way for a handler to both issue a message and perform an unwind is
to call LIB$SIGNAL and then call $UNWIND. If your program calls $UNWIND
before calling LIB$SIGNAL, the result is unpredictable.
 
When the OpenVMS Condition Handling facility calls the condition
handler that was established for each frame during unwind, the call is
of the standard form, described in Section 9.2. The arguments passed
to the condition handler (the signal and mechanism argument vectors)
are shown in Section 9.8.2, Section 9.8.3, and Section 9.8.4.
 
On VAX systems, if the handler is to specify the function value of the
last function to be unwound, it should modify the saved copies of R0
and R1 (CHF$L_MCH_SAVR0 and CHF$L_MCH_SAVR1) in the mechanism argument
vector.
 
On Alpha systems, the handler should modify the saved copies of R0 and
R1 (CHF$IH_MCH_SAVRnn).
 
R0 and R1 are restored from the mechanism argument vector at the end of
the unwind.
 
Figure 9-13 Unwinding the Call Stack
  
 
 
  
  
		 |