Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
v6:
* Add some tests for USD memory basic info.
* Open or create a __wine_user_shared_data section from client side, initialize it on creation (when wineboot completes), then pass the handle to the server which will then map it and start updating it.
* Use atomic builtins only when on non-x86 archs.
* Add a size reduction patch.
dlls/ntdll/tests/time.c | 78 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+)
diff --git a/dlls/ntdll/tests/time.c b/dlls/ntdll/tests/time.c index 5382a952d8d8..d11093a243da 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 @@ -29,6 +31,7 @@ static VOID (WINAPI *pRtlTimeFieldsToTime)( PTIME_FIELDS TimeFields, PLARGE_IN static NTSTATUS (WINAPI *pNtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency ); static NTSTATUS (WINAPI *pRtlQueryTimeZoneInformation)( RTL_TIME_ZONE_INFORMATION *); static NTSTATUS (WINAPI *pRtlQueryDynamicTimeZoneInformation)( RTL_DYNAMIC_TIME_ZONE_INFORMATION *); +static BOOL (WINAPI *pRtlQueryUnbiasedInterruptTime)( ULONGLONG *time );
static const int MonthLengths[2][12] = { @@ -153,6 +156,79 @@ static void test_RtlQueryTimeZoneInformation(void) wine_dbgstr_w(tzinfo.DaylightName)); }
+static ULONGLONG read_ksystem_time(volatile KSYSTEM_TIME *time) +{ + ULONGLONG high, low; + do + { + high = time->High1Time; + low = time->LowPart; + } + while (high != time->High2Time); + return high << 32 | low; +} + +static void test_user_shared_data_time(void) +{ + KSHARED_USER_DATA *user_shared_data = (void *)0x7ffe0000; + ULONGLONG t1, t2, t3; + int i = 0; + + i = 0; + do + { + t1 = GetTickCount(); + if (user_shared_data->NtMajorVersion <= 5 && user_shared_data->NtMinorVersion <= 1) + t2 = (*(volatile ULONG*)&user_shared_data->TickCountLowDeprecated * (ULONG64)user_shared_data->TickCountMultiplier) >> 24; + else + t2 = (read_ksystem_time(&user_shared_data->u.TickCount) * user_shared_data->TickCountMultiplier) >> 24; + t3 = GetTickCount(); + } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */ + + ok(t1 <= t2, "USD TickCount / GetTickCount are out of order: %s %s\n", + wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); + todo_wine + ok(t2 <= t3, "USD TickCount / GetTickCount are out of order: %s %s\n", + wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3)); + + i = 0; + do + { + LARGE_INTEGER system_time; + NtQuerySystemTime(&system_time); + t1 = system_time.QuadPart; + t2 = read_ksystem_time(&user_shared_data->SystemTime); + NtQuerySystemTime(&system_time); + t3 = system_time.QuadPart; + } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */ + + todo_wine + ok(t1 <= t2, "USD SystemTime / NtQuerySystemTime are out of order %s %s\n", + wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); + ok(t2 <= t3, "USD SystemTime / NtQuerySystemTime are out of order %s %s\n", + wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3)); + + if (!pRtlQueryUnbiasedInterruptTime) + win_skip("skipping RtlQueryUnbiasedInterruptTime tests\n"); + else + { + i = 0; + do + { + pRtlQueryUnbiasedInterruptTime(&t1); + t2 = read_ksystem_time(&user_shared_data->InterruptTime); + pRtlQueryUnbiasedInterruptTime(&t3); + } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */ + + todo_wine + ok(t1 <= t2, "USD InterruptTime / RtlQueryUnbiasedInterruptTime are out of order %s %s\n", + wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); + ok(t2 <= t3 || broken(t2 == t3 + 82410089070) /* w864 has some weird offset on testbot */, + "USD InterruptTime / RtlQueryUnbiasedInterruptTime are out of order %s %s\n", + wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3)); + } +} + START_TEST(time) { HMODULE mod = GetModuleHandleA("ntdll.dll"); @@ -163,6 +239,7 @@ START_TEST(time) (void *)GetProcAddress(mod, "RtlQueryTimeZoneInformation"); pRtlQueryDynamicTimeZoneInformation = (void *)GetProcAddress(mod, "RtlQueryDynamicTimeZoneInformation"); + pRtlQueryUnbiasedInterruptTime = (void *)GetProcAddress(mod, "RtlQueryUnbiasedInterruptTime");
if (pRtlTimeToTimeFields && pRtlTimeFieldsToTime) test_pRtlTimeToTimeFields(); @@ -170,4 +247,5 @@ START_TEST(time) win_skip("Required time conversion functions are not available\n"); test_NtQueryPerformanceCounter(); test_RtlQueryTimeZoneInformation(); + test_user_shared_data_time(); }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/tests/info.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index e28eefa986d7..fbc2e4e9d585 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -2181,6 +2181,7 @@ static void test_queryvirtualmemory(void) MEMORY_BASIC_INFORMATION mbi; char stackbuf[42]; HMODULE module; + void *user_shared_data = (void *)0x7ffe0000;
module = GetModuleHandleA( "ntdll.dll" ); trace("Check flags of the PE header of NTDLL.DLL at %p\n", module); @@ -2255,6 +2256,20 @@ static void test_queryvirtualmemory(void) } else skip( "bss is outside of module\n" ); /* this can happen on Mac OS */
+ trace("Check flags of user shared data at %p\n", user_shared_data); + status = pNtQueryVirtualMemory(NtCurrentProcess(), user_shared_data, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount); + ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status); + ok(readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount); + ok(mbi.AllocationBase == user_shared_data, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, user_shared_data); + todo_wine + ok(mbi.AllocationProtect == PAGE_READONLY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_READONLY); + ok(mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%X\n", mbi.State, MEM_COMMIT); + todo_wine + ok(mbi.Protect == PAGE_READONLY, "mbi.Protect is 0x%x\n", mbi.Protect); + ok(mbi.Type == MEM_PRIVATE, "mbi.Type is 0x%x, expected 0x%x\n", mbi.Type, MEM_PRIVATE); + todo_wine + ok(mbi.RegionSize == 0x1000, "mbi.RegionSize is 0x%x, expected 0x%x\n", mbi.RegionSize, 0x1000); + /* check error code when addr is higher than working set limit */ status = pNtQueryVirtualMemory(NtCurrentProcess(), (void *)~0, MemoryBasicInformation, &mbi, sizeof(mbi), &readcount); ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=71494
Your paranoid android.
=== wxppro (testbot log) ===
The task timed out
On 5/11/20 1:30 PM, Marvin wrote:
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=71494
Your paranoid android.
=== wxppro (testbot log) ===
The task timed out
Not sure why this is happening now, I previously ran the test successfully on wxppro here:
https://testbot.winehq.org/JobDetails.pl?Key=71492&f201=exe32.report#k20...
The last printed message is test_process_debug_flags, so I think this is timing out on another test.
The USD page is created when the first process (wineboot.exe) completes its creation, using its provided user_shared_data for initialization.
The server maps the page write-only and the clients map it read-only, then the server updates the timestamps every 16 ms.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=29168 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/server.c | 4 +++ dlls/ntdll/tests/info.c | 1 - dlls/ntdll/tests/time.c | 9 ++++-- dlls/ntdll/thread.c | 60 +++++++++++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/instr.c | 12 -------- server/file.h | 2 ++ server/mapping.c | 63 +++++++++++++++++++++++++++++++++++++++ server/process.c | 8 +++++ server/protocol.def | 1 + 10 files changed, 145 insertions(+), 16 deletions(-)
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 13771d230a88..4c8acab15dbf 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -221,6 +221,7 @@ extern void virtual_set_large_address_space(void) DECLSPEC_HIDDEN; extern void virtual_fill_image_information( const pe_image_info_t *pe_info, SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN; extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN; +extern HANDLE user_shared_data_init_done(void) DECLSPEC_HIDDEN;
/* completion */ extern NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue, diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index 41e6ea891c56..96f8e8f2a960 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -91,6 +91,7 @@ #include "wine/server.h" #include "wine/debug.h" #include "ntdll_misc.h" +#include "ddk/wdm.h"
WINE_DEFAULT_DEBUG_CHANNEL(server);
@@ -1863,6 +1864,7 @@ void server_init_process_done(void) IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress ); void *entry = (char *)peb->ImageBaseAddress + nt->OptionalHeader.AddressOfEntryPoint; NTSTATUS status; + HANDLE usd_handle = user_shared_data_init_done(); int suspend;
#ifdef __APPLE__ @@ -1886,10 +1888,12 @@ void server_init_process_done(void) #endif req->entry = wine_server_client_ptr( entry ); req->gui = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI); + req->usd_handle = wine_server_obj_handle( usd_handle ); status = wine_server_call( req ); suspend = reply->suspend; } SERVER_END_REQ; + NtClose( usd_handle );
assert( !status ); signal_start_process( entry, suspend ); diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index fbc2e4e9d585..757ef2691004 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -2264,7 +2264,6 @@ static void test_queryvirtualmemory(void) todo_wine ok(mbi.AllocationProtect == PAGE_READONLY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_READONLY); ok(mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%X\n", mbi.State, MEM_COMMIT); - todo_wine ok(mbi.Protect == PAGE_READONLY, "mbi.Protect is 0x%x\n", mbi.Protect); ok(mbi.Type == MEM_PRIVATE, "mbi.Type is 0x%x, expected 0x%x\n", mbi.Type, MEM_PRIVATE); todo_wine diff --git a/dlls/ntdll/tests/time.c b/dlls/ntdll/tests/time.c index d11093a243da..f50d4b4d7019 100644 --- a/dlls/ntdll/tests/time.c +++ b/dlls/ntdll/tests/time.c @@ -185,9 +185,10 @@ static void test_user_shared_data_time(void) t3 = GetTickCount(); } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */
+ /* FIXME: not always in order, but should be close */ + todo_wine_if(t1 > t2 && t1 - t2 < 50) ok(t1 <= t2, "USD TickCount / GetTickCount are out of order: %s %s\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); - todo_wine ok(t2 <= t3, "USD TickCount / GetTickCount are out of order: %s %s\n", wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3));
@@ -202,7 +203,8 @@ static void test_user_shared_data_time(void) t3 = system_time.QuadPart; } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */
- todo_wine + /* FIXME: not always in order, but should be close */ + todo_wine_if(t1 > t2 && t1 - t2 < 50 * TICKSPERMSEC) ok(t1 <= t2, "USD SystemTime / NtQuerySystemTime are out of order %s %s\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); ok(t2 <= t3, "USD SystemTime / NtQuerySystemTime are out of order %s %s\n", @@ -220,7 +222,8 @@ static void test_user_shared_data_time(void) pRtlQueryUnbiasedInterruptTime(&t3); } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */
- todo_wine + /* FIXME: not always in order, but should be close */ + todo_wine_if(t1 > t2 && t1 - t2 < 50 * TICKSPERMSEC) ok(t1 <= t2, "USD InterruptTime / RtlQueryUnbiasedInterruptTime are out of order %s %s\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); ok(t2 <= t3 || broken(t2 == t3 + 82410089070) /* w864 has some weird offset on testbot */, diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index b25f87e43755..78fe4e4fdf86 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -56,6 +56,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(thread); #endif
struct _KUSER_SHARED_DATA *user_shared_data = NULL; +static size_t user_shared_data_size; static const WCHAR default_windirW[] = {'C',':','\','w','i','n','d','o','w','s',0};
void (WINAPI *kernel32_start_process)(LPTHREAD_START_ROUTINE,void*) = NULL; @@ -212,6 +213,64 @@ static void set_process_name( int argc, char *argv[] ) #endif /* HAVE_PRCTL */ }
+HANDLE user_shared_data_init_done(void) +{ + static const WCHAR wine_usdW[] = {'\','K','e','r','n','e','l','O','b','j','e','c','t','s', + '\','_','_','w','i','n','e','_','u','s','e','r','_','s','h','a','r','e','d','_','d','a','t','a',0}; + OBJECT_ATTRIBUTES attr = {sizeof(attr)}; + UNICODE_STRING wine_usd_str; + LARGE_INTEGER section_size; + NTSTATUS status; + HANDLE section; + SIZE_T size; + void *addr; + ULONG old_prot; + int res, fd, needs_close; + + section_size.HighPart = 0; + section_size.LowPart = user_shared_data_size; + + RtlInitUnicodeString( &wine_usd_str, wine_usdW ); + InitializeObjectAttributes( &attr, &wine_usd_str, OBJ_OPENIF, NULL, NULL ); + if ((status = NtCreateSection( §ion, SECTION_ALL_ACCESS, &attr, + §ion_size, PAGE_READWRITE, SEC_COMMIT, NULL )) && + status != STATUS_OBJECT_NAME_EXISTS) + { + MESSAGE( "wine: failed to create or open the USD section: %08x\n", status ); + exit(1); + } + + if (status != STATUS_OBJECT_NAME_EXISTS) + { + addr = NULL; + size = user_shared_data_size; + + if ((status = NtMapViewOfSection( section, NtCurrentProcess(), &addr, 0, 0, 0, + &size, 0, 0, PAGE_READWRITE ))) + { + MESSAGE( "wine: failed to initialize the USD section: %08x\n", status ); + exit(1); + } + + memcpy( addr, user_shared_data, user_shared_data_size ); + NtUnmapViewOfSection( NtCurrentProcess(), addr ); + } + + addr = user_shared_data; + size = user_shared_data_size; + NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, PAGE_READONLY, &old_prot ); + + if ((res = server_get_unix_fd( section, 0, &fd, &needs_close, NULL, NULL )) || + (user_shared_data != mmap( user_shared_data, user_shared_data_size, + PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0 ))) + { + MESSAGE( "wine: failed to remap the process USD: %d\n", res ); + exit(1); + } + if (needs_close) close( fd ); + + return section; +}
/*********************************************************************** * thread_init @@ -244,6 +303,7 @@ TEB *thread_init(void) exit(1); } user_shared_data = addr; + user_shared_data_size = size; memcpy( user_shared_data->NtSystemRoot, default_windirW, sizeof(default_windirW) );
/* allocate and initialize the PEB and initial TEB */ diff --git a/dlls/ntoskrnl.exe/instr.c b/dlls/ntoskrnl.exe/instr.c index 77803f07d725..0973b3a80a07 100644 --- a/dlls/ntoskrnl.exe/instr.c +++ b/dlls/ntoskrnl.exe/instr.c @@ -593,15 +593,6 @@ static void fake_syscall_function(void) }
-static void update_shared_data(void) -{ - struct _KUSER_SHARED_DATA *shared_data = (struct _KUSER_SHARED_DATA *)wine_user_shared_data; - - shared_data->u.TickCountQuad = GetTickCount64(); - shared_data->u.TickCount.High2Time = shared_data->u.TickCount.High1Time; -} - - /*********************************************************************** * emulate_instruction * @@ -802,7 +793,6 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context ) if (offset <= sizeof(KSHARED_USER_DATA) - data_size) { ULONGLONG temp = 0; - update_shared_data(); memcpy( &temp, wine_user_shared_data + offset, data_size ); store_reg_word( context, instr[2], (BYTE *)&temp, long_op, rex ); context->Rip += prefixlen + len + 2; @@ -823,7 +813,6 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
if (offset <= sizeof(KSHARED_USER_DATA) - data_size) { - update_shared_data(); switch (*instr) { case 0x8a: store_reg_byte( context, instr[1], wine_user_shared_data + offset, rex ); break; @@ -845,7 +834,6 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
if (offset <= sizeof(KSHARED_USER_DATA) - data_size) { - update_shared_data(); memcpy( &context->Rax, wine_user_shared_data + offset, data_size ); context->Rip += prefixlen + len + 1; return ExceptionContinueExecution; diff --git a/server/file.h b/server/file.h index 7395814dadd2..4c454de4d411 100644 --- a/server/file.h +++ b/server/file.h @@ -173,6 +173,8 @@ extern struct file *get_mapping_file( struct process *process, client_ptr_t base extern void free_mapped_views( struct process *process ); extern int get_page_size(void);
+extern void init_kusd_mapping( struct mapping *mapping ); + /* device functions */
extern struct object *create_named_pipe_device( struct object *root, const struct unicode_str *name ); diff --git a/server/mapping.c b/server/mapping.c index 6990a1913d76..6970c86ffc1a 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -35,6 +35,7 @@ #define WIN32_NO_STATUS #include "windef.h" #include "winternl.h" +#include "ddk/wdm.h"
#include "file.h" #include "handle.h" @@ -943,6 +944,68 @@ int get_page_size(void) return page_mask + 1; }
+static KSHARED_USER_DATA *kusd = MAP_FAILED; +static const timeout_t kusd_timeout = 16 * -TICKS_PER_SEC / 1000; + +static void kusd_set_current_time( void *private ) +{ + ULONG system_time_high = current_time >> 32; + ULONG system_time_low = current_time & 0xffffffff; + ULONG interrupt_time_high = monotonic_time >> 32; + ULONG interrupt_time_low = monotonic_time & 0xffffffff; + ULONG tick_count_high = (monotonic_time * 1000 / TICKS_PER_SEC) >> 32; + ULONG tick_count_low = (monotonic_time * 1000 / TICKS_PER_SEC) & 0xffffffff; + KSHARED_USER_DATA *ptr = kusd; + + add_timeout_user( kusd_timeout, kusd_set_current_time, NULL ); + + /* 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->SystemTime.High2Time = system_time_high; + ptr->SystemTime.LowPart = system_time_low; + ptr->SystemTime.High1Time = system_time_high; + + ptr->InterruptTime.High2Time = interrupt_time_high; + ptr->InterruptTime.LowPart = interrupt_time_low; + ptr->InterruptTime.High1Time = interrupt_time_high; + + ptr->TickCount.High2Time = tick_count_high; + ptr->TickCount.LowPart = tick_count_low; + ptr->TickCount.High1Time = tick_count_high; + *(volatile ULONG *)&ptr->TickCountLowDeprecated = tick_count_low; +#else + __atomic_store_n(&ptr->SystemTime.High2Time, system_time_high, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->SystemTime.LowPart, system_time_low, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->SystemTime.High1Time, system_time_high, __ATOMIC_SEQ_CST); + + __atomic_store_n(&ptr->InterruptTime.High2Time, interrupt_time_high, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->InterruptTime.LowPart, interrupt_time_low, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->InterruptTime.High1Time, interrupt_time_high, __ATOMIC_SEQ_CST); + + __atomic_store_n(&ptr->TickCount.High2Time, tick_count_high, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->TickCount.LowPart, tick_count_low, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->TickCount.High1Time, tick_count_high, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->TickCountLowDeprecated, tick_count_low, __ATOMIC_SEQ_CST); +#endif +} + +void init_kusd_mapping( struct mapping *mapping ) +{ + if (kusd != MAP_FAILED) return; + + grab_object( mapping ); + make_object_static( &mapping->obj ); + + if ((kusd = mmap( NULL, mapping->size, PROT_WRITE, MAP_SHARED, + get_unix_fd( mapping->fd ), 0 )) == MAP_FAILED) + set_error( STATUS_NO_MEMORY ); + else + kusd_set_current_time( NULL ); +} + /* create a file mapping */ DECL_HANDLER(create_mapping) { diff --git a/server/process.c b/server/process.c index 211207ed03b6..6722addb0915 100644 --- a/server/process.c +++ b/server/process.c @@ -1361,6 +1361,7 @@ DECL_HANDLER(init_process_done) { struct process_dll *dll; struct process *process = current->process; + struct mapping *mapping;
if (is_process_init_done(process)) { @@ -1372,6 +1373,13 @@ DECL_HANDLER(init_process_done) set_error( STATUS_DLL_NOT_FOUND ); return; } + if (!(mapping = get_mapping_obj( current->process, req->usd_handle, SECTION_MAP_WRITE ))) + { + set_error( STATUS_INVALID_PARAMETER ); + return; + } + init_kusd_mapping( mapping ); + release_object( mapping );
/* main exe is the first in the dll list */ list_remove( &dll->entry ); diff --git a/server/protocol.def b/server/protocol.def index 06a29b153ea0..2fb8e2ec80bd 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -854,6 +854,7 @@ struct rawinput_device mod_handle_t module; /* main module base address */ client_ptr_t ldt_copy; /* address of LDT copy (in thread address space) */ client_ptr_t entry; /* process entry point */ + obj_handle_t usd_handle; /* USD mapping handle */ @REPLY int suspend; /* is process suspended? */ @END
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/tests/info.c | 1 - dlls/ntdll/thread.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 757ef2691004..8e6f488df1d5 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -2266,7 +2266,6 @@ static void test_queryvirtualmemory(void) ok(mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%X\n", mbi.State, MEM_COMMIT); ok(mbi.Protect == PAGE_READONLY, "mbi.Protect is 0x%x\n", mbi.Protect); ok(mbi.Type == MEM_PRIVATE, "mbi.Type is 0x%x, expected 0x%x\n", mbi.Type, MEM_PRIVATE); - todo_wine ok(mbi.RegionSize == 0x1000, "mbi.RegionSize is 0x%x, expected 0x%x\n", mbi.RegionSize, 0x1000);
/* check error code when addr is higher than working set limit */ diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 78fe4e4fdf86..0fc8aa9e9285 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -294,7 +294,7 @@ TEB *thread_init(void) /* reserve space for shared user data */
addr = (void *)0x7ffe0000; - size = 0x10000; + size = 0x1000; status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); if (status)