Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SuspendingClock on Windows does not suspend #63225

Merged

Conversation

grynspan
Copy link
Contributor

@grynspan grynspan commented Jan 25, 2023

This PR replaces the implementation of SuspendingClock on Windows with one that uses QueryUnbiasedInterruptTimePrecise(), which does suspend.

I also updated swift_get_clock_res() to produce accurate values on Windows instead of a hard-coded 1µs resolution.

Raymond Chen gives a little bit of info about the various timer APIs here.

Resolves #63224.

@grynspan grynspan requested review from compnerd and phausler January 25, 2023 22:41
@grynspan grynspan force-pushed the jgrynspan/63224-suspending-clock-windows branch from 399945e to 27c684f Compare January 25, 2023 22:45
@grynspan
Copy link
Contributor Author

@swift-ci please test

Copy link
Member

@compnerd compnerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing this! I think that the commit message could be better (the issue helped me understand the change).

*seconds = 0;
*nanoseconds = 1000;
*nanoseconds = 1000000000 / freq.QuadPart;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QueryPerformanceFrequency() never reports zero post-Windows XP. If we're concerned about that, we can check.

@@ -159,7 +153,7 @@ switch (clock_id) {
*nanoseconds = suspending.tv_nsec;
#elif defined(_WIN32)
*seconds = 0;
*nanoseconds = 1000;
*nanoseconds = 100;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QueryUnbiasedInterruptTimePrecise() has a unit of 100ns, so its highest possible resolution is 100ns. Neat.

@grynspan
Copy link
Contributor Author

@swift-ci please test

… be dynamically looked up. Also, fix the math after calling it, and avoid floating-point math on the continuous

clock.
@grynspan
Copy link
Contributor Author

@swift-ci please test

@grynspan grynspan requested a review from al45tair January 26, 2023 17:31
Copy link
Contributor

@al45tair al45tair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about the change to the division; could you check that, please.

stdlib/public/Concurrency/Clock.cpp Outdated Show resolved Hide resolved
stdlib/public/Concurrency/Clock.cpp Outdated Show resolved Hide resolved
- Use 128-bit math with QueryPerformanceCounter() to avoid overflowing.
- Use swift::fatalError() instead of abort() for bad clock IDs.
- Use digit separators (C++14 feature, makes large integers easier to read.)
@grynspan
Copy link
Contributor Author

@swift-ci please test

// count in nanoseconds. Use 128-bit math to avoid overflowing.
DWORD64 hi = 0;
DWORD64 lo = _umul128(count.QuadPart, 1'000'000'000, &hi);
DWORD64 ns = _udiv128(hi, lo, freq.QuadPart, nullptr);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_udiv128() generates a GPF if the result can't fit in a 64-bit integer, but if that happens that means the computer's been up for more than 2^64 nanoseconds… that's 584 years. If anybody runs into that problem, please let my great-great-great-great-great-great-great-great-great-great-great-great-great-great-great-great-great-great-great-great-great-great-great-great-great-great-grandkid know.

@grynspan grynspan requested a review from al45tair January 26, 2023 19:40
@grynspan
Copy link
Contributor Author

@swift-ci please test windows

@grynspan
Copy link
Contributor Author

@swift-ci please test windows

@grynspan
Copy link
Contributor Author

@swift-ci please test

@grynspan
Copy link
Contributor Author

@swift-ci please test

@grynspan
Copy link
Contributor Author

@swift-ci please test linux

Copy link
Contributor

@al45tair al45tair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

stdlib/public/Concurrency/Clock.cpp Outdated Show resolved Hide resolved
@grynspan
Copy link
Contributor Author

@swift-ci please test

Copy link
Contributor

@phausler phausler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great to me, the cleanup for non-windows platforms looks correct (and definitely cleaner).

Thanks for taking this on!

@grynspan
Copy link
Contributor Author

This looks great to me, the cleanup for non-windows platforms looks correct (and definitely cleaner).

Thanks for taking this on!

Always happy to help! (Danger: I might noodle on this code a bit more in the future if I see ways to improve it further.)

@grynspan
Copy link
Contributor Author

@swift-ci please test

@grynspan
Copy link
Contributor Author

@swift-ci please test windows

1 similar comment
@grynspan
Copy link
Contributor Author

@swift-ci please test windows

@grynspan
Copy link
Contributor Author

The reported Windows failure is not related to this PR.

@grynspan
Copy link
Contributor Author

@swift-ci please test windows

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SuspendingClock on Windows does not suspend
4 participants