Alexandre Julliard : ws2_32: Don' t queue a user APC when there is no callback function.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Mar 3 09:42:10 CST 2015


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Mar  3 15:30:38 2015 +0900

ws2_32: Don't queue a user APC when there is no callback function.

---

 dlls/ws2_32/socket.c | 71 ++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 49 insertions(+), 22 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 01e9869..f1f00eb 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -378,6 +378,34 @@ struct ws2_accept_async
     struct ws2_async    *read;
 };
 
+static struct ws2_async_io *async_io_freelist;
+
+static void release_async_io( struct ws2_async_io *io )
+{
+    for (;;)
+    {
+        struct ws2_async_io *next = async_io_freelist;
+        io->next = next;
+        if (interlocked_cmpxchg_ptr( (void **)&async_io_freelist, io, next ) == next) return;
+    }
+}
+
+static struct ws2_async_io *alloc_async_io( DWORD size )
+{
+    /* first free remaining previous fileinfos */
+
+    struct ws2_async_io *io = interlocked_xchg_ptr( (void **)&async_io_freelist, NULL );
+
+    while (io)
+    {
+        struct ws2_async_io *next = io->next;
+        HeapFree( GetProcessHeap(), 0, io );
+        io = next;
+    }
+
+    return HeapAlloc( GetProcessHeap(), 0, size );
+}
+
 /****************************************************************/
 
 /* ----------------------------------- internal data */
@@ -1904,7 +1932,7 @@ static void WINAPI ws2_async_apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserv
     if (wsa->completion_func) wsa->completion_func( NtStatusToWSAError(iosb->u.Status),
                                                     iosb->Information, wsa->user_overlapped,
                                                     wsa->flags );
-    HeapFree( GetProcessHeap(), 0, wsa );
+    release_async_io( &wsa->io );
 }
 
 /***********************************************************************
@@ -2022,20 +2050,14 @@ static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS stat
     {
         iosb->u.Status = status;
         iosb->Information = result;
-        *apc = ws2_async_apc;
+        if (wsa->completion_func)
+            *apc = ws2_async_apc;
+        else
+            release_async_io( &wsa->io );
     }
     return status;
 }
 
-/* user APC called upon async accept completion */
-static void WINAPI ws2_async_accept_apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
-{
-    struct ws2_accept_async *wsa = arg;
-
-    HeapFree( GetProcessHeap(), 0, wsa->read );
-    HeapFree( GetProcessHeap(), 0, wsa );
-}
-
 /***********************************************************************
  *              WS2_async_accept_recv            (INTERNAL)
  *
@@ -2056,7 +2078,7 @@ static NTSTATUS WS2_async_accept_recv( void *arg, IO_STATUS_BLOCK *iosb, NTSTATU
     if (wsa->cvalue)
         WS_AddCompletion( HANDLE2SOCKET(wsa->listen_socket), wsa->cvalue, iosb->u.Status, iosb->Information );
 
-    *apc = ws2_async_accept_apc;
+    release_async_io( &wsa->io );
     return status;
 }
 
@@ -2139,7 +2161,8 @@ finish:
     if (wsa->user_overlapped->hEvent)
         SetEvent(wsa->user_overlapped->hEvent);
 
-    *apc = ws2_async_accept_apc;
+    if (wsa->read) release_async_io( &wsa->read->io );
+    release_async_io( &wsa->io );
     return status;
 }
 
@@ -2261,7 +2284,10 @@ static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS statu
     if (status != STATUS_PENDING)
     {
         iosb->u.Status = status;
-        *apc = ws2_async_apc;
+        if (wsa->completion_func)
+            *apc = ws2_async_apc;
+        else
+            release_async_io( &wsa->io );
     }
     return status;
 }
@@ -2293,7 +2319,7 @@ static NTSTATUS WS2_async_shutdown( void* user, PIO_STATUS_BLOCK iosb, NTSTATUS
     }
     iosb->u.Status = status;
     iosb->Information = 0;
-    *apc = ws2_async_apc;
+    release_async_io( &wsa->io );
     return status;
 }
 
@@ -2309,7 +2335,7 @@ static int WS2_register_async_shutdown( SOCKET s, int type )
 
     TRACE("s %04lx type %d\n", s, type);
 
-    wsa = HeapAlloc( GetProcessHeap(), 0, sizeof(*wsa) );
+    wsa = (struct ws2_async_shutdown *)alloc_async_io( sizeof(*wsa) );
     if ( !wsa )
         return WSAEFAULT;
 
@@ -2436,7 +2462,7 @@ static BOOL WINAPI WS2_AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DW
     }
     release_sock_fd( acceptor, fd );
 
-    wsa = HeapAlloc( GetProcessHeap(), 0, sizeof(*wsa) );
+    wsa = (struct ws2_accept_async *)alloc_async_io( sizeof(*wsa) );
     if(!wsa)
     {
         SetLastError(WSAEFAULT);
@@ -2456,7 +2482,7 @@ static BOOL WINAPI WS2_AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DW
     if (wsa->data_len)
     {
         /* set up a read request if we need it */
-        wsa->read = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET(struct ws2_async, iovec[1]) );
+        wsa->read = (struct ws2_async *)alloc_async_io( offsetof(struct ws2_async, iovec[1]) );
         if (!wsa->read)
         {
             HeapFree( GetProcessHeap(), 0, wsa );
@@ -2472,6 +2498,7 @@ static BOOL WINAPI WS2_AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DW
         wsa->read->control     = NULL;
         wsa->read->n_iovecs    = 1;
         wsa->read->first_iovec = 0;
+        wsa->read->completion_func = NULL;
         wsa->read->iovec[0].iov_base = wsa->buf;
         wsa->read->iovec[0].iov_len  = wsa->data_len;
     }
@@ -2915,7 +2942,7 @@ static BOOL WINAPI WS2_ConnectEx(SOCKET s, const struct WS_sockaddr* name, int n
                       FD_WINE_CONNECTED|FD_WINE_LISTENING);
 
         /* Indirectly call WSASend */
-        if (!(wsa = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( struct ws2_async, iovec[1] ))))
+        if (!(wsa = (struct ws2_async *)alloc_async_io( offsetof( struct ws2_async, iovec[1] ))))
         {
             SetLastError(WSAEFAULT);
         }
@@ -3800,7 +3827,7 @@ static DWORD server_ioctl_sock( SOCKET s, DWORD code, LPVOID in_buff, DWORD in_s
     NTSTATUS status;
     PIO_STATUS_BLOCK io;
 
-    if (!(wsa = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*wsa) )))
+    if (!(wsa = (struct ws2_async *)alloc_async_io( sizeof(*wsa) )))
         return WSA_NOT_ENOUGH_MEMORY;
     wsa->hSocket           = handle;
     wsa->user_overlapped   = overlapped;
@@ -4651,7 +4678,7 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
         !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
     if (overlapped || dwBufferCount > 1)
     {
-        if (!(wsa = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET(struct ws2_async, iovec[dwBufferCount]) )))
+        if (!(wsa = (struct ws2_async *)alloc_async_io( offsetof(struct ws2_async, iovec[dwBufferCount]))))
         {
             err = WSAEFAULT;
             goto error;
@@ -6666,7 +6693,7 @@ static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
         !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
     if (overlapped || dwBufferCount > 1)
     {
-        if (!(wsa = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET(struct ws2_async, iovec[dwBufferCount]) )))
+        if (!(wsa = (struct ws2_async *)alloc_async_io( offsetof(struct ws2_async, iovec[dwBufferCount]))))
         {
             err = WSAEFAULT;
             goto error;




More information about the wine-cvs mailing list