On Wed Jan 14 08:33:01 2026 +0000, Rémi Bernon wrote:
This is still not going to work. Trying to get a more accurate bias by reading it in a loop is inefficient. It also leads to varying bias values over time which could end up with spurious time jumps back and forth in time when read from client side. For the latter, after resuming from suspend you could have client read QPC, read interrupt bias before wineserver has updated it, wineserver gets scheduled and update interrupt bias and time, client reads interrupt time and finds it close enough to QPC, assumes that read bias is good when it's not. We can't be jumping back and forth, because the bias is only ever increased, and only past a comparatively large threshold of one millisecond for a measurement that has jitter in the nanosecond range.
For the latter, after resuming from suspend you could have client read QPC, read interrupt bias before wineserver has updated it, wineserver gets scheduled and update interrupt bias and time, client reads interrupt time and finds it close enough to QPC, assumes that read bias is good when it's not.
Reading the bias again after the presumed interrupt time again and comparing it would fix this, but I am not too sure such a complex solution for this case needs to be engineered here. On a side note regarding measuring this in user space and efficiency, the loop never did more than one iteration on any configuration I tested, with a script continually suspending and resuming the system. I originally thought that these are also system calls, but that is not true on modern Linux and macOS, where they are directly read from vDSO and commpage respectively. It is mostly for peace of mind in the unlikely case of suspend right between the biased and unbiased time measurement. Interestingly there are also the private macOS apis `mach_get_times(uint64_t* absolute_time, uint64_t* cont_time, struct timespec *tp)` and `uint64_t _mach_continuous_time_base(void)`, with the former fetching a triplet of all aligned values and the latter being exactly the offset between suspended and unsuspended time. Comparing this implementation to the true value the system uses, I got an error between 0 and 14ns with the current approach. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9875#note_126914