server: Change cancel_async to take an optional iosb and only_thread.
This commit is contained in:
parent
e49918b5a2
commit
b05774ee7e
|
@ -2859,6 +2859,9 @@ struct cancel_async_request
|
|||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t handle;
|
||||
client_ptr_t iosb;
|
||||
int only_thread;
|
||||
char __pad_28[4];
|
||||
};
|
||||
struct cancel_async_reply
|
||||
{
|
||||
|
@ -5312,6 +5315,6 @@ union generic_reply
|
|||
struct set_window_layered_info_reply set_window_layered_info_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 387
|
||||
#define SERVER_PROTOCOL_VERSION 388
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -288,6 +288,28 @@ int async_waiting( struct async_queue *queue )
|
|||
return async->status == STATUS_PENDING;
|
||||
}
|
||||
|
||||
int async_wake_up_by( struct async_queue *queue, struct process *process,
|
||||
struct thread *thread, client_ptr_t iosb, unsigned int status )
|
||||
{
|
||||
struct list *ptr, *next;
|
||||
int woken = 0;
|
||||
|
||||
if (!queue || (!process && !thread && !iosb)) return 0;
|
||||
|
||||
LIST_FOR_EACH_SAFE( ptr, next, &queue->queue )
|
||||
{
|
||||
struct async *async = LIST_ENTRY( ptr, struct async, queue_entry );
|
||||
if ( (!process || async->thread->process == process) &&
|
||||
(!thread || async->thread == thread) &&
|
||||
(!iosb || async->data.iosb == iosb) )
|
||||
{
|
||||
async_terminate( async, status );
|
||||
woken++;
|
||||
}
|
||||
}
|
||||
return woken;
|
||||
}
|
||||
|
||||
/* wake up async operations on the queue */
|
||||
void async_wake_up( struct async_queue *queue, unsigned int status )
|
||||
{
|
||||
|
|
15
server/fd.c
15
server/fd.c
|
@ -1856,11 +1856,15 @@ void default_fd_reselect_async( struct fd *fd, struct async_queue *queue )
|
|||
}
|
||||
|
||||
/* default cancel_async() fd routine */
|
||||
void default_fd_cancel_async( struct fd *fd )
|
||||
void default_fd_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb )
|
||||
{
|
||||
async_wake_up( fd->read_q, STATUS_CANCELLED );
|
||||
async_wake_up( fd->write_q, STATUS_CANCELLED );
|
||||
async_wake_up( fd->wait_q, STATUS_CANCELLED );
|
||||
int n = 0;
|
||||
|
||||
n += async_wake_up_by( fd->read_q, process, thread, iosb, STATUS_CANCELLED );
|
||||
n += async_wake_up_by( fd->write_q, process, thread, iosb, STATUS_CANCELLED );
|
||||
n += async_wake_up_by( fd->wait_q, process, thread, iosb, STATUS_CANCELLED );
|
||||
if (!n && iosb)
|
||||
set_error( STATUS_NOT_FOUND );
|
||||
}
|
||||
|
||||
/* default flush() routine */
|
||||
|
@ -2064,10 +2068,11 @@ DECL_HANDLER(register_async)
|
|||
DECL_HANDLER(cancel_async)
|
||||
{
|
||||
struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
|
||||
struct thread *thread = req->only_thread ? current : NULL;
|
||||
|
||||
if (fd)
|
||||
{
|
||||
if (get_unix_fd( fd ) != -1) fd->fd_ops->cancel_async( fd );
|
||||
if (get_unix_fd( fd ) != -1) fd->fd_ops->cancel_async( fd, current->process, thread, req->iosb );
|
||||
release_object( fd );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ struct fd_ops
|
|||
/* selected events for async i/o need an update */
|
||||
void (*reselect_async)( struct fd *, struct async_queue *queue );
|
||||
/* cancel an async operation */
|
||||
void (*cancel_async)(struct fd *);
|
||||
void (*cancel_async)(struct fd *, struct process *process, struct thread *thread, client_ptr_t iosb);
|
||||
};
|
||||
|
||||
/* file descriptor functions */
|
||||
|
@ -83,7 +83,7 @@ extern obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, const as
|
|||
int blocking, const void *data, data_size_t size );
|
||||
extern void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
|
||||
extern void default_fd_reselect_async( struct fd *fd, struct async_queue *queue );
|
||||
extern void default_fd_cancel_async( struct fd *fd );
|
||||
extern void default_fd_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb );
|
||||
extern void no_flush( struct fd *fd, struct event **event );
|
||||
extern void main_loop(void);
|
||||
extern void remove_process_locks( struct process *process );
|
||||
|
@ -143,6 +143,8 @@ extern void async_set_result( struct object *obj, unsigned int status,
|
|||
unsigned int total, client_ptr_t apc );
|
||||
extern int async_waiting( struct async_queue *queue );
|
||||
extern void async_terminate( struct async *async, unsigned int status );
|
||||
extern int async_wake_up_by( struct async_queue *queue, struct process *process,
|
||||
struct thread *thread, client_ptr_t iosb, unsigned int status );
|
||||
extern void async_wake_up( struct async_queue *queue, unsigned int status );
|
||||
extern struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key );
|
||||
extern void fd_copy_completion( struct fd *src, struct fd *dst );
|
||||
|
|
|
@ -2072,6 +2072,8 @@ enum message_type
|
|||
/* Cancel all async op on a fd */
|
||||
@REQ(cancel_async)
|
||||
obj_handle_t handle; /* handle to comm port, socket or file */
|
||||
client_ptr_t iosb; /* I/O status block (NULL=all) */
|
||||
int only_thread; /* cancel matching this thread */
|
||||
@END
|
||||
|
||||
|
||||
|
|
|
@ -1351,7 +1351,9 @@ C_ASSERT( FIELD_OFFSET(struct register_async_request, async) == 16 );
|
|||
C_ASSERT( FIELD_OFFSET(struct register_async_request, count) == 56 );
|
||||
C_ASSERT( sizeof(struct register_async_request) == 64 );
|
||||
C_ASSERT( FIELD_OFFSET(struct cancel_async_request, handle) == 12 );
|
||||
C_ASSERT( sizeof(struct cancel_async_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct cancel_async_request, iosb) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct cancel_async_request, only_thread) == 24 );
|
||||
C_ASSERT( sizeof(struct cancel_async_request) == 32 );
|
||||
C_ASSERT( FIELD_OFFSET(struct ioctl_request, code) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct ioctl_request, async) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct ioctl_request, blocking) == 56 );
|
||||
|
|
|
@ -97,7 +97,7 @@ static void sock_poll_event( struct fd *fd, int event );
|
|||
static enum server_fd_type sock_get_fd_type( struct fd *fd );
|
||||
static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
|
||||
static void sock_reselect_async( struct fd *fd, struct async_queue *queue );
|
||||
static void sock_cancel_async( struct fd *fd );
|
||||
static void sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb );
|
||||
|
||||
static int sock_get_error( int err );
|
||||
static void sock_set_error(void);
|
||||
|
@ -538,13 +538,16 @@ static void sock_reselect_async( struct fd *fd, struct async_queue *queue )
|
|||
if (events) sock_try_event( sock, events );
|
||||
}
|
||||
|
||||
static void sock_cancel_async( struct fd *fd )
|
||||
static void sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb )
|
||||
{
|
||||
struct sock *sock = get_fd_user( fd );
|
||||
int n = 0;
|
||||
assert( sock->obj.ops == &sock_ops );
|
||||
|
||||
async_wake_up( sock->read_q, STATUS_CANCELLED );
|
||||
async_wake_up( sock->write_q, STATUS_CANCELLED );
|
||||
n += async_wake_up_by( sock->read_q, process, thread, iosb, STATUS_CANCELLED );
|
||||
n += async_wake_up_by( sock->write_q, process, thread, iosb, STATUS_CANCELLED );
|
||||
if (!n && iosb)
|
||||
set_error( STATUS_NOT_FOUND );
|
||||
}
|
||||
|
||||
static struct fd *sock_get_fd( struct object *obj )
|
||||
|
|
|
@ -2568,6 +2568,8 @@ static void dump_register_async_request( const struct register_async_request *re
|
|||
static void dump_cancel_async_request( const struct cancel_async_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
dump_uint64( ", iosb=", &req->iosb );
|
||||
fprintf( stderr, ", only_thread=%d", req->only_thread );
|
||||
}
|
||||
|
||||
static void dump_ioctl_request( const struct ioctl_request *req )
|
||||
|
@ -4583,12 +4585,12 @@ static const struct
|
|||
{ "IO_TIMEOUT", STATUS_IO_TIMEOUT },
|
||||
{ "KEY_DELETED", STATUS_KEY_DELETED },
|
||||
{ "MAPPED_FILE_SIZE_ZERO", STATUS_MAPPED_FILE_SIZE_ZERO },
|
||||
{ "MEDIA_WRITE_PROTECTED", STATUS_MEDIA_WRITE_PROTECTED },
|
||||
{ "MUTANT_NOT_OWNED", STATUS_MUTANT_NOT_OWNED },
|
||||
{ "NAME_TOO_LONG", STATUS_NAME_TOO_LONG },
|
||||
{ "NOTIFY_ENUM_DIR", STATUS_NOTIFY_ENUM_DIR },
|
||||
{ "NOT_ALL_ASSIGNED", STATUS_NOT_ALL_ASSIGNED },
|
||||
{ "NOT_A_DIRECTORY", STATUS_NOT_A_DIRECTORY },
|
||||
{ "NOT_FOUND", STATUS_NOT_FOUND },
|
||||
{ "NOT_IMPLEMENTED", STATUS_NOT_IMPLEMENTED },
|
||||
{ "NOT_REGISTRY_FILE", STATUS_NOT_REGISTRY_FILE },
|
||||
{ "NOT_SUPPORTED", STATUS_NOT_SUPPORTED },
|
||||
|
|
Loading…
Reference in New Issue