winedos / Speed up RM software interrupt handling
jhei at iki.fi
Sun Mar 16 12:25:39 CST 2003
On Wed, Mar 12, Ove Kaaven wrote:
> What I might have done if we sticked to exceptions would be to have the
> whole DOS VM thread (that runs the code) be protected by a
> __TRY/__EXCEPT block, not just DOSVM_Enter, and then have a flag (maybe
> in the TEB) that the DPMI could set whenever executing in app protected
> mode, and either set_vm86_pend or the exception handler could check; the
> point being that exceptions would still be thrown in protected mode,
> which the thread-wide exception handler could then catch and handle
> appropriately. If you really don't want to use exceptions, then I
> suppose you'll have to do a whole lot of stack frame mangling (change
> the context so the code resumes at some custom winedos handler, which
> would then dispatch to the right stuff) instead, which could get ugly.
> Why not rather address the root cause of why you don't like to use
> exceptions, that they're slow? I don't see any fundamental reason they
> have to be, since as I understand, after the frame is set up, they
> basically just need to look up some memory addresses and jump to the
> appropriate code. There isn't an obvious reason a direct call should be
> that much faster. I'm pretty sure Windows does it reasonably fast, why
> can't Wine? I think that'd be worth looking into.
Well, an educated guess would be that SEH is going to be 10-100 times
slower than direct function call, even if the implementation was
optimal. However, this would be acceptable. Unfortunately, Wine SEH
handling makes a server call in order to notify debugger and I suspect
this is what makes SEH slow (using SEH also makes running DOS programs under
winedbg hard, but this is most likely because I don't know how to make
winedbg ignore VM86 exceptions).
It is likely that I shall not try to change the mechanism from SEH to
something faster because it is not a particularly interesting problem.
It would improve the performance of real mode DOS programs, but
I guess I have more important things to do. However, I think replacing
SEH would be much easier than you believe. As far as I understand
it, something like the following would be enough:
* Replace custom vm86_enter with glibc vm86 function.
* Make set_vm86_pend to return immediately if context is in VM86
(vm86 syscall will automatically return with return value of VM86_SIGNAL).
If, instead teb->vm86_ptr is set and interrupts are enabled, push CS/IP to
stack and replace them with pointer to real mode stub that does "sti and ret".
This makes vm86 return with VM86_STI.
* Make __wine_enter_vm86 check after return from vm86 that CS/IP does not
point to stub defined above. If this is the case, just pop old CS/IP from stack.
This fixes race if signal is received during return from vm86 and before
teb->vm86_ptr is cleared.
* Add some mechanism (return or direct call) to __wine_enter_vm86 for handling
software interrupts and pending events (this is unlikely to make the function
more than a few lines longer).
Jukka Heinonen <http://www.iki.fi/jhei/>
More information about the wine-devel