Generating interrupt each 100 microsecond on windows

806 views Asked by At

i want to generate interrupt every 100 microseconds on windows. Actually i couldnt do this on windows,because windows does not guarantee the interrupts less then 500 microseconds. So, i generate 2 threads. One of them is for timer counter(query performance counter), the other thread is the actual work. When timer counter is 100 microseconds, it change the state of the other thread(actual work) . But i have problem with race condition, because i dont want the threads wait each others, they must always run. So actually i need interrupts. How do i write such fast interrupt on windows with c++?

1

There are 1 answers

4
Ted Lyngmo On BEST ANSWER

To avoid having two threads communicating when you have these short time windows, I'd put both the work and the timer in a loop in one thread.

  • Take a sample of the clock when the thread starts and add 100μs to that each loop.
  • Sleep until the calculated time occurs. Normally, one would use std::this_thread::sleep_until to do such a sleep, but in this case, when the naps are so short, it often becomes a little too inaccurate, so I suggest busy-waiting in a tight loop that just checks the time.
  • Do your work.

In this example a worker thread runs for 10s without doing any real work. On my machine I could add work consisting of ~3000 additions in the slot where you are supposed to do your work before the whole loop started taking more than 100μs, so you'd better do what you aim to do really fast.

Example:

#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>

using namespace std::chrono_literals;

static std::atomic<bool> running = true;

using myclock = std::chrono::steady_clock;

void worker() {
    int loops = 0;
    auto sleeper = myclock::now();
    while(running) {
        ++loops; // count loops to check that it's good enough afterwards

        // add 100us to the sleeper time_point
        sleeper += 100us;

        // busy-wait until it's time to do some work
        while(myclock::now() < sleeper);

        // do your work here
    }
    std::cout << loops << " (should be ~100000)\n";
}

int main() {
    auto th = std::thread(worker);

    // let the thread work for 10 seconds
    std::this_thread::sleep_for(10s);

    running = false;
    th.join();
}

Possible output:

99996 (should be ~100000)

It takes a few clock cycles to get the thread started so don't worry about the number of loops not being exactly on target. Double the time the thread runs and you should still stay close to the target number of loops. What matters is that it's pretty good (but not realtime-good) once it's started running.