This now accounts for system suspend periods on Linux, similar to how native win32 ticks work.
On macOS `mach_continuous_time` already does so.
On BSDs (and other POSIX compliant operating systems) `CLOCK_MONOTONIC` likewise includes suspend time. However they also provide a `CLOCK_BOOTTIME`, which does *not* include suspend time, hence the added `__linux__` check there.
From: Marc-Aurel Zent mzent@codeweavers.com
This now accounts for system suspend periods.
See https://lkml.org/lkml/2020/5/8/1707 --- dlls/ntdll/unix/sync.c | 4 ++-- server/request.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index acdb7b3d9f8..87cd2b2f4b9 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -94,8 +94,8 @@ static inline ULONGLONG monotonic_counter(void) return mach_continuous_time() * timebase.numer / timebase.denom / 100; #elif defined(HAVE_CLOCK_GETTIME) struct timespec ts; -#ifdef CLOCK_MONOTONIC_RAW - if (!clock_gettime( CLOCK_MONOTONIC_RAW, &ts )) +#if defined(__linux__) && defined(CLOCK_BOOTTIME) + if (!clock_gettime( CLOCK_BOOTTIME, &ts )) return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100; #endif if (!clock_gettime( CLOCK_MONOTONIC, &ts )) diff --git a/server/request.c b/server/request.c index 835ea30cec3..9b791b68bc3 100644 --- a/server/request.c +++ b/server/request.c @@ -515,8 +515,8 @@ timeout_t monotonic_counter(void) return mach_continuous_time() * timebase.numer / timebase.denom / 100; #elif defined(HAVE_CLOCK_GETTIME) struct timespec ts; -#ifdef CLOCK_MONOTONIC_RAW - if (!clock_gettime( CLOCK_MONOTONIC_RAW, &ts )) +#if defined(__linux__) && defined(CLOCK_BOOTTIME) + if (!clock_gettime( CLOCK_BOOTTIME, &ts )) return (timeout_t)ts.tv_sec * TICKS_PER_SEC + ts.tv_nsec / 100; #endif if (!clock_gettime( CLOCK_MONOTONIC, &ts ))
On BSDs (and other POSIX compliant operating systems) `CLOCK_MONOTONIC` likewise includes suspend time. However they also provide a `CLOCK_BOOTTIME`, which does _not_ include suspend time, hence the added `__linux__` check there.
Which BSDs? As far as I can see, FreeBSD seems to include suspend time, and NetBSD doesn't have this clock.
On Tue Sep 9 12:12:14 2025 +0000, Elizabeth Figura wrote:
On BSDs (and other POSIX compliant operating systems)
`CLOCK_MONOTONIC` likewise includes suspend time. However they also provide a `CLOCK_BOOTTIME`, which does _not_ include suspend time, hence the added `__linux__` check there. Which BSDs? As far as I can see, FreeBSD seems to include suspend time, and NetBSD doesn't have this clock.
I was looking at FreeBSD indeed (and others, but can't remember the details).
My original assumption was that it does have `CLOCK_BOOTTIME`, and that it does not include suspend time, but `CLOCK_MONOTONIC` does given the following man page:
``` CLOCK_MONOTONIC Increments in SI seconds.
CLOCK_BOOTTIME Starts at zero when the kernel boots and increments monotoni- cally in SI seconds while the machine is running. ```
The also state
Finally, `CLOCK_BOOTTIME` is an alias for `CLOCK_UPTIME` for compatibility with other systems.
Now this makes it sound like `CLOCK_BOOTTIME` should be without suspend (which it is) and that `CLOCK_MONOTONIC` is different, but in reality it is a bit more messy, at least for [FreeBSD](https://reviews.freebsd.org/D39270?id=).
On OpenBSD and macOS `CLOCK_MONOTONIC` does include suspend time, but on FreeBSD there still isn't a suspend-aware clock AFAICT, but they are working on it and it will also be `CLOCK_MONOTONIC` and not `CLOCK_BOOTTIME`.
Which probably means that technically that `__linux__` check there might not be needed right now, but in the future. Even so Linux was the only platform I found that works in this way with `CLOCK_MONOTONIC` not including suspend and a `CLOCK_BOOTTIME` (or equivalent) including suspend. There was even a try to change this, but it got reverted due to application breakage: https://lkml.indiana.edu/1804.3/02844.html
Is this really how we want monotonic_counter to work? AFAIK native RtlQueryPerformanceCounter is mostly just a rdtscp, and although its behavior is hardware-dependent, I'm not sure it should account for suspend time but rather just start counting again from where it was resumed.
On Tue Sep 9 13:19:22 2025 +0000, Rémi Bernon wrote:
Is this really how we want monotonic_counter to work? AFAIK native RtlQueryPerformanceCounter is mostly just a rdtscp, and although its behavior is hardware-dependent, I'm not sure it should account for suspend time but rather just start counting again from where it was resumed.
It does include suspend time at least in my own testing and according to [MSDN](https://learn.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resol...):
QueryPerformanceCounter reads the performance counter and returns the total number of ticks that have occurred since the Windows operating system was started, including the time when the machine was in a sleep state such as standby, hibernate, or connected standby.
It can also be a more abstract and does not need represent a hardware value
Often QueryPerformanceFrequency doesn't return the actual frequency of the hardware tick generator. For example, in some older versions of Windows, QueryPerformanceFrequency returns the TSC frequency divided by 1024; and when running under a hypervisor that implements the hypervisor version 1.0 interface (or always in some newer versions of Windows), the performance counter frequency is fixed to 10 MHz. As a result, don't assume that QueryPerformanceFrequency will return a value derived from the hardware frequency.
`GetTickCount`, etc. similarly include suspend time. The most interesting thing I found though in regards to suspend time counting behavior was that `WaitForSingleObjectEx` and friends *stopped* including suspend time in newer versions (which is a different problem to the one here though):
Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008, and Windows Server 2008 R2: The dwMilliseconds value does include time spent in low-power states. For example, the timeout does keep counting down while the computer is asleep.
Windows 8 and newer, Windows Server 2012 and newer: The dwMilliseconds value does not include time spent in low-power states. For example, the timeout does not keep counting down while the computer is asleep.
On Tue Sep 9 12:23:41 2025 +0000, Marc-Aurel Zent wrote:
I was looking at FreeBSD indeed (and others, but can't remember the details). My original assumption was that it does have `CLOCK_BOOTTIME`, and that it does not include suspend time, but `CLOCK_MONOTONIC` does given the following man page:
CLOCK_MONOTONIC Increments in SI seconds. CLOCK_BOOTTIME Starts at zero when the kernel boots and increments monotoni- cally in SI seconds while the machine is running.
They also state
Finally, `CLOCK_BOOTTIME` is an alias for `CLOCK_UPTIME` for
compatibility with other systems. Now this makes it sound like `CLOCK_BOOTTIME` should be without suspend (which it is) and that `CLOCK_MONOTONIC` is different, but in reality it is a bit more messy, at least for [FreeBSD](https://reviews.freebsd.org/D39270?id=). On OpenBSD and macOS `CLOCK_MONOTONIC` does include suspend time, but on FreeBSD there still isn't a suspend-aware clock AFAICT, but they are working on it and it will also be `CLOCK_MONOTONIC` and not `CLOCK_BOOTTIME`. Which probably means that technically that `__linux__` check there might not be needed right now, but in the future. Even so Linux was the only platform I found that works in this way with `CLOCK_MONOTONIC` not including suspend and a `CLOCK_BOOTTIME` (or equivalent) including suspend. There was even a try to change this, but it got reverted due to application breakage: https://lkml.indiana.edu/1804.3/02844.html
Hmm okay, I found a different FreeBSD manpage, which more explicitly says that both BOOTTIME and MONOTONIC do include suspend:
https://man.freebsd.org/cgi/man.cgi?query=clock_gettime&apropos=0&se...
On Thu Sep 11 17:29:39 2025 +0000, Elizabeth Figura wrote:
Hmm okay, I found a different FreeBSD manpage, which more explicitly says that both BOOTTIME and MONOTONIC do include suspend: https://man.freebsd.org/cgi/man.cgi?query=clock_gettime&apropos=0&se...
Ah I was looking at https://man.freebsd.org/cgi/man.cgi?query=clock_gettime
Well it seems they implemented things differently to what they intended to do, and given that previous versions did not include suspend and now `CLOCK_BOOTTIME` behaves identical to `CLOCK_MONOTONIC` (both including suspend) that `__linux__` check is really unnecessary there now.
I couldn't find any other BSD with `CLOCK_BOOTTIME` so I will just remove it.