Install timer/clock ISR on Windows - Asynchronous

2019-05-23 20:48发布

问题:

I'm refining some code which simulated a context-switching scheduler on x86 Windows systems. The program compiles on Windows XP (Edit: probably not Windows 7) with some ancient Borland C compiler, and is being ported to being MSVC compilable.

At one point, the code installs ISRs through these unavailable functions in dos.h:

void (*)() getvect(int)
void setvect(int, void (*)());

Specifically, the code installs an ISR for a (cyclic) timer interrupt. The calls are:

tick_isr_old = getvect(0x08);
setvect(0xF2, tick_isr_old);
setvect(0x08, (void interrupt (*)(void)) tick_isr);
setvect(0xF1, (void interrupt (*)(void)) context_switch_isr);

Does anyone have any idea what would be a reasonable way to set those ISRs (with the Windows API maybe?). To make things worse, the functions are implemented in assembly language (they need to perform a context switch after all...). Is there at least any documentation which interrupt vectors the integer constants (0x08, 0xF2, 0xF1) refer to? Google didn't really come up with something I could work with.


UPDATE: Since it is apparently not possible to get those DOS calls working in Windows 7, I need a way to asynchronously call a function in a generally single threaded environment.

Under linux, the signal() and raise() functions can do this, but under Windows they are only supported in the most minimal way that is possible. Is there a way to achieve that under Windows?

回答1:

You'll definitely need to replace tick_isr and and context_switch_isr, since they're implementing context-switching for a DOS environment. There's no way the existing code will do anything meaningful in Windows, even if you could sensibly execute it.

Since, in the original code, the context switches are preemptive, you could probably just eliminate that logic altogether and use Windows threads instead. Presumably the existing code has some routines for creating and removing contexts, and these can be replaced with corresponding Windows API thread functions.

If you need to ensure that only one thread is running at a time, you could use SetProcessAffinityMask to tie the process to a single CPU.

Alternatively, you could use the debugging functions GetThreadContext and SetThreadContext to implement your own context switching. In this situation you would have one thread for the main program code and a second thread running the context switcher.



回答2:

See the wikipedia entry on BIOS interrupts; it says:

08h​ IRQ0: Implemented by the system timing component; called 18.2 times per second (once every 55 ms) by the programmable interval timer

On Windows 7, you will need to create kernel mode drivers to access interrupts, though.

You may be able to emulate interrupts for your scheduler using Windows user mode scheduling and fibers.