POSIX (and Linux in general) never really has guaranteed timers in the sense if you put something to sleep you can expect it to wake up at an exactly certain time. You can only ever guarantee that the wakeup occurred AFTER said time, not exactly on it and never before it*.
Linux isn't meant to be realtime and really just tries its best.
From man 2 nanosleep
which is POSIX compliant:
nanosleep() suspends the execution of the calling thread until either
at least the time specified in *req has elapsed, or the delivery of a
signal that triggers the invocation of a handler in the calling thread
or that terminates the process.
If you're expecting the ticks to be reliable, then the issue there is more likely you've got not a heuristic in place to manage a slide inside of a given window.
My suggestion here would be to rethink you're application design to be less reliable on exact wakeups, or have a failsafe in the case of a unexpected delay.
IE
- The software aborts due to some delay anomaly.
- The software on wakeup notices a difference in comparison to some other authoritative time source and 'steps' its idea of the next wakeup to compensate.
- You a print a warning or provide some other notice.
Its not really plausible to think of time as being reliable in a preemptible system. Even on bare metal.
- Non-Maskable Interrupts cannot be blocked.
- High load means you're just scheduled out for a long time.
- Interrupts to the CPU invoked by hardware can cause delays.
- Minor and Major page faults can produce very long delays between timer wakeups.
- Memory allocation on non owned memory banks by CPU adds delays.
This is really just a function of modern x86 computing.
At least on KVM, there is a clocksource called 'kvm-clock' which is supposed to represent ticks from the underlying hypervisor irrespective of any unknown delays in a VM. You can find that file and what you have set in this path: /sys/devices/system/clocksource/clocksource*/current_clocksource
and see what your options are at /sys/devices/system/clocksource/clocksource*/available_clocksource
.
But again, the underlying host can have its own delays. So its just turtles all the way down..
Don't rely on realtime guarantees where non exist. Build the software to either cope with unexpected delays or at least know about them.
NTP in general is a whole protocol meant to handle the problem of time, what time is 'correct' and what to do about handling changes to time. Its a pretty complicated problem.
The best practice is you want to set the system up to statistically make the problem unlikely, think about what (if any) would constitute a reliable authority for time in your application and then how you want to deal with the unlikely events where time does change.
Maybe you setup some SLA saying that the time will be incorrect 1 check in 1000000 samples. That is -- its possible, albeit statistically unlikely that the ticks are off.
The way I consider time when working with groups of different systems that all are related, is that its more important that their time locality* is within a small window of difference. To that extent I'd have a local time server setup which itself uses some authoritative source, then have all computers in that group sync to that local system. The very low latency to the local time server serves to reduce the local jitter and all the hosts should remain very closely synchronized.
Some timer implementations use a signal handler to trap events. IE SIGALRM, if you send a process an ALRM signal outside of the timer, it would wake up before it.
Locality here would be all computers logically related to one another all are within perhaps a few milliseconds of time within one another. But they could differ wildly between another locality, IE a group of systems which is latency wise 500ms away.