Question

I'm developing the game server, which is written on C. And I need to develop a cycle with a certain frequency (50 times per second) to perform an algorithm. The problem is that I can't pause the program for an exact time interval - 20000 microseconds. Function usleep(20000) runs about 30000 microseconds. The result is always more on 10000 microseconds than expected.

Here is my simple example of code:

#include <stdio.h>
#include <time.h>
#include <unistd.h>

int main( int argc, char ** argv )
{

        const unsigned long long nano = 1000000000;
        unsigned long long t1, t2;

        struct timespec tm;

        for(;;)
        {

                clock_gettime( CLOCK_REALTIME, &tm );
                t1 = tm.tv_nsec + tm.tv_sec * nano;

                usleep( 20000 );

                clock_gettime( CLOCK_REALTIME, &tm );
                t2 = tm.tv_nsec + tm.tv_sec * nano;

                printf( "delay: %ld\n", ( t2 - t1 ) / 1000 );
        }

        return 0;

}

And the result of it's running:

$ ./a.out
delay: 29233
delay: 29575
delay: 29621
delay: 29694
delay: 29688
delay: 29732
delay: 29709
delay: 29706
delay: 29666
delay: 29702
delay: 29702
delay: 29705
delay: 29789
delay: 29619
delay: 29785
delay: 29634
delay: 29692
delay: 29708
delay: 29701
delay: 29703

I also tried to use function select(), but result is the same as with the sleep().

Explain to me, please, what's wrong with my code.

p.s.:

$ uname -a
FreeBSD home.com 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan  3 07:46:30 UTC 2012     root@farrell.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  amd64
Was it helpful?

Solution

Instead of sleeping for 20000 useconds, sleep for the time left till you want to run again, based on the call to clock_gettime

I.e:

usleep( lasttime+20000-now ); // But make sure you don't sleep when the result is negative

It is not that your code has a problem, but the actual call to sleep, reading the time, etc. takes time, and the system can't sleep for the exact time anyway unless it is a multiple of its exact clock cycle

OTHER TIPS

Sleeping functions on non-realtime systems are not guaranteed to sleep the exact period specified; on a busy system, the process will be woken up only when its time slice begins. Or, as the man page puts it, "system activity may lengthen the sleep by an indeterminate amount".

The close-to-10ms amount sounds like the kern.hz frequency is lowered to 100, as some recommend for VM setups.

The classic workaround for this problem is the one offered by Ofir: instead of specifying a fixed sleeping interval, specify the remaining time to sleep. In average, your loop will run every 20ms, which is what you most likely want to achieve.

In usleep function 1000000 = 1sec.

Try to change your code accordingly. So:

usleep(1000000) // generates 1 second delay
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top