Synchronously deliver the pending system APC via server call reply if possible, instead of interrupting the target thread with a signal.
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com ---
Notes: Alternative approaches considered:
1. Don't use thread_queue_apc to deliver the pseudo-APC; instead, use create_apc directly. In this case, this would shorten this patch a lot, but would transfer the complexity of this patch to the previous one in the serie.
2. Don't use APC at all (the previous patch). In this case we do not create APCs at all, and this patch becomes unnecessary.
server/async.c | 1 + server/protocol.def | 1 + server/sock.c | 10 ++++++++++ server/trace.c | 3 --- 4 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/server/async.c b/server/async.c index 5d0857f3eec..cf49a309da6 100644 --- a/server/async.c +++ b/server/async.c @@ -396,6 +396,7 @@ void async_start_sync_io_request( struct async *async, data_size_t information ) assert( async->thread == current ); assert( !async->pending );
+ try_suspend_apc_interrupt(); async->direct_result = 0; /* force APC to fire off */ async->iosb->result = information; } diff --git a/server/protocol.def b/server/protocol.def index f21f7187c4d..348791c28da 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1447,6 +1447,7 @@ enum server_fd_type @REPLY obj_handle_t wait; /* handle to wait on for blocking recv */ unsigned int options; /* device open options */ + VARARG(inline_apc,inline_apc); /* Next system APC to execute immediately */ @END
diff --git a/server/sock.c b/server/sock.c index 03c867317b2..683cbb21aa6 100644 --- a/server/sock.c +++ b/server/sock.c @@ -3470,6 +3470,16 @@ DECL_HANDLER(recv_socket)
reply->wait = async_handoff( async, NULL, 0 ); reply->options = get_fd_options( fd ); + + if (status == STATUS_ALERTED) + { + inline_apc_t inline_apc; + if (get_reply_max_size() == sizeof(inline_apc) && dequeue_synchronous_system_apc( &inline_apc )) + set_reply_data( &inline_apc, sizeof(inline_apc) ); + else + resume_apc_interrupt(); + } + release_object( async ); } release_object( sock ); diff --git a/server/trace.c b/server/trace.c index 7a6f5e1c119..40aa1078cf2 100644 --- a/server/trace.c +++ b/server/trace.c @@ -540,9 +540,6 @@ static void dump_varargs_apc_result( const char *prefix, data_size_t size ) remove_data( size ); }
-#ifdef __GNUC__ -__attribute__((unused)) -#endif static void dump_varargs_inline_apc( const char *prefix, data_size_t size ) { const inline_apc_t *result = cur_data;