From a18444984171ee86503d1250094965fb50a198ee Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 4 Jun 2020 20:06:53 +0200 Subject: [PATCH] ntdll: Move some wait functions to the Unix library. Signed-off-by: Alexandre Julliard --- dlls/ntdll/Makefile.in | 1 + dlls/ntdll/sync.c | 76 ++---------------- dlls/ntdll/unix/loader.c | 5 ++ dlls/ntdll/unix/sync.c | 167 +++++++++++++++++++++++++++++++++++++++ dlls/ntdll/unixlib.h | 11 ++- 5 files changed, 189 insertions(+), 71 deletions(-) create mode 100644 dlls/ntdll/unix/sync.c diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index ca195eba76a..36edde9388c 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -58,6 +58,7 @@ C_SRCS = \ unix/signal_i386.c \ unix/signal_powerpc.c \ unix/signal_x86_64.c \ + unix/sync.c \ unix/thread.c \ unix/virtual.c \ version.c \ diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 7aee9c1a02b..64b64555bf8 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -1089,22 +1089,6 @@ NTSTATUS WINAPI NtSetTimerResolution(IN ULONG resolution, /* wait operations */ -static NTSTATUS wait_objects( DWORD count, const HANDLE *handles, - BOOLEAN wait_any, BOOLEAN alertable, - const LARGE_INTEGER *timeout ) -{ - select_op_t select_op; - UINT i, flags = SELECT_INTERRUPTIBLE; - - if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1; - - if (alertable) flags |= SELECT_ALERTABLE; - select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL; - for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] ); - return unix_funcs->server_wait( &select_op, offsetof( select_op_t, wait.handles[count] ), flags, timeout ); -} - - /****************************************************************** * NtWaitForMultipleObjects (NTDLL.@) */ @@ -1112,7 +1096,7 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { - return wait_objects( count, handles, wait_any, alertable, timeout ); + return unix_funcs->NtWaitForMultipleObjects( count, handles, wait_any, alertable, timeout ); } @@ -1121,26 +1105,17 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, */ NTSTATUS WINAPI NtWaitForSingleObject(HANDLE handle, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { - return wait_objects( 1, &handle, FALSE, alertable, timeout ); + return unix_funcs->NtWaitForSingleObject( handle, alertable, timeout ); } /****************************************************************** * NtSignalAndWaitForSingleObject (NTDLL.@) */ -NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE hSignalObject, HANDLE hWaitObject, +NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { - select_op_t select_op; - UINT flags = SELECT_INTERRUPTIBLE; - - if (!hSignalObject) return STATUS_INVALID_HANDLE; - - if (alertable) flags |= SELECT_ALERTABLE; - select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT; - select_op.signal_and_wait.wait = wine_server_obj_handle( hWaitObject ); - select_op.signal_and_wait.signal = wine_server_obj_handle( hSignalObject ); - return unix_funcs->server_wait( &select_op, sizeof(select_op.signal_and_wait), flags, timeout ); + return unix_funcs->NtSignalAndWaitForSingleObject( signal, wait, alertable, timeout ); } @@ -1149,12 +1124,7 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE hSignalObject, HANDLE hWa */ NTSTATUS WINAPI NtYieldExecution(void) { -#ifdef HAVE_SCHED_YIELD - sched_yield(); - return STATUS_SUCCESS; -#else - return STATUS_NO_YIELD_PERFORMED; -#endif + return unix_funcs->NtYieldExecution(); } @@ -1163,41 +1133,7 @@ NTSTATUS WINAPI NtYieldExecution(void) */ NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeout ) { - /* if alertable, we need to query the server */ - if (alertable) - return unix_funcs->server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, timeout ); - - if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE) /* sleep forever */ - { - for (;;) select( 0, NULL, NULL, NULL, NULL ); - } - else - { - LARGE_INTEGER now; - timeout_t when, diff; - - if ((when = timeout->QuadPart) < 0) - { - NtQuerySystemTime( &now ); - when = now.QuadPart - when; - } - - /* Note that we yield after establishing the desired timeout */ - NtYieldExecution(); - if (!when) return STATUS_SUCCESS; - - for (;;) - { - struct timeval tv; - NtQuerySystemTime( &now ); - diff = (when - now.QuadPart + 9) / 10; - if (diff <= 0) break; - tv.tv_sec = diff / 1000000; - tv.tv_usec = diff % 1000000; - if (select( 0, NULL, NULL, NULL, &tv ) != -1) break; - } - } - return STATUS_SUCCESS; + return unix_funcs->NtDelayExecution( alertable, timeout ); } diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index b6838809f14..882e9cea750 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -987,6 +987,7 @@ static struct unix_funcs unix_funcs = NtAreMappedFilesTheSame, NtClose, NtCurrentTeb, + NtDelayExecution, NtDuplicateObject, NtFlushVirtualMemory, NtFreeVirtualMemory, @@ -1001,9 +1002,13 @@ static struct unix_funcs unix_funcs = NtResetWriteWatch, NtSetContextThread, NtSetLdtEntries, + NtSignalAndWaitForSingleObject, NtUnlockVirtualMemory, NtUnmapViewOfSection, + NtWaitForMultipleObjects, + NtWaitForSingleObject, NtWriteVirtualMemory, + NtYieldExecution, get_main_args, get_paths, get_dll_path, diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c new file mode 100644 index 00000000000..6faba509cc3 --- /dev/null +++ b/dlls/ntdll/unix/sync.c @@ -0,0 +1,167 @@ +/* + * Process synchronisation + * + * Copyright 1996, 1997, 1998 Marcus Meissner + * Copyright 1997, 1999 Alexandre Julliard + * Copyright 1999, 2000 Juergen Schmied + * Copyright 2003 Eric Pouech + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#ifdef HAVE_SYS_SYSCALL_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +# include +#endif +#ifdef HAVE_POLL_H +#include +#endif +#ifdef HAVE_SYS_POLL_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SCHED_H +# include +#endif +#include +#include +#include +#include +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#define NONAMELESSUNION +#include "windef.h" +#include "winternl.h" +#include "wine/server.h" +#include "unix_private.h" + + +/****************************************************************** + * NtWaitForMultipleObjects (NTDLL.@) + */ +NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, + BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + select_op_t select_op; + UINT i, flags = SELECT_INTERRUPTIBLE; + + if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1; + + if (alertable) flags |= SELECT_ALERTABLE; + select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL; + for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] ); + return server_wait( &select_op, offsetof( select_op_t, wait.handles[count] ), flags, timeout ); +} + + +/****************************************************************** + * NtWaitForSingleObject (NTDLL.@) + */ +NTSTATUS WINAPI NtWaitForSingleObject( HANDLE handle, BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + return NtWaitForMultipleObjects( 1, &handle, FALSE, alertable, timeout ); +} + + +/****************************************************************** + * NtSignalAndWaitForSingleObject (NTDLL.@) + */ +NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, + BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + select_op_t select_op; + UINT flags = SELECT_INTERRUPTIBLE; + + if (!signal) return STATUS_INVALID_HANDLE; + + if (alertable) flags |= SELECT_ALERTABLE; + select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT; + select_op.signal_and_wait.wait = wine_server_obj_handle( wait ); + select_op.signal_and_wait.signal = wine_server_obj_handle( signal ); + return server_wait( &select_op, sizeof(select_op.signal_and_wait), flags, timeout ); +} + + +/****************************************************************** + * NtYieldExecution (NTDLL.@) + */ +NTSTATUS WINAPI NtYieldExecution(void) +{ +#ifdef HAVE_SCHED_YIELD + sched_yield(); + return STATUS_SUCCESS; +#else + return STATUS_NO_YIELD_PERFORMED; +#endif +} + + +/****************************************************************** + * NtDelayExecution (NTDLL.@) + */ +NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + /* if alertable, we need to query the server */ + if (alertable) return server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, timeout ); + + if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE) /* sleep forever */ + { + for (;;) select( 0, NULL, NULL, NULL, NULL ); + } + else + { + LARGE_INTEGER now; + timeout_t when, diff; + + if ((when = timeout->QuadPart) < 0) + { + NtQuerySystemTime( &now ); + when = now.QuadPart - when; + } + + /* Note that we yield after establishing the desired timeout */ + NtYieldExecution(); + if (!when) return STATUS_SUCCESS; + + for (;;) + { + struct timeval tv; + NtQuerySystemTime( &now ); + diff = (when - now.QuadPart + 9) / 10; + if (diff <= 0) break; + tv.tv_sec = diff / 1000000; + tv.tv_usec = diff % 1000000; + if (select( 0, NULL, NULL, NULL, &tv ) != -1) break; + } + } + return STATUS_SUCCESS; +} diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index b456139adfc..fcbe352de66 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -28,7 +28,7 @@ struct ldt_copy; struct msghdr; /* increment this when you change the function table */ -#define NTDLL_UNIXLIB_VERSION 20 +#define NTDLL_UNIXLIB_VERSION 21 struct unix_funcs { @@ -38,6 +38,7 @@ struct unix_funcs NTSTATUS (WINAPI *NtAreMappedFilesTheSame)(PVOID addr1, PVOID addr2); NTSTATUS (WINAPI *NtClose)( HANDLE handle ); TEB * (WINAPI *NtCurrentTeb)(void); + NTSTATUS (WINAPI *NtDelayExecution)( BOOLEAN alertable, const LARGE_INTEGER *timeout ); NTSTATUS (WINAPI *NtDuplicateObject)( HANDLE source_process, HANDLE source, HANDLE dest_process, HANDLE *dest, ACCESS_MASK access, ULONG attributes, ULONG options ); @@ -65,11 +66,19 @@ struct unix_funcs NTSTATUS (WINAPI *NtResetWriteWatch)( HANDLE process, PVOID base, SIZE_T size ); NTSTATUS (WINAPI *NtSetContextThread)( HANDLE handle, const CONTEXT *context ); NTSTATUS (WINAPI *NtSetLdtEntries)( ULONG sel1, LDT_ENTRY entry1, ULONG sel2, LDT_ENTRY entry2 ); + NTSTATUS (WINAPI *NtSignalAndWaitForSingleObject)( HANDLE signal, HANDLE wait, + BOOLEAN alertable, const LARGE_INTEGER *timeout ); NTSTATUS (WINAPI *NtUnlockVirtualMemory)( HANDLE process, PVOID *addr, SIZE_T *size, ULONG unknown ); NTSTATUS (WINAPI *NtUnmapViewOfSection)( HANDLE process, PVOID addr ); + NTSTATUS (WINAPI *NtWaitForMultipleObjects)( DWORD count, const HANDLE *handles, + BOOLEAN wait_any, BOOLEAN alertable, + const LARGE_INTEGER *timeout ); + NTSTATUS (WINAPI *NtWaitForSingleObject)( HANDLE handle, BOOLEAN alertable, + const LARGE_INTEGER *timeout ); NTSTATUS (WINAPI *NtWriteVirtualMemory)( HANDLE process, void *addr, const void *buffer, SIZE_T size, SIZE_T *bytes_written ); + NTSTATUS (WINAPI *NtYieldExecution)(void); /* environment functions */ void (CDECL *get_main_args)( int *argc, char **argv[], char **envp[] );