Link to home
Start Free TrialLog in
Avatar of jgreaves
jgreaves

asked on

millisecond sleep for linux

I am looking for a millisecond acurate sleep for linux

similar to
Irmx sysrtsleep()
Avatar of dimitry
dimitry

If delay is Ok for you, you can use:
#include <linux/delay.h>
void mdelay( unsigned long milliseconds );
void udelay( unsigned long microseconds );

Note: it will be delay, not sleep.
ASKER CERTIFIED SOLUTION
Avatar of bryanh
bryanh

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
accurate to the what millisecond?  usleep can server you in micros, and you do the math etc etc etc.  as long as you are talking 10+ milliseconds, it should be real "REAL" close acuraccy to the milliseconds. If you are looking for microseconds accuracy, use real time linux www.rtl.org, the kernel is modified to real time processing.
Glibc has a bunch of high res time functions and structures in timex.h.  Check out the glibc manual at GNU.org for the details.  Maybe one of the functions will meet your needs.
Use select(). This is portable over most if not
all UNIX like platforms. As already stated by the others
posters the resolution is limited by the scheduler's
resolution (abt. 10ms in Linux).

e.g:

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int waitms(int millisecs) {

  fd_set dummy;
  struct timeval toWait;

  FD_ZERO(&dummy);
  toWait.tv_sec = millisecs / 1000;
  toWait.tv_usec = (millisecs % 1000) * 1000;

  return select(0, &dummy, NULL, NULL, &toWait);

}
If you are:
  using scheduling policy SCHED_FIFO or SCHED_RR (see "man sched_setparam")
  sleeping for <= 2ms
then use nanosleep. The kernel will busy-wait rather than rescheduling the process, so it should be accurate enough.

You can only usefully do this if the process is the only one running since you need to ensure that you aren't rescheduled immediately before or after the nanosleep.

For long time accurate sleep:

0. your task should have root privileges.

1. make sure your application pages locked in RAM (mlock or mlockall).

2. Set real-time scheduling (SHED_RR or SCHED_FIFO policy) and high priority using sched_setscheduler.

3. Let process sleep requred time minus 1/HZ (usually 10ms) using nanosleep.

4. Check the remaining time to sleep using gettimeofday (with tz == NULL).

5. Sleep the rest of time using several short nanosleep calls (<=2ms).

Of course, it is not the perfect method, use RTLinux for most accuracy (http://fsmlabs.com/community/) or any other hard real-time OS.

Andrey
I pretty much see everybody on the same page, and whatever you do, do Not use select.  Select is pretty powerful when it comes to listening to files or sockets, and will even do your timeout,BUT, Biiiig BUT.  If you receive an interrup, any type of signal, select will exit with an error code.
to determine where an error occured, one should check errno and see if it was just a signal, SIGCHLD, empty all sets and back. This is lots of time, LOTS if you are looking for ms accuracy.  

Sapa  if my mind is Not playing tricks on me, One hz is a second.
garboua:

1. you can block all signals before entering select(...), but in any case select does not provide enough accuracy. It use 1/HZ granularity.

2. HZ is not One Herz in this context. It is macros defined in /usr/include/asm/param.h and usually it equals 100. It means the frequency of timer interrupts in this system.
I he's got hard real time requirements, vanilla linux
isn't the platform to use, as already pointed out by garboua.
I don't see how any userland program can sleep with better than 1/HZ accurary (unless using SCHED_RR) since that is the timer interrupt frequency which in turn determines how often the OS is guaranteed to switch into kernel mode and schedule a waiting/sleeping process for execution.

I doesn't matter that you 'loose' some time when checking
for an interrupted sleep, if the accuracy is only about 10ms.

nanosleep with SCHED_RR is the best method, if you are sure
that the program will only run on UNIXes having that function.
Sleeps less than the clock period make sense when you're using them as a minimum delay rather than an absolute delay.  E.g. "don't bother running me again until at least 2 ms from now".  If there happens to be a clock tick or other interrupt 3 ms from now, it's OK for you to run.  If there isn't one for another 10 ms, that's OK too.

Also, it's not a very substantial change to conventional Linux to make the clock period less than 100 ms.
I was told this over the past week, but it is not 100% confirmed. there is a patch of realtime linux that would create a "software driven second auxilary clock." if this is correct, then it could be clocked at a higher rate, and you can use it to generate your interrupts and use your scheduler to use it VS onboard system clock.  
i have a pice of code in ANSI C, this is basic but useful.

#include <time.h>
void Sleep(clock_t wait)
{
        clock_t goal;
        goal = wait * (CLOCKS_PER_SEC / 1000);
        while( goal >=  clock())
                ;
}

I tooke the amouts of clock cycles per seconds, so in time in milliseconds I diveded by 1000 so i count cycles until I get my amount of time.
thx.
Fisu
Avatar of jgreaves

ASKER

used usleep();  iy worked well enough thanks