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:
Alexandre Julliard 2003-06-30 21:00:15 +00:00
parent 4e1ef0c114
commit 217fdab78f
9 changed files with 108 additions and 39 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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