The OS maintains various clocks, such as CLOCK_REALTIME, CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW.
CLOCK_REALTIME is defined as being the "wall clock" time, and as such, is subject to being changed by NTP, calls to adjtime(), clock changes by the system administrator, and jumps to and from DST.
PThread conditionals allow you to choose which clock the calls are synchronised with; so pthread_cond_timedwait() can synchronise with CLOCK_MONOTONIC_RAW by calling pthread_cond_init() with an appropriate attribute set.
However, no such facility exists for pthread_mutex_timedwait() or sem_timedwait(). Looking at the source code to sem_timedwait(), it appears to just translate the time given into a relative offset against gettimeofday() and then call the underlying futex() system call.
Please add facility to semaphores and mutexes to allow a choice of clocks to prevent the following scenario:
1. Program wants to call wait on a semaphore, but also process 1 second 'ticks'.
2. Program determines what the CLOCK_REALTIME time will be in 1 second, and loads this value into a 'struct timespec'.
3. At this point in time, a clock change happens (DST/NTP/adjtime/admin changing clock) - let's say DST changes the clock time by minus one hour.
4. Program calls sem_timedwait() with its timespec set to what the program believes is 1 second.
5. sem_timedwait() calls gettimeofday() and prepares its relative offset, which is now 1 hour and 1 second. It could feasibly not wake up for another hour.
This scenario isn't good if the tick is, for example, to process updates to a UI. (It could even be to update a clock time :P).
So to repeat, please add functionality to allow a C program to choose the clock source for calls to sem_timedwait() and pthread_mutex_timedwait().
DST does not affect the clock whatsoever.
Accepted - I was inferring from the Debian man page for clock_gettime() - as the "wall clock" time does change for DST. However, the issue does still apply because the clocks used for programmatic threads are subject to change with the race condition I described, even if DST isn't one of the factors that influence it (the other three do, and those are directly stated by the man pages).
I'll paste the descriptions of the clocks from the man page here, as it does add to the conversation.
Sufficiently recent versions of glibc and the Linux kernel support the
System-wide clock that measures real (i.e., wall-clock) time.
Setting this clock requires appropriate privileges. This clock
is affected by discontinuous jumps in the system time (e.g., if
the system administrator manually changes the clock), and by the
incremental adjustments performed by adjtime(3) and NTP.
Clock that cannot be set and represents monotonic time since
some unspecified starting point. This clock is not affected by
discontinuous jumps in the system time (e.g., if the system
administrator manually changes the clock), but is affected by
the incremental adjustments performed by adjtime(3) and NTP.
CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific)
Similar to CLOCK_MONOTONIC, but provides access to a raw hardâ€
ware-based time that is not subject to NTP adjustments or the
incremental adjustments performed by adjtime(3).
We must pass a time to kernel. For specifing time in other formats you would need add appropriate choice in syscalls.
Is there any news on allowing CLOCK_MONOTONIC to be used with sem_timedwait() ?
The issue we are facing on an embedded ARM project is that sem_timedwait() can misbehave when the system clock aka CLOCK_REALTIME is modified such as by a GPS timebase. Typically the system does not have a real RTC and starts at the EPOCH of 1970 and then sometime after boot the system clock gets adjusted to the present day time. This causes a misbehaviour of sem_timedwait() because an absolute timespec is used such as a time in 1970.
I think a lack of a monotonic clock for functions such as sem_timedwait() is a serious limitation in embedded systems.
I read reports on the Internet about sem_timedwait() not having a monotonic clock but no solutions or workarounds appear to be written in the reports. Does anyone have a workaround because this seems to be a long-standing issue/limitation ?
I'm using wait-calls and have problems if another process changes the time.
Would very much appreciate it if monotonic was supported somehow.
It seems this would need kernel work, to add new futex wait operations which specify a clock type. I don't think we can address this inside glibc.
I am going to assume it's not possible to use a similar method to the PThread conditionals then; shame.
As it stands (although I've not tested either - this paragraph at the moment is hypothetical) it's potentially possible for any process with the permission to set the clock to effectively hang other processes (DoS) by using a "while(1) adjtime(..);" call or by "abuse" of an upstream NTP server achieve the same thing. (Although admittedly, there would be two problems if this were to happen ;-). Doubly so if the processes use the timeout to actually do background work (which would no longer get done).
However, now three of us have seen this problem on a smaller scale in real use (myself and two other commenters), the bug is clearly not just hypothetical.
Is it worth someone who understands the underlying code better (hint, probably not me because I could not be sufficiently pedantic with the description :-), pushing this into the kernel bug tracker?
I created ticket 112521
Hmm, I'm into this problem as well. But futex(2) has supported CLOCK_MONOTONIC at least since linux kernel 3.0. It does not support CLOCK_MONOTONIC_RAW. Hint: just OR your futex command with FUTEX_CLOCK_REALTIME.
So maybe it falls back to the libc implementors after all. It should be more or less just a matter of cut'n'paste sem_timedwait() but just with OR'ing all FUTEX-commands with FUTEX_CLOCK_REALTIME.