ieee_handler(3M)
NAME
ieee_handler − IEEE exception trap handler function
SYNOPSIS
cc [ flag ... ] file ... −lsunmath -lm [ library ... ]
#include <sunmath.h>
long ieee_handler(const char ∗action, const char ∗exception, sigfpe_handler_type hdl);
DESCRIPTION
This function provides easy exception handling to exploit ANSI/IEEE Std 754-1985 arithmetic in a C program. The first two arguments are pointers to strings. For efficiency, results arising from invalid arguments and invalid combinations are undefined.
There are three types of action : “get”, “set”, and “clear”. There are five types of exception :
“inexact”
“division” ... division by zero exception
“underflow”
“overflow”
“invalid”
“all” ... all five exceptions above
“common” ... invalid, overflow, and division exceptions
Note: “all” and “common” only make sense with “set” or “clear”.
hdl contains the address of a signal-handling routine. <floatingpoint.h> defines sigfpe_handler_type .
“get” will return the location of the current handler routine for exception cast to a long.
“set” will set the routine pointed at by hdl to be the handler routine and at the same time enable the trap on exception, except when hdl == SIGFPE_DEFAULT or SIGFPE_IGNORE; then ieee_handler() will disable the trap on exception. When hdl == SIGFPE_ABORT, any trap on exception will dump core using abort(3).
“clear” disables trapping on exception and sets the handler routine for exception to SIGFPE_DEFAULT. “clear” “all” disables trapping on all five exceptions and sets the handler routine for all five exceptions to SIGFPE_DEFAULT.
Two steps are required to intercept an IEEE-related SIGFPE code with ieee_handler:
1) Set up a handler with ieee_handler.
2) Perform a floating-point operation that generates the intended IEEE exception.
ieee_handler() also adjusts floating-point hardware mode bits affecting IEEE trapping. For “clear”, “set” SIGFPE_DEFAULT, or “set” SIGFPE_IGNORE, the hardware trap is disabled. For any other “set”, the hardware trap is enabled.
SIGFPE signals can be handled using sigaction(2) ieee_handler(3M), or fex_set_handling(3M).
In a particular program, to avoid confusion, use only one of these interfaces to handle SIGFPE signals.
DIAGNOSTICS
ieee_handler() normally returns 0 for “set”; 1 will be returned if the action is not available (for instance, not supported in hardware). For “get”, the address of the current handler is returned, cast to a long.
EXAMPLE
Here we give an example of how to trap an invalid signal and change the default output (NaN) to a user given value if the exception is caused by zero/zero. Following is a user-specified signal handler (appropriate for SPARC systems only):
/∗
∗ Sample user exception handler routine. In this example, we trap on the
∗ invalid signal. Then we check if the exception is of zero/zero type. If
∗ yes, we set the result = zero_over_zero_value (user given).
∗/
#include <sunmath.h>
#include <siginfo.h>
#include <ucontext.h>
extern double zero_over_zero_value;
void zero_over_zero_handler(int sig, siginfo_t ∗sip, ucontext_t ∗uap) {
fpregset_t ∗uc = &uap->uc_mcontext.fpregs; /∗ see <sys/reg.h> for structure fpregset_t ∗/
const int fopshift = 5, frdshift = 25, frs1shift = 14, frs2shift = 0;
inti, j, fop, frd, frs1, frs2;
int ∗con = (int ∗) &zero_over_zero_value;
/∗
∗ find out registers rd, rs1, rs2, and opf
∗/
fop = ((uc->fpu_q->FQu.fpq.fpq_instr)>>fopshift) &0x1ff;
frd = ((uc->fpu_q->FQu.fpq.fpq_instr)>>frdshift) &0x1f;
frs1= ((uc->fpu_q->FQu.fpq.fpq_instr)>>frs1shift)&0x1f;
frs2= ((uc->fpu_q->FQu.fpq.fpq_instr)>>frs2shift )&0x1f;
/∗
∗ check if both rs1 and rs2 are zero (0/0 case)
∗/
i = (uc->fpu_fr.fpu_regs[frs2]&0x7fffffff)|uc->fpu_fr.fpu_regs[frs2+1];
j = (uc->fpu_fr.fpu_regs[frs1]&0x7fffffff)|uc->fpu_fr.fpu_regs[frs1+1];
switch (fop) {
case 0x4e:/∗ fdivd ∗/
if((i|j) == 0) {/∗ 0/0 , set rd to be zero_over_zero_value ∗/
uc->fpu_fr.fpu_regs[frd] = con[0];
uc->fpu_fr.fpu_regs[frd+1] = con[1];
}
break;
}
}
and it might be set up like this:
#include <stdio.h>
#include <stdlib.h>
#include <sunmath.h>
#include <siginfo.h>
#include <ucontext.h>
extern void zero_over_zero_handler(int, siginfo_t ∗, ucontext_t ∗);
double zero_over_zero_value;
void
main(void) {
extern double sin(double);
double x, w;
int i, k;
sigfpe_handler_type hdl, old_handler1;
/∗
∗ save current invalid handler
∗/
old_handler1 = (sigfpe_handler_type) ieee_handler("get", "invalid", (sigfpe_handler_type)0);
/∗
∗ set up new invalid handler
∗/
hdl = (sigfpe_handler_type) zero_over_zero_handler;
(void) ieee_handler("set", "invalid", hdl);
/∗
∗ compute (k∗x)/sin(x) for k=2, x=0.5, 0.4, ..., 0.1, 0.0
∗/
k = 2.0;/∗ user specified ∗/
(void) printf("Evaluating f(x) = (k∗x)/sin(x)\n\n");
zero_over_zero_value = k;
for (i = 5; i >= 0; i--) {
x = (double) i ∗ 0.1;
w = (k ∗ x) / sin(x);
(void) printf("\tx=%3.3f\t f(x) = % 1.20e\n", x, w);
}
/∗
∗ restore old invalid handler
∗/
(void) ieee_handler("set", "invalid", old_handler1);
exit(0);
/∗ NOTREACHED ∗/
}
Here is what the output looks like:
Evaluating f(x) = (k∗x)/sin(x)
x=0.500 f(x) = 2.08582964293348816000e+00
x=0.400 f(x) = 2.05434596443822626000e+00
x=0.300 f(x) = 2.03031801709447368000e+00
x=0.200 f(x) = 2.01339581906893761000e+00
x=0.100 f(x) = 2.00333722632695554000e+00
x=0.000 f(x) = 2.00000000000000000000e+00
Note that when x=0, f(x) = 0/0 and an invalid exception occurs. The value of 0/0 is set to be 2.0 in this example.
ATTRIBUTES
See attributes(5) for descriptions of the following attributes:
| ATTRIBUTE TYPE | ATTRIBUTE VALUE |
| Availability | SPROlang |
| Interface Stability | Evolving |
| MT-Level | MT-Safe |
SEE ALSO
sigaction(2), signal(2), sigfpe(3), abort(3C), fex_set_handling(3M), ieee_flags(3M), attributes(5), siginfo(5), signal(5), ucontext(5)
NOTES
On Intel systems, the floating point hardware traps whenever an exception’s trap is enabled (i.e., the exception is "unmasked") and its corresponding flag is raised. Thus, enabling a trap for an exception via ieee_handler() will provoke a subsequent trap if the exception’s flag is already raised when ieee_handler() is called. To avoid such spurious traps, a program should clear the flags corresponding to each exception for which trapping will be enabled before calling ieee_handler(). (The ieee_flags(3M) function provides one way to clear exception flags.)
SunOS 5.0 — Last change: 09/02/97