Posix Timer периодически пропускает половину своего периода - PullRequest
5 голосов
/ 02 сентября 2011

У меня есть задача, связанная с Posix Timer (timer_create ()), который выполняется каждые 20 мс / 50 Гц.По большей части работает нормально, за исключением каждых 334,5 секунд (приблиз.), Таймер запускается на 10 мс раньше для одного цикла.В течение следующих 334,5 секунд все интервалы снова равны 20 мс.

Я включил соответствующий код для настройки таймера.Приложение работает на Gumstix Verdex Pro XL6P с версией Gumstix по умолчанию для Linux.У меня также это запланировано с помощью алгоритма планирования FIFO.

В моей интуиции сказано, что это проблема целочисленного переполнения.Может быть, что-то еще использует тот же сигнал?Мне постоянно удавалось воспроизводить пропуски между исполнениями и сеансами на плате.

Проблема не в том, чтобы остановить показ, но мне бы очень хотелось понять, почему это происходит.

Вот код для настройки таймера:

//------------------------------------------------------------------------------
// Create a timer which fires at the specified time and calls a timer event
// handler.
//
// handler : function to be called when the timer expires
// us      : number of microseconds to add to timer
// ms      : number of milliseconds to add to timer
// sec     : number of seconds to add to timer
//------------------------------------------------------------------------------
void createTimer(void (*handler)(void), uint32 us, uint32 ms, uint32 sec)
{
    struct sigaction sigact;
    struct sigevent sigev;
    timer_t timerid;
    struct itimerspec itval;
    struct itimerspec oitval;
    timer_info_t* newTimer = NULL;

    // Initialize signalNum.
    if (timers == NULL)
        signalNum = SIGRTMAX;

    if (signalNum < SIGRTMIN)
        exitWithError("no avaiable signals, unable to create timers");

    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = SA_SIGINFO;
    sigact.sa_sigaction = signalHandler;

    // Set up sigaction to catch signal
    if (sigaction(signalNum, &sigact, NULL) == -1)
        exitWithError("sigaction() failed, unabled to creat timers");

    // Create the POSIX timer to generate signo
    sigev.sigev_notify = SIGEV_SIGNAL;
    sigev.sigev_signo = signalNum;
    sigev.sigev_value.sival_ptr = &timerid;        

    long ret = timer_create(CLOCK_REALTIME, &sigev, &timerid);

    if (ret == 0) 
    {
        // Prevent overflow in calculation of nsec below.
        if (ms >= 1000)
        {
            sec += (ms / 1000);
            ms = ms % 1000;
        }

        itval.it_value.tv_sec = sec;
        itval.it_value.tv_nsec = (long)(us * 1000L) + (long)(ms * 1000L * 1000L);

        // Configure it as a repeat timer.
        itval.it_interval.tv_sec = itval.it_value.tv_sec;
        itval.it_interval.tv_nsec = itval.it_value.tv_nsec;

        if (timer_settime(timerid, 0, &itval, &oitval) != 0)
            exitWithError("time_settime() error!");
    }
    else
        exitWithError("timer_create() error!");

    newTimer = (timer_info_t*)malloc(sizeof(timer_info_t));
    newTimer->timer = timerid;
    newTimer->handler = handler;
    newTimer->sigNum = signalNum;
    newTimer->next = NULL;

    // Check to see if this is the first time through.
    if (timers == NULL)
    {
        timers = newTimer;
        atexit(deleteTimers);
    }
    else
        lastTimer->next = newTimer;

    lastTimer = newTimer;

    signalNum--;
}

Заранее спасибо.

1 Ответ

1 голос
/ 13 сентября 2011

Я предполагаю, что вы используете ntp, и что он меняет время с этими интервалами.Вместо этого вы можете попытаться использовать CLOCK_MONOTONIC, но в соответствии с http://juliusdavies.ca/posix_clocks/clock_realtime_linux_faq.html это также может быть затронуто.

...