Timing issues

I recently tried moving some existing software from 9.3 to 10.3 but this seems to cause some issues with timing.

when running the code on 10.3 it seems to go through phases where timed events seem to take twice as long although most of the time it seems correct.

The only thing I think of that might cause this is the change to a tickless kernel, but rebuilding the kernel with this disabled didn’t seem to make any difference

Any ideas of what could cause this?

The program is written in c++ and uses setitimer and sigaction to run a funtion every microsecond

Did you just “move” it or recompile it?

I did a full recompilation of the software.

I have rebuilt on 10.2 and it seems to work fine on that, so it must be something that was introduced in 10.3

It all starts up working properly, and if i am actively using the computer it is fine, but when I leave the programme running the clock seems to slow down after 5-10 minutes

bewildered wrote:

>
> I did a full recompilation of the software.
>
> I have rebuilt on 10.2 and it seems to work fine on that, so it must be
> something that was introduced in 10.3
>
>
> It all starts up working properly, and if i am actively using the
> computer it is fine, but when I leave the programme running the clock
> seems to slow down after 5-10 minutes
>
>

Sounds like cpu frequency scaling is contributing. As long as you’re using
the system, the cpu clock is kept high, when you leave it idle, the system
saves energy by shifting the cpu to a lower, slower clock speed. If your
program calibrates itself against the ‘high speed’ clock, it will be slow
when running during the ‘slow clock’ periods.

If you’re running a function every microsecond, goodness! 1,000,000 times
a second? With system overhead and non-optimal interrupt routines, I would
imagine that it gets skipped occasionally while in slow-clock.

Just wondering… what on earth needs to be run each micro second? Wow.

Consider: 2Ghz machine, 2,000,000,000 (approx) clock ticks a second. If
you’re running something 1,000,000 times a second, it (theoretically) only
gets 2,000 ticks to get anything done before it gets called again. Many
instructions take 2 or more clock ticks to perform… so you’ve got LESS
than 1,000 instructions (probably more like 500-600 really) you can execute
before your interrupt is called again.

And that’s only considering the cpu running your function alone. Not
counting the overhead involved with watching the keyboard for your inputs,
displaying things on the screen, handling network packets, etc.

Wow.

Interesting.

L R Nix
lornix@lornix.com

The micro-second is from the struct timeval which I have just set to be the shortest possible interval to make it as accurate as possible. As the Linux kernel only ‘ticks’ at a maximum of 1000Hz (I had to recompile the kernel to enable this as the default changed from 9.x to 10.x) it will only be milli-seconds.

I had assumed it was due to CPU frequency scaling, but as far as i am aware I have disabled all those options from the kernel and changed the power saving settings so it should not happen

bewildered wrote:

>
> The micro-second is from the struct timeval which I have just set to be
> the shortest possible interval to make it as accurate as possible. As
> the Linux kernel only ‘ticks’ at a maximum of 1000Hz (I had to
> recompile the kernel to enable this as the default changed from 9.x to
> 10.x) it will only be milli-seconds.
>
>
> I had assumed it was due to CPU frequency scaling, but as far as i am
> aware I have disabled all those options from the kernel and changed the
> power saving settings so it should not happen
>
>

Oh, ok.

Looking more at setitimer… are you using ‘ITIMER_REAL’, ‘ITIMER_VIRTUAL’,
or ‘ITIMER_PROF’? The man page tells that _REAL counts in real-time, while
_VIRTUAL only counts when the process is running. That could be an issue,
since a process could be bumped if higher priority items needed to be run.

Also, if you don’t handle the signal quickly enough, it may be dropped when
another signal is generated from setitimer. Are you doing heavy work in
the signal handler?


L R Nix
lornix@lornix.com

the handler is set up as follows

    // Set the timer to run continuously, producing a signal every 10ms
    timer_value.it_value.tv_sec = 0;
    timer_value.it_value.tv_usec = 1;
    timer_value.it_interval.tv_sec = 0;
    timer_value.it_interval.tv_usec = 1;

    // Store the process id of the rt transmit thread
    pid_t pid = getpid();
    Thread_Manager->Store_RT_Transmit_Process_ID( pid );

    action.sa_handler = Alarm_Signal_Wrapper;
    action.sa_flags = SA_NOMASK;
    sigemptyset(&action.sa_mask);

    sigaction( SIGALRM, &action, NULL);

    // Create the alarm timer to run every 10ms
    res = setitimer( ITIMER_REAL, &timer_value, NULL );

and the process called has only a small amount of processing:

void CTransmitter::Alarm_Signal_Wrapper( int data )
{

    static pthread_mutex_t runOnceMutex = PTHREAD_MUTEX_INITIALIZER;

    CTransmitter::instance()->Received_Signals++;

    if(pthread_mutex_trylock(&runOnceMutex) == 0)
    {
        CTransmitter::instance()->Alarm_Signal_Handler();
        pthread_mutex_unlock(&runOnceMutex);
    }

}

The alarm signal should always be processed, i will put some debug text in to try and determine if the thread is being locked out for any significant times

bewildered wrote:

>
> the handler is set up as follows
>
>
> Code:
> --------------------
> // Set the timer to run continuously, producing a signal every
> 10ms
> timer_value.it_value.tv_sec = 0;
> timer_value.it_value.tv_usec = 1;
> timer_value.it_interval.tv_sec = 0;
> timer_value.it_interval.tv_usec = 1;
>
> // Store the process id of the rt transmit thread
> pid_t pid = getpid();
> Thread_Manager->Store_RT_Transmit_Process_ID( pid );
>
> action.sa_handler = Alarm_Signal_Wrapper;
> action.sa_flags = SA_NOMASK;
> sigemptyset(&action.sa_mask);
>
> sigaction( SIGALRM, &action, NULL);
>
> // Create the alarm timer to run every 10ms
> res = setitimer( ITIMER_REAL, &timer_value, NULL );
> --------------------
>
>
> and the process called has only a small amount of processing:
>
>
> Code:
> --------------------
> void CTransmitter::Alarm_Signal_Wrapper( int data )
> {
>
> static pthread_mutex_t runOnceMutex = PTHREAD_MUTEX_INITIALIZER;
>
> CTransmitter::instance()->Received_Signals++;
>
> if(pthread_mutex_trylock(&runOnceMutex) == 0)
> {
> CTransmitter::instance()->Alarm_Signal_Handler();
> pthread_mutex_unlock(&runOnceMutex);
> }
>
> }
> --------------------
>
>
>
> The alarm signal should always be processed, i will put some debug text
> in to try and determine if the thread is being locked out for any
> significant times
>
>

Based on your code… you’re asking for a signal every microsecond, not
every 10 milliseconds.

the lines near the top of your post where you have

timer_value.it_value.tv_usec = 1;
timer_value.it_interval.tv_usec = 1;

Should be 10000 to give 10msec timing.

The units are microseconds on those struct entries.


L R Nix
lornix@lornix.com