server: Use a standard user APC also for timers.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-05-25 13:03:49 +02:00
parent 118bd9fee3
commit e1716530d9
8 changed files with 41 additions and 83 deletions

View File

@ -351,30 +351,18 @@ static int wait_select_reply( void *cookie )
}
static void invoke_apc( CONTEXT *context, const user_apc_t *apc )
/***********************************************************************
* invoke_user_apc
*/
static void invoke_user_apc( CONTEXT *context, const user_apc_t *apc )
{
switch( apc->type )
{
case APC_USER:
call_user_apc_dispatcher( context, apc->user.args[0], apc->user.args[1], apc->user.args[2],
wine_server_get_ptr( apc->user.func ), pKiUserApcDispatcher );
break;
case APC_TIMER:
call_user_apc_dispatcher( context, (ULONG_PTR)wine_server_get_ptr( apc->user.args[1] ),
(DWORD)apc->timer.time, (DWORD)(apc->timer.time >> 32),
wine_server_get_ptr( apc->user.func ), pKiUserApcDispatcher );
break;
default:
server_protocol_error( "get_apc_request: bad type %d\n", apc->type );
break;
}
call_user_apc_dispatcher( context, apc->args[0], apc->args[1], apc->args[2],
wine_server_get_ptr( apc->func ), pKiUserApcDispatcher );
}
/***********************************************************************
* invoke_apc
*
* Invoke a single APC.
*
* invoke_system_apc
*/
static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOOL self )
{
@ -702,7 +690,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, NULL, NULL, &apc );
if (ret == STATUS_USER_APC) invoke_apc( NULL, &apc );
if (ret == STATUS_USER_APC) invoke_user_apc( NULL, &apc );
/* A test on Windows 2000 shows that Windows always yields during
a wait, but a wait that is hit by an event gets a priority
@ -723,7 +711,7 @@ NTSTATUS WINAPI NtContinue( CONTEXT *context, BOOLEAN alertable )
if (alertable)
{
status = server_select( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, 0, NULL, NULL, &apc );
if (status == STATUS_USER_APC) invoke_apc( context, &apc );
if (status == STATUS_USER_APC) invoke_user_apc( context, &apc );
}
status = NtSetContextThread( GetCurrentThread(), context );
if (!status && (context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)

View File

@ -1296,11 +1296,11 @@ NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1
req->handle = wine_server_obj_handle( handle );
if (func)
{
req->call.type = APC_USER;
req->call.user.user.func = wine_server_client_ptr( func );
req->call.user.user.args[0] = arg1;
req->call.user.user.args[1] = arg2;
req->call.user.user.args[2] = arg3;
req->call.type = APC_USER;
req->call.user.func = wine_server_client_ptr( func );
req->call.user.args[0] = arg1;
req->call.user.args[1] = arg2;
req->call.user.args[2] = arg3;
}
else req->call.type = APC_NONE; /* wake up only */
ret = wine_server_call( req );

View File

@ -455,7 +455,6 @@ enum apc_type
{
APC_NONE,
APC_USER,
APC_TIMER,
APC_ASYNC_IO,
APC_VIRTUAL_ALLOC,
APC_VIRTUAL_FREE,
@ -471,24 +470,12 @@ enum apc_type
APC_BREAK_PROCESS
};
typedef union
typedef struct
{
enum apc_type type;
struct
{
enum apc_type type;
int __pad;
client_ptr_t func;
apc_param_t args[3];
} user;
struct
{
enum apc_type type;
int __pad;
client_ptr_t func;
abstime_t time;
client_ptr_t arg;
} timer;
enum apc_type type;
int __pad;
client_ptr_t func;
apc_param_t args[3];
} user_apc_t;
typedef union
@ -6300,7 +6287,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 705
#define SERVER_PROTOCOL_VERSION 706
/* ### protocol_version end ### */

View File

@ -406,11 +406,11 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
{
apc_call_t data;
memset( &data, 0, sizeof(data) );
data.type = APC_USER;
data.user.user.func = async->data.apc;
data.user.user.args[0] = async->data.apc_context;
data.user.user.args[1] = async->data.iosb;
data.user.user.args[2] = 0;
data.type = APC_USER;
data.user.func = async->data.apc;
data.user.args[0] = async->data.apc_context;
data.user.args[1] = async->data.iosb;
data.user.args[2] = 0;
thread_queue_apc( NULL, async->thread, NULL, &data );
}
else if (async->data.apc_context && (async->pending ||

View File

@ -471,7 +471,6 @@ enum apc_type
{
APC_NONE,
APC_USER,
APC_TIMER,
APC_ASYNC_IO,
APC_VIRTUAL_ALLOC,
APC_VIRTUAL_FREE,
@ -487,24 +486,12 @@ enum apc_type
APC_BREAK_PROCESS
};
typedef union
typedef struct
{
enum apc_type type;
struct
{
enum apc_type type; /* APC_USER */
int __pad;
client_ptr_t func; /* void (__stdcall *func)(ULONG_PTR,ULONG_PTR,ULONG_PTR); */
apc_param_t args[3]; /* arguments for user function */
} user;
struct
{
enum apc_type type; /* APC_TIMER */
int __pad;
client_ptr_t func; /* void (__stdcall *func)(void*, unsigned int, unsigned int); */
abstime_t time; /* time of expiration */
client_ptr_t arg; /* user argument */
} timer;
enum apc_type type; /* APC_USER */
int __pad;
client_ptr_t func; /* void (__stdcall *func)(ULONG_PTR,ULONG_PTR,ULONG_PTR); */
apc_param_t args[3]; /* arguments for user function */
} user_apc_t;
typedef union

View File

@ -1071,7 +1071,6 @@ static inline struct list *get_apc_queue( struct thread *thread, enum apc_type t
case APC_NONE:
return NULL;
case APC_USER:
case APC_TIMER:
return &thread->user_apc;
default:
return &thread->system_apc;

View File

@ -128,10 +128,11 @@ static void timer_callback( void *private )
assert (timer->callback);
memset( &data, 0, sizeof(data) );
data.type = APC_TIMER;
data.user.timer.func = timer->callback;
data.user.timer.time = timer->when;
data.user.timer.arg = timer->arg;
data.type = APC_USER;
data.user.func = timer->callback;
data.user.args[0] = timer->arg;
data.user.args[1] = (unsigned int)timer->when;
data.user.args[2] = timer->when >> 32;
if (!thread_queue_apc( NULL, timer->thread, &timer->obj, &data ))
{
@ -165,7 +166,7 @@ static int cancel_timer( struct timer *timer )
}
if (timer->thread)
{
thread_cancel_apc( timer->thread, &timer->obj, APC_TIMER );
thread_cancel_apc( timer->thread, &timer->obj, APC_USER );
release_object( timer->thread );
timer->thread = NULL;
}

View File

@ -156,16 +156,12 @@ static void dump_apc_call( const char *prefix, const apc_call_t *call )
fprintf( stderr, "APC_NONE" );
break;
case APC_USER:
dump_uint64( "APC_USER,func=", &call->user.user.func );
dump_uint64( ",args={", &call->user.user.args[0] );
dump_uint64( ",", &call->user.user.args[1] );
dump_uint64( ",", &call->user.user.args[2] );
dump_uint64( "APC_USER,func=", &call->user.func );
dump_uint64( ",args={", &call->user.args[0] );
dump_uint64( ",", &call->user.args[1] );
dump_uint64( ",", &call->user.args[2] );
fputc( '}', stderr );
break;
case APC_TIMER:
dump_timeout( "APC_TIMER,time=", &call->user.timer.time );
dump_uint64( ",arg=", &call->user.timer.arg );
break;
case APC_ASYNC_IO:
dump_uint64( "APC_ASYNC_IO,user=", &call->async_io.user );
dump_uint64( ",sb=", &call->async_io.sb );