Alexandre Julliard : server: Properly wake the waiting threads when an APC is cancelled.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Jan 16 05:22:14 CST 2007


Module: wine
Branch: master
Commit: 46d7fa4852df8ff226bca32382e7214116bf3ef0
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=46d7fa4852df8ff226bca32382e7214116bf3ef0

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Jan 15 20:02:05 2007 +0100

server: Properly wake the waiting threads when an APC is cancelled.

---

 server/thread.c |   27 +++++++++++++++++++++++----
 1 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/server/thread.c b/server/thread.c
index b8ee6fc..13563c3 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -77,6 +77,7 @@ struct thread_apc
 
 static void dump_thread_apc( struct object *obj, int verbose );
 static int thread_apc_signaled( struct object *obj, struct thread *thread );
+static void clear_apc_queue( struct list *queue );
 
 static const struct object_ops thread_apc_ops =
 {
@@ -102,7 +103,6 @@ static int thread_signaled( struct objec
 static unsigned int thread_map_access( struct object *obj, unsigned int access );
 static void thread_poll_event( struct fd *fd, int event );
 static void destroy_thread( struct object *obj );
-static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system_only );
 
 static const struct object_ops thread_ops =
 {
@@ -227,9 +227,9 @@ static void thread_poll_event( struct fd
 static void cleanup_thread( struct thread *thread )
 {
     int i;
-    struct thread_apc *apc;
 
-    while ((apc = thread_dequeue_apc( thread, 0 ))) release_object( apc );
+    clear_apc_queue( &thread->system_apc );
+    clear_apc_queue( &thread->user_apc );
     free( thread->req_data );
     free( thread->reply_data );
     if (thread->request_fd) release_object( thread->request_fd );
@@ -709,12 +709,14 @@ void thread_cancel_apc( struct thread *t
     {
         if (apc->owner != owner) continue;
         list_remove( &apc->entry );
+        apc->executed = 1;
+        wake_up( &apc->obj, 0 );
         release_object( apc );
         return;
     }
 }
 
-/* remove the head apc from the queue; the returned pointer must be freed by the caller */
+/* remove the head apc from the queue; the returned object must be released by the caller */
 static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system_only )
 {
     struct thread_apc *apc = NULL;
@@ -729,6 +731,21 @@ static struct thread_apc *thread_dequeue
     return apc;
 }
 
+/* clear an APC queue, cancelling all the APCs on it */
+static void clear_apc_queue( struct list *queue )
+{
+    struct list *ptr;
+
+    while ((ptr = list_head( queue )))
+    {
+        struct thread_apc *apc = LIST_ENTRY( ptr, struct thread_apc, entry );
+        list_remove( &apc->entry );
+        apc->executed = 1;
+        wake_up( &apc->obj, 0 );
+        release_object( apc );
+    }
+}
+
 /* add an fd to the inflight list */
 /* return list index, or -1 on error */
 int thread_add_inflight_fd( struct thread *thread, int client, int server )
@@ -1108,6 +1125,8 @@ DECL_HANDLER(get_apc)
          * wake up a thread, but since we got here the thread woke up already.
          */
         if (apc->call.type != APC_NONE) break;
+        apc->executed = 1;
+        wake_up( &apc->obj, 0 );
         release_object( apc );
     }
 




More information about the wine-cvs mailing list