Home > OS >  Running thread periodically every 20 ms fails
Running thread periodically every 20 ms fails

Time:10-21

currently i am programming for an embedded application which reads values from sensors periodically. I want them to be read, every 20 ms.

Im using this tutorial

struct periodic_info {
    int sig;
    sigset_t alarm_sig;
};

static int make_periodic(int unsigned period, struct periodic_info *info)
{
    static int next_sig;
    int ret;
    unsigned int ns;
    unsigned int sec;
    struct sigevent sigev;
    timer_t timer_id;
    struct itimerspec itval;

    /* Initialise next_sig first time through. We can't use static
       initialisation because SIGRTMIN is a function call, not a constant */
    if (next_sig == 0)
        next_sig = SIGRTMIN;
    /* Check that we have not run out of signals */
    if (next_sig > SIGRTMAX)
        return -1;
    info->sig = next_sig;
    next_sig  ;
    /* Create the signal mask that will be used in wait_period */
    sigemptyset(&(info->alarm_sig));
    sigaddset(&(info->alarm_sig), info->sig);

    /* Create a timer that will generate the signal we have chosen */
    sigev.sigev_notify = SIGEV_SIGNAL;
    sigev.sigev_signo = info->sig;
    sigev.sigev_value.sival_ptr = (void *)&timer_id;
    ret = timer_create(CLOCK_MONOTONIC, &sigev, &timer_id);
    if (ret == -1)
        return ret;

    /* Make the timer periodic */
    sec = period / 1000000;
    ns = (period - (sec * 1000000)) * 1000;
    itval.it_interval.tv_sec = sec;
    itval.it_interval.tv_nsec = ns;
    itval.it_value.tv_sec = sec;
    itval.it_value.tv_nsec = ns;
    ret = timer_settime(timer_id, 0, &itval, NULL);
    return ret;
}

static void wait_period(struct periodic_info *info)
{
    int sig;
    sigwait(&(info->alarm_sig), &sig);
}

static int thread_1_count;

The Main:

int main(){



    pthread_t t_1;
    pthread_t t_2;
    sigset_t alarm_sig;
    int i;

    printf("Periodic threads using POSIX timers\n");

    /* Block all real time signals so they can be used for the timers.
       Note: this has to be done in main() before any threads are created
       so they all inherit the same mask. Doing it later is subject to
       race conditions */
    sigemptyset(&alarm_sig);
    for (i = SIGRTMIN; i <= SIGRTMAX; i  )
        sigaddset(&alarm_sig, i);
    sigprocmask(SIG_BLOCK, &alarm_sig, NULL);

    pthread_create(&t_1, NULL, thread_1, NULL);
    sleep(10);
    printf("Thread 1 %d iterations\n", thread_1_count);
    return 0;

My Problem now, i measured the time with high resolution clock with a period of 20ms.

static void *thread_1(void *arg)
{
    struct periodic_info info;

    printf("Thread 1 period 10ms\n");
    make_periodic(20000, &info);
    while (1) {
        auto start = std::chrono::high_resolution_clock::now();
        printf("Hello\n");
        thread_1_count  ;
        wait_period(&info);
        auto finish = std::chrono::high_resolution_clock::now();
        std::chrono::duration<double, std::milli> ms_double = finish - start;
        std::cout << ms_double.count() << "ms\n";
    }
    return NULL;
}

The output i get ist:

...
19.8556ms
19.8587ms
19.8556ms
19.8543ms
19.8562ms
19.8809ms
19.7592ms
19.8381ms
19.8302ms
19.8437ms
...

So my Question, why is the Time shorter than my Period time, what am i doing wrong ?

CodePudding user response:

To be more accurate, don't take time twice on each iteration, keep the last value, like this:

static void *thread_1(void *arg)
{
    struct periodic_info info;

    printf("Thread 1 period 10ms\n");
    make_periodic(20000, &info);
    auto start = std::chrono::high_resolution_clock::now();
    while (1) {
        wait_period(&info);
  
        auto finish = std::chrono::high_resolution_clock::now();
        std::chrono::duration<double, std::milli> ms_double = finish - start;
        std::cout << ms_double.count() << "ms\n";
        start = finish;
    }
    return NULL;
}

This way, it will make the time measuring more accurate.

  • Related