Implemented NtDelayExecution and make Sleep call it.
The handle count must not be 0 in NtWaitForMultipleObjects (spotted by Troy Rollo).
This commit is contained in:
parent
4e1ef0c114
commit
217fdab78f
|
@ -1059,7 +1059,7 @@ NTSTATUS WINAPI NtLockFile( HANDLE hFile, HANDLE lock_granted_event,
|
|||
/* Unix lock conflict, sleep a bit and retry */
|
||||
time.QuadPart = 100 * (ULONGLONG)10000;
|
||||
time.QuadPart = -time.QuadPart;
|
||||
NtWaitForMultipleObjects( 0, NULL, FALSE, FALSE, &time );
|
||||
NtDelayExecution( FALSE, &time );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
@ stdcall NtCreateTimer(ptr long ptr long)
|
||||
@ stub NtCreateToken
|
||||
@ stdcall NtCurrentTeb()
|
||||
@ stub NtDelayExecution
|
||||
@ stdcall NtDelayExecution(long ptr)
|
||||
@ stub NtDeleteFile
|
||||
@ stdcall NtDeleteKey(long)
|
||||
@ stdcall NtDeleteValueKey(long ptr)
|
||||
|
@ -627,7 +627,7 @@
|
|||
@ stub ZwCreateThread
|
||||
@ stdcall ZwCreateTimer(ptr long ptr long) NtCreateTimer
|
||||
@ stub ZwCreateToken
|
||||
@ stub ZwDelayExecution
|
||||
@ stdcall ZwDelayExecution(long ptr) NtDelayExecution
|
||||
@ stub ZwDeleteFile
|
||||
@ stdcall ZwDeleteKey(long) NtDeleteKey
|
||||
@ stdcall ZwDeleteValueKey(long ptr) NtDeleteValueKey
|
||||
|
|
|
@ -30,6 +30,8 @@ extern LPCSTR debugstr_us( const UNICODE_STRING *str );
|
|||
extern void dump_ObjectAttributes (const OBJECT_ATTRIBUTES *ObjectAttributes);
|
||||
|
||||
extern void NTDLL_get_server_timeout( abs_time_t *when, const LARGE_INTEGER *timeout );
|
||||
extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UINT flags,
|
||||
const LARGE_INTEGER *timeout );
|
||||
|
||||
/* module handling */
|
||||
extern WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename );
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
#include "windef.h"
|
||||
#include "winternl.h"
|
||||
#include "wine/library.h"
|
||||
|
||||
#include "ntdll_misc.h"
|
||||
#include "selectors.h"
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -1111,7 +1111,7 @@ static HANDLER_DEF(usr1_handler)
|
|||
init_handler( HANDLER_CONTEXT );
|
||||
/* wait with 0 timeout, will only return once the thread is no longer suspended */
|
||||
timeout.QuadPart = 0;
|
||||
NtWaitForMultipleObjects( 0, NULL, FALSE, FALSE, &timeout );
|
||||
NTDLL_wait_for_multiple_objects( 0, NULL, 0, &timeout );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "selectors.h"
|
||||
#include "stackframe.h"
|
||||
#include "global.h"
|
||||
#include "ntdll_misc.h"
|
||||
#include "miscemu.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
|
@ -585,7 +586,7 @@ static HANDLER_DEF(usr1_handler)
|
|||
|
||||
/* wait with 0 timeout, will only return once the thread is no longer suspended */
|
||||
timeout.QuadPart = 0;
|
||||
NtWaitForMultipleObjects( 0, NULL, FALSE, FALSE, &timeout );
|
||||
NTDLL_wait_for_multiple_objects( 0, NULL, 0, &timeout );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "wine/exception.h"
|
||||
#include "global.h"
|
||||
#include "stackframe.h"
|
||||
#include "ntdll_misc.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
|
@ -388,7 +389,7 @@ static HANDLER_DEF(usr1_handler)
|
|||
|
||||
/* wait with 0 timeout, will only return once the thread is no longer suspended */
|
||||
timeout.QuadPart = 0;
|
||||
NtWaitForMultipleObjects( 0, NULL, FALSE, FALSE, &timeout );
|
||||
NTDLL_wait_for_multiple_objects( 0, NULL, 0, &timeout );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -547,6 +547,39 @@ static void call_apcs( BOOL alertable )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* NTDLL_wait_for_multiple_objects
|
||||
*
|
||||
* Implementation of NtWaitForMultipleObjects
|
||||
*/
|
||||
NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UINT flags,
|
||||
const LARGE_INTEGER *timeout )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
int cookie;
|
||||
|
||||
if (timeout) flags |= SELECT_TIMEOUT;
|
||||
for (;;)
|
||||
{
|
||||
SERVER_START_REQ( select )
|
||||
{
|
||||
req->flags = flags;
|
||||
req->cookie = &cookie;
|
||||
NTDLL_get_server_timeout( &req->timeout, timeout );
|
||||
wine_server_add_data( req, handles, count * sizeof(HANDLE) );
|
||||
ret = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret == STATUS_PENDING) ret = wait_reply( &cookie );
|
||||
if (ret != STATUS_USER_APC) break;
|
||||
call_apcs( (flags & SELECT_ALERTABLE) != 0 );
|
||||
if (flags & SELECT_ALERTABLE) break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* wait operations */
|
||||
|
||||
/******************************************************************
|
||||
|
@ -554,41 +587,62 @@ static void call_apcs( BOOL alertable )
|
|||
*/
|
||||
NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles,
|
||||
BOOLEAN wait_all, BOOLEAN alertable,
|
||||
PLARGE_INTEGER timeout )
|
||||
const LARGE_INTEGER *timeout )
|
||||
{
|
||||
int ret, cookie;
|
||||
UINT flags = SELECT_INTERRUPTIBLE;
|
||||
|
||||
if (count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1;
|
||||
if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
SERVER_START_REQ( select )
|
||||
{
|
||||
req->flags = SELECT_INTERRUPTIBLE;
|
||||
req->cookie = &cookie;
|
||||
NTDLL_get_server_timeout( &req->timeout, timeout );
|
||||
wine_server_add_data( req, handles, count * sizeof(HANDLE) );
|
||||
|
||||
if (wait_all) req->flags |= SELECT_ALL;
|
||||
if (alertable) req->flags |= SELECT_ALERTABLE;
|
||||
if (timeout) req->flags |= SELECT_TIMEOUT;
|
||||
|
||||
ret = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret == STATUS_PENDING) ret = wait_reply( &cookie );
|
||||
if (ret != STATUS_USER_APC) break;
|
||||
call_apcs( alertable );
|
||||
if (alertable) break;
|
||||
}
|
||||
return ret;
|
||||
if (wait_all) flags |= SELECT_ALL;
|
||||
if (alertable) flags |= SELECT_ALERTABLE;
|
||||
return NTDLL_wait_for_multiple_objects( count, handles, flags, timeout );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* NtWaitForSingleObject (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtWaitForSingleObject(HANDLE handle, BOOLEAN alertable, PLARGE_INTEGER timeout )
|
||||
NTSTATUS WINAPI NtWaitForSingleObject(HANDLE handle, BOOLEAN alertable, const LARGE_INTEGER *timeout )
|
||||
{
|
||||
return NtWaitForMultipleObjects( 1, &handle, FALSE, alertable, timeout );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* NtDelayExecution (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeout )
|
||||
{
|
||||
/* if alertable or async I/O in progress, we need to query the server */
|
||||
if (alertable || NtCurrentTeb()->pending_list)
|
||||
{
|
||||
UINT flags = SELECT_INTERRUPTIBLE;
|
||||
if (alertable) flags |= SELECT_ALERTABLE;
|
||||
return NTDLL_wait_for_multiple_objects( 0, NULL, flags, timeout );
|
||||
}
|
||||
|
||||
if (!timeout) /* sleep forever */
|
||||
{
|
||||
for (;;) select( 0, NULL, NULL, NULL, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
abs_time_t when;
|
||||
|
||||
NTDLL_get_server_timeout( &when, timeout );
|
||||
for (;;)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday( &tv, 0 );
|
||||
tv.tv_sec = when.sec - tv.tv_sec;
|
||||
if ((tv.tv_usec = when.usec - tv.tv_usec) < 0)
|
||||
{
|
||||
tv.tv_usec += 1000000;
|
||||
tv.tv_sec--;
|
||||
}
|
||||
if (tv.tv_sec < 0) tv.tv_sec = tv.tv_usec = 0;
|
||||
if (select( 0, NULL, NULL, NULL, &tv ) != -1) break;
|
||||
}
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -924,6 +924,7 @@ NTSTATUS WINAPI NtCreateKey(PHKEY,ACCESS_MASK,const OBJECT_ATTRIBUTES*,ULONG,co
|
|||
NTSTATUS WINAPI NtCreateSection(HANDLE*,ACCESS_MASK,const OBJECT_ATTRIBUTES*,const LARGE_INTEGER*,ULONG,ULONG,HANDLE);
|
||||
NTSTATUS WINAPI NtCreateSemaphore(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES*,ULONG,ULONG);
|
||||
NTSTATUS WINAPI NtCreateTimer(HANDLE*, ACCESS_MASK, const OBJECT_ATTRIBUTES*, TIMER_TYPE);
|
||||
NTSTATUS WINAPI NtDelayExecution(BOOLEAN,const LARGE_INTEGER*);
|
||||
NTSTATUS WINAPI NtDeleteKey(HKEY);
|
||||
NTSTATUS WINAPI NtDeleteValueKey(HKEY,const UNICODE_STRING *);
|
||||
NTSTATUS WINAPI NtDeviceIoControlFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,PVOID,ULONG,PVOID,ULONG);
|
||||
|
@ -989,8 +990,8 @@ NTSTATUS WINAPI NtUnloadKey(HKEY);
|
|||
NTSTATUS WINAPI NtUnlockFile(HANDLE,PIO_STATUS_BLOCK,PLARGE_INTEGER,PLARGE_INTEGER,PULONG);
|
||||
NTSTATUS WINAPI NtUnlockVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG);
|
||||
NTSTATUS WINAPI NtUnmapViewOfSection(HANDLE,PVOID);
|
||||
NTSTATUS WINAPI NtWaitForSingleObject(HANDLE,BOOLEAN,PLARGE_INTEGER);
|
||||
NTSTATUS WINAPI NtWaitForMultipleObjects(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,PLARGE_INTEGER);
|
||||
NTSTATUS WINAPI NtWaitForSingleObject(HANDLE,BOOLEAN,const LARGE_INTEGER*);
|
||||
NTSTATUS WINAPI NtWaitForMultipleObjects(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
|
||||
NTSTATUS WINAPI NtWriteFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,const void*,ULONG,PLARGE_INTEGER,PULONG);
|
||||
|
||||
void WINAPI RtlAcquirePebLock(void);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
VOID WINAPI Sleep( DWORD timeout )
|
||||
{
|
||||
WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, FALSE );
|
||||
SleepEx( timeout, FALSE );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -38,9 +38,19 @@ VOID WINAPI Sleep( DWORD timeout )
|
|||
*/
|
||||
DWORD WINAPI SleepEx( DWORD timeout, BOOL alertable )
|
||||
{
|
||||
DWORD ret = WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, alertable );
|
||||
if (ret != WAIT_IO_COMPLETION) ret = 0;
|
||||
return ret;
|
||||
NTSTATUS status;
|
||||
|
||||
if (timeout == INFINITE) status = NtDelayExecution( alertable, NULL );
|
||||
else
|
||||
{
|
||||
LARGE_INTEGER time;
|
||||
|
||||
time.QuadPart = timeout * (ULONGLONG)10000;
|
||||
time.QuadPart = -time.QuadPart;
|
||||
status = NtDelayExecution( alertable, &time );
|
||||
}
|
||||
if (status != STATUS_USER_APC) status = STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue