Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Jan 2003 05:43:45 -0800
From:      Terry Lambert <tlambert2@mindspring.com>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        Kris Kennaway <kris@obsecurity.org>, sparc@FreeBSD.ORG, current@FreeBSD.ORG
Subject:   Re: fpsetmask on sparc64
Message-ID:  <3E217111.B3C4C512@mindspring.com>
References:  <20030112194827.S6039-100000@gamplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Bruce Evans wrote:
> On Sun, 12 Jan 2003, Terry Lambert wrote:
> > Bruce Evans wrote:
> > > > Is this an omission, or are the ports wrong?
> > >
> > > First answer:
> > > This is a bug in the ports.  The non-i386 arches are apparently including
> > > <machine/floatingpoint.h> instead of the documented interface <ieeefp.h>.
> >
> > Wow, gotta disagree with that; the problem doesn't magically go
> > away when you include the standard header file.
> 
> Yes it does (should).

We're at cross-purposes here, I think.  It doesn't go away, even if
it should; here's ieeefp.h:

	#ifndef _IEEEFP_H_
	#define _IEEEFP_H_

	#include <sys/cdefs.h>
	#include <machine/ieeefp.h>

	#ifdef __i386__	
	#include <machine/floatingpoint.h>
	#else /* !__i386__ */
	__BEGIN_DECLS
	extern fp_rnd_t    fpgetround(void);
	extern fp_rnd_t    fpsetround(fp_rnd_t);
	extern fp_except_t fpgetmask(void);
	extern fp_except_t fpsetmask(fp_except_t);
	extern fp_except_t fpgetsticky(void);
	extern fp_except_t fpsetsticky(fp_except_t);
	__END_DECLS
	#endif /* __i386__ */

	#endif /* _IEEEFP_H_ */

The function will still be missing from the library, even if there's
a valid prototype in scope, because you included the header file, and
didn't get any of the manifests.  To get the manifests, you have to
include the <machine/ieeefp.h>, seperately.

Notice that the only real difference is whether or not the
operations end up using an inline version of the functions, or
expect one to be in the library.

That's a library bug, that they would not be implemented on SPARC.


The second problem where the manifest wasn't defined is a real
problem in the ported code; technically, they are required to
feature test before using the manifest constant.



> Including an implementation detail like
> <machine/floatingpoint.h> gives undefined behaviour.  In this case,
> one aspect of the undefined behaviour is that fpsetmask() is not
> declared in the MD file except in the i386 case as a side effect
> of being implemented as a macro that calls an inline function there.
> In all the other arches, it is an extern function that is only
> declared in <ieeefp.h>.

The problem was not one of a prototype not being in scope, which
is basically a stupid pseudo-compiler error that came from not
mandating that that crap get handled at link-time (which is very
easy to do, if you are willing to break legacy object compatability,
just like symbol decoration can go away).


> > > I think the ports are only meddling the FP mask to hide their FP errors
> > > when running under FreeBSD-3.x and earlier anyway.
> >
> > They are meddling with it because the FreeBSD default, while it is
>                                                                   ^^ iswas (1)
> > permitted by the standard, is different from what most software
>                              was (2)
> > expects the default to be.
> 
> (1) was permitted by C90; is not permitted by C99, but C99 is not supported
>     yet.

So it's irrelevent, right?


> (2) was different before FreeBSD-4.0.  Are there any ports that still
>     support FreeBSD-3?

Not this software, certainly... making it also irrelevent, right?


> > Yeah, it'd be nice if it weren't there, but the man page itself
> > specifically uses fpsetmask() in an example (to prevent some trap).
> 
> The man page still supports FreeBSD-3 :-).  It is version-agnostic.  The
> default setting is very MD, so software that actually cares must not
> assume anything about the defaults.

Exactly.  And therfore must call the function to set the FPU into
a known state, with regatd to exception handling, etc..  Which
makes my case, there.


> Anything else would be very expensive both in source code complexity
> and runtime costs.

A push/pop paradigm could do this without any real cost, actually;
when you add threading, things get complicated, but since you are
screwing with signal masks before and after threaded calls, to
get around the fact that the BSD default of system call restart has
been removed in favor of the System V default of system call
non-restart, following a signal, you have an amplification factor of
3 on system call overhead anyway, so additional overhead for threads
is basically totally lost in the noise of all that *other* overhead
you get, just from using threads in the first place.


> The environment would have to be switched for every
> library function that uses FP.  C99 only requires a few specialized
> math functions to be aware of this.

Everyone who uses FP has to do it anyway: if they want consistent
results, and the FP doesn't start in a preferred state, then the
answer is that you *always* have to save and restore the state.
You could get around this a little, by doing two things:

1)	Cache the current state in a user space global, so that
	the code involved can decide to not do the save/restore,
	if it's already in the preferred state.

2)	FreeBSD could quit being so contrarian, and adopt the
	same default state that Linux, Solaris, and SCO use,
	which is, now, for programmers, the preferred state.


> > What this really comes down to is that Intel FP hardware sucks,
> > and should be redesigned to raise exceptions when they occur,
> > instead of on the next operation.  It's like the old VT100's, or
> 
> This is not suckagae, but a normal consequence of pipelining.  Intel
> hardware is relatively nice here.  It gives precise exceptions on the
> next operation.  Less-unmodern hardware like alphas has very imprecise
> exceptions unless everything is pessimized using trap barriers.  See
> -mtrap-precision in gcc.info.  But exceptions are now almost moot on
> i386's since they don't cause traps.  However, at least some alphas
> need to cause traps to be IEEE conformant since traps are needed to
> implement some parts of IEEE conformance in software, and the largest
> of the -mtrap-precision pessimizations are needed for this to work.
> See -mieee-conformant in gcc.info.

The preferred state of the hardware for most programmers is "no
exceptions by default" anyway.  FeeBSD tried to be more precise,
and makes programmers go out of their way to get the same imprecision
and behaviour that they expect, because of their code being written
for other platforms.  It's not like FreeBSD is the reference platform
for much software, so it's not like this is really a moral high ground,
here.

In any case, trap barriers are not really necessary; implying a
barrier when an exception is raised is enough.  As long as you don't
hit an exceptional condition, you are free to pipeline, and, given
that exceptional conditions are, well, "exceptional", and therefore
don't happen very often, it's not like you'd be giving up speed in
the common case.  In the barrier case, you are running a trap
handler, anyway (at least, FreeBSD assumes you will be).

Add to this the MMX, bcopy, and other abuse of the FP registers,
and you've got a lot of good reasons to trap on the event.  8-(.


> > I understand the pipeline stall that would happen on an exception,
> > if this is how they were handed; on the other hand, it's a little
> > bogus to assume that exceptions aren't going to be rare, what with
> > them being "exceptional" and all.  8-).
> 
> As far as I understand the hardware issues (not far), the stall would
> be necessary after every FP instruction, not just ones which generate
> the exception.  FP performance would be reduced by approximately a
> factor of (pipeline_length * number_of_concurrent_FP_ops_achieved).
> I guess speculative execution code get near appearing to not stall
> though.

I keep getting this rationale, but it doesn't really fly for me.
If you are going to raise an exception, you are going to lose
the speculative execution that was done on the basis of the idea
that you were not going to get an exception.

I'm half inclined to say that FP state should be saved and restored
on context switches of a process, after it has once used FP, and
get rid of all this special crap that comes from trying to lazy-bind
FPU context switching.  The worst case for this will be the worst
case in any case; in the best case, you will save context, and then
decide that it's still present, so it doesn't need to be restored.
That's an overhead that I think is livable, since it assumes a
loaded system in the first place, context switching away from the
FP-using process, because there's other stuff that wants to run.


> > The C99 soapbox is a nice place to stand, if you want to criticize
> > all other implementations; but as you point out, C99 is not really
> > there yet, and even if it were, you could not really expect all
> > code to be changed to conform to it (or any other standard, for
> > that matter, considering the amount of legacy code everywhere).
> 
> True.  It just gives applications a chance of handling environment-
> related FP stuff almost portably.

I'm willing to cross that bridge when someone fully implements C99
compliance, and ignore it, until then.  It's not really useful to
drive by some place that under construction for 4 years now, and
every day sigh about not being able to use the parking garage, or
complain about the places you can park to get where you need to go
today (IMO).  More than 4 years, if you consider that it was possible
to start implementation when C99 was still draft.

-- Terry

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-sparc" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3E217111.B3C4C512>