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_fd( struct object
*obj
);
62 static int async_get_info( struct object
*obj
, struct get_file_info_request
*req
);
63 static void async_poll_event( struct object
*obj
, int event
);
65 static const struct object_ops async_ops
=
67 sizeof(struct async
), /* size */
68 async_dump
, /* dump */
69 default_poll_add_queue
, /* add_queue */
70 default_poll_remove_queue
, /* remove_queue */
71 default_poll_signaled
, /* signaled */
72 no_satisfied
, /* satisfied */
73 async_get_poll_events
, /* get_poll_events */
74 async_poll_event
, /* poll_event */
75 async_get_fd
, /* get_fd */
77 async_get_info
, /* get_file_info */
78 async_destroy
/* destroy */
81 static void async_dump( struct object
*obj
, int verbose
)
83 struct async
*ov
= (struct async
*)obj
;
85 assert( obj
->ops
== &async_ops
);
87 fprintf( stderr
, "async: overlapped %p %s\n",
88 ov
->client_overlapped
, ov
->timeout
?"with timeout":"");
91 /* same as file_destroy, but don't delete comm ports */
92 static void async_destroy( struct object
*obj
)
94 struct async
*ov
= (struct async
*)obj
;
95 assert( obj
->ops
== &async_ops
);
98 remove_timeout_user(ov
->timeout
);
102 struct async
*get_async_obj( struct process
*process
, int handle
, unsigned int access
)
104 return (struct async
*)get_handle_obj( process
, handle
, access
, &async_ops
);
107 static int async_get_poll_events( struct object
*obj
)
109 struct async
*ov
= (struct async
*)obj
;
110 assert( obj
->ops
== &async_ops
);
112 /* FIXME: this should be a function pointer */
113 return serial_async_get_poll_events(ov
);
116 static int async_get_fd( struct object
*obj
)
118 struct async
*async
= (struct async
*)obj
;
119 assert( obj
->ops
== &async_ops
);
120 return async
->obj
.fd
;
123 static int async_get_info( struct object
*obj
, struct get_file_info_request
*req
) {
124 assert( obj
->ops
== &async_ops
);
125 req
->type
= FILE_TYPE_CHAR
;
127 req
->access_time
= 0;
138 /* data access functions */
139 int async_type(struct async
*ov
)
144 int async_count(struct async
*ov
)
149 int async_get_eventmask(struct async
*ov
)
151 return ov
->eventmask
;
154 int async_set_eventmask(struct async
*ov
, int eventmask
)
156 return ov
->eventmask
= eventmask
;
159 DECL_HANDLER(create_async
)
162 struct async
*ov
= NULL
;
166 if (!(obj
= get_handle_obj( current
->process
, req
->file_handle
, 0, NULL
)) )
173 set_error(STATUS_UNSUCCESSFUL
);
177 if(0>fcntl(fd
, F_SETFL
, O_NONBLOCK
))
180 set_error(STATUS_UNSUCCESSFUL
);
184 ov
= alloc_object (&async_ops
, fd
);
188 set_error(STATUS_UNSUCCESSFUL
);
192 ov
->client_overlapped
= req
->overlapped
;
195 ov
->type
= req
->type
;
196 ov
->thread
= current
;
197 ov
->func
= req
->func
;
199 ov
->buffer
= req
->buffer
;
200 ov
->count
= req
->count
;
202 /* FIXME: this should be a function pointer */
203 serial_async_setup(obj
,ov
);
205 ov
->obj
.ops
->add_queue(&ov
->obj
,&ov
->wait
);
207 req
->ov_handle
= alloc_handle( current
->process
, ov
, GENERIC_READ
|GENERIC_WRITE
, 0 );
212 /* handler for async poll() events */
213 static void async_poll_event( struct object
*obj
, int event
)
215 struct async
*ov
= (struct async
*) obj
;
217 /* queue an APC in the client thread to do our dirty work */
218 ov
->obj
.ops
->remove_queue(&ov
->obj
,&ov
->wait
);
220 /* FIXME: this should be a function pointer */
221 event
= serial_async_poll_event(obj
,event
);
223 thread_queue_apc(ov
->thread
, NULL
, ov
->func
, APC_ASYNC
, 3,
224 ov
->client_overlapped
, ov
->buffer
, event
);
227 /* handler for async i/o timeouts */
228 static void overlapped_timeout (void *private)
230 struct async
*ov
= (struct async
*) private;
232 ov
->obj
.ops
->remove_queue(&ov
->obj
,&ov
->wait
);
234 thread_queue_apc(ov
->thread
, NULL
, ov
->func
, APC_ASYNC
, 3,
235 ov
->client_overlapped
,ov
->buffer
, 0);
238 void async_add_timeout(struct async
*ov
, int timeout
)
243 add_timeout(&tv
,timeout
);
244 ov
->timeout
= add_timeout_user(&tv
, overlapped_timeout
, ov
);
247 DECL_HANDLER(async_result
)
251 if ((ov
= get_async_obj( current
->process
, req
->ov_handle
, 0 )))
253 ov
->result
= req
->result
;
254 if(ov
->result
== STATUS_PENDING
)
256 ov
->obj
.ops
->add_queue(&ov
->obj
,&ov
->wait
);
258 release_object( ov
);