Alexandre Julliard : server: Fix the handling of the signaled status for file descriptors.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Apr 4 15:40:06 CDT 2007


Module: wine
Branch: master
Commit: ba896e75d7fce68e5183007b65eae7e35490ccd4
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=ba896e75d7fce68e5183007b65eae7e35490ccd4

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Apr  4 19:39:29 2007 +0200

server: Fix the handling of the signaled status for file descriptors.
    
File handles are signaled when an I/O operation completes, and reset
when another operation is queued.

---

 server/async.c      |    2 +
 server/fd.c         |   58 ++++++++++----------------------------------------
 server/file.c       |    4 +-
 server/file.h       |    3 +-
 server/mailslot.c   |    4 +-
 server/named_pipe.c |    8 +++---
 server/serial.c     |    4 +-
 7 files changed, 25 insertions(+), 58 deletions(-)

diff --git a/server/async.c b/server/async.c
index 027dd25..e0877b2 100644
--- a/server/async.c
+++ b/server/async.c
@@ -193,6 +193,7 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
     list_add_tail( &queue->queue, &async->queue_entry );
     grab_object( async );
 
+    if (queue->fd) set_fd_signaled( queue->fd, 0 );
     if (event) reset_event( event );
     return async;
 }
@@ -230,6 +231,7 @@ void async_set_result( struct object *obj, unsigned int status )
             thread_queue_apc( async->thread, NULL, &data );
         }
         if (async->event) set_event( async->event );
+        else if (async->queue->fd) set_fd_signaled( async->queue->fd, 1 );
     }
 }
 
diff --git a/server/fd.c b/server/fd.c
index 25917ae..3a044b2 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -168,6 +168,7 @@ struct fd
     unsigned int         access;      /* file access (FILE_READ_DATA etc.) */
     unsigned int         sharing;     /* file sharing mode */
     int                  unix_fd;     /* unix file descriptor */
+    int                  signaled :1; /* is the fd signaled? */
     int                  fs_locks :1; /* can we use filesystem locks for this fd? */
     int                  unmounted :1;/* has the device been unmounted? */
     int                  poll_index;  /* index of fd in poll array */
@@ -1360,6 +1361,7 @@ static struct fd *alloc_fd_object(void)
     fd->access     = 0;
     fd->sharing    = 0;
     fd->unix_fd    = -1;
+    fd->signaled   = 1;
     fd->fs_locks   = 1;
     fd->unmounted  = 0;
     fd->poll_index = -1;
@@ -1391,6 +1393,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
     fd->access     = 0;
     fd->sharing    = 0;
     fd->unix_fd    = -1;
+    fd->signaled   = 0;
     fd->fs_locks   = 0;
     fd->unmounted  = 0;
     fd->poll_index = -1;
@@ -1610,6 +1613,13 @@ int is_fd_removable( struct fd *fd )
     return (fd->inode && fd->inode->device->removable);
 }
 
+/* set or clear the fd signaled state */
+void set_fd_signaled( struct fd *fd, int signaled )
+{
+    fd->signaled = signaled;
+    if (signaled) wake_up( fd->user, 0 );
+}
+
 /* 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 )
 {
@@ -1635,55 +1645,11 @@ int check_fd_events( struct fd *fd, int events )
     return pfd.revents;
 }
 
-/* default add_queue() routine for objects that poll() on an fd */
-int default_fd_add_queue( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct fd *fd = get_obj_fd( obj );
-
-    if (!fd) return 0;
-    if (!fd->inode && list_empty( &obj->wait_queue ))  /* first on the queue */
-        set_fd_events( fd, fd->fd_ops->get_poll_events( fd ) );
-    add_queue( obj, entry );
-    release_object( fd );
-    return 1;
-}
-
-/* default remove_queue() routine for objects that poll() on an fd */
-void default_fd_remove_queue( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct fd *fd = get_obj_fd( obj );
-
-    grab_object( obj );
-    remove_queue( obj, entry );
-    if (!fd->inode && list_empty( &obj->wait_queue ))  /* last on the queue is gone */
-        set_fd_events( fd, 0 );
-    release_object( obj );
-    release_object( fd );
-}
-
 /* default signaled() routine for objects that poll() on an fd */
 int default_fd_signaled( struct object *obj, struct thread *thread )
 {
-    int events, ret;
     struct fd *fd = get_obj_fd( obj );
-
-    if (fd->inode) ret = 1; /* regular files are always signaled */
-    else
-    {
-        events = fd->fd_ops->get_poll_events( fd );
-        ret = check_fd_events( fd, events ) != 0;
-
-        if (ret)
-        {
-            /* stop waiting on select() if we are signaled */
-            set_fd_events( fd, 0 );
-        }
-        else if (!list_empty( &obj->wait_queue ))
-        {
-            /* restart waiting on poll() if we are no longer signaled */
-            set_fd_events( fd, events );
-        }
-    }
+    int ret = fd->signaled;
     release_object( fd );
     return ret;
 }
@@ -1705,7 +1671,7 @@ void default_poll_event( struct fd *fd, int event )
 
     /* if an error occurred, stop polling this fd to avoid busy-looping */
     if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 );
-    wake_up( fd->user, 0 );
+    else set_fd_events( fd, fd->fd_ops->get_poll_events( fd ) );
 }
 
 struct async *fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
diff --git a/server/file.c b/server/file.c
index 5f5349d..edc92f7 100644
--- a/server/file.c
+++ b/server/file.c
@@ -76,8 +76,8 @@ static const struct object_ops file_ops =
 {
     sizeof(struct file),          /* size */
     file_dump,                    /* dump */
-    default_fd_add_queue,         /* add_queue */
-    default_fd_remove_queue,      /* remove_queue */
+    add_queue,                    /* add_queue */
+    remove_queue,                 /* remove_queue */
     default_fd_signaled,          /* signaled */
     no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */
diff --git a/server/file.h b/server/file.h
index 3514022..096b9df 100644
--- a/server/file.h
+++ b/server/file.h
@@ -63,9 +63,8 @@ extern int check_fd_events( struct fd *fd, int events );
 extern void set_fd_events( struct fd *fd, int events );
 extern obj_handle_t lock_fd( struct fd *fd, file_pos_t offset, file_pos_t count, int shared, int wait );
 extern void unlock_fd( struct fd *fd, file_pos_t offset, file_pos_t count );
+extern void set_fd_signaled( struct fd *fd, int signaled );
 
-extern int default_fd_add_queue( struct object *obj, struct wait_queue_entry *entry );
-extern void default_fd_remove_queue( struct object *obj, struct wait_queue_entry *entry );
 extern int default_fd_signaled( struct object *obj, struct thread *thread );
 extern int default_fd_get_poll_events( struct fd *fd );
 extern void default_poll_event( struct fd *fd, int event );
diff --git a/server/mailslot.c b/server/mailslot.c
index 89af2bf..2898d1a 100644
--- a/server/mailslot.c
+++ b/server/mailslot.c
@@ -74,8 +74,8 @@ static const struct object_ops mailslot_ops =
 {
     sizeof(struct mailslot),   /* size */
     mailslot_dump,             /* dump */
-    default_fd_add_queue,      /* add_queue */
-    default_fd_remove_queue,   /* remove_queue */
+    add_queue,                 /* add_queue */
+    remove_queue,              /* remove_queue */
     default_fd_signaled,       /* signaled */
     no_satisfied,              /* satisfied */
     no_signal,                 /* signal */
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 0a4ab96..a736d83 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -143,8 +143,8 @@ static const struct object_ops pipe_server_ops =
 {
     sizeof(struct pipe_server),   /* size */
     pipe_server_dump,             /* dump */
-    default_fd_add_queue,         /* add_queue */
-    default_fd_remove_queue,      /* remove_queue */
+    add_queue,                    /* add_queue */
+    remove_queue,                 /* remove_queue */
     default_fd_signaled,          /* signaled */
     no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */
@@ -177,8 +177,8 @@ static const struct object_ops pipe_client_ops =
 {
     sizeof(struct pipe_client),   /* size */
     pipe_client_dump,             /* dump */
-    default_fd_add_queue,         /* add_queue */
-    default_fd_remove_queue,      /* remove_queue */
+    add_queue,                    /* add_queue */
+    remove_queue,                 /* remove_queue */
     default_fd_signaled,          /* signaled */
     no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */
diff --git a/server/serial.c b/server/serial.c
index f2b88c1..8dc1d18 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -89,8 +89,8 @@ static const struct object_ops serial_ops =
 {
     sizeof(struct serial),        /* size */
     serial_dump,                  /* dump */
-    default_fd_add_queue,         /* add_queue */
-    default_fd_remove_queue,      /* remove_queue */
+    add_queue,                    /* add_queue */
+    remove_queue,                 /* remove_queue */
     default_fd_signaled,          /* signaled */
     no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */




More information about the wine-cvs mailing list