Commit 111610c4 authored by Alexandre Julliard's avatar Alexandre Julliard

server: Add an async_data_t structure to store parameters for async I/O requests.

parent 50975c81
......@@ -2272,9 +2272,9 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event,
req->filter = CompletionFilter;
req->want_data = (Buffer != NULL);
req->subtree = WatchTree;
req->io_apc = read_changes_apc;
req->io_sb = IoStatusBlock;
req->io_user = info;
req->async.callback = read_changes_apc;
req->async.iosb = IoStatusBlock;
req->async.arg = info;
status = wine_server_call( req );
}
SERVER_END_REQ;
......
......@@ -318,9 +318,9 @@ static ULONG fileio_queue_async(async_fileio* fileio, IO_STATUS_BLOCK* iosb,
SERVER_START_REQ( register_async )
{
req->handle = fileio->handle;
req->io_apc = apc;
req->io_sb = iosb;
req->io_user = fileio;
req->async.callback = apc;
req->async.iosb = iosb;
req->async.arg = fileio;
req->type = do_read ? ASYNC_TYPE_READ : ASYNC_TYPE_WRITE;
req->count = (fileio->count < iosb->Information) ?
0 : fileio->count - iosb->Information;
......@@ -983,9 +983,9 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
SERVER_START_REQ(connect_named_pipe)
{
req->handle = handle;
req->io_apc = pipe_completion_wait;
req->io_sb = io;
req->io_user = event ? event : internal_event;
req->async.callback = pipe_completion_wait;
req->async.iosb = io;
req->async.arg = event ? event : internal_event;
io->u.Status = wine_server_call(req);
}
SERVER_END_REQ;
......@@ -1019,9 +1019,9 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
req->handle = handle;
req->timeout = buff->TimeoutSpecified ? buff->Timeout.QuadPart / -10000L
: NMPWAIT_USE_DEFAULT_WAIT;
req->io_apc = pipe_completion_wait;
req->io_sb = io;
req->io_user = event ? event : internal_event;
req->async.callback = pipe_completion_wait;
req->async.iosb = io;
req->async.arg = event ? event : internal_event;
wine_server_add_data( req, buff->Name, buff->NameLength );
io->u.Status = wine_server_call( req );
}
......
......@@ -1158,9 +1158,9 @@ static ULONG ws2_queue_async(struct ws2_async* wsa, IO_STATUS_BLOCK* iosb)
SERVER_START_REQ( register_async )
{
req->handle = wsa->hSocket;
req->io_apc = apc;
req->io_sb = iosb;
req->io_user = wsa;
req->async.callback = apc;
req->async.iosb = iosb;
req->async.arg = wsa;
req->type = type;
req->count = iosb->Information;
status = wine_server_call( req );
......
......@@ -157,6 +157,14 @@ typedef struct
} rectangle_t;
typedef struct
{
void *callback;
void *iosb;
void *arg;
} async_data_t;
struct callback_msg_data
{
......@@ -1649,9 +1657,7 @@ struct read_directory_changes_request
obj_handle_t event;
int subtree;
int want_data;
void* io_apc;
void* io_sb;
void* io_user;
async_data_t async;
};
struct read_directory_changes_reply
{
......@@ -2639,10 +2645,8 @@ struct register_async_request
struct request_header __header;
obj_handle_t handle;
int type;
void* io_apc;
void* io_sb;
void* io_user;
int count;
async_data_t async;
};
struct register_async_reply
{
......@@ -2714,9 +2718,7 @@ struct connect_named_pipe_request
{
struct request_header __header;
obj_handle_t handle;
void* io_apc;
void* io_sb;
void* io_user;
async_data_t async;
};
struct connect_named_pipe_reply
{
......@@ -2729,10 +2731,8 @@ struct wait_named_pipe_request
{
struct request_header __header;
obj_handle_t handle;
async_data_t async;
unsigned int timeout;
void* io_apc;
void* io_sb;
void* io_user;
/* VARARG(name,unicode_str); */
};
struct wait_named_pipe_reply
......@@ -4699,6 +4699,6 @@ union generic_reply
struct allocate_locally_unique_id_reply allocate_locally_unique_id_reply;
};
#define SERVER_PROTOCOL_VERSION 282
#define SERVER_PROTOCOL_VERSION 283
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -38,9 +38,7 @@ struct async
struct thread *thread; /* owning thread */
struct list queue_entry; /* entry in file descriptor queue */
struct timeout_user *timeout;
void *apc; /* apc function to call when alerted */
void *user; /* user-private argument for apc */
void *sb; /* pointer to I/O status block in client addr space */
async_data_t data; /* data for async I/O call */
};
static void async_dump( struct object *obj, int verbose );
......@@ -86,9 +84,9 @@ static void async_terminate( struct async *async, unsigned int status )
memset( &data, 0, sizeof(data) );
data.type = APC_ASYNC_IO;
data.async_io.func = async->apc;
data.async_io.user = async->user;
data.async_io.sb = async->sb;
data.async_io.func = async->data.callback;
data.async_io.user = async->data.arg;
data.async_io.sb = async->data.iosb;
data.async_io.status = status;
thread_queue_apc( async->thread, &async->obj, &data );
......@@ -109,16 +107,14 @@ static void async_timeout( void *private )
/* create an async on a given queue of a fd */
struct async *create_async( struct thread *thread, const struct timeval *timeout,
struct list *queue, void *io_apc, void *io_user, void *io_sb )
struct list *queue, const async_data_t *data )
{
struct async *async = alloc_object( &async_ops );
if (!async) return NULL;
async->thread = (struct thread *)grab_object( thread );
async->apc = io_apc;
async->user = io_user;
async->sb = io_sb;
async->data = *data;
list_add_tail( queue, &async->queue_entry );
......
......@@ -1100,9 +1100,7 @@ DECL_HANDLER(read_directory_changes)
dir->event = event;
/* requests don't timeout */
if ( req->io_apc && !create_async( current, NULL, &dir->change_q,
req->io_apc, req->io_user, req->io_sb ))
return;
if (!create_async( current, NULL, &dir->change_q, &req->async )) return;
/* assign it once */
if (!dir->filter)
......
......@@ -1711,7 +1711,7 @@ void default_poll_event( struct fd *fd, int event )
wake_up( fd->user, 0 );
}
void fd_queue_async_timeout( struct fd *fd, void *apc, void *user, void *io_sb, int type, int count,
void fd_queue_async_timeout( struct fd *fd, const async_data_t *data, int type, int count,
const struct timeval *timeout )
{
struct list *queue;
......@@ -1737,8 +1737,7 @@ void fd_queue_async_timeout( struct fd *fd, void *apc, void *user, void *io_sb,
return;
}
if (!create_async( current, timeout, queue, apc, user, io_sb ))
return;
if (!create_async( current, timeout, queue, data )) return;
/* Check if the new pending request can be served immediately */
events = check_fd_events( fd, fd->fd_ops->get_poll_events( fd ) );
......@@ -1747,9 +1746,9 @@ void fd_queue_async_timeout( struct fd *fd, void *apc, void *user, void *io_sb,
set_fd_events( fd, fd->fd_ops->get_poll_events( fd ) );
}
void default_fd_queue_async( struct fd *fd, void *apc, void *user, void *io_sb, int type, int count )
void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
{
fd_queue_async_timeout( fd, apc, user, io_sb, type, count, NULL );
fd_queue_async_timeout( fd, data, type, count, NULL );
}
void default_fd_cancel_async( struct fd *fd )
......@@ -1773,8 +1772,7 @@ enum server_fd_type no_get_file_info( struct fd *fd, int *flags )
}
/* default queue_async() routine */
void no_queue_async( struct fd *fd, void* apc, void* user, void* io_sb,
int type, int count)
void no_queue_async( struct fd *fd, const async_data_t *data, int type, int count)
{
set_error( STATUS_OBJECT_TYPE_MISMATCH );
}
......@@ -1945,8 +1943,7 @@ DECL_HANDLER(register_async)
if (fd)
{
fd->fd_ops->queue_async( fd, req->io_apc, req->io_user, req->io_sb,
req->type, req->count );
fd->fd_ops->queue_async( fd, &req->async, req->type, req->count );
release_object( fd );
}
}
......
......@@ -39,7 +39,7 @@ struct fd_ops
/* get file information */
enum server_fd_type (*get_file_info)(struct fd *fd, int *flags);
/* queue an async operation */
void (*queue_async)(struct fd *, void* apc, void* user, void* io_sb, int type, int count);
void (*queue_async)(struct fd *, const async_data_t *data, int type, int count);
/* cancel an async operation */
void (*cancel_async)(struct fd *);
};
......@@ -68,13 +68,13 @@ extern void default_fd_remove_queue( struct object *obj, struct wait_queue_entry
extern int default_fd_signaled( struct object *obj, struct thread *thread );
extern int default_fd_get_poll_events( struct fd *fd );
extern void default_poll_event( struct fd *fd, int event );
extern void fd_queue_async_timeout( struct fd *fd, void *apc, void *user, void *io_sb, int type,
extern void fd_queue_async_timeout( struct fd *fd, const async_data_t *data, int type,
int count, const struct timeval *timeout );
extern void default_fd_queue_async( struct fd *fd, void *apc, void *user, void *io_sb, int type, int count );
extern void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
extern void default_fd_cancel_async( struct fd *fd );
extern int no_flush( struct fd *fd, struct event **event );
extern enum server_fd_type no_get_file_info( struct fd *fd, int *flags );
extern void no_queue_async( struct fd *fd, void* apc, void* user, void* io_sb, int type, int count);
extern void no_queue_async( struct fd *fd, const async_data_t *data, int type, int count);
extern void no_cancel_async( struct fd *fd );
extern void main_loop(void);
extern void remove_process_locks( struct process *process );
......@@ -123,7 +123,7 @@ extern struct object *create_serial( struct fd *fd, unsigned int options );
/* async I/O functions */
extern struct async *create_async( struct thread *thread, const struct timeval *timeout,
struct list *queue, void *, void *, void *);
struct list *queue, const async_data_t *data );
extern void async_terminate_head( struct list *queue, unsigned int status );
extern void async_terminate_queue( struct list *queue, unsigned int status );
......
......@@ -85,7 +85,7 @@ static const struct object_ops mailslot_ops =
};
static enum server_fd_type mailslot_get_info( struct fd *fd, int *flags );
static void mailslot_queue_async( struct fd *, void*, void*, void*, int, int );
static void mailslot_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
static const struct fd_ops mailslot_fd_ops =
{
......@@ -236,8 +236,7 @@ static unsigned int mailslot_map_access( struct object *obj, unsigned int access
return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
}
static void mailslot_queue_async( struct fd *fd, void *apc, void *user,
void *iosb, int type, int count )
static void mailslot_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
{
struct mailslot *mailslot = get_fd_user( fd );
......@@ -260,9 +259,9 @@ static void mailslot_queue_async( struct fd *fd, void *apc, void *user,
{
struct timeval when = current_time;
add_timeout( &when, mailslot->read_timeout );
fd_queue_async_timeout( fd, apc, user, iosb, type, count, &when );
fd_queue_async_timeout( fd, data, type, count, &when );
}
else fd_queue_async_timeout( fd, apc, user, iosb, type, count, NULL );
else fd_queue_async_timeout( fd, data, type, count, NULL );
}
static void mailslot_device_dump( struct object *obj, int verbose )
......
......@@ -824,7 +824,7 @@ DECL_HANDLER(connect_named_pipe)
case ps_wait_connect:
assert( !server->fd );
server->state = ps_wait_open;
create_async( current, NULL, &server->wait_q, req->io_apc, req->io_user, req->io_sb );
create_async( current, NULL, &server->wait_q, &req->async );
async_terminate_queue( &server->pipe->waiters, STATUS_SUCCESS );
break;
case ps_connected_server:
......@@ -872,9 +872,9 @@ DECL_HANDLER(wait_named_pipe)
/* there's already a server waiting for a client to connect */
memset( &data, 0, sizeof(data) );
data.type = APC_ASYNC_IO;
data.async_io.func = req->io_apc;
data.async_io.user = req->io_user;
data.async_io.sb = req->io_sb;
data.async_io.func = req->async.callback;
data.async_io.user = req->async.arg;
data.async_io.sb = req->async.iosb;
data.async_io.status = STATUS_SUCCESS;
thread_queue_apc( current, NULL, &data );
release_object( server );
......@@ -882,14 +882,13 @@ DECL_HANDLER(wait_named_pipe)
else
{
if (req->timeout == NMPWAIT_WAIT_FOREVER)
create_async( current, NULL, &pipe->waiters,
req->io_apc, req->io_user, req->io_sb );
create_async( current, NULL, &pipe->waiters, &req->async );
else
{
struct timeval when = current_time;
if (req->timeout == NMPWAIT_USE_DEFAULT_WAIT) add_timeout( &when, pipe->timeout );
else add_timeout( &when, req->timeout );
create_async( current, &when, &pipe->waiters, req->io_apc, req->io_user, req->io_sb );
create_async( current, &when, &pipe->waiters, &req->async );
}
}
......
......@@ -172,6 +172,14 @@ typedef struct
int bottom;
} rectangle_t;
/* structure for parameters of async I/O calls */
typedef struct
{
void *callback; /* client-side callback to call upon end of async */
void *iosb; /* I/O status block in client addr space */
void *arg; /* opaque user data to pass to callback */
} async_data_t;
/* structures for extra message data */
struct callback_msg_data
......@@ -1293,9 +1301,7 @@ enum char_info_mode
obj_handle_t event; /* handle to the event */
int subtree; /* watch the subtree? */
int want_data; /* flag indicating whether change data should be collected */
void* io_apc; /* APC routine to queue upon end of async */
void* io_sb; /* I/O status block (unique across all async on this handle) */
void* io_user; /* data to pass back to caller */
async_data_t async; /* async I/O parameters */
@END
......@@ -1949,10 +1955,8 @@ enum message_type
@REQ(register_async)
obj_handle_t handle; /* handle to comm port, socket or file */
int type; /* type of queue to look after */
void* io_apc; /* APC routine to queue upon end of async */
void* io_sb; /* I/O status block (unique across all async on this handle) */
void* io_user; /* data to pass back to caller */
int count; /* count - usually # of bytes to be read/written */
async_data_t async; /* async I/O parameters */
@END
#define ASYNC_TYPE_READ 0x01
#define ASYNC_TYPE_WRITE 0x02
......@@ -2002,19 +2006,15 @@ enum message_type
/* Connect to a named pipe */
@REQ(connect_named_pipe)
obj_handle_t handle;
void* io_apc; /* APC routine to queue upon end of async */
void* io_sb; /* I/O status block */
void* io_user; /* data to pass back to caller */
async_data_t async; /* async I/O parameters */
@END
/* Wait for a named pipe */
@REQ(wait_named_pipe)
obj_handle_t handle;
async_data_t async; /* async I/O parameters */
unsigned int timeout;
void* io_apc; /* APC routine to queue upon end of async */
void* io_sb; /* I/O status block */
void* io_user; /* data to pass back to caller */
VARARG(name,unicode_str); /* pipe name */
@END
......
......@@ -65,7 +65,7 @@ static int serial_get_poll_events( struct fd *fd );
static void serial_poll_event( struct fd *fd, int event );
static enum server_fd_type serial_get_info( struct fd *fd, int *flags );
static int serial_flush( struct fd *fd, struct event **event );
static void serial_queue_async( struct fd *fd, void *apc, void *user, void *iosb, int type, int count );
static void serial_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
static void serial_cancel_async( struct fd *fd );
struct serial
......@@ -241,8 +241,7 @@ static void serial_poll_event(struct fd *fd, int event)
set_fd_events( fd, serial_get_poll_events(fd) );
}
static void serial_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
int type, int count )
static void serial_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
{
struct serial *serial = get_fd_user( fd );
struct list *queue;
......@@ -272,7 +271,7 @@ static void serial_queue_async( struct fd *fd, void *apc, void *user, void *iosb
}
add_timeout( &when, timeout );
if (!create_async( current, timeout ? &when : NULL, queue, apc, user, iosb )) return;
if (!create_async( current, timeout ? &when : NULL, queue, data )) return;
/* Check if the new pending request can be served immediately */
events = check_fd_events( fd, serial_get_poll_events( fd ) );
......
......@@ -96,7 +96,7 @@ static void sock_destroy( struct object *obj );
static int sock_get_poll_events( struct fd *fd );
static void sock_poll_event( struct fd *fd, int event );
static enum server_fd_type sock_get_info( struct fd *fd, int *flags );
static void sock_queue_async( struct fd *fd, void *apc, void *user, void *iosb, int type, int count );
static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
static void sock_cancel_async( struct fd *fd );
static int sock_get_error( int err );
......@@ -508,8 +508,7 @@ static enum server_fd_type sock_get_info( struct fd *fd, int *flags )
return FD_TYPE_SOCKET;
}
static void sock_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
int type, int count )
static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
{
struct sock *sock = get_fd_user( fd );
struct list *queue;
......@@ -544,8 +543,7 @@ static void sock_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
}
else
{
if (!create_async( current, NULL, queue, apc, user, iosb ))
return;
if (!create_async( current, NULL, queue, data )) return;
}
pollev = sock_reselect( sock );
......
......@@ -243,6 +243,11 @@ static void dump_apc_result( const apc_result_t *result )
fputc( '}', stderr );
}
static void dump_async_data( const async_data_t *data )
{
fprintf( stderr, "{callback=%p,iosb=%p,arg=%p}", data->callback, data->iosb, data->arg );
}
static void dump_luid( const luid_t *luid )
{
fprintf( stderr, "%d.%u", luid->high_part, luid->low_part );
......@@ -1652,9 +1657,8 @@ static void dump_read_directory_changes_request( const struct read_directory_cha
fprintf( stderr, " event=%p,", req->event );
fprintf( stderr, " subtree=%d,", req->subtree );
fprintf( stderr, " want_data=%d,", req->want_data );
fprintf( stderr, " io_apc=%p,", req->io_apc );
fprintf( stderr, " io_sb=%p,", req->io_sb );
fprintf( stderr, " io_user=%p", req->io_user );
fprintf( stderr, " async=" );
dump_async_data( &req->async );
}
static void dump_read_change_request( const struct read_change_request *req )
......@@ -2380,10 +2384,9 @@ static void dump_register_async_request( const struct register_async_request *re
{
fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " io_apc=%p,", req->io_apc );
fprintf( stderr, " io_sb=%p,", req->io_sb );
fprintf( stderr, " io_user=%p,", req->io_user );
fprintf( stderr, " count=%d", req->count );
fprintf( stderr, " count=%d,", req->count );
fprintf( stderr, " async=" );
dump_async_data( &req->async );
}
static void dump_cancel_async_request( const struct cancel_async_request *req )
......@@ -2429,18 +2432,17 @@ static void dump_open_named_pipe_reply( const struct open_named_pipe_reply *req
static void dump_connect_named_pipe_request( const struct connect_named_pipe_request *req )
{
fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " io_apc=%p,", req->io_apc );
fprintf( stderr, " io_sb=%p,", req->io_sb );
fprintf( stderr, " io_user=%p", req->io_user );
fprintf( stderr, " async=" );
dump_async_data( &req->async );
}
static void dump_wait_named_pipe_request( const struct wait_named_pipe_request *req )
{
fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " async=" );
dump_async_data( &req->async );
fprintf( stderr, "," );
fprintf( stderr, " timeout=%08x,", req->timeout );
fprintf( stderr, " io_apc=%p,", req->io_apc );
fprintf( stderr, " io_sb=%p,", req->io_sb );
fprintf( stderr, " io_user=%p,", req->io_user );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( cur_size );
}
......
......@@ -44,6 +44,7 @@ my %formats =
"char_info_t" => "&dump_char_info",
"apc_call_t" => "&dump_apc_call",
"apc_result_t" => "&dump_apc_result",
"async_data_t" => "&dump_async_data",
"luid_t" => "&dump_luid",
);
......
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