C/C++ High Resolution Persistent Timer with 1000 ticks per second

Hi All,
I want to develop a functionality which should give me 1000 ticks per second. earlier on i have achieve it with Big Kernel Lock and using preemptive kernel and using CPU freq of 1000 Hz. but now in latest OpenSuse 11.3 or 11.4 Big Kernel Lock is not present and i want to produce something which can replace the existing code.
The only thing i am concerns me is to be persistence and i should raise an event or alarm every 1000th of a second. (i don’t mind if it gets more precise)

I have tried itimers, clock_settime() and clock_gettime() but i can not build my confidence on them.

Can someone please help me on this or if they have already done that would be great. I am happy to recompile the kernel and at present i recompiled it with tick-less option unchecked.

btw i am using 11.3 and 11.4 both, actually whichever works better will be my final choice.

Thanks

Shouldn’t this help?

What’s the problem? You can use clock_getres() to verify if the system have precise enough timers.

clock_getres() gives me 0 sec and 1 nsec… but is that true ?

I am going to post the code and the reasons why i think it is not reliable…

This is the code below: May be not well written but you can identify if there are any issues…


#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <iostream>
#include <cstdlib>


#define CLOCKID CLOCK_REALTIME
#define SIG SIGRTMIN

#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); } while (0)

timer_t             timerid;
struct itimerspec   last_itimer;
struct itimerspec   current_itimer;
struct itimerspec   diff_itimer;
struct timespec     res_itimer;
struct timeval last_time;
struct timeval curr_time;


long long int       counter         = 0;
static double       reps            = 0.0;
double              diff            = 0.0;
double              freq_sum        = 0.0;
double              freq_min        = 99999.0;
double              freq_max        = 0.0;
long long int       num_too_low     = 0;

static void
handler(int sig, siginfo_t *si, void *uc)
{
    /* Note: calling printf() from a signal handler is not
      strictly correct, since printf() is not async-signal-safe;
      see signal(7) */

    ++counter;
    if(counter >= 1000)
    {
        ++reps;
        if( timer_gettime(timerid, &current_itimer) != 0)
        printf ("crash");

        printf("looks like its a second, %d ", timer_getoverrun(timerid));
        printf("tv_sec  last: %d , curernt: %d , diff: %d    ", last_itimer.it_value.tv_sec, current_itimer.it_value.tv_sec, (current_itimer.it_value.tv_sec - last_itimer.it_value.tv_sec));
        printf("tv_nsec last: %d , curernt: %d , diff: %d  
", last_itimer.it_value.tv_nsec, current_itimer.it_value.tv_nsec, (current_itimer.it_value.tv_nsec - last_itimer.it_value.tv_nsec));

        last_itimer = current_itimer;
        counter = 0;
    }
}

int
main(int argc, char *argv])
{
    //timer_t timerid;
    struct      sigevent            sev;
    struct      itimerspec          its;
    long long   freq_nanosecs;
    sigset_t    mask;
    struct      sigaction           sa;

    /* Establish handler for timer signal */
    printf("Establishing handler for signal %d
", SIG);
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = handler;
    sigemptyset(&sa.sa_mask);

    if (sigaction(SIG, &sa, NULL) == -1)
        errExit("sigaction");

    /* Create the timer */
    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIG;
    sev.sigev_value.sival_ptr = &timerid;

    if (timer_create(CLOCKID, &sev, &timerid) == -1)
        errExit("timer_create");

    printf("timer ID is 0x%lx
", (long) timerid);

    /* Start the timer */
    its.it_value.tv_sec = 0;
    its.it_value.tv_nsec = 1000000;

    printf("its.it_value.tv_sec:  %d
", its.it_value.tv_sec);
    printf("its.it_value.tv_nsec: %d
", its.it_value.tv_nsec);

    its.it_interval.tv_sec = 0;
    its.it_interval.tv_nsec = 1000000;

    if (timer_settime(timerid, 0, &its, NULL) == -1)
        errExit("timer_settime");

    clock_getres(CLOCKID, &res_itimer);

    printf("Clock resolution - sec: %d ", res_itimer.tv_sec);
    printf("nsec: %d 
", res_itimer.tv_nsec);

    /* Sleep for a while; meanwhile, the timer may expire multiple times */
    while(reps <= 30.0)
    {
        sleep(1);
    }

    exit(EXIT_SUCCESS);
}

And this is output when i compile it with g++ -lrt -o
and run using
./

the output appears to be every second… but ,…


Establishing handler for signal 34
timer ID is 0x804b008
its.it_value.tv_sec:  0
its.it_value.tv_nsec: 1000000
Clock resolution - sec: 0 nsec: 1
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 0 , curernt: 988307 , diff: 988307
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 988307 , curernt: 976078 , diff: -12229
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 976078 , curernt: 986469 , diff: 10391
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 986469 , curernt: 910381 , diff: -76088
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 910381 , curernt: 990134 , diff: 79753
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990134 , curernt: 986030 , diff: -4104
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 986030 , curernt: 986349 , diff: 319
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 986349 , curernt: 990956 , diff: 4607
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990956 , curernt: 990215 , diff: -741
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990215 , curernt: 991776 , diff: 1561
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991776 , curernt: 991923 , diff: 147
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991923 , curernt: 926336 , diff: -65587
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 926336 , curernt: 912838 , diff: -13498
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 912838 , curernt: 991112 , diff: 78274
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991112 , curernt: 991231 , diff: 119
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991231 , curernt: 986628 , diff: -4603
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 986628 , curernt: 991195 , diff: 4567
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991195 , curernt: 991163 , diff: -32
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991163 , curernt: 991016 , diff: -147
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991016 , curernt: 988656 , diff: -2360
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 988656 , curernt: 990801 , diff: 2145
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990801 , curernt: 990767 , diff: -34
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990767 , curernt: 991837 , diff: 1070
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991837 , curernt: 991886 , diff: 49
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991886 , curernt: 990674 , diff: -1212
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990674 , curernt: 912867 , diff: -77807
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 912867 , curernt: 990602 , diff: 77735
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990602 , curernt: 991561 , diff: 959
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991561 , curernt: 987454 , diff: -4107
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987454 , curernt: 990754 , diff: 3300
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990754 , curernt: 990528 , diff: -226  

please advice if i am doing something wrong and how it should work …

Reasons that i think it is not good enough that ,… when i change values for


    its.it_value.tv_sec = 0;
    its.it_value.tv_nsec = 1000000;
    its.it_interval.tv_sec = 0;
    its.it_interval.tv_nsec = 1000000;

to some other value i.e. 1000000 to 1000 it stops displaying anything and this is also true for various other values i.e. if i change sec to other than zero…

SOS!!! :slight_smile:

sorry i am not professional about it…

Better off Ted Season 1 DVD

worked fine for me changing to 1 second.


Establishing handler for signal 34
timer ID is 0x603010
its.it_value.tv_sec:  1
its.it_value.tv_nsec: 0
Clock resolution - sec: 0 nsec: 1 
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 0 , curernt: 999973549 , diff: 999973549  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999973549 , curernt: 999982506 , diff: 8957  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999982506 , curernt: 999981875 , diff: -631  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999981875 , curernt: 999981486 , diff: -389  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999981486 , curernt: 999981384 , diff: -102  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999981384 , curernt: 999980558 , diff: -826  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999980558 , curernt: 999979980 , diff: -578  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999979980 , curernt: 999979878 , diff: -102  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999979878 , curernt: 999982981 , diff: 3103  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999982981 , curernt: 999981622 , diff: -1359  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999981622 , curernt: 999980107 , diff: -1515  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999980107 , curernt: 999979506 , diff: -601  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999979506 , curernt: 999981776 , diff: 2270  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999981776 , curernt: 999982544 , diff: 768  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999982544 , curernt: 999980260 , diff: -2284  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999980260 , curernt: 999979632 , diff: -628  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999979632 , curernt: 999979589 , diff: -43  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999979589 , curernt: 999980404 , diff: 815  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999980404 , curernt: 999979602 , diff: -802  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999979602 , curernt: 999981590 , diff: 1988  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999981590 , curernt: 999981295 , diff: -295  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999981295 , curernt: 999982073 , diff: 778  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999982073 , curernt: 999981292 , diff: -781  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999981292 , curernt: 999980008 , diff: -1284  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999980008 , curernt: 999980678 , diff: 670  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999980678 , curernt: 999980165 , diff: -513  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999980165 , curernt: 999980532 , diff: 367  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999980532 , curernt: 999980129 , diff: -403  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999980129 , curernt: 999975106 , diff: -5023  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999975106 , curernt: 999980244 , diff: 5138  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 999980244 , curernt: 999973721 , diff: -6523  


All I changed was the its values and then I the signal handler to display everything if counter >= 1:

Oh I junked the two c++ headers and compiled with gcc instead while I was fiddling around, I doubt that did anything though, anyhow here’s the diff:

6a7
> /*
9c10
< 
---
> */
41c42
<     if(counter >= 1000)
---
>     if(counter >= 1)
80c81
<     if (timer_create(CLOCKID, &sev, &timerid) == -1)
---
>     if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1)
86,87c87,88
<     its.it_value.tv_sec = 0;
<     its.it_value.tv_nsec = 1000000;
---
>     its.it_value.tv_sec = 1;
>     its.it_value.tv_nsec = 0;
92,93c93,94
<     its.it_interval.tv_sec = 0;
<     its.it_interval.tv_nsec = 1000000;
---
>     its.it_interval.tv_sec = 1;
>     its.it_interval.tv_nsec = 0;

As far as I know, you can just ignore values under a millisecond, I’ve never seen anything suggesting you can get a better timer frequency than that, meaning everything’s working fine.

Don’t know why your code isn’t printing, did you overlook changing the threshold value on the counter variable in the signal handler when you fiddled with the frequencies?

oh wait, carry the one…

Yeah I guess those are off by more than a millisecond on some of them. I’m in the standard desktop kernel in 11.3, I have a custom kernel with all the frequency things jacked up that I will try as an experiment as soon as I can reboot.

Ok, I just tried this with a custom kernel, on the original code posted got the accuracy to within a microsecond:


Establishing handler for signal 34
timer ID is 0x603010
its.it_value.tv_sec:  0
its.it_value.tv_nsec: 1000000
Clock resolution - sec: 0 nsec: 1 
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 0 , curernt: 982290 , diff: 982290  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 982290 , curernt: 987449 , diff: 5159  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987449 , curernt: 987456 , diff: 7  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987456 , curernt: 987167 , diff: -289  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987167 , curernt: 987274 , diff: 107  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987274 , curernt: 987375 , diff: 101  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987375 , curernt: 987392 , diff: 17  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987392 , curernt: 987243 , diff: -149  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987243 , curernt: 987305 , diff: 62  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987305 , curernt: 987357 , diff: 52  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987357 , curernt: 987213 , diff: -144  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987213 , curernt: 987546 , diff: 333  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987546 , curernt: 987598 , diff: 52  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987598 , curernt: 987434 , diff: -164  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987434 , curernt: 987160 , diff: -274  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987160 , curernt: 986931 , diff: -229  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 986931 , curernt: 987349 , diff: 418  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987349 , curernt: 987601 , diff: 252  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987601 , curernt: 987598 , diff: -3  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987598 , curernt: 987324 , diff: -274  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987324 , curernt: 987260 , diff: -64  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987260 , curernt: 987106 , diff: -154  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987106 , curernt: 987324 , diff: 218  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987324 , curernt: 987431 , diff: 107  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987431 , curernt: 987091 , diff: -340  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987091 , curernt: 987299 , diff: 208  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987299 , curernt: 987466 , diff: 167  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987466 , curernt: 987432 , diff: -34  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987432 , curernt: 987434 , diff: 2  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987434 , curernt: 987441 , diff: 7  
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987441 , curernt: 987382 , diff: -59  

Was considerably less accurate using the version giving the timing interval in seconds. I’m actually pretty flabergasted, I had mixed up the decimial places in my last post, everything there was well under a millesecond, but that many timers under a microsecond must mean something and I didn’t think that was supported.

I don’t know why the timer claims it has a resolution of a nanosecond, since I really, really, don’t think there is any way to get it that accurate. The clockspeed of my chip is less than 2 gigahertz, unless it’s spending half it’s time updating the clock then it’s not going to get to nanosecond accuracy, and that’s assuming that it’s free to switch between threads, which it isn’t (but I guess there are 4 hardware threads on a Core 2 Duo?).

Are you sure you have all the low-latency options that fall under the processor category in “make menuconfig” checked off? I was customizing a stock 2.6.37, latency options I have checked off are: “Tickless System,” “High Resolution Timer Support,” (that one kind of sounds important), “Preemption Model,” “Timer frequency (1000 hz),” (that’s why I thought you couldn’t get a timer to work at better than a millisecond), “SMT (Hyperthreading) Scheduler Support”, “Multi-core scheduler support”, “Fine-granularity task level IRQ reporting,” and I hope that’s it because my fingers are sore.

On a personal note, I have a lot of stuff in my kernel that doesn’t have to be there, I think I will yank it out when I get around to it.

Thanks Malcolm,

Right i think my code requires the mods to the kernel as u have mentioned to run “little” accurate then on standard kernel.

I agree there is no posible way to get the time accuracey upto nanoseconds. i think the Timer Frequency listed under kernel options as 1000Hz could be the one preventing it.


My kernel has following options set to:

Preemption Model -> Preemptible Kernel (Low-Latancy Desktop) --- ON
Tickless System ------------------------------------------------ OFF
SMT (Hyperthreading) Scheduler Support ------------------------  ON
High Resolution Timer Support ---------------------------------  ON
Timer frequency -> 1000 hz  -----------------------------------  ON 
Multi-core scheduler support ----------------------------------  ON

In addtion to the above, you may be interested in knowing these:
Process Family -> Pentium Pro ---------------------------------  ON
(my processor is Pentium Intel Core vPro)
HPET Timer Support --------------------------------------------  ON

Also, do u think that power management could influence this:
Power management and ACPI options -> CPU Frequency Scaling is turned ON

Kernel Version i have here is: 2.6.34-12-desktop #1 SMP PREEMPT (extracted from uname -a)

I could not find the option for:

Fine-granularity task level IRQ reporting: ??????


The output of this program where it says…


"looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 0 , curernt: 982290 , diff: 982290 "

i am expecting “diff: 1” at least with plus or minus few nanoseconds… i think which will show that this line is output after every 1 second.

I think it is a second at that time but the only thing i want to ensure is that if my understanding is correct or not… or in other words i want a way to prove this happen every second…

Let me know if i am thinking correct of is there anything i am completly missing…

can anyone help ?

any one ?

it will be really helpful

I don’t think you can achieve nanosecond accuracy on a Linux kernel, not even with special realtime patches. Also you should not confuse resolution (=1ns) and accuracy (>=1ns).

If i’m reading the output right, while your average error is pretty good (single microseconds), your problem are the spikes at ~70 microseconds?

To make this more deterministic, don’t use blocking calls (like printf) and maybe have a look at scheduling parameters… maybe also at CLOCK_MONOTONIC.

Thanks Chenz, I can understand calls like printf are not helpful but i dont have anyother option as well, I read Monotonic and i think realtime clock if not better than monotonic is not worst either i.e. both are similar in the fashion they go through each tick only difference is the point of reference from where they start.

Also i know i can not achieve ns accuracy because Time Freq specified in kernel can go up to 1000Hz, i am just only trying to achieve CONSISTANCE 1000 Hz clock freq.

Thanks a lot for looking into this.

I will try to run it in my compiler and see.

thanks i will wait for your reply

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <iostream>
#include <cstdlib>


#define CLOCKID CLOCK_REALTIME
#define SIG SIGRTMIN

#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); } while (0)

timer_t             timerid;
struct itimerspec   last_itimer;
struct itimerspec   current_itimer;
struct itimerspec   diff_itimer;
struct timespec     res_itimer;
struct timeval last_time;
struct timeval curr_time;


long long int       counter         = 0;
static double       reps            = 0.0;
double              diff            = 0.0;
double              freq_sum        = 0.0;
double              freq_min        = 99999.0;
double              freq_max        = 0.0;
long long int       num_too_low     = 0;

static void
handler(int sig, siginfo_t *si, void *uc)
{
    /* Note: calling printf() from a signal handler is not
      strictly correct, since printf() is not async-signal-safe;
      see signal(7) */

    ++counter;
    if(counter >= 1000)
    {
        ++reps;
        if( timer_gettime(timerid, &current_itimer) != 0)
        printf ("crash");

        printf("looks like its a second, %d ", timer_getoverrun(timerid));
        printf("tv_sec  last: %d , curernt: %d , diff: %d    ", last_itimer.it_value.tv_sec, current_itimer.it_value.tv_sec, (current_itimer.it_value.tv_sec - last_itimer.it_value.tv_sec));
        printf("tv_nsec last: %d , curernt: %d , diff: %d  
", last_itimer.it_value.tv_nsec, current_itimer.it_value.tv_nsec, (current_itimer.it_value.tv_nsec - last_itimer.it_value.tv_nsec));

        last_itimer = current_itimer;
        counter = 0;
    }
}

int
main(int argc, char *argv])
{
    //timer_t timerid;
    struct      sigevent            sev;
    struct      itimerspec          its;
    long long   freq_nanosecs;
    sigset_t    mask;
    struct      sigaction           sa;

    /* Establish handler for timer signal */
    printf("Establishing handler for signal %d
", SIG);
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = handler;
    sigemptyset(&sa.sa_mask);

    if (sigaction(SIG, &sa, NULL) == -1)
        errExit("sigaction");

    /* Create the timer */
    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIG;
    sev.sigev_value.sival_ptr = &timerid;

    if (timer_create(CLOCKID, &sev, &timerid) == -1)
        errExit("timer_create");

    printf("timer ID is 0x%lx
", (long) timerid);

    /* Start the timer */
    its.it_value.tv_sec = 0;
    its.it_value.tv_nsec = 1000000;

    printf("its.it_value.tv_sec:  %d
", its.it_value.tv_sec);
    printf("its.it_value.tv_nsec: %d
", its.it_value.tv_nsec);

    its.it_interval.tv_sec = 0;
    its.it_interval.tv_nsec = 1000000;

    if (timer_settime(timerid, 0, &its, NULL) == -1)
        errExit("timer_settime");

    clock_getres(CLOCKID, &res_itimer);

    printf("Clock resolution - sec: %d ", res_itimer.tv_sec);
    printf("nsec: %d 
", res_itimer.tv_nsec);

    /* Sleep for a while; meanwhile, the timer may expire multiple times */
    while(reps <= 30.0)
    {
        sleep(1);
    }

    exit(EXIT_SUCCESS);
}

This program looks like a Endless loop. See in red. I will try to write it in the begging in C++ only.
I must check firstly these libraries, and then I will start it in my compiler. These days I will check it more carefully and correct it if I will find errors. ok??? Anyway could you give me the vocalization of this program??? Sorry but I have checked it very quickly.

His result is that

looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 0 , curernt: 988307 , diff: 988307
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 988307 , curernt: 976078 , diff: -12229
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 976078 , curernt: 986469 , diff: 10391
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 986469 , curernt: 910381 , diff: -76088
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 910381 , curernt: 990134 , diff: 79753
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990134 , curernt: 986030 , diff: -4104
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 986030 , curernt: 986349 , diff: 319
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 986349 , curernt: 990956 , diff: 4607
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990956 , curernt: 990215 , diff: -741
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990215 , curernt: 991776 , diff: 1561
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991776 , curernt: 991923 , diff: 147
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991923 , curernt: 926336 , diff: -65587
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 926336 , curernt: 912838 , diff: -13498
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 912838 , curernt: 991112 , diff: 78274
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991112 , curernt: 991231 , diff: 119
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991231 , curernt: 986628 , diff: -4603
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 986628 , curernt: 991195 , diff: 4567
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991195 , curernt: 991163 , diff: -32
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991163 , curernt: 991016 , diff: -147
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991016 , curernt: 988656 , diff: -2360
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 988656 , curernt: 990801 , diff: 2145
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990801 , curernt: 990767 , diff: -34
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990767 , curernt: 991837 , diff: 1070
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991837 , curernt: 991886 , diff: 49
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991886 , curernt: 990674 , diff: -1212
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990674 , curernt: 912867 , diff: -77807
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 912867 , curernt: 990602 , diff: 77735
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990602 , curernt: 991561 , diff: 959
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 991561 , curernt: 987454 , diff: -4107
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 987454 , curernt: 990754 , diff: 3300
looks like its a second, 0 tv_sec  last: 0 , curernt: 0 , diff: 0    tv_nsec last: 990754 , curernt: 990528 , diff: -226

I’m not sure what the situation is for openSuSE, but in the SLES 11 SP1 world the stability of the kernel (ie how fast it gives a core to the process being scheduled) depends on a lot of factors. If the default is taken, then the stability can be as bad as multiple milliseconds.

I’m not entirely sure that CLOCK_REALTIME is a good clock choice if you’re on multiple cores / CPUs - you may have to go to CLOCK_MONOTONIC to avoid the problem of different TSC values on different CPU cores.

Another factor that plays in to scheduling stability is which scheduler you use - forcing the SCHED_RR scheduler for the process, with a scheduling priority of 90+ is a good start.

Something that’s often overlooked is that one of the biggest contributors to low stability for the linux kernel is the hardware interrupts from the ACPI etc - they can take “relatively” forever to deal with. So turning off all manners of CPU power saving in the BIOS (and killing powersaved), CPU “Turbo” settings, etc, is a good start as well.

The best scenario we’ve seen so far with the SLRrt 11 SP1 setup is a stability in single microseconds range.

I will create it from the beginning using other libraries.

These libraries you need to use to solve this problem: first library iostream(for input and output devices), cstdlib, sys/time,signal and cpufreq.h
Firstly write your program in a compiler or in Kwrite and test it there, then write it in your terminal.

Be careful with repetitions.

I started this thread, but i think we kind of deviated from the original topic into the coding practice,…

All you said above regarding loops and etc,… i am aware of that,… the only thing i want is the presistance timers which can do any job at a specific interval.

I think if you re-read my earlier posts in this thread it is more obvious… by the way i really appreciate that you guys spend some time looking at it,… but on this side i m still confused and not confident on these timers…

if you guys think that above code is rubish,… i have no problem with that but can you come up with something more realistic i.e. another code which does the job.

One thing i m certain that CLOCK_REALTIME and CLOCK_MONOTONIC is not going to make any difference because it is not about when the clock started running but the time between the 2 ticks of a clock, which i believe should be exactly same.

Hope to hear from you guys soon, i want to fix this asap. Thanks for all your efforts.