From: Paul Gofman pgofman@codeweavers.com
--- dlls/ws2_32/socket.c | 61 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 6507f2e3c5b..009b4882564 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -157,6 +157,57 @@ DECLARE_CRITICAL_SECTION(cs_socket_list); static SOCKET *socket_list; static unsigned int socket_list_size;
+struct io_buf +{ + struct io_buf *next; + IO_STATUS_BLOCK io; +}; +static struct io_buf *io_freelist; + +static IO_STATUS_BLOCK *alloc_io(void) +{ + struct io_buf *io, *ret, *next; + + if (!(io = InterlockedExchangePointer( (void **)&io_freelist, NULL ))) + { + if (!(io = malloc(sizeof(*io)))) + { + ERR( "No memory.\n" ); + return NULL; + } + return &io->io; + } + + ret = io; + next = io->next; + if (next && InterlockedCompareExchangePointer( (void **)&io_freelist, next, NULL )) + { + while ((io = next)) + { + next = io->next; + free( io ); + } + } + return &ret->io; +} + +static void free_io(IO_STATUS_BLOCK *io_data) +{ + struct io_buf *io, *next; + + if (!io_data) return; + + io = CONTAINING_RECORD(io_data, struct io_buf, io); + + while (1) + { + next = io_freelist; + io->next = next; + if (InterlockedCompareExchangePointer( (void **)&io_freelist, io, next ) == next) + return; + } +} + const char *debugstr_sockaddr( const struct sockaddr *a ) { if (!a) return "(nil)"; @@ -2529,7 +2580,7 @@ int WINAPI select( int count, fd_set *read_ptr, fd_set *write_ptr, unsigned int poll_count = 0; ULONG params_size, i, j; SOCKET poll_socket = 0; - IO_STATUS_BLOCK io; + IO_STATUS_BLOCK *io; HANDLE sync_event; int ret_count = 0; NTSTATUS status; @@ -2605,7 +2656,8 @@ int WINAPI select( int count, fd_set *read_ptr, fd_set *write_ptr,
assert( params->count == poll_count );
- status = NtDeviceIoControlFile( (HANDLE)poll_socket, sync_event, NULL, NULL, &io, + io = alloc_io(); + status = NtDeviceIoControlFile( (HANDLE)poll_socket, sync_event, NULL, NULL, io, IOCTL_AFD_POLL, params, params_size, params, params_size ); if (status == STATUS_PENDING) { @@ -2613,10 +2665,13 @@ int WINAPI select( int count, fd_set *read_ptr, fd_set *write_ptr, { free( read_input ); free( params ); + free_io( io ); return -1; } - status = io.u.Status; + status = io->u.Status; } + free_io( io ); + if (status == STATUS_TIMEOUT) status = STATUS_SUCCESS; if (!status) {