Improve threading and i/o routines

- On Windows connect() can now be interrupted by a signal; connect() w/
  O_NONBLOCK will now raise EINPROGRESS; and connect() with SO_SNDTIMEO
  will raise ETIMEDOUT after the interval has elapsed.

- We now get the AcceptEx(), ConnectEx(), and TransmitFile() functions
  from the WIN32 API the officially blessed way, using WSAIoctl().

- Do nothing on Windows when fsync() is called on a directory handle.
  This was raising EACCES earlier becaues GENERIC_WRITE is required on
  the handle. It's possible to FlushFileBuffers() a directory handle if
  it's opened with write access but MSDN doesn't document what it does.
  If you have any idea, please let us know!

- Prefer manual reset event objects for read() and write() on Windows.

- Do some code cleanup on our dlmalloc customizations.

- Fix errno type error in Windows blocking routines.

- Make the futex polyfill simpler and faster.
This commit is contained in:
Justine Tunney 2023-10-12 18:53:17 -07:00
parent f7343319cc
commit 49b0eaa69f
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
43 changed files with 528 additions and 425 deletions

View file

@ -1,18 +0,0 @@
#include "libc/nt/codegen.h"
.imp MsWSock,__imp_AcceptEx,AcceptEx
.text.windows
.ftrace1
AcceptEx:
.ftrace2
#ifdef __x86_64__
push %rbp
mov %rsp,%rbp
mov __imp_AcceptEx(%rip),%rax
jmp __sysv2nt8
#elif defined(__aarch64__)
mov x0,#0
ret
#endif
.endfn AcceptEx,globl
.previous

View file

@ -1,18 +0,0 @@
#include "libc/nt/codegen.h"
.imp MsWSock,__imp_DisconnectEx,DisconnectEx
.text.windows
.ftrace1
DisconnectEx:
.ftrace2
#ifdef __x86_64__
push %rbp
mov %rsp,%rbp
mov __imp_DisconnectEx(%rip),%rax
jmp __sysv2nt
#elif defined(__aarch64__)
mov x0,#0
ret
#endif
.endfn DisconnectEx,globl
.previous

View file

@ -1,18 +0,0 @@
#include "libc/nt/codegen.h"
.imp MsWSock,__imp_GetAcceptExSockaddrs,GetAcceptExSockaddrs
.text.windows
.ftrace1
GetAcceptExSockaddrs:
.ftrace2
#ifdef __x86_64__
push %rbp
mov %rsp,%rbp
mov __imp_GetAcceptExSockaddrs(%rip),%rax
jmp __sysv2nt8
#elif defined(__aarch64__)
mov x0,#0
ret
#endif
.endfn GetAcceptExSockaddrs,globl
.previous

View file

@ -1,18 +0,0 @@
#include "libc/nt/codegen.h"
.imp MsWSock,__imp_TransmitFile,TransmitFile
.text.windows
.ftrace1
TransmitFile:
.ftrace2
#ifdef __x86_64__
push %rbp
mov %rsp,%rbp
mov __imp_TransmitFile(%rip),%rax
jmp __sysv2nt8
#elif defined(__aarch64__)
mov x0,#0
ret
#endif
.endfn TransmitFile,globl
.previous

View file

@ -1,18 +0,0 @@
#include "libc/nt/codegen.h"
.imp MsWSock,__imp_WSARecvEx,WSARecvEx
.text.windows
.ftrace1
WSARecvEx:
.ftrace2
#ifdef __x86_64__
push %rbp
mov %rsp,%rbp
mov __imp_WSARecvEx(%rip),%rax
jmp __sysv2nt
#elif defined(__aarch64__)
mov x0,#0
ret
#endif
.endfn WSARecvEx,globl
.previous

View file

@ -39,13 +39,13 @@ typedef void (*NtOverlappedCompletionRoutine)(
int64_t CreateIoCompletionPort(int64_t FileHandleOrNeg1,
int64_t opt_ExistingCompletionPortOrZero,
void *StatePointer,
uint64_t CompletionKey,
uint32_t NumberOfConcurrentThreads);
bool32 GetQueuedCompletionStatus(int64_t CompletionPort,
uint32_t *lpNumberOfBytesTransferred,
void *StatePointerPointer,
struct NtOverlapped **lpOverlapped,
uint64_t *out_lpCompletionKey,
struct NtOverlapped **out_lpOverlapped,
uint32_t dwMilliseconds);
bool32 GetQueuedCompletionStatusEx(
@ -56,7 +56,7 @@ bool32 GetQueuedCompletionStatusEx(
bool32 PostQueuedCompletionStatus(int64_t CompletionPort,
uint32_t dwNumberOfBytesTransferred,
uint32_t *dwCompletionKey,
uint64_t dwCompletionKey,
struct NtOverlapped *opt_lpOverlapped);
bool32 SetFileCompletionNotificationModes(int64_t FileHandle,

View file

@ -483,15 +483,6 @@ imp 'GetSaveFileName' GetSaveFileNameW comdlg32 1
imp 'PrintDlg' PrintDlgW comdlg32 1
imp 'ReplaceText' ReplaceTextW comdlg32 1
# MSWSOCK.DLL
#
# Name Actual DLL Arity
imp 'AcceptEx' AcceptEx MsWSock 8
imp 'DisconnectEx' DisconnectEx MsWSock 4
imp 'GetAcceptExSockaddrs' GetAcceptExSockaddrs MsWSock 8
imp 'TransmitFile' TransmitFile MsWSock 7
imp 'WSARecvEx' WSARecvEx MsWSock 4
# WS2_32.DLL
#
# Name Actual DLL Arity
@ -516,6 +507,7 @@ imp '' setsockopt ws2_32 5
imp '' shutdown ws2_32 2
imp '' socket ws2_32 3
imp '' socket ws2_32 3
imp '' socket ws2_32 3
imp 'FreeAddrInfo' FreeAddrInfoW ws2_32 1
imp 'FreeAddrInfoEx' FreeAddrInfoExW ws2_32 1
imp 'GetAddrInfo' GetAddrInfoW ws2_32 4

View file

@ -221,27 +221,6 @@ $(LIBC_NT_IPHLPAPI_A).pkg: \
#───────────────────────────────────────────────────────────────────────────────
LIBC_NT_ARTIFACTS += LIBC_NT_MSWSOCK_A
LIBC_NT_MSWSOCK = $(LIBC_NT_MSWSOCK_A_DEPS) $(LIBC_NT_MSWSOCK_A)
LIBC_NT_MSWSOCK_A = o/$(MODE)/libc/nt/MsWSock.a
LIBC_NT_MSWSOCK_A_SRCS := $(wildcard libc/nt/MsWSock/*.S)
LIBC_NT_MSWSOCK_A_OBJS = $(LIBC_NT_MSWSOCK_A_SRCS:%.S=o/$(MODE)/%.o)
LIBC_NT_MSWSOCK_A_CHECKS = $(LIBC_NT_MSWSOCK_A).pkg
LIBC_NT_MSWSOCK_A_DIRECTDEPS = LIBC_NT_KERNEL32
LIBC_NT_MSWSOCK_A_DEPS := \
$(call uniq,$(foreach x,$(LIBC_NT_MSWSOCK_A_DIRECTDEPS),$($(x))))
$(LIBC_NT_MSWSOCK_A): \
libc/nt/MsWSock/ \
$(LIBC_NT_MSWSOCK_A).pkg \
$(LIBC_NT_MSWSOCK_A_OBJS)
$(LIBC_NT_MSWSOCK_A).pkg: \
$(LIBC_NT_MSWSOCK_A_OBJS) \
$(foreach x,$(LIBC_NT_MSWSOCK_A_DIRECTDEPS),$($(x)_A).pkg)
#───────────────────────────────────────────────────────────────────────────────
LIBC_NT_ARTIFACTS += LIBC_NT_IPHLPAPI_A
LIBC_NT_IPHLPAPI = $(LIBC_NT_IPHLPAPI_A_DEPS) $(LIBC_NT_IPHLPAPI_A)
LIBC_NT_IPHLPAPI_A = o/$(MODE)/libc/nt/iphlpapi.a

View file

@ -5,7 +5,7 @@
COSMOPOLITAN_C_START_
struct NtOverlappedEntry {
uint32_t *lpCompletionKey;
uint64_t lpCompletionKey;
struct NtOverlapped *lpOverlapped;
uint32_t *Internal;
uint32_t dwNumberOfBytesTransferred;

View file

@ -297,6 +297,7 @@ int WSACleanup(void);
int WSAGetLastError(void) nosideeffect;
void WSASetLastError(int);
int64_t __sys_socket_nt(int, int, int);
int __sys_bind_nt(uint64_t, const void *, int);
int __sys_closesocket_nt(uint64_t);
int __sys_getpeername_nt(uint64_t, void *, uint32_t *);
@ -342,12 +343,6 @@ int64_t WSAAccept(uint64_t s, struct sockaddr *out_addr,
const NtConditionProc opt_lpfnCondition,
const uint32_t *opt_dwCallbackData) paramsnonnull((2)) __wur;
bool32 AcceptEx(int64_t sListenSocket, int64_t sAcceptSocket,
void *out_lpOutputBuffer /*[recvlen+local+remoteaddrlen]*/,
uint32_t dwReceiveDataLength, uint32_t dwLocalAddressLength,
uint32_t dwRemoteAddressLength, uint32_t *out_lpdwBytesReceived,
struct NtOverlapped *inout_lpOverlapped);
int WSASend(uint64_t s, const struct NtIovec *lpBuffers, uint32_t dwBufferCount,
uint32_t *opt_out_lpNumberOfBytesSent, uint32_t dwFlags,
struct NtOverlapped *opt_inout_lpOverlapped,
@ -494,19 +489,6 @@ int /* success==0 */ WSAGetServiceClassNameByClassId(
const struct NtGuid *lpServiceClassId, char16_t *out_lpszServiceClassName,
uint32_t *inout_lpdwBufferLength) paramsnonnull();
bool32 TransmitFile(int64_t hSocket, int64_t hFile,
uint32_t opt_nNumberOfBytesToWrite,
uint32_t opt_nNumberOfBytesPerSend,
struct NtOverlapped *opt_inout_lpOverlapped,
const struct NtTransmitFileBuffers *opt_lpTransmitBuffers,
uint32_t dwReserved);
bool32 AcceptEx(int64_t sListenSocket, int64_t sAcceptSocket,
void *out_lpOutputBuffer /*[recvlen+local+remoteaddrlen]*/,
uint32_t dwReceiveDataLength, uint32_t dwLocalAddressLength,
uint32_t dwRemoteAddressLength, uint32_t *out_lpdwBytesReceived,
struct NtOverlapped *inout_lpOverlapped);
void GetAcceptExSockaddrs(
const void *lpOutputBuffer /*[recvsize+addrsize+addrlen]*/,
uint32_t dwReceiveDataLength, uint32_t dwLocalAddressLength,