time delay in C. usleep

Andrew picture Andrew · Oct 8, 2012 · Viewed 76.7k times · Source

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     [email protected]:/usr/obj/usr/src/sys/GENERIC  amd64

Answer

Ofir picture Ofir · Oct 8, 2012

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