[PATCH v14 5/5] ntdll: Implement exclusive flag for IOCTL_AFD_POLL.

Zebediah Figura zfigura at codeweavers.com
Thu Sep 23 00:48:03 CDT 2021


From: Guillaume Charifi <guillaume.charifi at sfr.fr>

Signed-off-by: Guillaume Charifi <guillaume.charifi at sfr.fr>
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
Resent with a bit of restructuring; namely, use the introduced
complete_async_poll() helper.

 dlls/ntdll/unix/socket.c |  2 +-
 dlls/ws2_32/tests/afd.c  | 10 +++---
 server/protocol.def      |  1 +
 server/sock.c            | 66 ++++++++++++++++++++++++++++++++++++++--
 4 files changed, 70 insertions(+), 9 deletions(-)

diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c
index c1a29f5d5e0..75c54295c20 100644
--- a/dlls/ntdll/unix/socket.c
+++ b/dlls/ntdll/unix/socket.c
@@ -741,7 +741,6 @@ static NTSTATUS sock_poll( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi
             params->padding[0], params->padding[1], params->padding[2],
             params->sockets[0].socket, params->sockets[0].flags );
 
-    if (params->exclusive) FIXME( "ignoring exclusive flag\n" );
     if (params->padding[0]) FIXME( "padding[0] is %#x\n", params->padding[0] );
     if (params->padding[1]) FIXME( "padding[1] is %#x\n", params->padding[1] );
     if (params->padding[2]) FIXME( "padding[2] is %#x\n", params->padding[2] );
@@ -782,6 +781,7 @@ static NTSTATUS sock_poll( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi
     SERVER_START_REQ( poll_socket )
     {
         req->async = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) );
+        req->exclusive = !!params->exclusive;
         req->timeout = params->timeout;
         wine_server_add_data( req, input, params->count * sizeof(*input) );
         wine_server_set_reply( req, async->sockets, params->count * sizeof(async->sockets[0]) );
diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c
index 647b7e41f63..9e888f1fcb9 100644
--- a/dlls/ws2_32/tests/afd.c
+++ b/dlls/ws2_32/tests/afd.c
@@ -867,7 +867,7 @@ static void test_poll_exclusive(void)
     ok(ret == STATUS_PENDING, "got %#x\n", ret);
 
     ret = WaitForSingleObject(events[0], 100);
-    todo_wine ok(ret == STATUS_SUCCESS, "got %#x\n", ret);
+    ok(ret == STATUS_SUCCESS, "got %#x\n", ret);
 
     ret = WaitForSingleObject(events[1], 100);
     ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
@@ -927,7 +927,7 @@ static void test_poll_exclusive(void)
     ok(ret == STATUS_PENDING, "got %#x\n", ret);
 
     ret = WaitForSingleObject(events[1], 100);
-    todo_wine ok(ret == STATUS_SUCCESS, "got %#x\n", ret);
+    ok(ret == STATUS_SUCCESS, "got %#x\n", ret);
 
     ret = WaitForSingleObject(events[2], 100);
     ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
@@ -997,7 +997,7 @@ static void test_poll_exclusive(void)
     ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
 
     ret = WaitForSingleObject(events[2], 100);
-    todo_wine ok(ret == STATUS_SUCCESS, "got %#x\n", ret);
+    ok(ret == STATUS_SUCCESS, "got %#x\n", ret);
 
     ret = WaitForSingleObject(events[3], 100);
     ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
@@ -1048,7 +1048,7 @@ static void test_poll_exclusive(void)
     CloseHandle(thrd);
 
     ret = WaitForSingleObject(events[0], 100);
-    todo_wine ok(ret == STATUS_SUCCESS, "got %#x\n", ret);
+    ok(ret == STATUS_SUCCESS, "got %#x\n", ret);
 
     CancelIo((HANDLE)ctl_sock);
 
@@ -1073,7 +1073,7 @@ static void test_poll_exclusive(void)
     ok(ret == STATUS_PENDING, "got %#x\n", ret);
 
     ret = WaitForSingleObject(events[0], 100);
-    todo_wine ok(ret == STATUS_SUCCESS, "got %#x\n", ret);
+    ok(ret == STATUS_SUCCESS, "got %#x\n", ret);
 
     ret = WaitForSingleObject(events[1], 100);
     ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
diff --git a/server/protocol.def b/server/protocol.def
index ad0a6e2cdcf..1ae64d496f4 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1451,6 +1451,7 @@ struct poll_socket_output
 
 /* Perform an async poll on a socket */
 @REQ(poll_socket)
+    int          exclusive;     /* is the poll exclusive? */
     async_data_t async;         /* async I/O parameters */
     timeout_t    timeout;       /* timeout */
     VARARG(sockets,poll_socket_input); /* list of sockets to poll */
diff --git a/server/sock.c b/server/sock.c
index a44c127825c..396447a0aa4 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -128,6 +128,7 @@ struct poll_req
     struct async *async;
     struct iosb *iosb;
     struct timeout_user *timeout;
+    int exclusive;
     unsigned int count;
     struct poll_socket_output *output;
     struct
@@ -205,6 +206,7 @@ struct sock
     struct list         accept_list; /* list of pending accept requests */
     struct accept_req  *accept_recv_req; /* pending accept-into request which will recv on this socket */
     struct connect_req *connect_req; /* pending connection request */
+    struct poll_req    *main_poll;   /* main poll */
     union win_sockaddr  addr;        /* socket name */
     int                 addr_len;    /* socket name length */
     unsigned int        rcvbuf;      /* advisory recv buffer size */
@@ -231,6 +233,7 @@ static int sock_get_poll_events( struct fd *fd );
 static void sock_poll_event( struct fd *fd, int event );
 static enum server_fd_type sock_get_fd_type( struct fd *fd );
 static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
+static void sock_cancel_async( struct fd *fd, struct async *async );
 static void sock_queue_async( struct fd *fd, struct async *async, int type, int count );
 static void sock_reselect_async( struct fd *fd, struct async_queue *queue );
 
@@ -275,7 +278,7 @@ static const struct fd_ops sock_fd_ops =
     default_fd_get_file_info,     /* get_file_info */
     no_fd_get_volume_info,        /* get_volume_info */
     sock_ioctl,                   /* ioctl */
-    default_fd_cancel_async,      /* cancel_async */
+    sock_cancel_async,            /* cancel_async */
     sock_queue_async,             /* queue_async */
     sock_reselect_async           /* reselect_async */
 };
@@ -835,6 +838,16 @@ static int get_poll_flags( struct sock *sock, int event )
 
 static void complete_async_poll( struct poll_req *req, unsigned int status )
 {
+    unsigned int i;
+
+    for (i = 0; i < req->count; ++i)
+    {
+        struct sock *sock = req->sockets[i].sock;
+
+        if (sock->main_poll == req)
+            sock->main_poll = NULL;
+    }
+
     /* pass 0 as result; client will set actual result size */
     async_request_complete( req->async, status, 0, req->count * sizeof(*req->output), req->output );
 }
@@ -1223,6 +1236,29 @@ static enum server_fd_type sock_get_fd_type( struct fd *fd )
     return FD_TYPE_SOCKET;
 }
 
+static void sock_cancel_async( struct fd *fd, struct async *async )
+{
+    struct poll_req *req;
+
+    LIST_FOR_EACH_ENTRY( req, &poll_list, struct poll_req, entry )
+    {
+        unsigned int i;
+
+        if (req->async != async)
+            continue;
+
+        for (i = 0; i < req->count; i++)
+        {
+            struct sock *sock = req->sockets[i].sock;
+
+            if (sock->main_poll == req)
+                sock->main_poll = NULL;
+        }
+    }
+
+    async_terminate( async, STATUS_CANCELLED );
+}
+
 static void sock_queue_async( struct fd *fd, struct async *async, int type, int count )
 {
     struct sock *sock = get_fd_user( fd );
@@ -1384,6 +1420,7 @@ static struct sock *create_socket(void)
     sock->ifchange_obj = NULL;
     sock->accept_recv_req = NULL;
     sock->connect_req = NULL;
+    sock->main_poll = NULL;
     memset( &sock->addr, 0, sizeof(sock->addr) );
     sock->addr_len = 0;
     sock->rd_shutdown = 0;
@@ -2841,7 +2878,27 @@ static int poll_single_socket( struct sock *sock, int mask )
     return get_poll_flags( sock, pollfd.revents ) & mask;
 }
 
-static void poll_socket( struct sock *poll_sock, struct async *async, timeout_t timeout,
+static void handle_exclusive_poll(struct poll_req *req)
+{
+    unsigned int i;
+
+    for (i = 0; i < req->count; ++i)
+    {
+        struct sock *sock = req->sockets[i].sock;
+        struct poll_req *main_poll = sock->main_poll;
+
+        if (main_poll && main_poll->exclusive && req->exclusive)
+        {
+            complete_async_poll( main_poll, STATUS_SUCCESS );
+            main_poll = NULL;
+        }
+
+        if (!main_poll)
+            sock->main_poll = req;
+    }
+}
+
+static void poll_socket( struct sock *poll_sock, struct async *async, int exclusive, timeout_t timeout,
                          unsigned int count, const struct poll_socket_input *input )
 {
     struct poll_socket_output *output;
@@ -2882,11 +2939,14 @@ static void poll_socket( struct sock *poll_sock, struct async *async, timeout_t
         req->sockets[i].flags = input[i].flags;
     }
 
+    req->exclusive = exclusive;
     req->count = count;
     req->async = (struct async *)grab_object( async );
     req->iosb = async_get_iosb( async );
     req->output = output;
 
+    handle_exclusive_poll(req);
+
     list_add_tail( &poll_list, &req->entry );
     async_set_completion_callback( async, free_poll_req, req );
     queue_async( &poll_sock->poll_q, async );
@@ -3290,7 +3350,7 @@ DECL_HANDLER(poll_socket)
 
     if ((async = create_request_async( sock->fd, get_fd_comp_flags( sock->fd ), &req->async )))
     {
-        poll_socket( sock, async, req->timeout, count, input );
+        poll_socket( sock, async, req->exclusive, req->timeout, count, input );
         reply->wait = async_handoff( async, NULL, 0 );
         reply->options = get_fd_options( sock->fd );
         release_object( async );
-- 
2.33.0




More information about the wine-devel mailing list