ntdll: Move some wait functions to the Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Alexandre Julliard 2020-06-04 20:06:53 +02:00
parent 4ffe39573b
commit a184449841
5 changed files with 189 additions and 71 deletions

View File

@ -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 \

View File

@ -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 );
}

View File

@ -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,

View File

@ -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 <assert.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#ifdef HAVE_SYS_SYSCALL_H
#include <sys/syscall.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SCHED_H
# include <sched.h>
#endif
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#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;
}

View File

@ -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[] );