From: Jinoh Kang jinoh.kang.kr@gmail.com
This helper will later be rewritten to compute the flag from a state enum. --- server/async.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/server/async.c b/server/async.c index 3c9b9588c6e..7a326292544 100644 --- a/server/async.c +++ b/server/async.c @@ -160,12 +160,17 @@ static void async_destroy( struct object *obj ) release_object( async->thread ); }
+static int async_terminated( const struct async *async ) +{ + return async->terminated; +} + /* notifies client thread of new status of its async request */ void async_terminate( struct async *async, unsigned int status ) { struct iosb *iosb = async->iosb;
- if (async->terminated) return; + if (async_terminated( async )) return;
async->terminated = 1; if (async->iosb && async->iosb->status == STATUS_PENDING) async->iosb->status = status; @@ -489,7 +494,7 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
if (obj->ops != &async_ops) return; /* in case the client messed up the APC results */
- assert( async->terminated ); /* it must have been woken up if we get a result */ + assert( async_terminated( async ) ); /* it must have been woken up if we get a result */
if (async->unknown_status) async_set_initial_status( async, status );
@@ -569,7 +574,7 @@ int async_waiting( struct async_queue *queue )
if (!(ptr = list_head( &queue->queue ))) return 0; async = LIST_ENTRY( ptr, struct async, queue_entry ); - return !async->terminated; + return !async_terminated( async ); }
static int cancel_async( struct process *process, struct object *obj, struct thread *thread, client_ptr_t iosb ) @@ -584,7 +589,7 @@ static int cancel_async( struct process *process, struct object *obj, struct thr restart: LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry ) { - if (async->terminated || async->canceled) continue; + if (async_terminated( async ) || async->canceled) continue; if ((!obj || (get_fd_user( async->fd ) == obj)) && (!thread || async->thread == thread) && (!iosb || async->data.iosb == iosb)) @@ -606,7 +611,7 @@ static int cancel_blocking( struct process *process, struct thread *thread, clie restart: LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry ) { - if (async->terminated || async->canceled) continue; + if (async_terminated( async ) || async->canceled) continue; if (async->blocking && async->thread == thread && (!iosb || async->data.iosb == iosb)) { @@ -636,7 +641,7 @@ int async_close_obj_handle( struct object *obj, struct process *process, obj_han restart: LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry ) { - if (async->terminated || async->canceled || get_fd_user( async->fd ) != obj) continue; + if (async_terminated( async ) || async->canceled || get_fd_user( async->fd ) != obj) continue; if (!async->completion || !async->data.apc_context || async->event) continue;
async->canceled = 1; @@ -653,7 +658,7 @@ void cancel_terminating_thread_asyncs( struct thread *thread ) restart: LIST_FOR_EACH_ENTRY( async, &thread->process->asyncs, struct async, process_entry ) { - if (async->thread != thread || async->terminated || async->canceled) continue; + if (async->thread != thread || async_terminated( async ) || async->canceled) continue; if (async->completion && async->data.apc_context && !async->event) continue;
async->canceled = 1; @@ -780,7 +785,7 @@ struct async *find_pending_async( struct async_queue *queue ) { struct async *async; LIST_FOR_EACH_ENTRY( async, &queue->queue, struct async, queue_entry ) - if (!async->terminated) return (struct async *)grab_object( async ); + if (!async_terminated( async )) return (struct async *)grab_object( async ); return NULL; }
@@ -850,7 +855,7 @@ DECL_HANDLER(set_async_direct_result)
if (!async) return;
- if (!async->unknown_status || !async->terminated || !async->alerted) + if (!async->unknown_status || !async_terminated( async ) || !async->alerted) { set_error( STATUS_INVALID_PARAMETER ); release_object( &async->obj );
From: Jinoh Kang jinoh.kang.kr@gmail.com
This helper will later be rewritten to compute the flag from a state enum. --- server/async.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/server/async.c b/server/async.c index 7a326292544..3dfbd0051f0 100644 --- a/server/async.c +++ b/server/async.c @@ -165,6 +165,11 @@ static int async_terminated( const struct async *async ) return async->terminated; }
+static int async_alerted( const struct async *async ) +{ + return async->alerted; +} + /* notifies client thread of new status of its async request */ void async_terminate( struct async *async, unsigned int status ) { @@ -498,7 +503,7 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
if (async->unknown_status) async_set_initial_status( async, status );
- if (async->alerted && status == STATUS_PENDING) /* restart it */ + if (async_alerted( async ) && status == STATUS_PENDING) /* restart it */ { async->terminated = 0; async->alerted = 0; @@ -855,7 +860,7 @@ DECL_HANDLER(set_async_direct_result)
if (!async) return;
- if (!async->unknown_status || !async_terminated( async ) || !async->alerted) + if (!async->unknown_status || !async_terminated( async ) || !async_alerted( async )) { set_error( STATUS_INVALID_PARAMETER ); release_object( &async->obj );
From: Jinoh Kang jinoh.kang.kr@gmail.com
This helper will later be rewritten to compute the flag from a state enum. --- server/async.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/server/async.c b/server/async.c index 3dfbd0051f0..fbd7c37717d 100644 --- a/server/async.c +++ b/server/async.c @@ -170,6 +170,11 @@ static int async_alerted( const struct async *async ) return async->alerted; }
+static int async_unknown_status( const struct async *async ) +{ + return async->unknown_status; +} + /* notifies client thread of new status of its async request */ void async_terminate( struct async *async, unsigned int status ) { @@ -324,7 +329,7 @@ void set_async_pending( struct async *async )
void async_wake_obj( struct async *async ) { - assert( !async->unknown_status ); + assert( !async_unknown_status( async ) ); if (!async->blocking) { async->signaled = 1; @@ -344,7 +349,7 @@ obj_handle_t async_handoff( struct async *async, data_size_t *result, int force_ { async->blocking = force_blocking || async->blocking;
- if (async->unknown_status) + if (async_unknown_status( async )) { /* even the initial status is not known yet */ set_error( STATUS_PENDING ); @@ -501,7 +506,7 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
assert( async_terminated( async ) ); /* it must have been woken up if we get a result */
- if (async->unknown_status) async_set_initial_status( async, status ); + if (async_unknown_status( async )) async_set_initial_status( async, status );
if (async_alerted( async ) && status == STATUS_PENDING) /* restart it */ { @@ -566,7 +571,7 @@ int async_queue_has_waiting_asyncs( struct async_queue *queue ) struct async *async;
LIST_FOR_EACH_ENTRY( async, &queue->queue, struct async, queue_entry ) - if (!async->unknown_status) return 1; + if (!async_unknown_status( async )) return 1;
return 0; } @@ -860,7 +865,7 @@ DECL_HANDLER(set_async_direct_result)
if (!async) return;
- if (!async->unknown_status || !async_terminated( async ) || !async_alerted( async )) + if (!async_unknown_status( async ) || !async_terminated( async ) || !async_alerted( async )) { set_error( STATUS_INVALID_PARAMETER ); release_object( &async->obj );
From: Jinoh Kang jinoh.kang.kr@gmail.com
removetodo --- server/async.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+)
diff --git a/server/async.c b/server/async.c index fbd7c37717d..7f5ea3141b8 100644 --- a/server/async.c +++ b/server/async.c @@ -34,6 +34,30 @@ #include "process.h" #include "handle.h"
+enum async_state +{ + /* The I/O operation has just initiated, or initial status is known. */ + ASYNC_INITIAL, + + /* The initial status is not known yet. It will be determined by the client or winedevice.exe. */ + ASYNC_UNKNOWN_STATUS, + + /* The I/O operation is being processed by the wineserver or winedevice.eze. */ + ASYNC_IN_PROGRESS, + + /* The I/O operation is being processed by the client. */ + ASYNC_ALERTED, + + /* The I/O operation has finished synchronously but not been acknowledged by the client. */ + ASYNC_FINALIZING_SYNC, + + /* The I/O operation has finished asynchronously but not been acknowledged by the client. */ + ASYNC_FINALIZING_ASYNC, + + /* The I/O operation has finished and the result has been acknowledged by the client. */ + ASYNC_COMPLETED +}; + struct async { struct object obj; /* object header */ @@ -49,6 +73,7 @@ struct async struct iosb *iosb; /* I/O status block */ obj_handle_t wait_handle; /* pre-allocated wait handle */ unsigned int initial_status; /* status returned from initial request */ + enum async_state state; unsigned int signaled :1; unsigned int pending :1; /* request successfully queued, but pending */ unsigned int direct_result :1;/* a flag if we're passing result directly from request instead of APC */ @@ -109,6 +134,30 @@ static int async_signaled( struct object *obj, struct wait_queue_entry *entry ) { struct async *async = (struct async *)obj; assert( obj->ops == &async_ops ); + switch (async->state) + { + case ASYNC_INITIAL: + case ASYNC_UNKNOWN_STATUS: + assert( async->signaled == 0 ); + break; + case ASYNC_FINALIZING_SYNC: + /* If direct_result, the client will "wait" on the async to signal completion. */ + assert( async->signaled == async->direct_result ); + break; + case ASYNC_IN_PROGRESS: + case ASYNC_ALERTED: + case ASYNC_FINALIZING_ASYNC: + /* If nonblocking, the client will "wait" on the async to close it. */ + assert( async->signaled == (!async->blocking) ); + break; + case ASYNC_COMPLETED: + /* If there is an open async handle, notify the waiter of completion. */ + assert( async->signaled == 1 ); + break; + default: + assert( 0 ); + break; + } return async->signaled; }
@@ -162,16 +211,54 @@ static void async_destroy( struct object *obj )
static int async_terminated( const struct async *async ) { + switch (async->state) + { + case ASYNC_INITIAL: + case ASYNC_IN_PROGRESS: + assert( async->terminated == 0 ); + break; + case ASYNC_UNKNOWN_STATUS: + case ASYNC_ALERTED: + case ASYNC_FINALIZING_SYNC: + case ASYNC_FINALIZING_ASYNC: + case ASYNC_COMPLETED: + assert( async->terminated == 1 ); + break; + default: + assert( 0 ); + break; + } return async->terminated; }
static int async_alerted( const struct async *async ) { + switch (async->state) + { + case ASYNC_IN_PROGRESS: + case ASYNC_FINALIZING_SYNC: + case ASYNC_FINALIZING_ASYNC: + case ASYNC_COMPLETED: + assert( async->alerted == 0 ); + break; + case ASYNC_INITIAL: + /* initial status set from set_async_direct_result */ + assert( async->alerted == 1 ); + break; + case ASYNC_UNKNOWN_STATUS: + case ASYNC_ALERTED: + assert( async->alerted == 1 ); + break; + default: + assert( 0 ); + break; + } return async->alerted; }
static int async_unknown_status( const struct async *async ) { + assert( async->unknown_status == (async->state == ASYNC_UNKNOWN_STATUS) ); return async->unknown_status; }
@@ -181,12 +268,41 @@ void async_terminate( struct async *async, unsigned int status ) struct iosb *iosb = async->iosb;
if (async_terminated( async )) return; + assert( async->state == ASYNC_INITIAL || async->state == ASYNC_IN_PROGRESS ); + + if (status == STATUS_ALERTED) + { + if (async->direct_result) + { + assert( async->unknown_status ); + async->state = ASYNC_UNKNOWN_STATUS; + } + else + { + assert( !async->unknown_status ); + async->state = ASYNC_ALERTED; + } + } + else + { + if (async->state == ASYNC_INITIAL) + async->state = ASYNC_FINALIZING_SYNC; + else + async->state = ASYNC_FINALIZING_ASYNC; + }
async->terminated = 1; if (async->iosb && async->iosb->status == STATUS_PENDING) async->iosb->status = status; if (status == STATUS_ALERTED) async->alerted = 1;
+ if (async->state == ASYNC_FINALIZING_SYNC ? async->direct_result : + (async->state != ASYNC_UNKNOWN_STATUS && !async->blocking)) + { + async->signaled = 1; + wake_up( &async->obj, 0 ); + } + /* if no APC could be queued (e.g. the process is terminated), * thread_queue_apc() may trigger async_set_result(), which may drop the * last reference to the async, so grab a temporary reference here */ @@ -283,6 +399,7 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da async->queue = NULL; async->fd = (struct fd *)grab_object( fd ); async->initial_status = STATUS_PENDING; + async->state = ASYNC_INITIAL; async->signaled = 0; async->pending = 1; async->wait_handle = 0; @@ -319,10 +436,13 @@ void async_set_initial_status( struct async *async, unsigned int status ) { async->initial_status = status; async->unknown_status = 0; + if (async->state == ASYNC_UNKNOWN_STATUS) + async->state = ASYNC_INITIAL; }
void set_async_pending( struct async *async ) { + assert( (!async->terminated) == (async->state == ASYNC_INITIAL || async->state == ASYNC_UNKNOWN_STATUS) ); if (!async->terminated) async->pending = 1; } @@ -330,6 +450,8 @@ void set_async_pending( struct async *async ) void async_wake_obj( struct async *async ) { assert( !async_unknown_status( async ) ); + assert( async->state == ASYNC_INITIAL ); + async->state = ASYNC_IN_PROGRESS; if (!async->blocking) { async->signaled = 1; @@ -415,6 +537,8 @@ obj_handle_t async_handoff( struct async *async, data_size_t *result, int force_ } else { + assert( async->state == ASYNC_INITIAL ); + async->state = ASYNC_IN_PROGRESS; async->direct_result = 0; async->pending = 1; if (!async->blocking) @@ -470,6 +594,8 @@ void async_request_complete_alloc( struct async *async, unsigned int status, dat /* mark an async as having unknown initial status */ void async_set_unknown_status( struct async *async ) { + assert( async->state == ASYNC_INITIAL ); + async->state = ASYNC_UNKNOWN_STATUS; async->unknown_status = 1; async->direct_result = 0; } @@ -510,6 +636,8 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
if (async_alerted( async ) && status == STATUS_PENDING) /* restart it */ { + assert( async->state == ASYNC_INITIAL || async->state == ASYNC_ALERTED ); + async->state = ASYNC_IN_PROGRESS; async->terminated = 0; async->alerted = 0; async_reselect( async ); @@ -547,6 +675,7 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota else if (async->fd) set_fd_signaled( async->fd, 1 ); }
+ async->state = ASYNC_COMPLETED; if (!async->signaled) { async->signaled = 1;
From: Jinoh Kang jinoh.kang.kr@gmail.com
This helps simplify further refactoring that gets rid of 'signaled' flag entirely. --- server/async.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/server/async.c b/server/async.c index 7f5ea3141b8..666836b831e 100644 --- a/server/async.c +++ b/server/async.c @@ -676,11 +676,8 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota }
async->state = ASYNC_COMPLETED; - if (!async->signaled) - { - async->signaled = 1; - wake_up( &async->obj, 0 ); - } + async->signaled = 1; + wake_up( &async->obj, 0 );
async_call_completion_callback( async );
From: Jinoh Kang jinoh.kang.kr@gmail.com
--- server/async.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-)
diff --git a/server/async.c b/server/async.c index 666836b831e..5616407d6d6 100644 --- a/server/async.c +++ b/server/async.c @@ -74,7 +74,6 @@ struct async obj_handle_t wait_handle; /* pre-allocated wait handle */ unsigned int initial_status; /* status returned from initial request */ enum async_state state; - unsigned int signaled :1; unsigned int pending :1; /* request successfully queued, but pending */ unsigned int direct_result :1;/* a flag if we're passing result directly from request instead of APC */ unsigned int alerted :1; /* fd is signaled, but we are waiting for client-side I/O */ @@ -138,27 +137,22 @@ static int async_signaled( struct object *obj, struct wait_queue_entry *entry ) { case ASYNC_INITIAL: case ASYNC_UNKNOWN_STATUS: - assert( async->signaled == 0 ); - break; + return 0; case ASYNC_FINALIZING_SYNC: /* If direct_result, the client will "wait" on the async to signal completion. */ - assert( async->signaled == async->direct_result ); - break; + return async->direct_result; case ASYNC_IN_PROGRESS: case ASYNC_ALERTED: case ASYNC_FINALIZING_ASYNC: /* If nonblocking, the client will "wait" on the async to close it. */ - assert( async->signaled == (!async->blocking) ); - break; + return !async->blocking; case ASYNC_COMPLETED: /* If there is an open async handle, notify the waiter of completion. */ - assert( async->signaled == 1 ); - break; + return 1; default: assert( 0 ); - break; + return 0; } - return async->signaled; }
static void async_satisfied( struct object *obj, struct wait_queue_entry *entry ) @@ -299,7 +293,6 @@ void async_terminate( struct async *async, unsigned int status ) if (async->state == ASYNC_FINALIZING_SYNC ? async->direct_result : (async->state != ASYNC_UNKNOWN_STATUS && !async->blocking)) { - async->signaled = 1; wake_up( &async->obj, 0 ); }
@@ -400,7 +393,6 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da async->fd = (struct fd *)grab_object( fd ); async->initial_status = STATUS_PENDING; async->state = ASYNC_INITIAL; - async->signaled = 0; async->pending = 1; async->wait_handle = 0; async->direct_result = 0; @@ -454,7 +446,6 @@ void async_wake_obj( struct async *async ) async->state = ASYNC_IN_PROGRESS; if (!async->blocking) { - async->signaled = 1; wake_up( &async->obj, 0 ); } } @@ -533,7 +524,6 @@ obj_handle_t async_handoff( struct async *async, data_size_t *result, int force_ if (async->iosb->status != STATUS_PENDING) { if (result) *result = async->iosb->result; - async->signaled = 1; } else { @@ -676,7 +666,6 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota }
async->state = ASYNC_COMPLETED; - async->signaled = 1; wake_up( &async->obj, 0 );
async_call_completion_callback( async );
From: Jinoh Kang jinoh.kang.kr@gmail.com
--- server/async.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-)
diff --git a/server/async.c b/server/async.c index 5616407d6d6..5441b5ac094 100644 --- a/server/async.c +++ b/server/async.c @@ -77,7 +77,6 @@ struct async unsigned int pending :1; /* request successfully queued, but pending */ unsigned int direct_result :1;/* a flag if we're passing result directly from request instead of APC */ unsigned int alerted :1; /* fd is signaled, but we are waiting for client-side I/O */ - unsigned int terminated :1; /* async has been terminated */ unsigned int canceled :1; /* have we already queued cancellation for this async? */ unsigned int unknown_status :1; /* initial status is not known yet */ unsigned int blocking :1; /* async is blocking */ @@ -209,20 +208,17 @@ static int async_terminated( const struct async *async ) { case ASYNC_INITIAL: case ASYNC_IN_PROGRESS: - assert( async->terminated == 0 ); - break; + return 0; case ASYNC_UNKNOWN_STATUS: case ASYNC_ALERTED: case ASYNC_FINALIZING_SYNC: case ASYNC_FINALIZING_ASYNC: case ASYNC_COMPLETED: - assert( async->terminated == 1 ); - break; + return 1; default: assert( 0 ); - break; + return 0; } - return async->terminated; }
static int async_alerted( const struct async *async ) @@ -285,7 +281,6 @@ void async_terminate( struct async *async, unsigned int status ) async->state = ASYNC_FINALIZING_ASYNC; }
- async->terminated = 1; if (async->iosb && async->iosb->status == STATUS_PENDING) async->iosb->status = status; if (status == STATUS_ALERTED) async->alerted = 1; @@ -397,7 +392,6 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da async->wait_handle = 0; async->direct_result = 0; async->alerted = 0; - async->terminated = 0; async->canceled = 0; async->unknown_status = 0; async->blocking = !is_fd_overlapped( fd ); @@ -434,8 +428,7 @@ void async_set_initial_status( struct async *async, unsigned int status )
void set_async_pending( struct async *async ) { - assert( (!async->terminated) == (async->state == ASYNC_INITIAL || async->state == ASYNC_UNKNOWN_STATUS) ); - if (!async->terminated) + if (async->state == ASYNC_INITIAL || async->state == ASYNC_UNKNOWN_STATUS) async->pending = 1; }
@@ -628,7 +621,6 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota { assert( async->state == ASYNC_INITIAL || async->state == ASYNC_ALERTED ); async->state = ASYNC_IN_PROGRESS; - async->terminated = 0; async->alerted = 0; async_reselect( async ); } @@ -636,7 +628,6 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota { if (async->timeout) remove_timeout_user( async->timeout ); async->timeout = NULL; - async->terminated = 1; if (async->iosb) async->iosb->status = status;
/* don't signal completion if the async failed synchronously
From: Jinoh Kang jinoh.kang.kr@gmail.com
--- server/async.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-)
diff --git a/server/async.c b/server/async.c index 5441b5ac094..68df944a14f 100644 --- a/server/async.c +++ b/server/async.c @@ -76,7 +76,6 @@ struct async enum async_state state; unsigned int pending :1; /* request successfully queued, but pending */ unsigned int direct_result :1;/* a flag if we're passing result directly from request instead of APC */ - unsigned int alerted :1; /* fd is signaled, but we are waiting for client-side I/O */ unsigned int canceled :1; /* have we already queued cancellation for this async? */ unsigned int unknown_status :1; /* initial status is not known yet */ unsigned int blocking :1; /* async is blocking */ @@ -229,21 +228,17 @@ static int async_alerted( const struct async *async ) case ASYNC_FINALIZING_SYNC: case ASYNC_FINALIZING_ASYNC: case ASYNC_COMPLETED: - assert( async->alerted == 0 ); - break; + return 0; case ASYNC_INITIAL: /* initial status set from set_async_direct_result */ - assert( async->alerted == 1 ); - break; + return 1; case ASYNC_UNKNOWN_STATUS: case ASYNC_ALERTED: - assert( async->alerted == 1 ); - break; + return 1; default: assert( 0 ); - break; + return 0; } - return async->alerted; }
static int async_unknown_status( const struct async *async ) @@ -282,8 +277,6 @@ void async_terminate( struct async *async, unsigned int status ) }
if (async->iosb && async->iosb->status == STATUS_PENDING) async->iosb->status = status; - if (status == STATUS_ALERTED) - async->alerted = 1;
if (async->state == ASYNC_FINALIZING_SYNC ? async->direct_result : (async->state != ASYNC_UNKNOWN_STATUS && !async->blocking)) @@ -391,7 +384,6 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da async->pending = 1; async->wait_handle = 0; async->direct_result = 0; - async->alerted = 0; async->canceled = 0; async->unknown_status = 0; async->blocking = !is_fd_overlapped( fd ); @@ -621,7 +613,6 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota { assert( async->state == ASYNC_INITIAL || async->state == ASYNC_ALERTED ); async->state = ASYNC_IN_PROGRESS; - async->alerted = 0; async_reselect( async ); } else
From: Jinoh Kang jinoh.kang.kr@gmail.com
--- server/async.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-)
diff --git a/server/async.c b/server/async.c index 68df944a14f..6d9f502bb8e 100644 --- a/server/async.c +++ b/server/async.c @@ -77,7 +77,6 @@ struct async unsigned int pending :1; /* request successfully queued, but pending */ unsigned int direct_result :1;/* a flag if we're passing result directly from request instead of APC */ unsigned int canceled :1; /* have we already queued cancellation for this async? */ - unsigned int unknown_status :1; /* initial status is not known yet */ unsigned int blocking :1; /* async is blocking */ struct completion *completion; /* completion associated with fd */ apc_param_t comp_key; /* completion key associated with fd */ @@ -243,8 +242,7 @@ static int async_alerted( const struct async *async )
static int async_unknown_status( const struct async *async ) { - assert( async->unknown_status == (async->state == ASYNC_UNKNOWN_STATUS) ); - return async->unknown_status; + return async->state == ASYNC_UNKNOWN_STATUS; }
/* notifies client thread of new status of its async request */ @@ -259,12 +257,10 @@ void async_terminate( struct async *async, unsigned int status ) { if (async->direct_result) { - assert( async->unknown_status ); async->state = ASYNC_UNKNOWN_STATUS; } else { - assert( !async->unknown_status ); async->state = ASYNC_ALERTED; } } @@ -385,7 +381,6 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da async->wait_handle = 0; async->direct_result = 0; async->canceled = 0; - async->unknown_status = 0; async->blocking = !is_fd_overlapped( fd ); async->completion = fd_get_completion( fd, &async->comp_key ); async->comp_flags = 0; @@ -413,7 +408,6 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da void async_set_initial_status( struct async *async, unsigned int status ) { async->initial_status = status; - async->unknown_status = 0; if (async->state == ASYNC_UNKNOWN_STATUS) async->state = ASYNC_INITIAL; } @@ -464,17 +458,16 @@ obj_handle_t async_handoff( struct async *async, data_size_t *result, int force_ * instead. * * since we're deferring the initial I/O (to the client), we mark the - * async as having unknown initial status (unknown_status = 1). note - * that we don't reuse async_set_unknown_status() here. this is because - * the one responsible for performing the I/O is not the device driver, - * but instead the client that requested the I/O in the first place. + * async as having unknown initial status. note that we don't reuse + * async_set_unknown_status() here. this is because the one + * responsible for performing the I/O is not the device driver, but + * instead the client that requested the I/O in the first place. * * also, async_set_unknown_status() would set direct_result to zero * forcing APC_ASYNC_IO to fire in async_terminate(), which is not * useful due to subtle semantic differences between synchronous and * asynchronous completion. */ - async->unknown_status = 1; async_terminate( async, STATUS_ALERTED ); return async->wait_handle; } @@ -571,7 +564,6 @@ void async_set_unknown_status( struct async *async ) { assert( async->state == ASYNC_INITIAL ); async->state = ASYNC_UNKNOWN_STATUS; - async->unknown_status = 1; async->direct_result = 0; }
From: Jinoh Kang jinoh.kang.kr@gmail.com
--- server/async.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/server/async.c b/server/async.c index 6d9f502bb8e..946a19f8ac3 100644 --- a/server/async.c +++ b/server/async.c @@ -240,11 +240,6 @@ static int async_alerted( const struct async *async ) } }
-static int async_unknown_status( const struct async *async ) -{ - return async->state == ASYNC_UNKNOWN_STATUS; -} - /* notifies client thread of new status of its async request */ void async_terminate( struct async *async, unsigned int status ) { @@ -420,7 +415,6 @@ void set_async_pending( struct async *async )
void async_wake_obj( struct async *async ) { - assert( !async_unknown_status( async ) ); assert( async->state == ASYNC_INITIAL ); async->state = ASYNC_IN_PROGRESS; if (!async->blocking) @@ -441,7 +435,7 @@ obj_handle_t async_handoff( struct async *async, data_size_t *result, int force_ { async->blocking = force_blocking || async->blocking;
- if (async_unknown_status( async )) + if (async->state == ASYNC_UNKNOWN_STATUS) { /* even the initial status is not known yet */ set_error( STATUS_PENDING ); @@ -599,7 +593,7 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
assert( async_terminated( async ) ); /* it must have been woken up if we get a result */
- if (async_unknown_status( async )) async_set_initial_status( async, status ); + if (async->state == ASYNC_UNKNOWN_STATUS) async_set_initial_status( async, status );
if (async_alerted( async ) && status == STATUS_PENDING) /* restart it */ { @@ -660,7 +654,7 @@ int async_queue_has_waiting_asyncs( struct async_queue *queue ) struct async *async;
LIST_FOR_EACH_ENTRY( async, &queue->queue, struct async, queue_entry ) - if (!async_unknown_status( async )) return 1; + if (async->state != ASYNC_UNKNOWN_STATUS) return 1;
return 0; } @@ -954,7 +948,7 @@ DECL_HANDLER(set_async_direct_result)
if (!async) return;
- if (!async_unknown_status( async ) || !async_terminated( async ) || !async_alerted( async )) + if (async->state != ASYNC_UNKNOWN_STATUS) { set_error( STATUS_INVALID_PARAMETER ); release_object( &async->obj );
From: Jinoh Kang jinoh.kang.kr@gmail.com
--- server/async.c | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-)
diff --git a/server/async.c b/server/async.c index 946a19f8ac3..e4c82b1a3bb 100644 --- a/server/async.c +++ b/server/async.c @@ -219,27 +219,6 @@ static int async_terminated( const struct async *async ) } }
-static int async_alerted( const struct async *async ) -{ - switch (async->state) - { - case ASYNC_IN_PROGRESS: - case ASYNC_FINALIZING_SYNC: - case ASYNC_FINALIZING_ASYNC: - case ASYNC_COMPLETED: - return 0; - case ASYNC_INITIAL: - /* initial status set from set_async_direct_result */ - return 1; - case ASYNC_UNKNOWN_STATUS: - case ASYNC_ALERTED: - return 1; - default: - assert( 0 ); - return 0; - } -} - /* notifies client thread of new status of its async request */ void async_terminate( struct async *async, unsigned int status ) { @@ -594,10 +573,11 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota assert( async_terminated( async ) ); /* it must have been woken up if we get a result */
if (async->state == ASYNC_UNKNOWN_STATUS) async_set_initial_status( async, status ); + assert( async->state != ASYNC_UNKNOWN_STATUS );
- if (async_alerted( async ) && status == STATUS_PENDING) /* restart it */ + if ((async->state == ASYNC_INITIAL || async->state == ASYNC_ALERTED) && + status == STATUS_PENDING) /* restart it */ { - assert( async->state == ASYNC_INITIAL || async->state == ASYNC_ALERTED ); async->state = ASYNC_IN_PROGRESS; async_reselect( async ); }
Not finalized yet, but sharing early to hear some thoughts and possible directions. The intended audience is who already knows how server async works.
I'll write up about the motivation, overall design as well as the new state graph as soon as I find the time.