Commit 91bd8144 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

server: Allow creating async object not associated with a queue.

parent 13daca6f
...@@ -114,7 +114,7 @@ static const struct object_ops async_queue_ops = ...@@ -114,7 +114,7 @@ static const struct object_ops async_queue_ops =
static inline void async_reselect( struct async *async ) static inline void async_reselect( struct async *async )
{ {
if (async->queue->fd) fd_reselect_async( async->queue->fd, async->queue ); if (async->queue && async->queue->fd) fd_reselect_async( async->queue->fd, async->queue );
} }
static void async_dump( struct object *obj, int verbose ) static void async_dump( struct object *obj, int verbose )
...@@ -137,13 +137,17 @@ static void async_destroy( struct object *obj ) ...@@ -137,13 +137,17 @@ static void async_destroy( struct object *obj )
assert( obj->ops == &async_ops ); assert( obj->ops == &async_ops );
list_remove( &async->process_entry ); list_remove( &async->process_entry );
list_remove( &async->queue_entry );
async_reselect( async ); if (async->queue)
{
list_remove( &async->queue_entry );
async_reselect( async );
release_object( async->queue );
}
if (async->timeout) remove_timeout_user( async->timeout ); if (async->timeout) remove_timeout_user( async->timeout );
if (async->event) release_object( async->event ); if (async->event) release_object( async->event );
if (async->iosb) release_object( async->iosb ); if (async->iosb) release_object( async->iosb );
release_object( async->queue );
release_object( async->thread ); release_object( async->thread );
} }
...@@ -191,7 +195,7 @@ void async_terminate( struct async *async, unsigned int status ) ...@@ -191,7 +195,7 @@ void async_terminate( struct async *async, unsigned int status )
else async_set_result( &async->obj, STATUS_SUCCESS, 0, 0, 0 ); else async_set_result( &async->obj, STATUS_SUCCESS, 0, 0, 0 );
async_reselect( async ); async_reselect( async );
release_object( async ); /* so that it gets destroyed when the async is done */ if (async->queue) release_object( async ); /* so that it gets destroyed when the async is done */
} }
/* callback for timeout on an async request */ /* callback for timeout on an async request */
...@@ -227,9 +231,18 @@ void free_async_queue( struct async_queue *queue ) ...@@ -227,9 +231,18 @@ void free_async_queue( struct async_queue *queue )
release_object( queue ); release_object( queue );
} }
void queue_async( struct async_queue *queue, struct async *async )
{
async->queue = (struct async_queue *)grab_object( queue );
grab_object( async );
list_add_tail( &queue->queue, &async->queue_entry );
if (queue->fd) set_fd_signaled( queue->fd, 0 );
}
/* create an async on a given queue of a fd */ /* create an async on a given queue of a fd */
struct async *create_async( struct thread *thread, struct async_queue *queue, const async_data_t *data, struct async *create_async( struct thread *thread, const async_data_t *data, struct iosb *iosb )
struct iosb *iosb )
{ {
struct event *event = NULL; struct event *event = NULL;
struct async *async; struct async *async;
...@@ -248,18 +261,15 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co ...@@ -248,18 +261,15 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
async->status = STATUS_PENDING; async->status = STATUS_PENDING;
async->data = *data; async->data = *data;
async->timeout = NULL; async->timeout = NULL;
async->queue = (struct async_queue *)grab_object( queue ); async->queue = NULL;
async->signaled = 0; async->signaled = 0;
if (iosb) async->iosb = (struct iosb *)grab_object( iosb ); if (iosb) async->iosb = (struct iosb *)grab_object( iosb );
else async->iosb = NULL; else async->iosb = NULL;
list_add_tail( &queue->queue, &async->queue_entry );
list_add_head( &thread->process->asyncs, &async->process_entry ); list_add_head( &thread->process->asyncs, &async->process_entry );
grab_object( async );
if (queue->fd) set_fd_signaled( queue->fd, 0 );
if (event) reset_event( event ); if (event) reset_event( event );
return async; return async;
} }
...@@ -318,7 +328,8 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota ...@@ -318,7 +328,8 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
async->status = status; async->status = status;
if (status == STATUS_MORE_PROCESSING_REQUIRED) return; /* don't report the completion */ if (status == STATUS_MORE_PROCESSING_REQUIRED) return; /* don't report the completion */
if (async->data.cvalue) add_async_completion( async->queue, async->data.cvalue, status, total ); if (async->queue && async->data.cvalue)
add_async_completion( async->queue, async->data.cvalue, status, total );
if (apc) if (apc)
{ {
apc_call_t data; apc_call_t data;
...@@ -331,7 +342,7 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota ...@@ -331,7 +342,7 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
thread_queue_apc( async->thread, NULL, &data ); thread_queue_apc( async->thread, NULL, &data );
} }
if (async->event) set_event( async->event ); if (async->event) set_event( async->event );
else if (async->queue->fd) set_fd_signaled( async->queue->fd, 1 ); else if (async->queue && async->queue->fd) set_fd_signaled( async->queue->fd, 1 );
async->signaled = 1; async->signaled = 1;
wake_up( &async->obj, 0 ); wake_up( &async->obj, 0 );
} }
...@@ -364,7 +375,7 @@ restart: ...@@ -364,7 +375,7 @@ restart:
LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry ) LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry )
{ {
if (async->status == STATUS_CANCELLED) continue; if (async->status == STATUS_CANCELLED) continue;
if ((!obj || (async->queue->fd && get_fd_user( async->queue->fd ) == obj)) && if ((!obj || (async->queue && async->queue->fd && get_fd_user( async->queue->fd ) == obj)) &&
(!thread || async->thread == thread) && (!thread || async->thread == thread) &&
(!iosb || async->data.iosb == iosb)) (!iosb || async->data.iosb == iosb))
{ {
......
...@@ -2054,12 +2054,16 @@ struct async *fd_queue_async( struct fd *fd, const async_data_t *data, struct io ...@@ -2054,12 +2054,16 @@ struct async *fd_queue_async( struct fd *fd, const async_data_t *data, struct io
assert(0); assert(0);
} }
if ((async = create_async( current, queue, data, iosb )) && type != ASYNC_TYPE_WAIT) if ((async = create_async( current, data, iosb )))
{ {
if (!fd->inode) queue_async( queue, async );
set_fd_events( fd, fd->fd_ops->get_poll_events( fd ) ); if (type != ASYNC_TYPE_WAIT)
else /* regular files are always ready for read and write */ {
async_wake_up( queue, STATUS_ALERTED ); if (!fd->inode)
set_fd_events( fd, fd->fd_ops->get_poll_events( fd ) );
else /* regular files are always ready for read and write */
async_wake_up( queue, STATUS_ALERTED );
}
} }
return async; return async;
} }
......
...@@ -177,8 +177,8 @@ extern struct object *create_serial( struct fd *fd ); ...@@ -177,8 +177,8 @@ extern struct object *create_serial( struct fd *fd );
/* async I/O functions */ /* async I/O functions */
extern struct async_queue *create_async_queue( struct fd *fd ); extern struct async_queue *create_async_queue( struct fd *fd );
extern void free_async_queue( struct async_queue *queue ); extern void free_async_queue( struct async_queue *queue );
extern struct async *create_async( struct thread *thread, struct async_queue *queue, extern struct async *create_async( struct thread *thread, const async_data_t *data, struct iosb *iosb );
const async_data_t *data, struct iosb *iosb ); extern void queue_async( struct async_queue *queue, struct async *async );
extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status ); extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status );
extern void async_set_result( struct object *obj, unsigned int status, extern void async_set_result( struct object *obj, unsigned int status,
apc_param_t total, client_ptr_t apc, client_ptr_t apc_arg ); apc_param_t total, client_ptr_t apc, client_ptr_t apc_arg );
......
...@@ -838,6 +838,7 @@ static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, ...@@ -838,6 +838,7 @@ static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code,
struct named_pipe *pipe; struct named_pipe *pipe;
struct pipe_server *server; struct pipe_server *server;
struct unicode_str name; struct unicode_str name;
timeout_t when;
if (size < sizeof(*buffer) || if (size < sizeof(*buffer) ||
size < FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[buffer->NameLength/sizeof(WCHAR)])) size < FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[buffer->NameLength/sizeof(WCHAR)]))
...@@ -855,9 +856,10 @@ static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, ...@@ -855,9 +856,10 @@ static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code,
if (!pipe->waiters && !(pipe->waiters = create_async_queue( NULL ))) goto done; if (!pipe->waiters && !(pipe->waiters = create_async_queue( NULL ))) goto done;
if ((async = create_async( current, pipe->waiters, async_data, NULL ))) if ((async = create_async( current, async_data, NULL )))
{ {
timeout_t when = buffer->TimeoutSpecified ? buffer->Timeout.QuadPart : pipe->timeout; queue_async( pipe->waiters, async );
when = buffer->TimeoutSpecified ? buffer->Timeout.QuadPart : pipe->timeout;
async_set_timeout( async, when, STATUS_IO_TIMEOUT ); async_set_timeout( async, when, STATUS_IO_TIMEOUT );
if (blocking) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ); if (blocking) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 );
release_object( async ); release_object( async );
......
...@@ -552,7 +552,8 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *a ...@@ -552,7 +552,8 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *a
return 0; return 0;
} }
if (!(ifchange_q = sock_get_ifchange_q( sock ))) return 0; if (!(ifchange_q = sock_get_ifchange_q( sock ))) return 0;
if (!(async = create_async( current, ifchange_q, async_data, NULL ))) return 0; if (!(async = create_async( current, async_data, NULL ))) return 0;
queue_async( ifchange_q, async );
if (blocking) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ); if (blocking) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 );
release_object( async ); release_object( async );
set_error( STATUS_PENDING ); set_error( STATUS_PENDING );
...@@ -593,7 +594,8 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, ...@@ -593,7 +594,8 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type,
return; return;
} }
if (!(async = create_async( current, queue, data, NULL ))) return; if (!(async = create_async( current, data, NULL ))) return;
queue_async( queue, async );
release_object( async ); release_object( async );
sock_reselect( sock ); sock_reselect( sock );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment