[PATCH v2] server: Implement serial port read interval timeouts.
Alex Henrie
alexhenrie24 at gmail.com
Wed Jan 20 22:04:01 CST 2016
Fixes https://bugs.winehq.org/show_bug.cgi?id=39875
There is a test program attached to the bug report.
Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
server/async.c | 14 ++++++++++++++
server/fd.c | 12 ++++++++++++
server/file.h | 3 +++
server/serial.c | 13 ++++++++++++-
4 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/server/async.c b/server/async.c
index d2da976..e718462 100644
--- a/server/async.c
+++ b/server/async.c
@@ -216,6 +216,20 @@ void free_async_queue( struct async_queue *queue )
release_object( queue );
}
+/* set the timeout of the async queue head if the new timeout is shorter than the current one */
+/* only pass negative timeouts (i.e. timeouts relative to the current time) to this function */
+void async_queue_set_shorter_timeout( struct async_queue *queue, timeout_t timeout, unsigned int status )
+{
+ struct list *ptr;
+ struct async *async;
+
+ if (!(ptr = list_head( &queue->queue ))) return;
+ async = LIST_ENTRY( ptr, struct async, queue_entry );
+
+ if (!async->timeout || -timeout < get_timeout_user_remaining( async->timeout ))
+ async_set_timeout( async, timeout, status );
+}
+
/* create an async on a given queue of a fd */
struct async *create_async( struct thread *thread, struct async_queue *queue, const async_data_t *data )
{
diff --git a/server/fd.c b/server/fd.c
index 559a737..112f8a1 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -391,6 +391,12 @@ void remove_timeout_user( struct timeout_user *user )
free( user );
}
+/* return how much time is left before the timeout happens */
+timeout_t get_timeout_user_remaining( struct timeout_user *user )
+{
+ return user->when - current_time;
+}
+
/* return a text description of a timeout for debugging purposes */
const char *get_timeout_str( timeout_t timeout )
{
@@ -1958,6 +1964,12 @@ int is_fd_signaled( struct fd *fd )
return fd->signaled;
}
+/* check if a queue is this fd's read queue */
+int is_read_queue( struct fd *fd, struct async_queue *queue )
+{
+ return fd->read_q == queue;
+}
+
/* handler for close_handle that refuses to close fd-associated handles in other processes */
int fd_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
{
diff --git a/server/file.h b/server/file.h
index b59de1c..cdc761d 100644
--- a/server/file.h
+++ b/server/file.h
@@ -81,6 +81,7 @@ extern void unlock_fd( struct fd *fd, file_pos_t offset, file_pos_t count );
extern void allow_fd_caching( struct fd *fd );
extern void set_fd_signaled( struct fd *fd, int signaled );
extern int is_fd_signaled( struct fd *fd );
+extern int is_read_queue( struct fd *fd, struct async_queue *queue );
extern char *dup_fd_name( struct fd *root, const char *name );
extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry );
@@ -116,6 +117,7 @@ typedef void (*timeout_callback)( void *private );
extern struct timeout_user *add_timeout_user( timeout_t when, timeout_callback func, void *private );
extern void remove_timeout_user( struct timeout_user *user );
+extern timeout_t get_timeout_user_remaining( struct timeout_user *user );
extern const char *get_timeout_str( timeout_t timeout );
/* file functions */
@@ -167,6 +169,7 @@ extern struct object *create_serial( struct fd *fd );
/* async I/O functions */
extern struct async_queue *create_async_queue( struct fd *fd );
extern void free_async_queue( struct async_queue *queue );
+extern void async_queue_set_shorter_timeout( struct async_queue *queue, timeout_t timeout, unsigned int status );
extern struct async *create_async( struct thread *thread, struct async_queue *queue,
const async_data_t *data );
extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status );
diff --git a/server/serial.c b/server/serial.c
index 164a4b1..0767c12 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -62,6 +62,7 @@ static void serial_destroy(struct object *obj);
static enum server_fd_type serial_get_fd_type( struct fd *fd );
static void serial_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
+static void serial_reselect_async( struct fd *fd, struct async_queue *queue );
struct serial
{
@@ -115,7 +116,7 @@ static const struct fd_ops serial_fd_ops =
no_fd_flush, /* flush */
default_fd_ioctl, /* ioctl */
serial_queue_async, /* queue_async */
- default_fd_reselect_async, /* reselect_async */
+ serial_reselect_async, /* reselect_async */
default_fd_cancel_async /* cancel_async */
};
@@ -203,6 +204,16 @@ static void serial_queue_async( struct fd *fd, const async_data_t *data, int typ
}
}
+static void serial_reselect_async( struct fd *fd, struct async_queue *queue )
+{
+ struct serial *serial = get_fd_user( fd );
+
+ if (is_read_queue( fd, queue ) && serial->readinterval)
+ async_queue_set_shorter_timeout( queue, serial->readinterval * -10000, STATUS_TIMEOUT );
+
+ default_fd_reselect_async( fd, queue );
+}
+
DECL_HANDLER(get_serial_info)
{
struct serial *serial;
--
2.7.0
More information about the wine-patches
mailing list