svn commit: r232275 - in head/sys: amd64/include i386/include pc98/include x86/include

David Schultz das at FreeBSD.ORG
Sat Apr 7 16:57:34 UTC 2012


On Fri, Mar 02, 2012, Tijl Coosemans wrote:
> Thanks, that was quite informative. C11 does say something about the
> FP env and signals now though:
> 
> ``When the processing of the abstract machine is interrupted by receipt
> of a signal, the values of objects that are neither lock-free atomic
> objects nor of type volatile sig_atomic_t are unspecified, as is the
> state of the floating-point environment. The value of any object
> modified by the handler that is neither a lock-free atomic object nor
> of type volatile sig_atomic_t becomes indeterminate when the handler
> exits, as does the state of the floating-point environment if it is
> modified by the handler and not restored to its original state.''
> 
> This means a signal handler must not rely on the state of the FP env.
> It may install its own FP env if needed (e.g. FE_DFL_ENV), but then it
> must restore the original before returning. This allows for the
> rounding mode to be silently modified for integer conversions for
> instance.
> 
> If longjmp is not supposed to change the FP env then, when called from
> a signal handler, either the signal handler must install a proper FP
> env before calling longjmp or a proper FP env must be installed after
> the target setjmp call. Otherwise the FP env is unspecified.

There are two reasonable ways to handle the floating point control
word.  FreeBSD treats it as a register, resetting it on signal
handler entry and restoring it on longjmp or signal handler
return.  Virtually every other OS (e.g., Linux, NetBSD, Solaris)
treats it as global state, leaving it up to the signal handler to
preserve it as needed.

Both approaches have their merits.  FreeBSD's approach provides
better semantics.  Library functions, round-to-integer on most
CPUs, and other things may temporarily change the rounding mode.
Most programmers don't think about that, but on Linux, if an async
signal were delivered at the wrong time and did a longjmp, the
rounding mode would be in an unexpected state.  Most programmers
don't think about that; even a program that never changes the
rounding mode explicitly could wind up in round-to-zero mode after
jumping out of a signal handler.

The main advantage of the alternative approach is that it avoids
the overhead of saving and restoring the floating point control
word.  Many programs don't even use floating point, and the
efficiency is important for programs that use longjmp frequently,
e.g., to implement exceptions.

Either way, note the importance of being consistent: If the FP env
gets clobbered automatically on entry to a signal handler, then
longjmp must restore what the application had before.  Personally,
I'm not opposed to changing both signal handlers and longjmp to
match what the rest of the world does, but this isn't just about
the mxcsr, as suggested previously.

By the way, this commit is a good example of how getting rid of
duplication can actually make things more confusing.  The code is
the same on both amd64 and i386 now, but it means different
things.  Furthermore, each platform has a different setjmp
implementation, so if someone has to change jmpbuf on one of them
in the future, they have to worry about breaking the other as
well.  This is illustrated by the fact that this very commit
silently changed the i386 ABI by increasing the size of struct
jmpbuf.


More information about the svn-src-head mailing list