On second thought, starting with Windows 8, WaitForSingleObject() and WaitForMultipleObjects() exclude time when the system is suspended. For consistency, an external deadline (e.g. for SIGINT support) should work the same way. The monotonic clock should thus be based on QueryUnbiasedInterruptTime(). We can conditionally use QueryUnbiasedInterruptTimePrecise() in Windows 10, which I presume includes most users of Python 3.9+ on Windows since Windows 8.1 only has a 3% share of desktop/laptop systems.
If we can agree on the above, then the change to use QueryPerformanceCounter() to resolve bpo-41299 should be reverted. The deadline should instead be computed with QueryUnbiasedInterruptTime(). It's limited to the resolution of the system interrupt time, but at least compared to GetTickCount64() it returns the real interrupt time instead of an idealized 64 ticks/second.
> expose all of the Windows clocks directly (through clock_gettime enums?)
_Py_clock_gettime() and _Py_clock_getres() could be implemented in Python/pytime.c. For Windows we could implement the following clocks:
CLOCK_REALTIME GetSystemTimePreciseAsFileTime
CLOCK_REALTIME_COARSE GetSystemTimeAsFileTime
CLOCK_MONOTONIC_COARSE QueryUnbiasedInterruptTime
CLOCK_PROCESS_CPUTIME_ID GetProcessTimes
CLOCK_THREAD_CPUTIME_ID GetThreadTimes
CLOCK_PERF_COUNTER QueryPerformanceCounter
Windows 10+
CLOCK_MONOTONIC QueryUnbiasedInterruptTimePrecise
CLOCK_BOOTTIME QueryInterruptTimePrecise
CLOCK_BOOTTIME_COARSE QueryInterruptTime
> it may also be worth replacing time.time()'s GetSystemTimeAsFileTime with
> GetSystemTimePreciseAsFileTime
See bpo-19007, which is nearly 8 years old.