Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- server/fd.c | 61 ++++++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 29 deletions(-)
diff --git a/server/fd.c b/server/fd.c index de7c5d7e36d..60555032f21 100644 --- a/server/fd.c +++ b/server/fd.c @@ -385,41 +385,44 @@ timeout_t monotonic_time; struct _KUSER_SHARED_DATA *user_shared_data = NULL; static const int user_shared_data_timeout = 16;
+static void atomic_store_ulong(volatile ULONG *ptr, ULONG value) +{ + /* on x86 there should be total store order guarantees, so volatile is + * enough to ensure the stores aren't reordered by the compiler, and then + * they will always be seen in-order from other CPUs. On other archs, we + * need atomic intrinsics to guarantee that. */ +#if defined(__i386__) || defined(__x86_64__) + *ptr = value; +#else + __atomic_store_n(ptr, value, __ATOMIC_SEQ_CST); +#endif +} + +static void atomic_store_long(volatile LONG *ptr, LONG value) +{ +#if defined(__i386__) || defined(__x86_64__) + *ptr = value; +#else + __atomic_store_n(ptr, value, __ATOMIC_SEQ_CST); +#endif +} + static void set_user_shared_data_time(void) { timeout_t tick_count = monotonic_time / 10000;
- /* on X86 there should be total store order guarantees, so volatile is enough - * to ensure the stores aren't reordered by the compiler, and then they will - * always be seen in-order from other CPUs. On other archs, we need atomic - * intrinsics to guarantee that. */ -#if defined(__i386__) || defined(__x86_64__) - user_shared_data->SystemTime.High2Time = current_time >> 32; - user_shared_data->SystemTime.LowPart = current_time; - user_shared_data->SystemTime.High1Time = current_time >> 32; + atomic_store_long(&user_shared_data->SystemTime.High2Time, current_time >> 32); + atomic_store_ulong(&user_shared_data->SystemTime.LowPart, current_time); + atomic_store_long(&user_shared_data->SystemTime.High1Time, current_time >> 32);
- user_shared_data->InterruptTime.High2Time = monotonic_time >> 32; - user_shared_data->InterruptTime.LowPart = monotonic_time; - user_shared_data->InterruptTime.High1Time = monotonic_time >> 32; + atomic_store_long(&user_shared_data->InterruptTime.High2Time, monotonic_time >> 32); + atomic_store_ulong(&user_shared_data->InterruptTime.LowPart, monotonic_time); + atomic_store_long(&user_shared_data->InterruptTime.High1Time, monotonic_time >> 32);
- user_shared_data->TickCount.High2Time = tick_count >> 32; - user_shared_data->TickCount.LowPart = tick_count; - user_shared_data->TickCount.High1Time = tick_count >> 32; - *(volatile ULONG *)&user_shared_data->TickCountLowDeprecated = tick_count; -#else - __atomic_store_n(&user_shared_data->SystemTime.High2Time, current_time >> 32, __ATOMIC_SEQ_CST); - __atomic_store_n(&user_shared_data->SystemTime.LowPart, current_time, __ATOMIC_SEQ_CST); - __atomic_store_n(&user_shared_data->SystemTime.High1Time, current_time >> 32, __ATOMIC_SEQ_CST); - - __atomic_store_n(&user_shared_data->InterruptTime.High2Time, monotonic_time >> 32, __ATOMIC_SEQ_CST); - __atomic_store_n(&user_shared_data->InterruptTime.LowPart, monotonic_time, __ATOMIC_SEQ_CST); - __atomic_store_n(&user_shared_data->InterruptTime.High1Time, monotonic_time >> 32, __ATOMIC_SEQ_CST); - - __atomic_store_n(&user_shared_data->TickCount.High2Time, tick_count >> 32, __ATOMIC_SEQ_CST); - __atomic_store_n(&user_shared_data->TickCount.LowPart, tick_count, __ATOMIC_SEQ_CST); - __atomic_store_n(&user_shared_data->TickCount.High1Time, tick_count >> 32, __ATOMIC_SEQ_CST); - __atomic_store_n(&user_shared_data->TickCountLowDeprecated, tick_count, __ATOMIC_SEQ_CST); -#endif + atomic_store_long(&user_shared_data->TickCount.High2Time, tick_count >> 32); + atomic_store_ulong(&user_shared_data->TickCount.LowPart, tick_count); + atomic_store_long(&user_shared_data->TickCount.High1Time, tick_count >> 32); + atomic_store_ulong(&user_shared_data->TickCountLowDeprecated, tick_count); }
void set_current_time(void)
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntdll/tests/time.c | 8 ++++++++ server/fd.c | 14 ++++++++++++++ 2 files changed, 22 insertions(+)
diff --git a/dlls/ntdll/tests/time.c b/dlls/ntdll/tests/time.c index 7ea506337a4..549db5b22b6 100644 --- a/dlls/ntdll/tests/time.c +++ b/dlls/ntdll/tests/time.c @@ -410,7 +410,9 @@ static ULONGLONG read_ksystem_time(volatile KSYSTEM_TIME *time) static void test_user_shared_data_time(void) { KSHARED_USER_DATA *user_shared_data = (void *)0x7ffe0000; + SYSTEM_TIMEOFDAY_INFORMATION timeofday; ULONGLONG t1, t2, t3; + NTSTATUS status; int i = 0;
i = 0; @@ -464,6 +466,12 @@ static void test_user_shared_data_time(void) ok(t2 <= t3, "USD InterruptTime / RtlQueryUnbiasedInterruptTime are out of order %s %s\n", wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3)); } + + t1 = read_ksystem_time(&user_shared_data->TimeZoneBias); + status = NtQuerySystemInformation(SystemTimeOfDayInformation, &timeofday, sizeof(timeofday), NULL); + ok(!status, "failed to query time of day, status %#x\n", status); + ok(timeofday.TimeZoneBias.QuadPart == t1, "got USD bias %I64u, ntdll bias %I64u\n", + t1, timeofday.TimeZoneBias.QuadPart); }
START_TEST(time) diff --git a/server/fd.c b/server/fd.c index 60555032f21..86c51529147 100644 --- a/server/fd.c +++ b/server/fd.c @@ -410,6 +410,16 @@ static void atomic_store_long(volatile LONG *ptr, LONG value) static void set_user_shared_data_time(void) { timeout_t tick_count = monotonic_time / 10000; + timeout_t timezone_bias; + struct tm *tm; + time_t now; + + now = time( NULL ); + tm = gmtime( &now ); + timezone_bias = mktime( tm ) - now; + tm = localtime( &now ); + if (tm->tm_isdst) timezone_bias -= 3600; + timezone_bias *= TICKS_PER_SEC;
atomic_store_long(&user_shared_data->SystemTime.High2Time, current_time >> 32); atomic_store_ulong(&user_shared_data->SystemTime.LowPart, current_time); @@ -423,6 +433,10 @@ static void set_user_shared_data_time(void) atomic_store_ulong(&user_shared_data->TickCount.LowPart, tick_count); atomic_store_long(&user_shared_data->TickCount.High1Time, tick_count >> 32); atomic_store_ulong(&user_shared_data->TickCountLowDeprecated, tick_count); + + atomic_store_long(&user_shared_data->TimeZoneBias.High2Time, timezone_bias >> 32); + atomic_store_ulong(&user_shared_data->TimeZoneBias.LowPart, timezone_bias); + atomic_store_long(&user_shared_data->TimeZoneBias.High1Time, timezone_bias >> 32); }
void set_current_time(void)
Zebediah Figura zfigura@codeweavers.com writes:
@@ -410,6 +410,16 @@ static void atomic_store_long(volatile LONG *ptr, LONG value) static void set_user_shared_data_time(void) { timeout_t tick_count = monotonic_time / 10000;
- timeout_t timezone_bias;
- struct tm *tm;
- time_t now;
- now = time( NULL );
- tm = gmtime( &now );
- timezone_bias = mktime( tm ) - now;
- tm = localtime( &now );
- if (tm->tm_isdst) timezone_bias -= 3600;
- timezone_bias *= TICKS_PER_SEC;
Do we really want to do that on every request?
On 8/24/21 1:03 PM, Alexandre Julliard wrote:
Zebediah Figura zfigura@codeweavers.com writes:
@@ -410,6 +410,16 @@ static void atomic_store_long(volatile LONG *ptr, LONG value) static void set_user_shared_data_time(void) { timeout_t tick_count = monotonic_time / 10000;
- timeout_t timezone_bias;
- struct tm *tm;
- time_t now;
- now = time( NULL );
- tm = gmtime( &now );
- timezone_bias = mktime( tm ) - now;
- tm = localtime( &now );
- if (tm->tm_isdst) timezone_bias -= 3600;
- timezone_bias *= TICKS_PER_SEC;
Do we really want to do that on every request?
Presumably it can change whenever the user changes the time zone (or, more realistically, if DST happens to flip over). I'm not aware of a better way to detect that, and I didn't think we'd want to ignore changes. I guess we could always cache it for some fixed length of time, though it's not clear to me that's not a bad idea either.
"Zebediah Figura (she/her)" zfigura@codeweavers.com writes:
On 8/24/21 1:03 PM, Alexandre Julliard wrote:
Zebediah Figura zfigura@codeweavers.com writes:
@@ -410,6 +410,16 @@ static void atomic_store_long(volatile LONG *ptr, LONG value) static void set_user_shared_data_time(void) { timeout_t tick_count = monotonic_time / 10000;
- timeout_t timezone_bias;
- struct tm *tm;
- time_t now;
- now = time( NULL );
- tm = gmtime( &now );
- timezone_bias = mktime( tm ) - now;
- tm = localtime( &now );
- if (tm->tm_isdst) timezone_bias -= 3600;
- timezone_bias *= TICKS_PER_SEC;
Do we really want to do that on every request?
Presumably it can change whenever the user changes the time zone (or, more realistically, if DST happens to flip over). I'm not aware of a better way to detect that, and I didn't think we'd want to ignore changes. I guess we could always cache it for some fixed length of time, though it's not clear to me that's not a bad idea either.
At least it doesn't seem useful to update this more than once per second.