[PATCH] server: Implement serial port read interval timeouts.

Alexandre Julliard julliard at winehq.org
Mon Feb 1 03:54:53 CST 2016


Alex Henrie <alexhenrie24 at gmail.com> writes:

> Fixes https://bugs.winehq.org/show_bug.cgi?id=39875
>
> There is a test program attached to the bug report.
>
> Version 3 has all the logic in serial.c, even though this required
> adding a getter in async.c and another getter in fd.c. The first
> interval timeout no longer trashes subsequent interval timeouts or
> the total timeout, and absolute timeouts are used exclusively.

You should be able to do this without adding all the extra getter
functions. I'd suggest something along these lines (completely
untested):

diff --git a/server/serial.c b/server/serial.c
index 164a4b1fe717..04b517dd347e 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -62,12 +62,15 @@ 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
 {
     struct object       obj;
     struct fd          *fd;
 
+    struct timeout_user *read_timer;
+
     /* timeout values */
     unsigned int        readinterval;
     unsigned int        readconst;
@@ -115,7 +118,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 */
 };
 
@@ -134,6 +137,7 @@ struct object *create_serial( struct fd *fd )
 
     if (!(serial = alloc_object( &serial_ops ))) return NULL;
 
+    serial->read_timer   = NULL;
     serial->readinterval = 0;
     serial->readmult     = 0;
     serial->readconst    = 0;
@@ -157,6 +161,7 @@ static struct fd *serial_get_fd( struct object *obj )
 static void serial_destroy( struct object *obj)
 {
     struct serial *serial = (struct serial *)obj;
+    if (serial->read_timer) remove_timeout_user( serial->read_timer );
     release_object( serial->fd );
 }
 
@@ -203,6 +208,34 @@ static void serial_queue_async( struct fd *fd, const async_data_t *data, int typ
     }
 }
 
+static void serial_read_timeout( void *arg )
+{
+    struct serial *serial = arg;
+
+    serial->read_timer = NULL;
+    fd_async_wake_up( serial->fd, ASYNC_TYPE_READ, STATUS_TIMEOUT );
+}
+
+static void serial_reselect_async( struct fd *fd, struct async_queue *queue )
+{
+    struct serial *serial = get_fd_user( fd );
+
+    if (serial->read_timer)
+    {
+        if (!(default_fd_get_poll_events( fd ) & POLLIN))
+        {
+            remove_timeout_user( serial->read_timer );
+            serial->read_timer = NULL;
+        }
+    }
+    else if (!serial->read_timer && serial->readinterval && (default_fd_get_poll_events( fd ) & POLLIN))
+    {
+        serial->read_timer = add_timeout_user( (timeout_t)serial->readinterval * -10000,
+                                               serial_read_timeout, serial );
+    }
+    default_fd_reselect_async( fd, queue );
+}
+
 DECL_HANDLER(get_serial_info)
 {
     struct serial *serial;

-- 
Alexandre Julliard
julliard at winehq.org



More information about the wine-devel mailing list