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
);