Linux clock_gettime(CLOCK_MONOTONIC) strange non-monotonic behavior
Asked Answered
F

5

29

Folks, in my application I'm using clock_gettime(CLOCK_MONOTONIC) in order to measure the delta time between frames (a typical approach in gamedev) and from time to time I'm facing a strange behavior of clock_gettime(..) - returned values occasionally are not monotonic (i.e prev. time is bigger than current time).

Currently, if such a paradox happens I simply skip the current frame and start processing the next one.

The question is how can this be possible at all? Is it a bug in Linux POSIX implementation of clock_gettime? I'm using Ubuntu Server Edition 10.04 (kernel 2.6.32-24, x86_64), gcc-4.4.3.

Fraught answered 7/9, 2010 at 9:11 Comment(2)
Are you running it in a virtualised environment by any chance?Pump
Nope, no virtualization involvedFraught
C
24

man clock_gettime says:

CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific)

Similar to CLOCK_MONOTONIC, but provides access to a raw hardware-based time that is not subject to NTP adjustments.

Since CLOCK_MONOTONIC_RAW is not subject of NTP adjustments, I guess CLOCK_MONOTONIC could be.

We had similar problems with Redhat Enterprise 5.0 with 2.6.18 kernel and some specific Itanium processor. We couldn't reproduce it with other processor on the same OS. It was fixed in RHEL 5.3 with slightly newer kernel and some Redhat patches.

Canonicals answered 7/9, 2010 at 9:23 Comment(9)
Thanks for the tip. Another lesson for me - never ever absolutely trust even the most reliable libraries :)Fraught
Interesting. But according to markmail.org/thread/54bb663vi47kjxnu even CLOCK_MONOTONIC is not supposed to be able to jump. So shouldn't it always be at least increasing?Beshrew
It says the clock can slew (may go backward IIUC), so it could be decreasing.Canonicals
I worked on the kernel clock functions for a while. The way it's supposed to work is that the MONOTONIC clock never goes backwards. That's sort of by definition.Risner
In practice, MONOTONIC is implemented as an offset from REALTIME. Any time the realtime clock is adjusted, or the system sleeps, this offset is adjusted. Under the wrong circumstances, the offset could be miscalculated, resulting in a jump -- even a backwards jump -- of the MONOTONIC clock.Risner
@edward-falk could you comment on the "wrong circumstances" and provide a status regarding CLOCK_MONOTONIC on newer kernels ? thanks.Twosided
OP didn't mention how big the errors were, but this is my experience: The built-in realtime clock in most hardware only provides time to the nearest second, while Linux keeps time internally to the nearest microsecond or nanosecond. Linux tries to resolve these issues when going to sleep and waking up, but the logic is quite convoluted and I don't understand it. Add in adjustments to REALTIME caused by NTP adjustments, user time adjustments, and who knows what else, and you have a recipe for chaos. Bottom line is that I'm not really surprised that MONTONIC sometimes goes backwards.Risner
Shouldn't the difference between CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW be NTP adjustments for clock speed, since the monotonic clocks have their own offsets? If there's a bug that causes CLOCK_MONOTONIC to jump, it would affect CLOCK_MONOTONIC_RAW as well.Atomics
CLOCK_MONOTONIC is not supposed to jump backward (or forward); if it does, that's a bug. It's subject to subtle adjustments (looks like 500 parts per million) by the NTP daemon, whereas CLOCK_MONOTONIC_RAW is not. My understanding is that the "raw" monotonic clock may not be 100% accurate, so the NTP daemon can speed it up or slow it down by a tiny bit to make it match up with the actual passage of time. If you want to do things N times per second, the non-raw clock is probably more accurate.Sextet
G
21

Looks like an instance of

commit 0696b711e4be45fa104c12329f617beb29c03f78
Author: Lin Ming <[email protected]>
Date:   Tue Nov 17 13:49:50 2009 +0800

timekeeping: Fix clock_gettime vsyscall time warp

Since commit 0a544198 "timekeeping: Move NTP adjusted clock
multiplier to struct timekeeper" the clock multiplier of vsyscall is updated with
the unmodified clock multiplier of the clock source and not with the
NTP adjusted multiplier of the timekeeper.

This causes user space observerable time warps:
new CLOCK-warp maximum: 120 nsecs,  00000025c337c537 -> 00000025c337c4bf

See here for a patch. This was included into 2.6.32.19, but may not have been backported by the Debian team(?). You should check it out.

Gaiser answered 7/9, 2010 at 9:29 Comment(0)
W
6

Try CLOCK_MONOTONIC_RAW.

Werewolf answered 7/9, 2010 at 9:15 Comment(0)
P
4

Sure sounds like a bug to me. Perhaps you should report it in Ubuntu's bug tracker.

Pump answered 7/9, 2010 at 9:16 Comment(1)
Bug trackers are nice, and so is submitting bugs (which everyone should do), but they're unpopular because programmers want fixes NOW. Generally upstream bugs aren't fixed until long after you've finished coding the majority of a project, and you have to support people who haven't upgraded the upstream libs for a long time anyway. :(Werewolf
K
0

It's a linux bug. No ajustment in a monotonic clock can make it go backwards. You're using a very old kernel and a very old distribution.

Edit: are you sure you need to skip the frame ? If you call clock_gettime again, what happens ?

Kastner answered 16/3, 2013 at 15:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.