Originally reported as DevCom-10913616 / VSO-2495823.
My cleaned-up repro:
#include <chrono>
#include <print>
#include <semaphore>
#include <stop_token>
#include <thread>
using namespace std;
using namespace std::chrono;
void f(stop_token stop) {
binary_semaphore new_timer{0};
for (int i = 0; i < 50 && !stop.stop_requested(); ++i) {
const auto s = steady_clock::now();
(void) new_timer.try_acquire_for(800us);
const auto e = steady_clock::now();
println("{}", duration_cast<nanoseconds>(e - s));
}
}
int main() {
jthread t(f);
this_thread::sleep_for(1s);
}
C:\Temp>cl /EHsc /nologo /W4 /std:c++latest /MT /O2 meow.cpp
meow.cpp
C:\Temp>meow
200ns
100ns
0ns
0ns
0ns
0ns
100ns
0ns
[...]
I haven't fully analyzed this, but I observe that we still have some calls to GetTickCount64(), which IIRC uses the system clock instead of a steady clock:
|
unsigned long long __stdcall __std_atomic_wait_get_deadline(const unsigned long long _Timeout) noexcept { |
|
if (_Timeout == _Atomic_wait_no_deadline) { |
|
return _Atomic_wait_no_deadline; |
|
} else { |
|
return GetTickCount64() + _Timeout; |
|
} |
|
} |
|
|
|
unsigned long __stdcall __std_atomic_wait_get_remaining_timeout(unsigned long long _Deadline) noexcept { |
|
static_assert(__std_atomic_wait_no_timeout == INFINITE, |
|
"__std_atomic_wait_no_timeout is passed directly to underlying API, so should match it"); |
|
|
|
if (_Deadline == _Atomic_wait_no_deadline) { |
|
return INFINITE; |
|
} |
|
|
|
const unsigned long long _Current_time = GetTickCount64(); |
|
if (_Current_time >= _Deadline) { |
|
return 0; |
|
} |
|
|
|
unsigned long long _Remaining = _Deadline - _Current_time; |
|
constexpr unsigned long _Ten_days = 864'000'000; |
|
if (_Remaining > _Ten_days) { |
|
return _Ten_days; |
|
} |
|
return static_cast<unsigned long>(_Remaining); |
|
} |
🛠️ Previous fixes for this category of bugs
The other uses of GetTickCount64() in sharedmutex.cpp appear to be properly "checked" in the headers against steady_clock or the user's clock. This is after the series of fixes:
Originally reported as DevCom-10913616 / VSO-2495823.
My cleaned-up repro:
I haven't fully analyzed this, but I observe that we still have some calls to
GetTickCount64(), which IIRC uses the system clock instead of a steady clock:STL/stl/src/atomic_wait.cpp
Lines 180 to 207 in 7841cf8
🛠️ Previous fixes for this category of bugs
The other uses of
GetTickCount64()in sharedmutex.cpp appear to be properly "checked" in the headers againststeady_clockor the user's clock. This is after the series of fixes:this_thread::sleep_untilclock-aware #3914this_thread::sleep_until()to consistently use the giventime_point's clock type, instead of also depending on the system clock. This also fixedthis_thread::sleep_for()to consistently usesteady_clock.condition_variable::wait_until()andcondition_variable_any::wait_until()to consistently use the giventime_point's clock type, instead of also depending on the system clock. This also fixedcondition_variable::wait_for()to consistently usesteady_clock.condition_variable_anyforsteady_clock#4755`condition_variable_any::wait_for()to consistently usesteady_clock.