timer - How do I get the most accurate realtime periodic interrupts in Linux? -


i want interrupted @ frequencies powers of ten, enabling interrupts /dev/rtc isn't ideal. i'd sleep 1 millisecond or 250 microseconds between interrupts.

enabling periodic interrupts /dev/hpet works pretty well, doesn't seem work on machines. can't use on machines don't have hpet. can't working on machines have hpet available clocksource either. example, on core 2 quad, example program included in kernel documentation fails @ hpet_ie_on when set poll.

it nicer use itimer interface provided linux instead of interfacing hardware device driver directly. , on systems, itimer provides periodic interrupts more stable on time. is, since hpet can't interrupt @ frequency want, interrupts start drift wall time. i'm seeing systems sleep way longer (10+ milliseconds) should using itimer.

here's test program using itimer interrupts. on systems print out 1 warning that's slept 100 microseconds or on target time. on others, print out batches of warning slept 10+ milliseconds on target time. compile -lrt , run sudo chrt -f 50 [name]

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <error.h> #include <errno.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/time.h> #include <time.h> #include <signal.h> #include <fcntl.h> #define ns_per_second 1000000000ll #define timespec_to_ns( atime ) ( ( ns_per_second * ( ( long long int ) atime.tv_sec ) ) \     + atime.tv_nsec )  int main() {     // block alarm signal, waited on explicitly     sigset_t lalarm;     sigemptyset( &lalarm );     sigaddset( &lalarm, sigalrm  );     sigprocmask( sig_block, &lalarm, null );      // set periodic interrupt timer     struct itimerval ltimer;     int lreceivedsignal = 0;      ltimer.it_value.tv_sec = 0;     ltimer.it_value.tv_usec = 250;     ltimer.it_interval = ltimer.it_value;      // start timer     if ( setitimer( itimer_real, &ltimer, null ) != 0 )     {         error( exit_failure, errno, "could not start interval timer" );     }     struct timespec llasttime;     struct timespec lcurrenttime;     clock_gettime( clock_realtime, &llasttime );     while ( 1 )     {         //periodic wait         if ( sigwait( &lalarm, &lreceivedsignal ) != 0 )         {             error( exit_failure, errno, "failed wait next clock tick" );         }         clock_gettime( clock_realtime, &lcurrenttime );         long long int ldifference =              ( timespec_to_ns( lcurrenttime ) - timespec_to_ns( llasttime ) );         if ( ldifference  > 300000 )         {             fprintf( stderr, "waited long: %lld\n", ldifference  );         }         llasttime = lcurrenttime;     }     return 0; } 

i've had same problem bare setitimer() setup. problem process scheduled sched_other policy on static priority level 0 default. means you're in pool other processes, , dynamic priorities decide. moment there system load, latencies.

the solution use sched_setscheduler() system call, increase static priority @ least one, , specify sched_fifo policy. causes dramatic improvement.

#include <sched.h> ... int main(int argc, char *argv[]) {     ...     struct sched_param schedp;     schedp.sched_priority = 1;     sched_setscheduler(0, sched_fifo, &schedp);     ... } 

you have run root able this. alternative use chrt program same, must know pid of rt process.

sudo chrt -f -p 1 <pid> 

see blog post here.


Comments