server: Properly wake the waiting threads when an APC is cancelled.
This commit is contained in:
parent
0df37dd9e3
commit
46d7fa4852
|
@ -77,6 +77,7 @@ struct thread_apc
|
||||||
|
|
||||||
static void dump_thread_apc( struct object *obj, int verbose );
|
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 );
|
||||||
|
static void clear_apc_queue( struct list *queue );
|
||||||
|
|
||||||
static const struct object_ops thread_apc_ops =
|
static const struct object_ops thread_apc_ops =
|
||||||
{
|
{
|
||||||
|
@ -102,7 +103,6 @@ static int thread_signaled( struct object *obj, struct thread *thread );
|
||||||
static unsigned int thread_map_access( struct object *obj, unsigned int access );
|
static unsigned int thread_map_access( struct object *obj, unsigned int access );
|
||||||
static void thread_poll_event( struct fd *fd, int event );
|
static void thread_poll_event( struct fd *fd, int event );
|
||||||
static void destroy_thread( struct object *obj );
|
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 =
|
static const struct object_ops thread_ops =
|
||||||
{
|
{
|
||||||
|
@ -227,9 +227,9 @@ static void thread_poll_event( struct fd *fd, int event )
|
||||||
static void cleanup_thread( struct thread *thread )
|
static void cleanup_thread( struct thread *thread )
|
||||||
{
|
{
|
||||||
int i;
|
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->req_data );
|
||||||
free( thread->reply_data );
|
free( thread->reply_data );
|
||||||
if (thread->request_fd) release_object( thread->request_fd );
|
if (thread->request_fd) release_object( thread->request_fd );
|
||||||
|
@ -709,12 +709,14 @@ void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_ty
|
||||||
{
|
{
|
||||||
if (apc->owner != owner) continue;
|
if (apc->owner != owner) continue;
|
||||||
list_remove( &apc->entry );
|
list_remove( &apc->entry );
|
||||||
|
apc->executed = 1;
|
||||||
|
wake_up( &apc->obj, 0 );
|
||||||
release_object( apc );
|
release_object( apc );
|
||||||
return;
|
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 )
|
static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system_only )
|
||||||
{
|
{
|
||||||
struct thread_apc *apc = NULL;
|
struct thread_apc *apc = NULL;
|
||||||
|
@ -729,6 +731,21 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system_
|
||||||
return apc;
|
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 */
|
/* add an fd to the inflight list */
|
||||||
/* return list index, or -1 on error */
|
/* return list index, or -1 on error */
|
||||||
int thread_add_inflight_fd( struct thread *thread, int client, int server )
|
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.
|
* wake up a thread, but since we got here the thread woke up already.
|
||||||
*/
|
*/
|
||||||
if (apc->call.type != APC_NONE) break;
|
if (apc->call.type != APC_NONE) break;
|
||||||
|
apc->executed = 1;
|
||||||
|
wake_up( &apc->obj, 0 );
|
||||||
release_object( apc );
|
release_object( apc );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue