ntdll: Handle system APCs in a separate inner loop.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2020-02-05 11:49:39 +01:00 committed by Alexandre Julliard
parent 3ffa355d2b
commit 2dc99bfb30
2 changed files with 40 additions and 30 deletions

View file

@ -606,26 +606,31 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
do
{
SERVER_START_REQ( select )
for (;;)
{
req->flags = flags;
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, size );
ret = wine_server_call( req );
abs_timeout = reply->timeout;
apc_handle = reply->apc_handle;
call = reply->call;
SERVER_START_REQ( select )
{
req->flags = flags;
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, size );
ret = wine_server_call( req );
abs_timeout = reply->timeout;
apc_handle = reply->apc_handle;
call = reply->call;
}
SERVER_END_REQ;
/* don't signal multiple times */
if (size >= sizeof(select_op->signal_and_wait) && select_op->op == SELECT_SIGNAL_AND_WAIT)
size = offsetof( select_op_t, signal_and_wait.signal );
if (ret != STATUS_KERNEL_APC) break;
invoke_apc( &call, &result );
}
SERVER_END_REQ;
/* don't signal multiple times */
if (size >= sizeof(select_op->signal_and_wait) && select_op->op == SELECT_SIGNAL_AND_WAIT)
size = offsetof( select_op_t, signal_and_wait.signal );
if (ret == STATUS_KERNEL_APC) invoke_apc( &call, &result );
if (ret == STATUS_USER_APC)
{
invoke_apc( &call, &result );

View file

@ -2479,24 +2479,29 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
return STATUS_SUCCESS;
}
SERVER_START_REQ( select )
for (;;)
{
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 = wine_server_call( req );
abs_timeout = reply->timeout;
apc_handle = reply->apc_handle;
call = reply->call;
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 = wine_server_call( req );
abs_timeout = reply->timeout;
apc_handle = reply->apc_handle;
call = reply->call;
}
SERVER_END_REQ;
if (ret != STATUS_KERNEL_APC) break;
invoke_apc( &call, &result );
}
SERVER_END_REQ;
RtlLeaveCriticalSection( &addr_section );
if (ret == STATUS_KERNEL_APC) invoke_apc( &call, &result );
if (ret == STATUS_USER_APC)
{
invoke_apc( &call, &result );