siggenfunction. This type of user signal requires no special coding, only the use of these two functions. The default action for a user signal raised in this manner is always to ignore the signal. Refer to the descriptions of the
siggenfunctions for more information.
If, however, you want to raise a signal as a result of a software interrupt (such as an end-of-subtask notification) or a hardware interrupt (such as an I/O interrupt), you can do so by coding two or more routines to intercept these interrupts and make them known to the library. The first of the required routines, called the initialization routine, defines the signal to the library. The other required routine, called the signal-generating routine, is an operating system exit that is invoked to raise the signal for the library when the interrupt occurs. Both of these routines are normally written in assembler language. Most of the other routines that define how to handle the signal can be written in either C or assembler language. Routines for Adding Signals indicates the recommended language for each routine and describes how to write the routines that add user signals to the library.
Note: This book assumes that you are adding a signal that communicates to your C program when a software or hardware interrupt occurs. You may have other uses for this facility that are not explicitly discussed in this book.
Some familiarity with MVS or CMS interrupt handling facilities is assumed. Also, thorough familiarity with SAS/C signal functions and signal-handling techniques is assumed. Refer to Chapter 5, "Signal-Handling Functions," in SAS/C Library Reference, Volume 1 for more information.
sigsuspend, can be used in your program to control handling of the new signals. In some cases, you may want to define the new signal so that it does not permit the use of
returnin a handler. Refer to Executive Routine for more information.
Synchronous signals must be assigned one of the signal numbers defined by the symbols SIGUSR1 through SIGUSR8. Asynchronous signals must be assigned one of the signal numbers defined by the symbols SIGASY1 through SIGASY8. When you write the routine to define the signal, you can rename it to have a more useful and mnemonic name.
There are no special requirements for defining asynchronous signals.
Additional considerations may apply, however, when defining
asynchronous signals for programs that use
sleep; refer to the description of the ECBPP field of ZENQARGS in
Routine for Asynchronous Signals: L$CZENQ .
The following list describes the requirements for defining a signal as synchronous.
longjmp, the program must be able to resume execution at some point other than the point of interrupt. (It is possible, though not recommended, to use the executive routine, described later in this chapter, to prevent using
longjmpsuccessfully by the handler.)
Assembler routines called by the SAS/C Library rather than by the operating
system can use the
CEXIT macros for function linkage. (Refer to
Chapter 11, "Communication with Assembler Programs," in SAS/C Compiler and Library User's Guide, Fourth Edition , for
information on the
Assembler routines that call C
functions must use the
CEXIT macros to run successfully when
either the optimized or minimal form of function linkage is in use. Refer
to Chapter 9 of SAS/C Compiler and Library User's Guide, Fourth Edition for more information on the
Note: A routine that calls operating system macros is usually written in assembler language.
Table 12.1 Routines for Adding Signals
Routine Required?/ Recommended Description Frequency of Language* use?
initialization yes/always assembler calls sigdef to define the routine new signal and identify which of the following routines are coded. signal yes/always assembler intercepts the hardware or software interrupt and informs the library that the signal occurred. The routine is usually an operating system exit. default no/common C establishes default actions that occur when no handler is defined for the new signal. interrupt no/ seldom assembler communicates to the operating system when a signal is ignored, blocked, or handled in the default manner. final routine no/ very assembler cancels signal handling at common the end of the program. The routine is invoked after all files are closed. executive no/seldom C supervises linkage to routine handlers. For example, the routine can prevent use of longjmp or normal returns. jump no/rare assembler notifies the operating intercept system that the interrupt routine has been handled; that is, it clears the interrupt.
*Note that all of these routines except the jump intercept routine can be coded in either C
This table simply indicates which language is preferred.
sigdeffunction to define the signal. The initialization routine also calls an operating system macro to establish the address of the operating system exit that should be invoked when the signal occurs. For example, to define a CMS I/O interrupt signal called
SIGIOI, the initialization routine may issue calls similar to the ones here. The call to
sigdefin assembler might look like the following:
LA R1,DEFPARMS L R15,=V(SIGDEF) BALR R14,R15 sigdef(SIGASY1,0,0,0,0,"IOI"); DEFPARMS DC A(SIGASY1) symbol definition obtained by * "COPY SIGNALS" DC 4A(0) DC A(SIGNAME) SIGNAME DC C'IOI',X'00'The call to
sigdefrenames SIGASY1 to SIGIOI but does not define any special routines for processing the signal (indicated by the 0s for the second DC in the DEFPARMS area).
A sample call to the CMS HNDINT macro to handle the interrupt might look like the following:
HNDINT SET,(TAP1,EXIT,unit,ASAP)The call to HNDINT identifies the I/O unit number that causes the interrupt (
unit) and the address of the operating system exit routine (
EXIT) that you code to generate the signal for the library.
You can also use the initialization routine to save the C Run-Time Anchor Block (CRAB) address so that it can be accessed by the signal generator routine. (One way to do this is to request that the operating system provide the address as a user parameter to an exit routine.) Saving the address of the CRAB is frequently necessary because register 12 is dedicated to the CRAB address only during C program execution; it is usually not preserved by the operating system when an exit routine is called.
It is possible to raise, handle, or block a user signal before it has been
defined by a call to
sigdef is called, it has no
effect on the signal's status; that is, the signal remains blocked or
unblocked, and any user handler remains in effect. However, if the call to
sigdef defines a default handler, this default replaces the previous
#include <lcsignal.h> int sigdef(int signum, void (*dfl)(int), int (*intcntl)(int, int, int, int), void (*executive)(int, char **, _HANDLER), void (*final)(int, char *name));
signumargument is the signal number. Specify the signal number as one of the codes, SIGUSR1 through SIGUSR8 or SIGASY1 through SIGASY8. Only one definition of each signal number is allowed.
In an OpenEdition MVS application,
be treated as OpenEdition signals rather than as SAS/C signals,
depending on the use of the
oesigsetup function and the way the
program is run. Attempting to define a signal controlled by OpenEdition
MVS will cause
sigdef to fail. Note that if
has not been called when
sigdef is invoked, a default call to
oesigsetup will be generated, as described in the
name argument enables you to rename the signal.
is the address of a null-terminated string with a maximum of five
characters. The library appends these five characters to the
prefix to create the new name. For example, if the
EXT, the signal name appears in messages and traces as
arguments indicate the addresses of functions that provide special
processing for the signal. Each of these routines is described in
detail later in this appendix. Coding a 0 for any of these arguments
indicates that no function is supplied for that type of processing.
If you specify 0 for the
dfl argument, the signal is ignored
when default handling is in effect.
sigdefreturns 0 if it completes successfully or nonzero if it cannot complete. Specifying an invalid signal number or one that has already been defined is the most common reason for failure.
The signal generator routine raises the signal so that the library can detect it by calling the L$CZSYN routine (for synchronous signals) or the L$CZENQ routine (for asynchronous signals). These routines expect calls from assembler code and fully support them. The restrictions described in Restrictions on Synchronous and Asynchronous Signals apply when you can issue calls to L$CZSYN. There are no restrictions on when you can call L$CZENQ. These routines are described in more detail in SAS/C Library Routines for Adding New Signals .
The signal generator routine can build information that is passed to you
when the user-defined handler calls
siginfo. Refer to the SIGINFO
field description in Routine for Synchronous Signals: L$CZSYN for more information.
sigdef. If you do not define this routine, the default action is to ignore the signal. If you prefer to have the program ABEND by default, code this routine to call the
Refer to the
function to specify a particular
sigdef. This routine is called on the following occasions:
sigprocmaskchanges the mask for the signal.
sigactionrequests default or ignore handling, or replaces default or ignore handling with a user-defined handler. If the call to
signalmerely replaces one user-defined handler function with another, the interrupt control routine may not be called.
signalwith a second argument of
SIG_IGN, the interrupt control function can cause the operating system to ignore the signal when it occurs instead of calling an operating system exit. This saves the processing time required to transfer control to the default handler and produces the same results.
The linkage to the interrupt control routine is defined as follows:
int intcntl(int signum, int ignore, int default, int block, int context, struct sigaction *action)The
signumargument to the interrupt control routine specifies the signal number. The
defaultarguments indicate how your program handles the signal. If
ignoreis 0, the program has either defined a signal handler or default handling is in effect. If
ignoreis not 0, the signal is ignored. If
defaultis 0, the program has either defined a signal handler or the signal is to be ignored. If
defaultis not 0, default handling is in effect. (Both
defaultare nonzero if default handling is in effect and the default action is to ignore the signal.) The
blockargument is nonzero if the signal is blocked or 0 if the signal is not blocked.
argument is an integer indicating the reason that the
interrupt control routine was called. The possible values are
SC_COPROCSWT. (These are
symbolic values defined in
call as the result of a user call to
SC_PROCMASK indicates a call as the result of a user call to
SC_DEF indicates a call
as the result of the call to
a call as the result of a coprocess switch.
action argument is meaningful only for calls with context
In these cases,
action is a pointer to information
about the current handling as defined by
field of the action should be ignored, as it may be different from
the current handler. However, the
sa_flags fields are
guaranteed to be correct. In particular, this functionality allows
the interrupt control routine to take special action based on the
SA_USRFLAG n flags settings.
The interrupt control routine should return a negative number to
indicate an error. If a negative number
is returned, the call to
that caused the
interrupt control routine to be called returns
A return code of 1,
when the context
SC_BLOCK, indicates that the interrupt control routine
action for changes to blocking status. This enables the performance
of signal processing to be improved by avoid calls to the interrupt
control routine during
Any other positive return code (or a 1 returned when the context is
SC_PROCMASK) is treated as a success.
Note: An interrupt control routine is rarely required for correct operation of signal code; this routine simply provides improved performance for signals that can be ignored or blocked by the operating system. There may be times, however, when the interrupt control routine actually increases overhead. For example, signals are blocked while I/O is performed, so the interrupt control routine is called several times for each I/O operation.
siggen; thus, the executive routine is entered only when a signal occurs naturally.
The executive routine is usually coded in C. If you code this routine in
assembler language, use the
CEXIT macros to avoid problems calling
the user-defined handler. The initialization routine specifies the address
of this routine as the fourth argument in the call to
linkage to the executive routine is defined as follows:
void executive(int signum, char **infop, void (*handler)(int))The
signumargument is the number of the defined signal. The
infoppointer addresses the pointer that the signal handler in the program can access by a call to
siginfo. The executive routine may modify the information addressed by this pointer. The
handlerargument addresses the user-defined handler or contains 0 if the signal is to be ignored. This address can be used to call the user-defined handler from the executive routine.
The executive routine can be used to monitor or prevent certain handler
activity. For instance, you can use
blkjmp to prevent successful
longjmp by the handler, or you can refuse to allow normal
return from the handler by calling
abort if the handler returns. It
is assumed that the executive routine will call the handler using the normal
handler linkage, but this cannot be enforced.
The final routine is usually coded in assembler language. The initialization
routine specifies the address of this routine as the fifth argument in the
sigdef. The linkage to the final routine is defined as follows:
void final(int signum)The
signumargument is the number of the signal whose handling will be terminated.
The final routine is called after all files have been closed by the library. Therefore, this routine is not permitted to use I/O.
longjmp. This routine must be coded in assembler language. The jump intercept routine can inform the operating system that handling of the interrupt is complete but that control should not return to the point of interrupt. This is sometimes called clearing the interrupt. The jump intercept routine may need to be called before performing the
longjmproutine prevents return to the signal generation routine from the handler and, therefore, also prevents normal return to the operating system.
The jump intercept routine is rarely coded because it is frequently
impossible to correctly clear the interrupt. If you expect a user-defined
handler to call
longjmp, you can disallow
longjmp or define
the signal as asynchronous. The jump intercept routine should not attempt to
longjmp. If you want to disallow jumps, use the executive
routine to block them.
The jump intercept routine is not included as an argument in the call to
sigdef. To indicate that you want to provide this routine, set the
JUMPINT field of the
ZSYNARGS DSECT to the address of the jump
intercept routine. The jump intercept routine is called using standard MVS
linkage. Register 1 addresses the save area where registers have been saved (except
for register 14 and register 15, which are not available).
ZSYNARGS DSECT SIGNUM DS F signal number SIGINFO DS A address of associated information ABCODE DS A pointer to associated ABEND code (null-terminated), if any SIGNAME DS A pointer to five-character signal name SIGLOC DS A pointer to the interrupted instruction JUMPINT DS A address of a jump intercept routine, if neededYou must provide all of the information for these fields. The fields are described as follows:
siginfofunction. Refer to Chapter 5, "Signal-Handling Functions," in SAS/C Library Reference, Volume 1 for more information on
The signal-generating routine builds this information and stores the address in this field. Then the address is passed to the executive routine for the signal, if any. The executive routine may want to modify or make a copy of this information. For example, you might pass L$CZSYN the address of a system control block. The executive routine can make a copy of it to pass to the user-defined handler. This stops the user from attempting to modify the control block.
'U'if it is a user ABEND rather than a system ABEND. For example, if you define a signal associated with exceeding a CPU-time quota, you probably would define ABCODE as
"322"because that is the ABEND code normally produced by this condition.
sigdef. These five characters are appended to
SIGto form a new name that replaces the standard name,
SIGUSR1 - 8.
wherecommand is used. If you cannot provide this information, set this field to
longjmp, in which case no return occurs. If L$CZSYN returns a 4, the signal cannot be processed because one or more of the restrictions on the timing of synchronous signals is violated. Refer to Restrictions on Synchronous and Asynchronous Signals for more information. If L$CZSYN returns a 0, the signal is accepted, and a user-defined signal handler is called and returned. In either case, the signal generation routine should return to the operating system.
The address of L$CZENQ is located at offset X'1F4' (decimal 500) from the start of the CRAB. Linkage to L$CZENQ should be effected using this CRAB field, not a V-type address constant. Using a V-type constant works only if the calling routine is linked with the main load module of the application program.
The following shows the use of various registers by L$CZENQ:
1 addresses parameter list ZENQARGS 2 - 6 work registers; save contents before calling L$CZENQ 12 must address CRAB 13 ignored; no registers saved by L$CZENQ 14 contains return address 15 contains address of L$CZENQThe parameter list addressed by register 1 is described by the following DSECT:
ZENQARGS DSECT SIGNUM DS F signal number SIGINFO DS A address of associated information ABCODE DS A pointer to associated ABEND code (null-terminated), if any SIGNAME DS A pointer to five-character signal name SIGELEM DS A address of an interrupt element ECBPP DS A address of a word in which to store an ECB address
The first four fields have the same meaning as the corresponding fields in L$CZSYN. The SIGELEM and ECBPP fields should be used as follows:
sleepat the time of the call to L$CZENQ, the address of the Event Control Block (ECG) used by
sleepis stored in the word addressed by ECBPP. If ECBPP is 0, the ECB address is not stored; instead, the ECB is posted using SVC 2. Therefore, if you call L$CZENQ in a situation where SVC's cannot be issued (such as from an SRB routine or I/O appendage), you must provide an ECBPP value. Note that
sleepdo not complete until this ECB is posted. For this reason, in such cases you would normally call a branch entry to POST to awaken the C program.
Copyright (c) 1998 SAS Institute Inc. Cary, NC, USA. All rights reserved.