From 6966fa967a9e2f87358e9b24ffae33db101b9b59 Mon Sep 17 00:00:00 2001 From: Scott Lindeneau Date: Mon, 1 Sep 2008 02:24:13 +0900 Subject: [PATCH] Implements locatable async events To: wine-patches async.c: Implements create_async_l: Includes an addtional paramaterof type obj_handle_t. This handle will act as a locator that can be used by the second function implmented (async_wake_up_l). Implements async_wake_up_l: Wakes up a specific operation according to the additional paramater with the approprate locator. This is necessary for AcceptEx because multiple objects will wait on a queue of a single object. These objects may be deleted and have their assosciated handles destroyed independently of the object whose queue they are waiting on. This added functionality is the only change. fd.c: Implmentds DECL_HANDLER(register_async_l): Identical to register_async but takes an addtional paramater of type obj_handle_t which will be used as the locator for the async operation. file.h Adds register_async_l as a valid field_op protocol.def: Changes for the DECL_HANDLER addtion above. --- include/wine/server_protocol.h | 21 ++++++++++++++++++++- server/async.c | 31 +++++++++++++++++++++++++------ server/fd.c | 26 ++++++++++++++++++++++++++ server/file.h | 6 ++++++ server/protocol.def | 10 ++++++++++ server/request.h | 2 ++ server/trace.c | 13 +++++++++++++ 7 files changed, 102 insertions(+), 7 deletions(-) diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 7b6e631..327c174 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2661,6 +2661,22 @@ struct register_async_reply { struct reply_header __header; }; + + + +struct register_async_l_request +{ + struct request_header __header; + obj_handle_t handle; + int type; + int count; + obj_handle_t locator; + async_data_t async; +}; +struct register_async_l_reply +{ + struct reply_header __header; +}; #define ASYNC_TYPE_READ 0x01 #define ASYNC_TYPE_WRITE 0x02 #define ASYNC_TYPE_WAIT 0x03 @@ -4402,6 +4418,7 @@ enum request REQ_get_serial_info, REQ_set_serial_info, REQ_register_async, + REQ_register_async_l, REQ_cancel_async, REQ_ioctl, REQ_get_ioctl_result, @@ -4641,6 +4658,7 @@ union generic_request struct get_serial_info_request get_serial_info_request; struct set_serial_info_request set_serial_info_request; struct register_async_request register_async_request; + struct register_async_l_request register_async_l_request; struct cancel_async_request cancel_async_request; struct ioctl_request ioctl_request; struct get_ioctl_result_request get_ioctl_result_request; @@ -4878,6 +4896,7 @@ union generic_reply struct get_serial_info_reply get_serial_info_reply; struct set_serial_info_reply set_serial_info_reply; struct register_async_reply register_async_reply; + struct register_async_l_reply register_async_l_reply; struct cancel_async_reply cancel_async_reply; struct ioctl_reply ioctl_reply; struct get_ioctl_result_reply get_ioctl_result_reply; @@ -4979,6 +4998,6 @@ union generic_reply struct add_fd_completion_reply add_fd_completion_reply; }; -#define SERVER_PROTOCOL_VERSION 341 +#define SERVER_PROTOCOL_VERSION 342 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/async.c b/server/async.c index 879616d..2f57818 100644 --- a/server/async.c +++ b/server/async.c @@ -45,6 +45,7 @@ struct async struct completion *completion; unsigned long comp_key; async_data_t data; /* data for async I/O call */ + obj_handle_t locator; /* handle used to locate this async */ }; static void async_dump( struct object *obj, int verbose ); @@ -214,6 +215,7 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co async->timeout = NULL; async->queue = (struct async_queue *)grab_object( queue ); async->completion = NULL; + async->locator = NULL; if (queue->fd) fd_assign_completion( queue->fd, &async->completion, &async->comp_key ); list_add_tail( &queue->queue, &async->queue_entry ); @@ -224,6 +226,15 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co return async; } +/* create an async that you can locate later */ +struct async *create_async_l( struct thread *thread, struct async_queue *queue, const async_data_t *data, obj_handle_t l ) +{ + struct async *out; + out = create_async(thread,queue,data); + out->locator = l; + return out; +} + /* set the timeout of an async operation */ void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status ) { @@ -288,17 +299,25 @@ int async_waiting( struct async_queue *queue ) return async->status == STATUS_PENDING; } -/* wake up async operations on the queue */ -void async_wake_up( struct async_queue *queue, unsigned int status ) +/* wake up async with locator l operations on the queue */ +void async_wake_up_l( struct async_queue *queue, unsigned int status, obj_handle_t l ) { struct list *ptr, *next; - if (!queue) return; - LIST_FOR_EACH_SAFE( ptr, next, &queue->queue ) { struct async *async = LIST_ENTRY( ptr, struct async, queue_entry ); - async_terminate( async, status ); - if (status == STATUS_ALERTED) break; /* only wake up the first one */ + if( (async->locator == l || NULL == l) || + (status != STATUS_ALERTED) ) /*if we aren't alerting, notify everything*/ + { + async_terminate( async, status ); + if (status == STATUS_ALERTED) break; /* only wake up the first one */ + } } } + +/* wake up async operations on the queue */ +void async_wake_up( struct async_queue *queue, unsigned int status ) +{ + async_wake_up_l(queue,status,NULL); +} diff --git a/server/fd.c b/server/fd.c index 0d33e77..a03d7f7 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2048,6 +2048,32 @@ DECL_HANDLER(register_async) } } +/* create / reschedule an async I/O */ +DECL_HANDLER(register_async_l) +{ + unsigned int access; + struct fd *fd; + + switch(req->type) + { + case ASYNC_TYPE_READ: + access = FILE_READ_DATA; + break; + case ASYNC_TYPE_WRITE: + access = FILE_WRITE_DATA; + break; + default: + set_error( STATUS_INVALID_PARAMETER ); + return; + } + + if ((fd = get_handle_fd_obj( current->process, req->handle, access ))) + { + if (get_unix_fd( fd ) != -1) fd->fd_ops->queue_async_l( fd, &req->async, req->type, req->count, req->locator ); + release_object( fd ); + } +} + /* cancels all async I/O */ DECL_HANDLER(cancel_async) { diff --git a/server/file.h b/server/file.h index 26d1702..d0ae929 100644 --- a/server/file.h +++ b/server/file.h @@ -47,6 +47,9 @@ struct fd_ops void (*reselect_async)( struct fd *, struct async_queue *queue ); /* cancel an async operation */ void (*cancel_async)(struct fd *); + /* queue a locatable async operation */ + void (*queue_async_l)(struct fd *, const async_data_t *data, int type, int count, obj_handle_t locator); + }; /* file descriptor functions */ @@ -134,11 +137,14 @@ extern struct async_queue *create_async_queue( struct fd *fd ); extern void free_async_queue( struct async_queue *queue ); extern struct async *create_async( struct thread *thread, struct async_queue *queue, const async_data_t *data ); +extern struct async *create_async_l( struct thread *thread, struct async_queue *queue, + const async_data_t *data, obj_handle_t l ); 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, unsigned long total ); extern int async_waiting( struct async_queue *queue ); extern void async_terminate( struct async *async, unsigned int status ); extern void async_wake_up( struct async_queue *queue, unsigned int status ); +extern void async_wake_up_l( struct async_queue *queue, unsigned int status, obj_handle_t l ); extern void fd_assign_completion( struct fd *fd, struct completion **p_port, unsigned long *p_key ); /* access rights that require Unix read permission */ diff --git a/server/protocol.def b/server/protocol.def index db2d171..b78592f 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1968,6 +1968,16 @@ enum message_type int count; /* count - usually # of bytes to be read/written */ async_data_t async; /* async I/O parameters */ @END + + +/* Create a locatable async I/O */ +@REQ(register_async_l) + obj_handle_t handle; /* handle to comm port, socket or file */ + int type; /* type of queue to look after */ + int count; /* count - usually # of bytes to be read/written */ + obj_handle_t locator; /* used to locate a specific async request later */ + async_data_t async; /* async I/O parameters */ +@END #define ASYNC_TYPE_READ 0x01 #define ASYNC_TYPE_WRITE 0x02 #define ASYNC_TYPE_WAIT 0x03 diff --git a/server/request.h b/server/request.h index 14d3246..00bdcaf 100644 --- a/server/request.h +++ b/server/request.h @@ -244,6 +244,7 @@ DECL_HANDLER(is_window_hung); DECL_HANDLER(get_serial_info); DECL_HANDLER(set_serial_info); DECL_HANDLER(register_async); +DECL_HANDLER(register_async_l); DECL_HANDLER(cancel_async); DECL_HANDLER(ioctl); DECL_HANDLER(get_ioctl_result); @@ -482,6 +483,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_get_serial_info, (req_handler)req_set_serial_info, (req_handler)req_register_async, + (req_handler)req_register_async_l, (req_handler)req_cancel_async, (req_handler)req_ioctl, (req_handler)req_get_ioctl_result, diff --git a/server/trace.c b/server/trace.c index 70cb13b..d2b0411 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2470,6 +2470,16 @@ static void dump_register_async_request( const struct register_async_request *re dump_async_data( &req->async ); } +static void dump_register_async_l_request( const struct register_async_l_request *req ) +{ + fprintf( stderr, " handle=%p,", req->handle ); + fprintf( stderr, " type=%d,", req->type ); + fprintf( stderr, " count=%d,", req->count ); + fprintf( stderr, " locator=%p,", req->locator ); + fprintf( stderr, " async=" ); + dump_async_data( &req->async ); +} + static void dump_cancel_async_request( const struct cancel_async_request *req ) { fprintf( stderr, " handle=%p", req->handle ); @@ -3907,6 +3917,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_serial_info_request, (dump_func)dump_set_serial_info_request, (dump_func)dump_register_async_request, + (dump_func)dump_register_async_l_request, (dump_func)dump_cancel_async_request, (dump_func)dump_ioctl_request, (dump_func)dump_get_ioctl_result_request, @@ -4143,6 +4154,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)0, (dump_func)0, (dump_func)0, + (dump_func)0, (dump_func)dump_ioctl_reply, (dump_func)dump_get_ioctl_result_reply, (dump_func)dump_create_named_pipe_reply, @@ -4377,6 +4389,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "get_serial_info", "set_serial_info", "register_async", + "register_async_l", "cancel_async", "ioctl", "get_ioctl_result", -- 1.5.4.3