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