ntdll: Use server_select in RtlWaitOnAddress.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
8701260768
commit
4f673d5386
|
@ -116,6 +116,8 @@ extern sigset_t server_block_set DECLSPEC_HIDDEN;
|
||||||
extern unsigned int server_call_unlocked( void *req_ptr ) DECLSPEC_HIDDEN;
|
extern unsigned int server_call_unlocked( void *req_ptr ) DECLSPEC_HIDDEN;
|
||||||
extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
|
extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
|
||||||
extern void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
|
extern void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
|
||||||
|
extern unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT flags,
|
||||||
|
timeout_t abs_timeout, user_apc_t *user_apc ) DECLSPEC_HIDDEN;
|
||||||
extern unsigned int server_wait( const select_op_t *select_op, data_size_t size,
|
extern unsigned int server_wait( const select_op_t *select_op, data_size_t size,
|
||||||
UINT flags, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
|
UINT flags, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
|
||||||
extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, apc_result_t *result ) DECLSPEC_HIDDEN;
|
extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, apc_result_t *result ) DECLSPEC_HIDDEN;
|
||||||
|
@ -127,7 +129,7 @@ extern NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct o
|
||||||
data_size_t *ret_len ) DECLSPEC_HIDDEN;
|
data_size_t *ret_len ) DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS validate_open_object_attributes( const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN;
|
extern NTSTATUS validate_open_object_attributes( const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN;
|
||||||
extern int wait_select_reply( void *cookie ) DECLSPEC_HIDDEN;
|
extern int wait_select_reply( void *cookie ) DECLSPEC_HIDDEN;
|
||||||
extern void invoke_apc( const apc_call_t *call, apc_result_t *result ) DECLSPEC_HIDDEN;
|
extern void invoke_apc( const user_apc_t *apc ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* module handling */
|
/* module handling */
|
||||||
extern LIST_ENTRY tls_links DECLSPEC_HIDDEN;
|
extern LIST_ENTRY tls_links DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -381,7 +381,7 @@ int wait_select_reply( void *cookie )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void invoke_user_apc( const user_apc_t *apc )
|
void invoke_apc( const user_apc_t *apc )
|
||||||
{
|
{
|
||||||
switch( apc->type )
|
switch( apc->type )
|
||||||
{
|
{
|
||||||
|
@ -410,7 +410,7 @@ static void invoke_user_apc( const user_apc_t *apc )
|
||||||
* Invoke a single APC.
|
* Invoke a single APC.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void invoke_apc( const apc_call_t *call, apc_result_t *result )
|
static void invoke_system_apc( const apc_call_t *call, apc_result_t *result )
|
||||||
{
|
{
|
||||||
SIZE_T size;
|
SIZE_T size;
|
||||||
void *addr;
|
void *addr;
|
||||||
|
@ -422,10 +422,6 @@ void invoke_apc( const apc_call_t *call, apc_result_t *result )
|
||||||
{
|
{
|
||||||
case APC_NONE:
|
case APC_NONE:
|
||||||
break;
|
break;
|
||||||
case APC_USER:
|
|
||||||
case APC_TIMER:
|
|
||||||
invoke_user_apc( &call->user );
|
|
||||||
break;
|
|
||||||
case APC_ASYNC_IO:
|
case APC_ASYNC_IO:
|
||||||
{
|
{
|
||||||
IO_STATUS_BLOCK *iosb = wine_server_get_ptr( call->async_io.sb );
|
IO_STATUS_BLOCK *iosb = wine_server_get_ptr( call->async_io.sb );
|
||||||
|
@ -637,7 +633,7 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
|
||||||
if (ret != STATUS_KERNEL_APC) break;
|
if (ret != STATUS_KERNEL_APC) break;
|
||||||
invoke_apc( &call, &result );
|
invoke_system_apc( &call, &result );
|
||||||
|
|
||||||
/* don't signal multiple times */
|
/* don't signal multiple times */
|
||||||
if (size >= sizeof(select_op->signal_and_wait) && select_op->op == SELECT_SIGNAL_AND_WAIT)
|
if (size >= sizeof(select_op->signal_and_wait) && select_op->op == SELECT_SIGNAL_AND_WAIT)
|
||||||
|
@ -678,7 +674,7 @@ unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT f
|
||||||
{
|
{
|
||||||
ret = server_select( select_op, size, flags, abs_timeout, &apc );
|
ret = server_select( select_op, size, flags, abs_timeout, &apc );
|
||||||
if (ret != STATUS_USER_APC) break;
|
if (ret != STATUS_USER_APC) break;
|
||||||
invoke_user_apc( &apc );
|
invoke_apc( &apc );
|
||||||
|
|
||||||
/* if we ran a user apc we have to check once more if additional apcs are queued,
|
/* if we ran a user apc we have to check once more if additional apcs are queued,
|
||||||
* but we don't want to wait */
|
* but we don't want to wait */
|
||||||
|
@ -727,7 +723,7 @@ unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, a
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
invoke_apc( call, result );
|
invoke_system_apc( call, result );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -2458,13 +2458,9 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
|
||||||
{
|
{
|
||||||
select_op_t select_op;
|
select_op_t select_op;
|
||||||
NTSTATUS ret;
|
NTSTATUS ret;
|
||||||
int cookie;
|
|
||||||
BOOL user_apc = FALSE;
|
BOOL user_apc = FALSE;
|
||||||
obj_handle_t apc_handle = 0;
|
timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
|
||||||
apc_call_t call;
|
user_apc_t apc;
|
||||||
apc_result_t result;
|
|
||||||
abstime_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
|
|
||||||
sigset_t old_set;
|
|
||||||
|
|
||||||
if (size != 1 && size != 2 && size != 4 && size != 8)
|
if (size != 1 && size != 2 && size != 4 && size != 8)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
@ -2476,8 +2472,6 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
|
||||||
select_op.keyed_event.handle = wine_server_obj_handle( keyed_event );
|
select_op.keyed_event.handle = wine_server_obj_handle( keyed_event );
|
||||||
select_op.keyed_event.key = wine_server_client_ptr( addr );
|
select_op.keyed_event.key = wine_server_client_ptr( addr );
|
||||||
|
|
||||||
memset( &result, 0, sizeof(result) );
|
|
||||||
|
|
||||||
if (abs_timeout < 0)
|
if (abs_timeout < 0)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER now;
|
LARGE_INTEGER now;
|
||||||
|
@ -2486,54 +2480,25 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
|
||||||
abs_timeout -= now.QuadPart;
|
abs_timeout -= now.QuadPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
for (;;)
|
||||||
{
|
{
|
||||||
RtlEnterCriticalSection( &addr_section );
|
RtlEnterCriticalSection( &addr_section );
|
||||||
if (!compare_addr( addr, cmp, size ))
|
if (!compare_addr( addr, cmp, size ))
|
||||||
{
|
ret = STATUS_SUCCESS;
|
||||||
RtlLeaveCriticalSection( &addr_section );
|
else
|
||||||
return STATUS_SUCCESS;
|
ret = server_select( &select_op, sizeof(select_op.keyed_event), SELECT_INTERRUPTIBLE, abs_timeout, &apc );
|
||||||
}
|
|
||||||
|
|
||||||
pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
SERVER_START_REQ( select )
|
|
||||||
{
|
|
||||||
req->flags = SELECT_INTERRUPTIBLE;
|
|
||||||
req->cookie = wine_server_client_ptr( &cookie );
|
|
||||||
req->prev_apc = apc_handle;
|
|
||||||
req->timeout = abs_timeout;
|
|
||||||
wine_server_add_data( req, &result, sizeof(result) );
|
|
||||||
wine_server_add_data( req, &select_op, sizeof(select_op.keyed_event) );
|
|
||||||
ret = server_call_unlocked( req );
|
|
||||||
apc_handle = reply->apc_handle;
|
|
||||||
call = reply->call;
|
|
||||||
}
|
|
||||||
SERVER_END_REQ;
|
|
||||||
|
|
||||||
if (ret != STATUS_KERNEL_APC) break;
|
|
||||||
invoke_apc( &call, &result );
|
|
||||||
}
|
|
||||||
pthread_sigmask( SIG_SETMASK, &old_set, NULL );
|
|
||||||
|
|
||||||
RtlLeaveCriticalSection( &addr_section );
|
RtlLeaveCriticalSection( &addr_section );
|
||||||
|
|
||||||
if (ret == STATUS_USER_APC)
|
if (ret != STATUS_USER_APC) break;
|
||||||
{
|
invoke_apc( &apc );
|
||||||
invoke_apc( &call, &result );
|
|
||||||
/* if we ran a user apc we have to check once more if additional apcs are queued,
|
|
||||||
* but we don't want to wait */
|
|
||||||
abs_timeout = 0;
|
|
||||||
user_apc = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == STATUS_PENDING) ret = wait_select_reply( &cookie );
|
/* if we ran a user apc we have to check once more if additional apcs are queued,
|
||||||
|
* but we don't want to wait */
|
||||||
|
abs_timeout = 0;
|
||||||
|
user_apc = TRUE;
|
||||||
}
|
}
|
||||||
while (ret == STATUS_USER_APC || ret == STATUS_KERNEL_APC);
|
|
||||||
|
|
||||||
if (ret == STATUS_TIMEOUT && user_apc) ret = STATUS_USER_APC;
|
if (ret == STATUS_TIMEOUT && user_apc) ret = STATUS_USER_APC;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue