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 a09fc9edfcf..79ddd0a96a9 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 --- v2: Only update the time zone once every second.
dlls/ntdll/tests/time.c | 8 ++++++++ server/fd.c | 20 ++++++++++++++++++++ 2 files changed, 28 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 79ddd0a96a9..2991c0d63fe 100644 --- a/server/fd.c +++ b/server/fd.c @@ -410,6 +410,26 @@ 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; + static timeout_t last_timezone_update; + timeout_t timezone_bias; + struct tm *tm; + time_t now; + + if (monotonic_time - last_timezone_update > TICKS_PER_SEC) + { + 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->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); + + last_timezone_update = monotonic_time; + }
atomic_store_long(&user_shared_data->SystemTime.High2Time, current_time >> 32); atomic_store_ulong(&user_shared_data->SystemTime.LowPart, current_time);