mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Added patch to update user_shared_data timers.
This commit is contained in:
parent
31212d2845
commit
26438ad74c
@ -0,0 +1,253 @@
|
||||
From b01774078f03dcdc89d045d6c27106ce4059904e Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Fri, 5 May 2017 05:40:50 +0200
|
||||
Subject: ntdll: Create thread to update user_shared_data time values when
|
||||
necessary.
|
||||
|
||||
---
|
||||
dlls/kernel32/cpu.c | 4 +--
|
||||
dlls/ntdll/loader.c | 32 ++++++++++++++++++++++
|
||||
dlls/ntdll/ntdll_misc.h | 3 +++
|
||||
dlls/ntdll/thread.c | 70 ++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
dlls/ntdll/virtual.c | 16 +++++++++++
|
||||
5 files changed, 116 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/cpu.c b/dlls/kernel32/cpu.c
|
||||
index 01cb469b8db..d112368dcb4 100644
|
||||
--- a/dlls/kernel32/cpu.c
|
||||
+++ b/dlls/kernel32/cpu.c
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(reg);
|
||||
|
||||
-#define SHARED_DATA ((KSHARED_USER_DATA*)0x7ffe0000)
|
||||
+extern KSHARED_USER_DATA* CDECL __wine_user_shared_data(void);
|
||||
|
||||
/****************************************************************************
|
||||
* QueryPerformanceCounter (KERNEL32.@)
|
||||
@@ -206,7 +206,7 @@ BOOL WINAPI IsProcessorFeaturePresent (
|
||||
DWORD feature /* [in] Feature number, (PF_ constants from "winnt.h") */)
|
||||
{
|
||||
if (feature < PROCESSOR_FEATURE_MAX)
|
||||
- return SHARED_DATA->ProcessorFeatures[feature];
|
||||
+ return __wine_user_shared_data()->ProcessorFeatures[feature];
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
|
||||
index 630a9f66dc8..a00c3e17734 100644
|
||||
--- a/dlls/ntdll/loader.c
|
||||
+++ b/dlls/ntdll/loader.c
|
||||
@@ -3514,6 +3514,37 @@ static void start_process( void *arg )
|
||||
call_thread_entry_point( start_params->kernel_start, start_params->entry );
|
||||
}
|
||||
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * user_shared_data_init
|
||||
+ *
|
||||
+ * Initializes a user shared
|
||||
+ */
|
||||
+static void user_shared_data_init(void)
|
||||
+{
|
||||
+ void *addr = user_shared_data_external;
|
||||
+ SIZE_T data_size = page_size;
|
||||
+ ULONG old_prot;
|
||||
+
|
||||
+ /* initialize time fields */
|
||||
+ __wine_user_shared_data();
|
||||
+
|
||||
+ /* invalidate high times to prevent race conditions */
|
||||
+ user_shared_data->SystemTime.High2Time = 0;
|
||||
+ user_shared_data->SystemTime.High1Time = -1;
|
||||
+
|
||||
+ user_shared_data->InterruptTime.High2Time = 0;
|
||||
+ user_shared_data->InterruptTime.High1Time = -1;
|
||||
+
|
||||
+ user_shared_data->u.TickCount.High2Time = 0;
|
||||
+ user_shared_data->u.TickCount.High1Time = -1;
|
||||
+
|
||||
+ /* copy to correct address and make it non accessible */
|
||||
+ memcpy(user_shared_data_external, user_shared_data, sizeof(*user_shared_data));
|
||||
+ NtProtectVirtualMemory( NtCurrentProcess(), &addr, &data_size, PAGE_NOACCESS, &old_prot );
|
||||
+}
|
||||
+
|
||||
+
|
||||
/******************************************************************
|
||||
* LdrInitializeThunk (NTDLL.@)
|
||||
*
|
||||
@@ -3545,6 +3576,7 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2,
|
||||
peb->ProcessParameters->WindowTitle = wm->ldr.FullDllName;
|
||||
version_init( wm->ldr.FullDllName.Buffer );
|
||||
hidden_exports_init( wm->ldr.FullDllName.Buffer );
|
||||
+ user_shared_data_init();
|
||||
virtual_set_large_address_space();
|
||||
|
||||
LdrQueryImageFileExecutionOptions( &peb->ProcessParameters->ImagePathName, globalflagW,
|
||||
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
|
||||
index d556a21ee67..3ddbb6367c4 100644
|
||||
--- a/dlls/ntdll/ntdll_misc.h
|
||||
+++ b/dlls/ntdll/ntdll_misc.h
|
||||
@@ -180,6 +180,9 @@ extern void VIRTUAL_SetForceExec( BOOL enable ) DECLSPEC_HIDDEN;
|
||||
extern void virtual_release_address_space(void) DECLSPEC_HIDDEN;
|
||||
extern void virtual_set_large_address_space(void) DECLSPEC_HIDDEN;
|
||||
extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN;
|
||||
+extern struct _KUSER_SHARED_DATA *user_shared_data_external DECLSPEC_HIDDEN;
|
||||
+extern void create_user_shared_data_thread(void) DECLSPEC_HIDDEN;
|
||||
+extern BYTE* __wine_user_shared_data(void);
|
||||
|
||||
/* completion */
|
||||
extern NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue,
|
||||
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
|
||||
index 8da0779f4b2..b6cf2c8b794 100644
|
||||
--- a/dlls/ntdll/thread.c
|
||||
+++ b/dlls/ntdll/thread.c
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "wine/library.h"
|
||||
#include "wine/server.h"
|
||||
#include "wine/debug.h"
|
||||
+#include "winbase.h"
|
||||
#include "ntdll_misc.h"
|
||||
#include "ddk/wdm.h"
|
||||
#include "wine/exception.h"
|
||||
@@ -50,7 +51,9 @@
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(thread);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(relay);
|
||||
|
||||
-struct _KUSER_SHARED_DATA *user_shared_data = NULL;
|
||||
+static struct _KUSER_SHARED_DATA user_shared_data_internal;
|
||||
+struct _KUSER_SHARED_DATA *user_shared_data_external;
|
||||
+struct _KUSER_SHARED_DATA *user_shared_data = &user_shared_data_internal;
|
||||
|
||||
PUNHANDLED_EXCEPTION_FILTER unhandled_exception_filter = NULL;
|
||||
|
||||
@@ -345,18 +348,71 @@ static ULONG_PTR get_image_addr(void)
|
||||
*/
|
||||
BYTE* CDECL __wine_user_shared_data(void)
|
||||
{
|
||||
+ static int spinlock;
|
||||
+ ULARGE_INTEGER interrupt;
|
||||
LARGE_INTEGER now;
|
||||
+
|
||||
+ while (interlocked_cmpxchg( &spinlock, 1, 0 ) != 0);
|
||||
+
|
||||
NtQuerySystemTime( &now );
|
||||
- user_shared_data->SystemTime.LowPart = now.u.LowPart;
|
||||
- user_shared_data->SystemTime.High1Time = user_shared_data->SystemTime.High2Time = now.u.HighPart;
|
||||
- user_shared_data->u.TickCountQuad = (now.QuadPart - server_start_time) / 10000;
|
||||
- user_shared_data->u.TickCount.High2Time = user_shared_data->u.TickCount.High1Time;
|
||||
- user_shared_data->TickCountLowDeprecated = user_shared_data->u.TickCount.LowPart;
|
||||
+ user_shared_data->SystemTime.High2Time = now.u.HighPart;
|
||||
+ user_shared_data->SystemTime.LowPart = now.u.LowPart;
|
||||
+ user_shared_data->SystemTime.High1Time = now.u.HighPart;
|
||||
+
|
||||
+ RtlQueryUnbiasedInterruptTime( &interrupt.QuadPart );
|
||||
+ user_shared_data->InterruptTime.High2Time = interrupt.HighPart;
|
||||
+ user_shared_data->InterruptTime.LowPart = interrupt.LowPart;
|
||||
+ user_shared_data->InterruptTime.High1Time = interrupt.HighPart;
|
||||
+
|
||||
+ interrupt.QuadPart /= 10000;
|
||||
+ user_shared_data->u.TickCount.High2Time = interrupt.HighPart;
|
||||
+ user_shared_data->u.TickCount.LowPart = interrupt.LowPart;
|
||||
+ user_shared_data->u.TickCount.High1Time = interrupt.HighPart;
|
||||
+ user_shared_data->TickCountLowDeprecated = interrupt.LowPart;
|
||||
user_shared_data->TickCountMultiplier = 1 << 24;
|
||||
+
|
||||
+ spinlock = 0;
|
||||
return (BYTE *)user_shared_data;
|
||||
}
|
||||
|
||||
|
||||
+static void *user_shared_data_thread(void *arg)
|
||||
+{
|
||||
+ struct timeval tv;
|
||||
+
|
||||
+ while (TRUE)
|
||||
+ {
|
||||
+ __wine_user_shared_data();
|
||||
+
|
||||
+ tv.tv_sec = 0;
|
||||
+ tv.tv_usec = 15600;
|
||||
+ select(0, NULL, NULL, NULL, &tv);
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void create_user_shared_data_thread(void)
|
||||
+{
|
||||
+ static int thread_created;
|
||||
+ pthread_attr_t attr;
|
||||
+ pthread_t thread;
|
||||
+
|
||||
+ if (interlocked_cmpxchg(&thread_created, 1, 0) != 0)
|
||||
+ return;
|
||||
+
|
||||
+ FIXME("Creating user shared data update thread.\n");
|
||||
+
|
||||
+ user_shared_data = user_shared_data_external;
|
||||
+ __wine_user_shared_data();
|
||||
+
|
||||
+ pthread_attr_init(&attr);
|
||||
+ pthread_attr_setstacksize(&attr, 0x10000);
|
||||
+ pthread_create(&thread, &attr, user_shared_data_thread, NULL);
|
||||
+ pthread_attr_destroy(&attr);
|
||||
+}
|
||||
+
|
||||
+
|
||||
/***********************************************************************
|
||||
* thread_init
|
||||
*
|
||||
@@ -388,7 +444,7 @@ HANDLE thread_init(void)
|
||||
MESSAGE( "wine: failed to map the shared user data: %08x\n", status );
|
||||
exit(1);
|
||||
}
|
||||
- user_shared_data = addr;
|
||||
+ user_shared_data_external = addr;
|
||||
|
||||
/* allocate and initialize the PEB */
|
||||
|
||||
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
|
||||
index 872b1ce2d8f..bd8f54f78c3 100644
|
||||
--- a/dlls/ntdll/virtual.c
|
||||
+++ b/dlls/ntdll/virtual.c
|
||||
@@ -1561,6 +1561,7 @@ NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack )
|
||||
struct file_view *view;
|
||||
NTSTATUS ret = STATUS_ACCESS_VIOLATION;
|
||||
sigset_t sigset;
|
||||
+ BOOL update_shared_data = FALSE;
|
||||
|
||||
server_enter_uninterrupted_section( &csVirtual, &sigset );
|
||||
if ((view = VIRTUAL_FindView( addr, 0 )))
|
||||
@@ -1582,6 +1583,17 @@ NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack )
|
||||
/* ignore fault if page is writable now */
|
||||
if (VIRTUAL_GetUnixProt( *vprot ) & PROT_WRITE) ret = STATUS_SUCCESS;
|
||||
}
|
||||
+ else if (page == user_shared_data_external)
|
||||
+ {
|
||||
+ if (!(*vprot & VPROT_READ))
|
||||
+ {
|
||||
+ *vprot |= VPROT_READ | VPROT_WRITE;
|
||||
+ VIRTUAL_SetProt( view, page, page_size, *vprot );
|
||||
+ update_shared_data = TRUE;
|
||||
+ }
|
||||
+ /* ignore fault if page is readable now */
|
||||
+ if (VIRTUAL_GetUnixProt( *vprot ) & PROT_READ) ret = STATUS_SUCCESS;
|
||||
+ }
|
||||
if (!on_signal_stack && (*vprot & VPROT_GUARD))
|
||||
{
|
||||
VIRTUAL_SetProt( view, page, page_size, *vprot & ~VPROT_GUARD );
|
||||
@@ -1589,6 +1601,10 @@ NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack )
|
||||
}
|
||||
}
|
||||
server_leave_uninterrupted_section( &csVirtual, &sigset );
|
||||
+
|
||||
+ if (update_shared_data)
|
||||
+ create_user_shared_data_thread();
|
||||
+
|
||||
return ret;
|
||||
}
|
||||
|
||||
--
|
||||
2.12.2
|
||||
|
@ -0,0 +1,69 @@
|
||||
From 3f4763cc335ea4d8293862677fabe0f8218c5542 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Wesie <awesie@gmail.com>
|
||||
Date: Tue, 2 May 2017 21:19:03 -0500
|
||||
Subject: ntdll/tests: Test updating TickCount in user_shared_data.
|
||||
|
||||
---
|
||||
dlls/ntdll/tests/time.c | 22 ++++++++++++++++++++++
|
||||
1 file changed, 22 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/time.c b/dlls/ntdll/tests/time.c
|
||||
index b684bc1980d..0c8300a3428 100644
|
||||
--- a/dlls/ntdll/tests/time.c
|
||||
+++ b/dlls/ntdll/tests/time.c
|
||||
@@ -18,7 +18,9 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
+#define NONAMELESSUNION
|
||||
#include "ntdll_test.h"
|
||||
+#include "ddk/wdm.h"
|
||||
|
||||
#define TICKSPERSEC 10000000
|
||||
#define TICKSPERMSEC 10000
|
||||
@@ -27,6 +29,7 @@
|
||||
static VOID (WINAPI *pRtlTimeToTimeFields)( const LARGE_INTEGER *liTime, PTIME_FIELDS TimeFields) ;
|
||||
static VOID (WINAPI *pRtlTimeFieldsToTime)( PTIME_FIELDS TimeFields, PLARGE_INTEGER Time) ;
|
||||
static NTSTATUS (WINAPI *pNtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency );
|
||||
+static ULONG (WINAPI *pNtGetTickCount)(void);
|
||||
|
||||
static const int MonthLengths[2][12] =
|
||||
{
|
||||
@@ -115,15 +118,34 @@ static void test_NtQueryPerformanceCounter(void)
|
||||
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
|
||||
}
|
||||
|
||||
+static void test_NtGetTickCount(void)
|
||||
+{
|
||||
+#ifndef _WIN64
|
||||
+ KSHARED_USER_DATA *user_shared_data = (void *)0x7ffe0000;
|
||||
+ LONG diff;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < 5; ++i)
|
||||
+ {
|
||||
+ diff = (user_shared_data->u.TickCountQuad * user_shared_data->TickCountMultiplier) >> 24;
|
||||
+ diff = NtGetTickCount() - diff;
|
||||
+ ok(diff < 32, "NtGetTickCount - TickCountQuad too high, expected < 32 got %d\n", diff);
|
||||
+ Sleep(50);
|
||||
+ }
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
START_TEST(time)
|
||||
{
|
||||
HMODULE mod = GetModuleHandleA("ntdll.dll");
|
||||
pRtlTimeToTimeFields = (void *)GetProcAddress(mod,"RtlTimeToTimeFields");
|
||||
pRtlTimeFieldsToTime = (void *)GetProcAddress(mod,"RtlTimeFieldsToTime");
|
||||
pNtQueryPerformanceCounter = (void *)GetProcAddress(mod, "NtQueryPerformanceCounter");
|
||||
+ pNtGetTickCount = (void *)GetProcAddress(mod,"NtGetTickCount");
|
||||
if (pRtlTimeToTimeFields && pRtlTimeFieldsToTime)
|
||||
test_pRtlTimeToTimeFields();
|
||||
else
|
||||
win_skip("Required time conversion functions are not available\n");
|
||||
test_NtQueryPerformanceCounter();
|
||||
+ test_NtGetTickCount();
|
||||
}
|
||||
--
|
||||
2.12.2
|
||||
|
2
patches/ntdll-User_Shared_Data/definition
Normal file
2
patches/ntdll-User_Shared_Data/definition
Normal file
@ -0,0 +1,2 @@
|
||||
Fixes: [29168] Update user shared data at realtime
|
||||
Depends: ntdll-Hide_Wine_Exports
|
@ -2273,6 +2273,13 @@ if test "$enable_ntdll_WRITECOPY" -eq 1; then
|
||||
enable_ws2_32_WriteWatches=1
|
||||
fi
|
||||
|
||||
if test "$enable_ntdll_User_Shared_Data" -eq 1; then
|
||||
if test "$enable_ntdll_Hide_Wine_Exports" -gt 1; then
|
||||
abort "Patchset ntdll-Hide_Wine_Exports disabled, but ntdll-User_Shared_Data depends on that."
|
||||
fi
|
||||
enable_ntdll_Hide_Wine_Exports=1
|
||||
fi
|
||||
|
||||
if test "$enable_ntdll_SystemRoot_Symlink" -eq 1; then
|
||||
if test "$enable_ntdll_Exception" -gt 1; then
|
||||
abort "Patchset ntdll-Exception disabled, but ntdll-SystemRoot_Symlink depends on that."
|
||||
@ -6008,15 +6015,26 @@ fi
|
||||
|
||||
# Patchset ntdll-User_Shared_Data
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * ntdll-Attach_Process_DLLs, ntdll-ThreadTime, ntdll-Hide_Wine_Exports
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#29168] Update user shared data at realtime
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/ntdll.spec, dlls/ntdll/thread.c, dlls/ntoskrnl.exe/instr.c
|
||||
# | * dlls/kernel32/cpu.c, dlls/ntdll/loader.c, dlls/ntdll/ntdll.spec, dlls/ntdll/ntdll_misc.h, dlls/ntdll/tests/time.c,
|
||||
# | dlls/ntdll/thread.c, dlls/ntdll/virtual.c, dlls/ntoskrnl.exe/instr.c
|
||||
# |
|
||||
if test "$enable_ntdll_User_Shared_Data" -eq 1; then
|
||||
patch_apply ntdll-User_Shared_Data/0001-ntdll-Move-code-to-update-user-shared-data-into-a-se.patch
|
||||
patch_apply ntdll-User_Shared_Data/0002-ntoskrnl-Update-USER_SHARED_DATA-before-accessing-me.patch
|
||||
patch_apply ntdll-User_Shared_Data/0003-ntdll-Create-thread-to-update-user_shared_data-time-.patch
|
||||
patch_apply ntdll-User_Shared_Data/0004-ntdll-tests-Test-updating-TickCount-in-user_shared_d.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Move code to update user shared data into a separate function.", 1 },';
|
||||
printf '%s\n' '+ { "Sebastian Lackner", "ntoskrnl: Update USER_SHARED_DATA before accessing memory.", 1 },';
|
||||
printf '%s\n' '+ { "Michael Müller", "ntdll: Create thread to update user_shared_data time values when necessary.", 1 },';
|
||||
printf '%s\n' '+ { "Andrew Wesie", "ntdll/tests: Test updating TickCount in user_shared_data.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user