Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ ieee_handler(3M) — Sun WorkShop 5.0

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

sigaction(2)

signal(2)

sigfpe(3)

abort(3C)

fex_set_handling(3M)

ieee_flags(3M)

attributes(5)

siginfo(5)

signal(5)

ucontext(5)

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

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026