[PATCH 0/1] MR10977: ntdll: Allow calling NtContinue in syscall callbacks.
From: Jacek Caban <jacek@codeweavers.com> --- dlls/ntdll/tests/wow64.c | 50 ++++++++++++++++++++++++++++++++++ dlls/ntdll/unix/signal_arm64.c | 5 ++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/tests/wow64.c b/dlls/ntdll/tests/wow64.c index c05ac03f8ba..a246cd0abaa 100644 --- a/dlls/ntdll/tests/wow64.c +++ b/dlls/ntdll/tests/wow64.c @@ -3291,8 +3291,45 @@ static DWORD WINAPI pipe_read_thread( void *arg ) return 0; } +struct nested_continue_params +{ + HANDLE event; + ULONG64 suspend_rip; +}; + +static DWORD WINAPI nested_continue_thread( void *arg ) +{ + CHPE_V2_CPU_AREA_INFO *chpe = NtCurrentTeb()->ChpeV2CpuAreaInfo; + struct nested_continue_params *params = arg; + CONTEXT ctx, nested_ctx; + LONG i = 0; + + RtlCaptureContext( &ctx ); + if (InterlockedIncrement( &i ) != 1) return 0; + + params->suspend_rip = ctx.Rip; + chpe->InSyscallCallback = 1; + NtSetEvent( params->event, NULL ); + while (!*chpe->SuspendDoorbell) YieldProcessor(); + + /* with InSyscallCallback set, NtContinue does not suspend */ + RtlCaptureContext( &nested_ctx ); + if (InterlockedIncrement( &i ) == 2) NtContinue( &nested_ctx, FALSE ); + chpe->InSyscallCallback = 0; + + /* with InSimulation set, NtContinue does not suspend */ + chpe->InSimulation = 1; + RtlCaptureContext( &nested_ctx ); + if (InterlockedIncrement( &i ) == 3) NtContinue( &nested_ctx, FALSE ); + chpe->InSimulation = 0; + + NtContinue( &ctx, FALSE ); + return 0; +} + static void test_suspend_doorbell(void) { + struct nested_continue_params nested_params; struct pipe_read_params read_params; struct doorbell_params params; HANDLE thread, pipe; @@ -3361,6 +3398,19 @@ static void test_suspend_doorbell(void) CloseHandle( read_params.pipe ); CloseHandle( read_params.event ); } + + nested_params.event = CreateEventW( NULL, FALSE, FALSE, NULL ); + thread = CreateThread( NULL, 0, nested_continue_thread, &nested_params, 0, NULL ); + + ret = WaitForSingleObject( nested_params.event, 10000 ); + ok( ret == 0, "wait failed %lx\n", ret ); + + ctx.ContextFlags = CONTEXT_FULL; + GetThreadContext( thread, &ctx ); + ok( ctx.Rip == nested_params.suspend_rip, "Rip = %llx, expected %llx\n", ctx.Rip, params.suspend_rip ); + + CloseHandle( nested_params.event ); + CloseHandle( thread ); } #endif /* __arm64ec__ */ diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index f6d2e017f22..5a56c2d7d64 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -347,13 +347,14 @@ NTSTATUS signal_set_full_context( CONTEXT *context ) struct thread_data *data = get_thread_data(); struct syscall_frame *frame = get_syscall_frame( data ); struct arm64_thread_data *arm64_data = arm64_thread_data( data ); + CHPE_V2_CPU_AREA_INFO *cpu_area = data->teb->ChpeV2CpuAreaInfo; NTSTATUS status; - if (arm64_data->suspend_pending) + if (arm64_data->suspend_pending && !cpu_area->InSyscallCallback && !cpu_area->InSimulation) { sigset_t old_set; pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set ); - *data->teb->ChpeV2CpuAreaInfo->SuspendDoorbell = 0; + *cpu_area->SuspendDoorbell = 0; arm64_data->suspend_pending = FALSE; wait_suspend( context ); status = NtSetContextThread( GetCurrentThread(), context ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10977
participants (2)
-
Jacek Caban -
Jacek Caban (@jacek)