[PATCH RFC 0/5] Timer Resolution

Arkadiusz Hiler ahiler at codeweavers.com
Tue Aug 18 05:30:42 CDT 2020


On Tue, Aug 18, 2020 at 11:38:49AM +0200, Rémi Bernon wrote:
> On 2020-08-17 19:46, Arkadiusz Hiler wrote:
> > TL;DR: Good learning experience, lead to a fix in winmm but IMO we are better
> >         off defaulting to 1ms resolution and avoid all the extra complications.
<SNIP>
> I think that if it adds such complexity just for the sake of better mimicing
> Windows, and without actually fixing anything, it may indeed not be worth
> it. If and when we find an application that is broken by this behavior then
> maybe we could reconsider it.

Judging by the number of programs that are setting 1ms resolution, if it
a piece of software would be broken, it would be also broken on Windows,
so I don't think it's very likely we will ever get there.


> Then IIRC the DOSBOX issue is just about winmm and its assumptions that
> GetTickCount resolution is 1ms on Wine, which is now incorrect. But it is
> also incorrect on Windows too, regardless of this resolution thing right? So
> that definitely needs a fix.

The DOSBox problem was Wine aliasing timeGetTime() to GetTickCount()
on the assumption that GetTickCount() is 1ms-accurate.

DOSBox is using timeGetTime() and timeBeginPeriod().

There's a patch that fixes this by implementing timeGetTime() on top of
QueryPerformanceCounter().

https://www.winehq.org/pipermail/wine-devel/2020-August/171965.html


Going back to defaulting to 1ms resolution, I think I'll just write tests that:

  TIMERR_NOERROR == timeBeginPeriod(1); /* for Windows */
  HAS_1MS_RESOLUTION(Sleep(1)); /* for Wait*() and other calls that we know are affected */
  HAS_INCREMENT_OF_1(timeGetTime());
  ...

Also, we could stub NtQueryTimerResolution() to return the same values
as Win10 after timeBeginPeriod(1). This is not solving any real
bugs, but may save some hassle the next person going down the timer
resolution lane:

diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 23dca9c61b..2743b17e54 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -81,6 +81,9 @@ static const LARGE_INTEGER zero_timeout;
 
 static pthread_mutex_t addr_mutex = PTHREAD_MUTEX_INITIALIZER;
 
+static ULONG timer_resolution_min = 156250;
+static ULONG timer_resolution_max = 5000;
+
 /* return a monotonic time counter, in Win32 ticks */
 static inline ULONGLONG monotonic_counter(void)
 {
@@ -1438,8 +1441,15 @@ NTSTATUS WINAPI NtSetSystemTime( const LARGE_INTEGER *new, LARGE_INTEGER *old )
  */
 NTSTATUS WINAPI NtQueryTimerResolution( ULONG *min_res, ULONG *max_res, ULONG *current_res )
 {
-    FIXME( "(%p,%p,%p), stub!\n", min_res, max_res, current_res );
-    return STATUS_NOT_IMPLEMENTED;
+    TRACE( "(%p,%p,%p)\n", min_res, max_res, current_res );
+
+    if (!min_res || !max_res || !current_res) return STATUS_ACCESS_VIOLATION;
+
+    *min_res = timer_resolution_min;
+    *max_res = timer_resolution_max;
+    *current_res = timer_resolution_max;
+
+    return STATUS_SUCCESS;
 }
 
 
@@ -1448,8 +1458,13 @@ NTSTATUS WINAPI NtQueryTimerResolution( ULONG *min_res, ULONG *max_res, ULONG *c
  */
 NTSTATUS WINAPI NtSetTimerResolution( ULONG res, BOOLEAN set, ULONG *current_res )
 {
-    FIXME( "(%u,%u,%p), stub!\n", res, set, current_res );
-    return STATUS_NOT_IMPLEMENTED;
+    TRACE( "(%u,%u,%p)\n", res, set, current_res );
+
+    if (!current_res) return STATUS_ACCESS_VIOLATION;
+
+    *current_res = timer_resolution_max;
+
+    return STATUS_SUCCESS;
 }

-- 
Cheers,
Arek



More information about the wine-devel mailing list