Alexandre Julliard : server:
Notify the server that an APC has completed in the next get_apc call.
Alexandre Julliard
julliard at wine.codeweavers.com
Thu Jan 4 15:09:22 CST 2007
Module: wine
Branch: master
Commit: 49b49c30fcfcd72d7b388125d7ccf481f8b1f294
URL: http://source.winehq.org/git/wine.git/?a=commit;h=49b49c30fcfcd72d7b388125d7ccf481f8b1f294
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Jan 4 13:17:53 2007 +0100
server: Notify the server that an APC has completed in the next get_apc call.
---
dlls/ntdll/sync.c | 21 ++++++++++++++-------
include/wine/server_protocol.h | 4 +++-
server/protocol.def | 2 ++
server/thread.c | 32 ++++++++++++++++++++++++--------
server/trace.c | 4 +++-
5 files changed, 46 insertions(+), 17 deletions(-)
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 852bfde..5857c46 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -659,6 +659,8 @@ static int wait_reply( void *cookie )
*/
static void call_apcs( BOOL alertable )
{
+ NTSTATUS ret;
+ HANDLE handle = 0;
FARPROC proc;
LARGE_INTEGER time;
void *arg1, *arg2, *arg3;
@@ -669,18 +671,23 @@ static void call_apcs( BOOL alertable )
SERVER_START_REQ( get_apc )
{
req->alertable = alertable;
- if (!wine_server_call( req )) type = reply->type;
- proc = reply->func;
- arg1 = reply->arg1;
- arg2 = reply->arg2;
- arg3 = reply->arg3;
+ req->prev = handle;
+ if (!(ret = wine_server_call( req )))
+ {
+ handle = reply->handle;
+ type = reply->type;
+ proc = reply->func;
+ arg1 = reply->arg1;
+ arg2 = reply->arg2;
+ arg3 = reply->arg3;
+ }
}
SERVER_END_REQ;
+ if (ret) return; /* no more APCs */
+
switch (type)
{
- case APC_NONE:
- return; /* no more APCs */
case APC_USER:
proc( arg1, arg2, arg3 );
break;
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 040afcf..6858985 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -529,10 +529,12 @@ struct get_apc_request
{
struct request_header __header;
int alertable;
+ obj_handle_t prev;
};
struct get_apc_reply
{
struct reply_header __header;
+ obj_handle_t handle;
void* func;
int type;
void* arg1;
@@ -4415,6 +4417,6 @@ union generic_reply
struct query_symlink_reply query_symlink_reply;
};
-#define SERVER_PROTOCOL_VERSION 261
+#define SERVER_PROTOCOL_VERSION 262
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index 80821ab..7cde312 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -447,7 +447,9 @@ struct token_groups
/* Get next APC to call */
@REQ(get_apc)
int alertable; /* is thread alertable? */
+ obj_handle_t prev; /* handle to previous APC */
@REPLY
+ obj_handle_t handle; /* handle to APC */
void* func; /* function to call */
int type; /* function type */
void* arg1; /* function arguments */
diff --git a/server/thread.c b/server/thread.c
index 2d05ffa..630447a 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -71,6 +71,7 @@ struct thread_apc
struct object obj; /* object header */
struct list entry; /* queue linked list */
struct object *owner; /* object that queued this apc */
+ int executed; /* has it been executed by the client? */
void *func; /* function to call in client */
enum apc_type type; /* type of apc function */
void *arg1; /* function arguments */
@@ -310,7 +311,8 @@ static void dump_thread_apc( struct obje
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) */
@@ -679,6 +681,7 @@ int thread_queue_apc( struct thread *thr
apc->arg1 = arg1;
apc->arg2 = arg2;
apc->arg3 = arg3;
+ apc->executed = 0;
list_add_tail( queue, &apc->entry );
if (!list_prev( queue, &apc->entry )) /* first one */
wake_thread( thread );
@@ -1061,13 +1064,22 @@ DECL_HANDLER(get_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 (;;)
{
if (!(apc = thread_dequeue_apc( current, !req->alertable )))
{
/* no more APCs */
- reply->func = NULL;
- reply->type = APC_NONE;
+ set_error( STATUS_PENDING );
return;
}
/* 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;
release_object( apc );
}
- reply->func = apc->func;
- reply->type = apc->type;
- reply->arg1 = apc->arg1;
- reply->arg2 = apc->arg2;
- reply->arg3 = apc->arg3;
+
+ if ((reply->handle = alloc_handle( current->process, apc, SYNCHRONIZE, 0 )))
+ {
+ reply->func = apc->func;
+ reply->type = apc->type;
+ reply->arg1 = apc->arg1;
+ reply->arg2 = apc->arg2;
+ reply->arg3 = apc->arg3;
+ }
release_object( apc );
}
diff --git a/server/trace.c b/server/trace.c
index b128ad5..5018423 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -854,11 +854,13 @@ static void dump_queue_apc_request( cons
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 )
{
+ fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " func=%p,", req->func );
fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " arg1=%p,", req->arg1 );
More information about the wine-cvs
mailing list