server: Notify the server that an APC has completed in the next get_apc call.
This commit is contained in:
parent
2606ad538b
commit
49b49c30fc
@ -659,6 +659,8 @@ static int wait_reply( void *cookie )
|
|||||||
*/
|
*/
|
||||||
static void call_apcs( BOOL alertable )
|
static void call_apcs( BOOL alertable )
|
||||||
{
|
{
|
||||||
|
NTSTATUS ret;
|
||||||
|
HANDLE handle = 0;
|
||||||
FARPROC proc;
|
FARPROC proc;
|
||||||
LARGE_INTEGER time;
|
LARGE_INTEGER time;
|
||||||
void *arg1, *arg2, *arg3;
|
void *arg1, *arg2, *arg3;
|
||||||
@ -669,18 +671,23 @@ static void call_apcs( BOOL alertable )
|
|||||||
SERVER_START_REQ( get_apc )
|
SERVER_START_REQ( get_apc )
|
||||||
{
|
{
|
||||||
req->alertable = alertable;
|
req->alertable = alertable;
|
||||||
if (!wine_server_call( req )) type = reply->type;
|
req->prev = handle;
|
||||||
proc = reply->func;
|
if (!(ret = wine_server_call( req )))
|
||||||
arg1 = reply->arg1;
|
{
|
||||||
arg2 = reply->arg2;
|
handle = reply->handle;
|
||||||
arg3 = reply->arg3;
|
type = reply->type;
|
||||||
|
proc = reply->func;
|
||||||
|
arg1 = reply->arg1;
|
||||||
|
arg2 = reply->arg2;
|
||||||
|
arg3 = reply->arg3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
|
||||||
|
if (ret) return; /* no more APCs */
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case APC_NONE:
|
|
||||||
return; /* no more APCs */
|
|
||||||
case APC_USER:
|
case APC_USER:
|
||||||
proc( arg1, arg2, arg3 );
|
proc( arg1, arg2, arg3 );
|
||||||
break;
|
break;
|
||||||
|
@ -529,10 +529,12 @@ struct get_apc_request
|
|||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
int alertable;
|
int alertable;
|
||||||
|
obj_handle_t prev;
|
||||||
};
|
};
|
||||||
struct get_apc_reply
|
struct get_apc_reply
|
||||||
{
|
{
|
||||||
struct reply_header __header;
|
struct reply_header __header;
|
||||||
|
obj_handle_t handle;
|
||||||
void* func;
|
void* func;
|
||||||
int type;
|
int type;
|
||||||
void* arg1;
|
void* arg1;
|
||||||
@ -4415,6 +4417,6 @@ union generic_reply
|
|||||||
struct query_symlink_reply query_symlink_reply;
|
struct query_symlink_reply query_symlink_reply;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 261
|
#define SERVER_PROTOCOL_VERSION 262
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
@ -447,7 +447,9 @@ struct token_groups
|
|||||||
/* Get next APC to call */
|
/* Get next APC to call */
|
||||||
@REQ(get_apc)
|
@REQ(get_apc)
|
||||||
int alertable; /* is thread alertable? */
|
int alertable; /* is thread alertable? */
|
||||||
|
obj_handle_t prev; /* handle to previous APC */
|
||||||
@REPLY
|
@REPLY
|
||||||
|
obj_handle_t handle; /* handle to APC */
|
||||||
void* func; /* function to call */
|
void* func; /* function to call */
|
||||||
int type; /* function type */
|
int type; /* function type */
|
||||||
void* arg1; /* function arguments */
|
void* arg1; /* function arguments */
|
||||||
|
@ -71,6 +71,7 @@ struct thread_apc
|
|||||||
struct object obj; /* object header */
|
struct object obj; /* object header */
|
||||||
struct list entry; /* queue linked list */
|
struct list entry; /* queue linked list */
|
||||||
struct object *owner; /* object that queued this apc */
|
struct object *owner; /* object that queued this apc */
|
||||||
|
int executed; /* has it been executed by the client? */
|
||||||
void *func; /* function to call in client */
|
void *func; /* function to call in client */
|
||||||
enum apc_type type; /* type of apc function */
|
enum apc_type type; /* type of apc function */
|
||||||
void *arg1; /* function arguments */
|
void *arg1; /* function arguments */
|
||||||
@ -310,7 +311,8 @@ static void dump_thread_apc( struct object *obj, int verbose )
|
|||||||
|
|
||||||
static int thread_apc_signaled( struct object *obj, struct thread *thread )
|
static int thread_apc_signaled( struct object *obj, struct thread *thread )
|
||||||
{
|
{
|
||||||
return 0;
|
struct thread_apc *apc = (struct thread_apc *)obj;
|
||||||
|
return apc->executed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get a thread pointer from a thread id (and increment the refcount) */
|
/* get a thread pointer from a thread id (and increment the refcount) */
|
||||||
@ -679,6 +681,7 @@ int thread_queue_apc( struct thread *thread, struct object *owner, void *func,
|
|||||||
apc->arg1 = arg1;
|
apc->arg1 = arg1;
|
||||||
apc->arg2 = arg2;
|
apc->arg2 = arg2;
|
||||||
apc->arg3 = arg3;
|
apc->arg3 = arg3;
|
||||||
|
apc->executed = 0;
|
||||||
list_add_tail( queue, &apc->entry );
|
list_add_tail( queue, &apc->entry );
|
||||||
if (!list_prev( queue, &apc->entry )) /* first one */
|
if (!list_prev( queue, &apc->entry )) /* first one */
|
||||||
wake_thread( thread );
|
wake_thread( thread );
|
||||||
@ -1061,13 +1064,22 @@ DECL_HANDLER(get_apc)
|
|||||||
{
|
{
|
||||||
struct thread_apc *apc;
|
struct thread_apc *apc;
|
||||||
|
|
||||||
|
if (req->prev)
|
||||||
|
{
|
||||||
|
if (!(apc = (struct thread_apc *)get_handle_obj( current->process, req->prev,
|
||||||
|
0, &thread_apc_ops ))) return;
|
||||||
|
apc->executed = 1;
|
||||||
|
wake_up( &apc->obj, 0 );
|
||||||
|
close_handle( current->process, req->prev );
|
||||||
|
release_object( apc );
|
||||||
|
}
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (!(apc = thread_dequeue_apc( current, !req->alertable )))
|
if (!(apc = thread_dequeue_apc( current, !req->alertable )))
|
||||||
{
|
{
|
||||||
/* no more APCs */
|
/* no more APCs */
|
||||||
reply->func = NULL;
|
set_error( STATUS_PENDING );
|
||||||
reply->type = APC_NONE;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Optimization: ignore APCs that have a NULL func; they are only used
|
/* Optimization: ignore APCs that have a NULL func; they are only used
|
||||||
@ -1077,11 +1089,15 @@ DECL_HANDLER(get_apc)
|
|||||||
if (apc->func || apc->type == APC_ASYNC_IO) break;
|
if (apc->func || apc->type == APC_ASYNC_IO) break;
|
||||||
release_object( apc );
|
release_object( apc );
|
||||||
}
|
}
|
||||||
reply->func = apc->func;
|
|
||||||
reply->type = apc->type;
|
if ((reply->handle = alloc_handle( current->process, apc, SYNCHRONIZE, 0 )))
|
||||||
reply->arg1 = apc->arg1;
|
{
|
||||||
reply->arg2 = apc->arg2;
|
reply->func = apc->func;
|
||||||
reply->arg3 = apc->arg3;
|
reply->type = apc->type;
|
||||||
|
reply->arg1 = apc->arg1;
|
||||||
|
reply->arg2 = apc->arg2;
|
||||||
|
reply->arg3 = apc->arg3;
|
||||||
|
}
|
||||||
release_object( apc );
|
release_object( apc );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,11 +854,13 @@ static void dump_queue_apc_request( const struct queue_apc_request *req )
|
|||||||
|
|
||||||
static void dump_get_apc_request( const struct get_apc_request *req )
|
static void dump_get_apc_request( const struct get_apc_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " alertable=%d", req->alertable );
|
fprintf( stderr, " alertable=%d,", req->alertable );
|
||||||
|
fprintf( stderr, " prev=%p", req->prev );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_get_apc_reply( const struct get_apc_reply *req )
|
static void dump_get_apc_reply( const struct get_apc_reply *req )
|
||||||
{
|
{
|
||||||
|
fprintf( stderr, " handle=%p,", req->handle );
|
||||||
fprintf( stderr, " func=%p,", req->func );
|
fprintf( stderr, " func=%p,", req->func );
|
||||||
fprintf( stderr, " type=%d,", req->type );
|
fprintf( stderr, " type=%d,", req->type );
|
||||||
fprintf( stderr, " arg1=%p,", req->arg1 );
|
fprintf( stderr, " arg1=%p,", req->arg1 );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user