How to do something every millisecond or better on Windows

This question is not related to pinpointing accuracy in Windows (XP or higher), but rather about doing something very fast through a callback or interrupt .

I need to do something regularly every 1 millisecond, or preferably even every 100 microseconds. What I need to do is connect some asynchronous hardware (ethernet) at such a speed that I can output a constant stream of packets to the network and make the stream as regular and synchronous as possible. But if the question can be separated from the (ethernet) device, it would be nice to know the general answer.

Before saying “don't even think about using Windows !!!!”, a little context. Not all real-time systems have the same requirements. In most cases, songs and videos are played on Windows, despite the need to process blocks of audio or images every 10-16 m or more on average. With proper buffering, Windows can have its own delay variables, but the hardware can be generally immune to them and maintain a steady, synchronous stream of events. Despite this, most of us experience an accidental failure. My application looks like this - perhaps quite bearable.

An expensive option for me is to port my entire application to Linux. But Linux is just another software that runs on the same hardware, so my strong preference is to write better software and use Windows. I have the luxury of being able to eliminate all competing hardware and software (no Internet access or other network access, other applications not working, etc.). Do I have the prospect of getting Windows to do this? What restrictions have I encountered?

I know that my target equipment has a High Performance Event Timer and this timer can be programmed to interrupt, but there is no driver for this. Can i write it? Are there any useful examples? I haven't found it yet. Will this interfere with the QueryPerformanceCounter? Is the fact that I'm going to use an ethernet device mean that everything becomes simple if I use select () correctly?

Pointers to useful articles are welcome - I have found dozens of reviews on how to get the exact time, but not yet, how to do something similar, except to use what constitutes a lively expectation. Is there any way to avoid busy waiting? Is there a kernel mode or device driver option?

+7
source share
4 answers

You should consider viewing multimedia timers. These are timers that are designed for the resolution you are looking for.

Take a look at MSDN .

+4
source

I did this with DirectX 9 using QueryPerformanceCounter , but you will need to deflate at least one core, as task switching will ruin your work.

For a good comparison with the players you can see

http://www.geisswerks.com/ryan/FAQS/timing.html

0
source

If you run into problems with timer granularity, I would suggest using the good old Sleep () with a spin loop. Essentially, the code should do something like:

 void PrecisionSleep(uint64 microSec) { uint64 start_time; start_time = GetCurrentTime(); // assuming GetCurrentTime() returns microsecs // Calculate number of 10ms intervals using standard OS sleep. Sleep(10*(microSec/10000)); // assuming Sleep() takes millisecs as argument // Spin loop to spend the rest of the time in while(GetCurrentTime() - start_time < microSec) {} } 

This way you will have a high-precision sleep that will not tax your processor if many of them are larger than the planning granularity (assuming 10 ms). You can send your packets in a loop while you use high-precision sleep in time.

The reason sound works on most systems is because the audio device has its own clock. You just buffer the audio data, and it takes care to play it and interrupt the program when the buffer is empty. In fact, a time warp between the sound card clock and the CPU clock can cause problems if the playback mechanism relies on the processor clock.

EDIT: You can abstraction the timer from this using a thread that uses a blocking-proof minimum bunch of misleading entries (heap comparisons are done by expiration timestamp), and then you can call callback () or SetEvent () when PrecisionSleep () on the next timestamp.

0
source

Use NtSetTimerResolution when the program starts setting the timer resolution. Yes, this is an undocumented feature, but it works well. You can also use NtQueryTimerResolution to find out the timer resolution (before and after setting a new resolution).

You need to dynamically obtain the address of these functions using GetProcAddress from NTDLL.DLL , since it is not declared in the header or in any LIB file.

Setting the timer resolution in this way would affect Sleep , Windows timers, functions that return the current time, etc.

0
source

All Articles