Jacek Caban : server Introduce write queue for server-side named pipe I/O.
Alexandre Julliard
julliard at winehq.org
Wed Mar 22 15:52:36 CDT 2017
Module: wine
Branch: master
Commit: 4b2d5171e01427a8c003a5c61263c726508f64a9
URL: http://source.winehq.org/git/wine.git/?a=commit;h=4b2d5171e01427a8c003a5c61263c726508f64a9
Author: Jacek Caban <jacek at codeweavers.com>
Date: Tue Mar 21 13:03:26 2017 +0100
server Introduce write queue for server-side named pipe I/O.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
server/named_pipe.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 66 insertions(+), 2 deletions(-)
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 6dc032d..b0aa55d 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -81,6 +81,7 @@ struct pipe_end
struct pipe_end *connection; /* the other end of the pipe */
data_size_t buffer_size;/* size of buffered data that doesn't block caller */
struct list message_queue;
+ struct async_queue *write_q; /* write queue */
};
struct pipe_server
@@ -154,6 +155,7 @@ static const struct object_ops named_pipe_ops =
/* common server and client pipe end functions */
static void pipe_end_queue_async( struct fd *fd, struct async *async, int type, int count );
+static void pipe_end_reselect_async( struct fd *fd, struct async_queue *queue );
/* server end functions */
static void pipe_server_dump( struct object *obj, int verbose );
@@ -196,7 +198,7 @@ static const struct fd_ops pipe_server_fd_ops =
pipe_server_flush, /* flush */
pipe_server_ioctl, /* ioctl */
pipe_end_queue_async, /* queue_async */
- default_fd_reselect_async /* reselect_async */
+ pipe_end_reselect_async /* reselect_async */
};
/* client end functions */
@@ -239,7 +241,7 @@ static const struct fd_ops pipe_client_fd_ops =
pipe_client_flush, /* flush */
default_fd_ioctl, /* ioctl */
pipe_end_queue_async, /* queue_async */
- default_fd_reselect_async /* reselect_async */
+ pipe_end_reselect_async /* reselect_async */
};
static void named_pipe_device_dump( struct object *obj, int verbose );
@@ -388,6 +390,20 @@ static void notify_empty( struct pipe_server *server )
fd_async_wake_up( server->pipe_end.fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS );
}
+static void wake_message( struct pipe_message *message )
+{
+ struct async *async = message->async;
+
+ message->async = NULL;
+ message->iosb->status = STATUS_SUCCESS;
+ message->iosb->result = message->iosb->in_size;
+ if (async)
+ {
+ async_terminate( async, message->iosb->result ? STATUS_ALERTED : STATUS_SUCCESS );
+ release_object( async );
+ }
+}
+
static void free_message( struct pipe_message *message )
{
list_remove( &message->entry );
@@ -450,6 +466,8 @@ static void pipe_end_destroy( struct pipe_end *pipe_end )
assert( !message->async );
free_message( message );
}
+
+ free_async_queue( pipe_end->write_q );
}
static void pipe_server_destroy( struct object *obj)
@@ -660,6 +678,39 @@ static obj_handle_t pipe_client_flush( struct fd *fd, struct async *async, int b
return 0;
}
+/* We call async_terminate in our reselect implementation, which causes recursive reselect.
+ * We're not interested in such reselect calls, so we ignore them. */
+static int ignore_reselect;
+
+static void reselect_write_queue( struct pipe_end *pipe_end )
+{
+ struct pipe_message *message, *next;
+ struct pipe_end *reader = pipe_end->connection;
+ data_size_t avail = 0;
+
+ if (!reader) return;
+
+ ignore_reselect = 1;
+
+ LIST_FOR_EACH_ENTRY_SAFE( message, next, &reader->message_queue, struct pipe_message, entry )
+ {
+ if (message->async && message->iosb->status != STATUS_PENDING)
+ {
+ release_object( message->async );
+ message->async = NULL;
+ free_message( message );
+ }
+ else
+ {
+ avail += message->iosb->in_size - message->read_pos;
+ if (message->iosb->status == STATUS_PENDING && (avail <= reader->buffer_size || !message->iosb->in_size))
+ wake_message( message );
+ }
+ }
+
+ ignore_reselect = 0;
+}
+
static void pipe_end_queue_async( struct fd *fd, struct async *async, int type, int count )
{
struct pipe_end *pipe_end = get_fd_user( fd );
@@ -667,6 +718,18 @@ static void pipe_end_queue_async( struct fd *fd, struct async *async, int type,
else default_fd_queue_async( fd, async, type, count );
}
+static void pipe_end_reselect_async( struct fd *fd, struct async_queue *queue )
+{
+ struct pipe_end *pipe_end = get_fd_user( fd );
+
+ if (ignore_reselect) return;
+
+ if (!use_server_io( pipe_end ))
+ default_fd_reselect_async( fd, queue );
+ else if (pipe_end->write_q && pipe_end->write_q == queue)
+ reselect_write_queue( pipe_end );
+}
+
static inline int is_overlapped( unsigned int options )
{
return !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
@@ -767,6 +830,7 @@ static void init_pipe_end( struct pipe_end *pipe_end, unsigned int pipe_flags, d
pipe_end->flags = pipe_flags;
pipe_end->connection = NULL;
pipe_end->buffer_size = buffer_size;
+ pipe_end->write_q = NULL;
list_init( &pipe_end->message_queue );
}
More information about the wine-cvs
mailing list