2 * Server-side support for async i/o operations
4 * Copyright (C) 1998 Alexandre Julliard
5 * Copyright (C) 2000 Mike McCormack
8 * Fix up WaitCommEvent operations. Currently only EV_RXCHAR is supported.
9 * This may require modifications to the linux kernel to enable select
10 * to wait on Modem Status Register deltas. (delta DCD, CTS, DSR or RING)
22 #ifdef HAVE_SYS_ERRNO_H
23 #include <sys/errno.h>
27 #include <sys/types.h>
32 #include <sys/ioctl.h>
44 void *client_overlapped;
50 struct timeout_user *timeout;
51 struct wait_queue_entry wait;
54 struct thread *thread;
58 static void async_dump( struct object *obj, int verbose );
59 static void async_destroy( struct object *obj );
60 static int async_get_poll_events( struct object *obj );
61 static int async_get_read_fd( struct object *obj );
62 static int async_get_write_fd( struct object *obj );
63 static int async_get_info( struct object *obj, struct get_file_info_request *req );
64 static void async_poll_event( struct object *obj, int event );
66 static const struct object_ops async_ops =
68 sizeof(struct async), /* size */
69 async_dump, /* dump */
70 default_poll_add_queue, /* add_queue */
71 default_poll_remove_queue, /* remove_queue */
72 default_poll_signaled, /* signaled */
73 no_satisfied, /* satisfied */
74 async_get_poll_events, /* get_poll_events */
75 async_poll_event, /* poll_event */
76 async_get_read_fd, /* get_read_fd */
77 async_get_write_fd, /* get_write_fd */
79 async_get_info, /* get_file_info */
80 async_destroy /* destroy */
83 static void async_dump( struct object *obj, int verbose )
85 struct async *ov = (struct async *)obj;
87 assert( obj->ops == &async_ops );
89 fprintf( stderr, "async: overlapped %p %s\n",
90 ov->client_overlapped, ov->timeout?"with timeout":"");
93 /* same as file_destroy, but don't delete comm ports */
94 static void async_destroy( struct object *obj )
96 struct async *ov = (struct async *)obj;
97 assert( obj->ops == &async_ops );
100 remove_timeout_user(ov->timeout);
104 struct async *get_async_obj( struct process *process, int handle, unsigned int access )
106 return (struct async *)get_handle_obj( process, handle, access, &async_ops );
109 static int async_get_poll_events( struct object *obj )
111 struct async *ov = (struct async *)obj;
112 assert( obj->ops == &async_ops );
114 /* FIXME: this should be a function pointer */
115 return serial_async_get_poll_events(ov);
118 static int async_get_read_fd( struct object *obj )
120 struct async *async = (struct async *)obj;
121 assert( obj->ops == &async_ops );
122 return dup( async->obj.fd );
125 static int async_get_write_fd( struct object *obj )
127 struct async *async = (struct async *)obj;
128 assert( obj->ops == &async_ops );
129 return dup( async->obj.fd );
132 static int async_get_info( struct object *obj, struct get_file_info_request *req ) {
133 assert( obj->ops == &async_ops );
134 req->type = FILE_TYPE_CHAR;
136 req->access_time = 0;
147 /* data access functions */
148 int async_type(struct async *ov)
153 int async_count(struct async *ov)
158 int async_get_eventmask(struct async *ov)
160 return ov->eventmask;
163 int async_set_eventmask(struct async *ov, int eventmask)
165 return ov->eventmask = eventmask;
168 DECL_HANDLER(create_async)
171 struct async *ov = NULL;
175 if (!(obj = get_handle_obj( current->process, req->file_handle, 0, NULL)) )
182 set_error(STATUS_UNSUCCESSFUL);
186 if(0>fcntl(fd, F_SETFL, O_NONBLOCK))
189 set_error(STATUS_UNSUCCESSFUL);
193 ov = alloc_object (&async_ops, fd);
197 set_error(STATUS_UNSUCCESSFUL);
201 ov->client_overlapped = req->overlapped;
204 ov->type = req->type;
205 ov->thread = current;
206 ov->func = req->func;
208 ov->buffer = req->buffer;
209 ov->count = req->count;
211 /* FIXME: this should be a function pointer */
212 serial_async_setup(obj,ov);
214 ov->obj.ops->add_queue(&ov->obj,&ov->wait);
216 req->ov_handle = alloc_handle( current->process, ov, GENERIC_READ|GENERIC_WRITE, 0 );
221 /* handler for async poll() events */
222 static void async_poll_event( struct object *obj, int event )
224 struct async *ov = (struct async *) obj;
226 /* queue an APC in the client thread to do our dirty work */
227 ov->obj.ops->remove_queue(&ov->obj,&ov->wait);
229 /* FIXME: this should be a function pointer */
230 event = serial_async_poll_event(obj,event);
232 thread_queue_apc(ov->thread, NULL, ov->func, APC_ASYNC, 3,
233 ov->client_overlapped, ov->buffer, event);
236 /* handler for async i/o timeouts */
237 static void overlapped_timeout (void *private)
239 struct async *ov = (struct async *) private;
241 ov->obj.ops->remove_queue(&ov->obj,&ov->wait);
243 thread_queue_apc(ov->thread, NULL, ov->func, APC_ASYNC, 3,
244 ov->client_overlapped,ov->buffer, 0);
247 void async_add_timeout(struct async *ov, int timeout)
252 add_timeout(&tv,timeout);
253 ov->timeout = add_timeout_user(&tv, overlapped_timeout, ov);
256 DECL_HANDLER(async_result)
260 if ((ov = get_async_obj( current->process, req->ov_handle, 0 )))
262 ov->result = req->result;
263 if(ov->result == STATUS_PENDING)
265 ov->obj.ops->add_queue(&ov->obj,&ov->wait);
267 release_object( ov );