Discussion:
fpcw trashing, revisited
(too old to reply)
Michal Necasek
2006-02-14 03:07:16 UTC
Permalink
Maybe people still remember the discussion about the floating-point
control word getting corrupted in certain situations. I have since made
some discoveries, but the diagnosis is extremely difficult because:

- If I run the testcase - a VIO app running in a PM window - under a
debugger (IBM, Watcom, or just homebrew DosDebug thingy), the behaviour
is altered and the bug does not occur; the initialization sequence of
the process is different and some DLLs get loaded earlier.

- When the corruption occurs, it is after a call to DosWrite to the
console. This will load the BVH subsystem *unless* output is redirected.
There may be other calls that will cause DLLs to load and corrupt the FPCW.

- I have not managed to track this down through KDB because it appears
to offer absolutely no way of displaying any floating-point registers.

- I did discover that my own SDDPMI.DLL is involved; however, SDDPMI
itself doesn't even use floating-point and the culprit is either the
VAC++ runtime or possibly SOM.DLL.

- When I prevented SDDPMI from messing with the FPCW, it was no longer
getting trashed in FS sessions, but was still modified in VIO windows.
In fact the FPCW was getting corrupted even when plain VGAGRADD was
used. Since most if not all of the DLLs in question are using IBM's
runtime, this is probably not surprising. Unfortunately, a VIO app will
load quite a few PM DLLs the first time it does console I/O.

Right now I can't tell which other DLL is responsible (could be more
than one) - I haven't found a tool that is not a Ring 3 debugger, will
let me stop at each DLL load, *and* will display the FPCW.


Michal
Veit Kannegieser
2006-02-14 12:28:40 UTC
Permalink
Post by Michal Necasek
There may be other calls that will cause DLLs to load and corrupt the FPCW.
Idea for hack solution: install a filter that wraps the call to the
DLL initialisation/finalisation entrypoint. Assuming that a DLL
should not change the FPCW.
--
Veit Kannegieser
Michal Necasek
2006-02-14 18:24:04 UTC
Permalink
Post by Veit Kannegieser
Idea for hack solution: install a filter that wraps the call to the
DLL initialisation/finalisation entrypoint.
Install how/where?
Post by Veit Kannegieser
Assuming that a DLL should not change the FPCW.
That is not a valid assumption... for instance the VAC++ runtime
clearly is supposed to change the FPCW when it inits, that just happens
to wreak havoc if the DLL is loaded dynamically.


Michal
Scott G.
2006-02-14 19:55:47 UTC
Permalink
Post by Michal Necasek
Post by Veit Kannegieser
Idea for hack solution: install a filter that wraps the call to the
DLL initialisation/finalisation entrypoint.
Install how/where?
Post by Veit Kannegieser
Assuming that a DLL should not change the FPCW.
That is not a valid assumption... for instance the VAC++ runtime
clearly is supposed to change the FPCW when it inits, that just happens
to wreak havoc if the DLL is loaded dynamically.
Not only that, but what about DLLs that want to do FP and can't depend
on the FPCW having been initialized at all by the app! Basically the
whole design of OS/2 is miserably deficient in (at least) this one
regard. Next time I visit Boca Raton ca. 1990, I'll tell them that.
-Scott
Michal Necasek
2006-02-14 23:37:21 UTC
Permalink
Post by Scott G.
Not only that, but what about DLLs that want to do FP and can't depend
on the FPCW having been initialized at all by the app! Basically the
whole design of OS/2 is miserably deficient in (at least) this one
regard. Next time I visit Boca Raton ca. 1990, I'll tell them that.
I don't think it's a deficient OS design. Or at least I don't see what
the OS can do to really help. I see it as a general library/DLL design
problem, exacerbated by the peculiarities of x86 design.

The only way I can think of that would avoid (not really solve) the
problem would be requiring all applications and DLLs to use a single
OS-provided dynamic runtime library; that clearly wasn't feasible and
perhaps wasn't even desirable.

Basically the FPCW (FPU in general) is a 'shared' resource (not
between threads or processes, but for all code executing on a given
thread) that anyone can access/modify without any sort of access control
mechanism, and that's the crux of the problem. For a safe solution,
every runtime environment would have to save the FPCW (perhaps more than
that) every time it needs to do math and gets entered with FPU in
unknown state, set it to its own value, do math, then restore the state
on return to caller. Much like CPU registers are saved/restored. That
would probably kill the performance pretty well for lots of math stuff
and I can see why no one took this approach.

The other approach is requiring users to ensure that the FPU is in the
expected state, ie. they would have to save/restore it whenever
necessary. Except we all know that users can't be relied upon.

In other words, I don't think there's any good solution and I would
certainly not blame the Boca Raton team. Maybe the Toronto compiler
people ;)

I don't believe any x86 OS solves this problem...


Michal
Peter Flass
2006-02-15 00:07:46 UTC
Permalink
After the previous discussions I developed a temporary workaround. I
save the fpcw value on every entry to an external procedure, and set it
to my desired value, and then restore it on exit to be a good citizen.
I have called routine that resets it after calls to DosWrite - I do all
calls to be safe, not just the first. I probably should restore it
after all calls to external procedures, but I may make that optional.
Ilya Zakharevich
2006-02-19 21:50:22 UTC
Permalink
[A complimentary Cc of this posting was sent to
Peter Flass
Post by Peter Flass
After the previous discussions I developed a temporary workaround. I
save the fpcw value on every entry to an external procedure, and set it
to my desired value, and then restore it on exit to be a good citizen.
I have called routine that resets it after calls to DosWrite - I do all
calls to be safe, not just the first. I probably should restore it
after all calls to external procedures, but I may make that optional.
[Preceeding messages are not on my server, so I answer via this one]

Michal wrote:

Yes, I could substantiate. What I meant is not that changing FPU
state during DLL initialization is desirable or good design, but
that existing runtime DLLs clearly expect to do that.

Can't agree. They DO this, but this is not an "expected" reasonable
behaviour.

So my earlier statement meant that forcibly saving/restoring FPU
state across DLL load is going to break some applications.

Please give ONE example where this happens. OS/2 kernel (or a parent;
is it inherited?) sets a FPU flag to a reasonable value on startup.
The DLL which change FPU flag set it (AFAIU) to UNREASONABLE value.
Post by Peter Flass
Changing FP flags immediately before calling constructors/main()
makes sense. Doing it any other way does not.
Doing it any other way *without explicit user control* you mean.

Thanks for a correction.

I don't think it's a deficient OS design. Or at least I don't see
what the OS can do to really help. I see it as a general
library/DLL design problem, exacerbated by the peculiarities of
x86 design.

How about these (lousy) proposals: each module has two bitmaps: the bits
in FP flags it needs set, and those it needs unset. The EXE and
statically loaded DLLs are checked on startup, and if requirements
fit, the program is loaded with "optimal" flags.

Or (better?): the loader ignores the bitmaps, but there is an API to
check the loaded DLLs for these bitmaps. Or, the minimal: at least
there is a way to mark the process as "do not touch my FP flags; it is
already set to a reasonable value".

In short, the OS should provide a way for components to "negotiate"
the desired value of FP flags.

Hope this helps,
Ilya
Michal Necasek
2006-02-20 00:51:21 UTC
Permalink
Post by Michal Necasek
Yes, I could substantiate. What I meant is not that changing FPU
state during DLL initialization is desirable or good design, but
that existing runtime DLLs clearly expect to do that.
Can't agree. They DO this, but this is not an "expected" reasonable
behaviour.
Reasonable it's not, but the expectation is still there :)
Post by Michal Necasek
So my earlier statement meant that forcibly saving/restoring FPU
state across DLL load is going to break some applications.
Please give ONE example where this happens. OS/2 kernel (or a parent;
is it inherited?) sets a FPU flag to a reasonable value on startup.
The DLL which change FPU flag set it (AFAIU) to UNREASONABLE value.
The IBM VisualAge C++ runtime DLL will modify the FPU control word and
set it to the value IBM's math library expects. It's bad design but it's
not going to get changed...

The reasonableness of the values is relative. I don't know if that is
the case in reality, but the VAC++ runtime docs mention that the default
FPCW value may change between releases. If that was the case, then
obviously mixing DLLs built with different compiler versions could be a
major headache. Compilers from different vendors may also well have
different defaults.
Post by Michal Necasek
Or (better?): the loader ignores the bitmaps, but there is an API to
check the loaded DLLs for these bitmaps. Or, the minimal: at least
there is a way to mark the process as "do not touch my FP flags; it is
already set to a reasonable value".
That might work. I'm pretty sure in some of the cases I have seen a
DLL will set the FP control word even though it actually won't be doing
any math; it's just part of generic startup code.

I have a feeling that this whole issue is largely x86 specific,
because other architectures do not have such elaborate set of FP control
flags. The precision control is tricky, because if someone sets lower or
higher precision than what a piece of code expects, the results may be
unexpected too. Rounding control falls into the same category. I'm not
even talking about masking and unmasking FP exceptions, which is always
dangerous.

The other part of the problem is surely that x87 was for the longest
time an optional add-on, and OS and tools designers tended to ignore it.
For instance I never figured out how to display FPU registers in KDB -
it probably isn't possible.


Michal
Ilya Zakharevich
2006-02-20 04:09:37 UTC
Permalink
[A complimentary Cc of this posting was NOT [per weedlist] sent to
Michal Necasek
Post by Michal Necasek
Post by Michal Necasek
So my earlier statement meant that forcibly saving/restoring FPU
state across DLL load is going to break some applications.
Please give ONE example where this happens. OS/2 kernel (or a parent;
is it inherited?) sets a FPU flag to a reasonable value on startup.
The DLL which change FPU flag set it (AFAIU) to UNREASONABLE value.
The IBM VisualAge C++ runtime DLL will modify the FPU control word and
set it to the value IBM's math library expects.
I asked for an example where "forcibly saving/restoring FPU state
across DLL load is going to break some applications". Do you see the
difference with what you posted?
Post by Michal Necasek
The reasonableness of the values is relative. I don't know if that is
the case in reality, but the VAC++ runtime docs mention that the default
FPCW value may change between releases.
[Releases of what? Default of what? I assume default of "value after
loading CRT DLL", and releases of CRT DLL...]

And it still does not address the questions of "reasonable". Given
that OS/2 does not allow reliable intercept of FP exceptions (at
least, according to Scott; myself, I do not know what is the problem),
any value which raises exceptions is not reasonable. This lives
exactly one reasonable value of the "exception" part; and it so
happens that this is the value at startup of an executable...
Post by Michal Necasek
Post by Michal Necasek
Or (better?): the loader ignores the bitmaps, but there is an API to
check the loaded DLLs for these bitmaps. Or, the minimal: at least
there is a way to mark the process as "do not touch my FP flags; it is
already set to a reasonable value".
That might work. I'm pretty sure in some of the cases I have seen a
DLL will set the FP control word even though it actually won't be doing
any math; it's just part of generic startup code.
I must say that such are ALL the cases I saw: setting flags on DLL
startup is always accompanied by not needing them. ;-) ;-(
Post by Michal Necasek
The precision control is tricky, because if someone sets lower or
higher precision than what a piece of code expects, the results may be
unexpected too.
Let me restate this:

having directories on a file system is tricky, because if someone
changes a directory to a different one than what a piece of code
expects, the results may be unexpected too.

1/20 ;-)
Post by Michal Necasek
The other part of the problem is surely that x87 was for the longest
time an optional add-on, and OS and tools designers tended to ignore it.
For instance I never figured out how to display FPU registers in KDB -
it probably isn't possible.
All I use is gdb and sd386. I know how to inspect FPU in sd386, but
not in gdb...

Yours,
Ilya
Michal Necasek
2006-02-20 05:36:04 UTC
Permalink
Post by Ilya Zakharevich
Post by Michal Necasek
The IBM VisualAge C++ runtime DLL will modify the FPU control word and
set it to the value IBM's math library expects.
I asked for an example where "forcibly saving/restoring FPU state
across DLL load is going to break some applications". Do you see the
difference with what you posted?
(I'm not sure if the answer is "yes" or "no" here) My point is that
although right now I am not aware of an application that would be broken
by forcibly saving/restoring FPU state across DLL load, I can very well
imagine that such applications exist.
Post by Ilya Zakharevich
Post by Michal Necasek
The reasonableness of the values is relative. I don't know if that is
the case in reality, but the VAC++ runtime docs mention that the default
FPCW value may change between releases.
[Releases of what? Default of what? I assume default of "value after
loading CRT DLL", and releases of CRT DLL...]
Default FPCW value, I thought that was clear. Releases of IBM C/C++
compilers and their associated libraries.
Post by Ilya Zakharevich
And it still does not address the questions of "reasonable". Given
that OS/2 does not allow reliable intercept of FP exceptions (at
least, according to Scott; myself, I do not know what is the problem),
any value which raises exceptions is not reasonable.
Exceptions are only part of the problem. The other part is precision
and rounding control.

As for reliable FP exception processing, I believe that is a "hard"
problem on any x86 OS. Very few libraries attempt to do it.
Post by Ilya Zakharevich
having directories on a file system is tricky, because if someone
changes a directory to a different one than what a piece of code
expects, the results may be unexpected too.
1/20 ;-)
The difference between precision control and directories is that
directories are simply too useful to live without. Quite a few hardware
architectures live happily without floating-point precision control.
Post by Ilya Zakharevich
Post by Michal Necasek
For instance I never figured out how to display FPU registers in KDB -
it probably isn't possible.
All I use is gdb and sd386. I know how to inspect FPU in sd386, but
not in gdb...
I avoid gdb whenever I can, but I'd be surprised if it couldn't
display FPU state. Anyway getting the FPU state in application debuggers
isn't a problem, DosDebug supports it (modulo bugs). But KDB allows
analysis of problems where Ring 3 debuggers cannot be used (for whatever
reason)... only when that problem is FPU related, KDB is no help.


Michal
Ilya Zakharevich
2006-02-21 00:21:03 UTC
Permalink
[A complimentary Cc of this posting was NOT [per weedlist] sent to
Michal Necasek
Post by Michal Necasek
Post by Ilya Zakharevich
And it still does not address the questions of "reasonable". Given
that OS/2 does not allow reliable intercept of FP exceptions (at
least, according to Scott; myself, I do not know what is the problem),
any value which raises exceptions is not reasonable.
Exceptions are only part of the problem. The other part is precision
and rounding control.
Rounding control can't be a problem. Let me recall its intent:
paraphrasing Kagan (sp?): in the "old days", anyone doing computer
arithmetic had a deep knowledge of how numeric algorithms can
misbehave. At the mid-70s, computers became so widespread that it was
hard to find a person who would be able to distinguish stable
algorithm from non-stable one looking at the description.

So "rounding control" was invented as a tool to distinguish these
situations *without reading the algorithm*: stable algorithm will give
only slightly different answer; non-stable one will give very
different answers when a rounding model was changed.

In short: there is no point in changing rounding control unless at
runtime.

Now chaning precision flags on DLL load is just so silly that I
absolutely refuse to discuss anything which would do this. ;-) This
leaves only exception handling
Post by Michal Necasek
As for reliable FP exception processing, I believe that is a "hard"
problem on any x86 OS. Very few libraries attempt to do it.
But the exception handling is THE CORE of the problem: the "broken
DLLs" set the exception handling flags to insane values.
Post by Michal Necasek
Post by Ilya Zakharevich
having directories on a file system is tricky, because if someone
changes a directory to a different one than what a piece of code
expects, the results may be unexpected too.
1/20 ;-)
The difference between precision control and directories is that
directories are simply too useful to live without. Quite a few hardware
architectures live happily without floating-point precision control.
Do you know an architecture which does not give you control over
division by 0?

Yours,
Ilya
Michal Necasek
2006-02-21 01:25:18 UTC
Permalink
Post by Ilya Zakharevich
In short: there is no point in changing rounding control unless at
runtime.
But that's the point, isn't it? If someone does change the rounding
control behind your back, you have a problem.
Post by Ilya Zakharevich
Now chaning precision flags on DLL load is just so silly that I
absolutely refuse to discuss anything which would do this. ;-)
The VAC++ runtime will do that, because it resets the entire FP
control word. Rounding control, precision, exception mask, everything.
Post by Ilya Zakharevich
But the exception handling is THE CORE of the problem: the "broken
DLLs" set the exception handling flags to insane values.
No, it's not "the core", it's just the most visible manifestation. If
exceptions get unmasked for code that isn't prepared to handle them,
things will crash and burn. If rounding or precision get changed, there
will be "only" unexpected results of floating-point calculations but
probably no crashes.
Post by Ilya Zakharevich
Post by Michal Necasek
The difference between precision control and directories is that
directories are simply too useful to live without. Quite a few hardware
architectures live happily without floating-point precision control.
Do you know an architecture which does not give you control over
division by 0?
Floating-point or integer? ;) I am not aware of an architecture that
does not provide control over floating-point divide by zero exceptions.
Those exceptions are I believe required by IEEE 754 and I'm not familiar
with any non-IEEE 754 architectures.


Michal
Ilya Zakharevich
2006-02-21 08:32:13 UTC
Permalink
[A complimentary Cc of this posting was NOT [per weedlist] sent to
Michal Necasek
Post by Michal Necasek
Post by Ilya Zakharevich
In short: there is no point in changing rounding control unless at
runtime.
But that's the point, isn't it? If someone does change the rounding
control behind your back, you have a problem.
Do not think so. For stable algorithms it does not matter; for
unstable ones - one would not care.
Post by Michal Necasek
Post by Ilya Zakharevich
Now chaning precision flags on DLL load is just so silly that I
absolutely refuse to discuss anything which would do this. ;-)
The VAC++ runtime will do that, because it resets the entire FP
control word. Rounding control, precision, exception mask, everything.
As I said - so silly a behaviour does not deserve a mention. ;-)
Post by Michal Necasek
Post by Ilya Zakharevich
But the exception handling is THE CORE of the problem: the "broken
DLLs" set the exception handling flags to insane values.
No, it's not "the core", it's just the most visible manifestation. If
exceptions get unmasked for code that isn't prepared to handle them,
things will crash and burn.
Let me repeat it yet one more time: AFAIK, there is "no reliable way"
to handle FP exceptions on OS/2 (and I do not know what this sentence
means *exactly* ;-( ).

Yours,
Ilya
Michal Necasek
2006-02-21 19:54:39 UTC
Permalink
Post by Ilya Zakharevich
Post by Michal Necasek
But that's the point, isn't it? If someone does change the rounding
control behind your back, you have a problem.
Do not think so. For stable algorithms it does not matter; for
unstable ones - one would not care.
OK - so what's the rounding control for?
Post by Ilya Zakharevich
Post by Michal Necasek
The VAC++ runtime will do that, because it resets the entire FP
control word. Rounding control, precision, exception mask, everything.
As I said - so silly a behaviour does not deserve a mention. ;-)
Silly or not, people do it and it is a problem. It's like saying that
drunk driving does not deserve a mention because it is a silly behaviour.
Post by Ilya Zakharevich
Let me repeat it yet one more time: AFAIK, there is "no reliable way"
to handle FP exceptions on OS/2 (and I do not know what this sentence
means *exactly* ;-( ).
So why do you keep repeating it? ;) As I mentioned earlier, precise
handling of FP exceptions is extremely difficult on any OS. The
exception may be reported "late", after other (non-FP) instructions got
executed. The exception record does not necessarily contain the address
of the faulting FP instruction and one must look into the FPU to find
that address.

I can certainly imagine that given this, it may be impossible to
implement 100% reliable FP exception handling on a multi-tasking OS.


Michal
Ilya Zakharevich
2006-02-21 21:16:12 UTC
Permalink
[A complimentary Cc of this posting was NOT [per weedlist] sent to
Michal Necasek
Post by Michal Necasek
Post by Ilya Zakharevich
Post by Michal Necasek
But that's the point, isn't it? If someone does change the rounding
control behind your back, you have a problem.
Do not think so. For stable algorithms it does not matter; for
unstable ones - one would not care.
OK - so what's the rounding control for?
See the preceeding message (or original Kagan (sp?) papers - actually,
they turn out to be very interesting and enlightening reading).
Post by Michal Necasek
Post by Ilya Zakharevich
Let me repeat it yet one more time: AFAIK, there is "no reliable way"
to handle FP exceptions on OS/2 (and I do not know what this sentence
means *exactly* ;-( ).
So why do you keep repeating it? ;)
I still hope that somebody will show an example of code which worked
before the crucial change (about Warp4 times?), and now does not. ;-)
Post by Michal Necasek
As I mentioned earlier, precise handling of FP exceptions is
extremely difficult on any OS. The exception may be reported "late",
after other (non-FP) instructions got executed. The exception record
does not necessarily contain the address of the faulting FP
instruction and one must look into the FPU to find that address.
Sure. But this is what everybody expects (on the borken i86
architecture); the problem with OS/2 is that reportedly, it kills some
crucial piece of information in the exception handling startup
envelop.
Post by Michal Necasek
I can certainly imagine that given this, it may be impossible to
implement 100% reliable FP exception handling on a multi-tasking OS.
MT is not a problem. The preemptor saves all the necessary bits of
the (co)processor state - otherwise the programs won't work after
preemption.

Hope this helps,
Ilya
Michal Necasek
2006-02-21 21:32:01 UTC
Permalink
Post by Ilya Zakharevich
Post by Michal Necasek
OK - so what's the rounding control for?
See the preceeding message (or original Kagan (sp?) papers - actually,
they turn out to be very interesting and enlightening reading).
Kahan, William? Do you know the title of the paper? I might want to
read it...
Post by Ilya Zakharevich
Post by Michal Necasek
So why do you keep repeating it? ;)
I still hope that somebody will show an example of code which worked
before the crucial change (about Warp4 times?), and now does not. ;-)
Do you have some reference to the claim? I did not realize there was
some change in OS/2 that caused it.
Post by Ilya Zakharevich
Sure. But this is what everybody expects (on the borken i86
architecture); the problem with OS/2 is that reportedly, it kills some
crucial piece of information in the exception handling startup
envelop.
It's probably something in the FPU state.


Michal
Ilya Zakharevich
2006-02-22 08:03:31 UTC
Permalink
[A complimentary Cc of this posting was NOT [per weedlist] sent to
Michal Necasek
Post by Michal Necasek
Post by Ilya Zakharevich
Post by Michal Necasek
OK - so what's the rounding control for?
See the preceeding message (or original Kagan (sp?) papers - actually,
they turn out to be very interesting and enlightening reading).
Kahan, William? Do you know the title of the paper? I might want to
read it...
Sorry, when I read it it was the time when I had a very high trust in
my memory; so I won't write the reference down. All I remember is
that it was available as a PDF about 2000; the paper itself could have
been much earlier...
Post by Michal Necasek
Post by Ilya Zakharevich
I still hope that somebody will show an example of code which worked
before the crucial change (about Warp4 times?), and now does not. ;-)
Do you have some reference to the claim? I did not realize there was
some change in OS/2 that caused it.
On this newsgroups, Scott claimed a couple of times that he knows
about this alleged issue, but he is not going to fix it... Do not
have any hard data for googling...

Hope htis helps,
Ilya
Michal Necasek
2006-02-22 18:33:20 UTC
Permalink
Post by Ilya Zakharevich
Post by Michal Necasek
Kahan, William? Do you know the title of the paper? I might want to
read it...
Sorry, when I read it it was the time when I had a very high trust in
my memory; so I won't write the reference down. All I remember is
that it was available as a PDF about 2000; the paper itself could have
been much earlier...
William Kahan's homepage is here:

http://http.cs.berkeley.edu/~wkahan/

His writings specifically pertaining to FP math are here:

http://www.cs.berkeley.edu/~wkahan/ieee754status/

Much interesting writing there, including the rationale for IEEE 754
(like why have a sign for zero).


Michal
Michal Necasek
2006-03-11 21:32:29 UTC
Permalink
As a side note, C99 defines a portable way to control floating-point
environment. It offers interfaces to query, set, save, and restore the
FP environment. A library that requires specific FP environment
(rounding, precision, exception control) can thus easily
save/set/restore the floating-point environment without causing disruptions.

Although C99 does not prescribe any particular floating-point
implementation (FP numbers don't even have to be binary), it devotes an
entire annex (Annex F) to IEC 60559 (IEEE 754 equivalent) conforming
implementations and provides detailed specifications beyond the general
C language standard. I believe Fortran 2003 has made similar moves
towards standardizing IEEE-compliant floating-point behaviour.


Michal

Ilya Zakharevich
2006-02-14 21:49:54 UTC
Permalink
[A complimentary Cc of this posting was NOT [per weedlist] sent to
Michal Necasek
Post by Michal Necasek
Post by Veit Kannegieser
Assuming that a DLL should not change the FPCW.
That is not a valid assumption... for instance the VAC++ runtime
clearly is supposed to change the FPCW when it inits,
Could you substantiate this? I thought about it a lot, and I could
not find any situation when changing FP flags on DLL load (if this is
what you mean by FPCW) makes any sense.

Changing FP flags immediately before calling constructors/main() makes
sense. Doing it any other way does not.
Post by Michal Necasek
that just happens to wreak havoc if the DLL is loaded dynamically.
It always will.

Hope this helps,
Ilya
Michal Necasek
2006-02-14 23:11:26 UTC
Permalink
Post by Ilya Zakharevich
Could you substantiate this? I thought about it a lot, and I could
not find any situation when changing FP flags on DLL load (if this is
what you mean by FPCW) makes any sense.
FPCW = floating-point control word, manipulated via fldcw/fstcw
instructions.

Yes, I could substantiate. What I meant is not that changing FPU state
during DLL initialization is desirable or good design, but that existing
runtime DLLs clearly expect to do that.

Whoever designed the runtime DLL(s) presumably operated with the
(incorrect) assumption that the DLL runtime is going to be statically
linked to executables, and hence loaded and initialized by the time any
user code gets executed. This assumption of course falls on a heap if
you have a DLL that (statically) links to such runtime DLL but is itself
loaded dynamically...

So my earlier statement meant that forcibly saving/restoring FPU state
across DLL load is going to break some applications. Yes, the apps are
poorly designed, but no, they're not going to get fixed.
Post by Ilya Zakharevich
Changing FP flags immediately before calling constructors/main() makes
sense. Doing it any other way does not.
Doing it any other way *without explicit user control* you mean. Of
course users should be free to modify the FPCW any time they want,
that's for _control87() is for after all.
Post by Ilya Zakharevich
Post by Michal Necasek
that just happens to wreak havoc if the DLL is loaded dynamically.
It always will.
If you mean "changing FPCW (or FPU state in general) behind the
application's back will wreak havoc" then I absolutely agree.


Michal
Veit Kannegieser
2006-02-15 10:49:29 UTC
Permalink
Post by Michal Necasek
Post by Veit Kannegieser
Idea for hack solution: install a filter that wraps the call to the
DLL initialisation/finalisation entrypoint.
Install how/where?
a device=fpcwdll.sys driver, hooking the code that calls
the dll entrypoints which is likely in os2krnl.
Post by Michal Necasek
Post by Veit Kannegieser
Assuming that a DLL should not change the FPCW.
That is not a valid assumption... for instance the VAC++ runtime
clearly is supposed to change the FPCW when it inits, that just happens
to wreak havoc if the DLL is loaded dynamically.
So the filter has to be selective. Maybe a table of 'known supects',
'known ok' dll names. And a user controllable default action for
all others. I do not want start guessing if the dll name contains
the chars 'cpp' in them then <keep fpcw> etc.
--
Veit Kannegieser
Michal Necasek
2006-02-15 18:50:41 UTC
Permalink
Post by Veit Kannegieser
Post by Michal Necasek
Install how/where?
a device=fpcwdll.sys driver, hooking the code that calls
the dll entrypoints which is likely in os2krnl.
No, thank you. That sounds like a cure worse than the disease.


Michal
Loading...