Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

time delay in C. usleep

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
like image 633
Andrew Avatar asked Oct 08 '12 07:10

Andrew


People also ask

What does usleep do in C?

The function usleep() is a C API that suspends the current process for the number of microseconds passed to it. It can be used for delaying a job.

Is Usleep obsolete?

There's nothing obsolete about usleep.

What does Usleep do in Linux?

The usleep() function suspends execution of the calling thread for (at least) usec microseconds. The sleep may be lengthened slightly by any system activity or by the time spent processing the call or by the granularity of system timers.

What is the difference between sleep and Usleep?

The difference between sleep() and usleep() is that sleep() takes a number of seconds as its parameter, whereas usleep() takes a number of microseconds - millionths of a second - as its parameter.


2 Answers

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

like image 97
Ofir Avatar answered Oct 15 '22 13:10

Ofir


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.

like image 31
user4815162342 Avatar answered Oct 15 '22 13:10

user4815162342