From a948d938b32efa8400ca3bd11f771376b99d138b Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sun, 7 Sep 2025 18:21:16 +0300 Subject: [PATCH] Correctly pack epoll_event to match POSIX --- wepoll.c | 2244 ++++++++++++++++++++++++++---------------------------- wepoll.h | 98 +-- 2 files changed, 1127 insertions(+), 1215 deletions(-) diff --git a/wepoll.c b/wepoll.c index e2c6a9c..9ccb3ea 100644 --- a/wepoll.c +++ b/wepoll.c @@ -28,120 +28,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if 1 #include "wepoll.h" -#else - -#ifndef WEPOLL_EXPORT -#define WEPOLL_EXPORT -#endif - -#include -#include - -enum EPOLL_EVENTS { - EPOLLIN = 0x0001, -#define EPOLLIN EPOLLIN - EPOLLPRI = 0x0002, -#define EPOLLPRI EPOLLPRI - EPOLLOUT = 0x0004, -#define EPOLLOUT EPOLLOUT - EPOLLERR = 0x0008, -#define EPOLLERR EPOLLERR - EPOLLHUP = 0x0010, -#define EPOLLHUP EPOLLHUP - EPOLLNVAL = 0x0020, -#define EPOLLNVAL EPOLLNVAL - EPOLLRDNORM = 0x0040, -#define EPOLLRDNORM EPOLLRDNORM - EPOLLRDBAND = 0x0080, -#define EPOLLRDBAND EPOLLRDBAND - EPOLLWRNORM = 0x0100, -#define EPOLLWRNORM EPOLLWRNORM - EPOLLWRBAND = 0x0200, -#define EPOLLWRBAND EPOLLWRBAND - EPOLLMSG = 0x0400, /* Never reported. */ -#define EPOLLMSG EPOLLMSG - EPOLLRDHUP = 0x2000, -#define EPOLLRDHUP EPOLLRDHUP - EPOLL_URING_WAKE = (unsigned)(1U << 27), -#define EPOLL_URING_WAKE EPOLL_URING_WAKE - EPOLLEXCLUSIVE = (unsigned)(1U << 28), -#define EPOLLEXCLUSIVE EPOLLEXCLUSIVE - EPOLLWAKEUP = (unsigned)(1U << 29), -#define EPOLLWAKEUP EPOLLWAKEUP - EPOLLONESHOT = (unsigned)(1U << 30), -#define EPOLLONESHOT EPOLLONESHOT - EPOLLET = (unsigned)(1U << 31) -#define EPOLLET EPOLLET -}; - -#define EPOLL_CTL_ADD 1 -#define EPOLL_CTL_DEL 2 -#define EPOLL_CTL_MOD 3 - -enum { - EPOLL_CLOEXEC = 02000000 /*O_CLOEXEC*/ -#define EPOLL_CLOEXEC EPOLL_CLOEXEC -}; - -typedef void* HANDLE; -typedef uintptr_t SOCKET; - -#define _SIGSET_NWORDS (1024 / (8 * sizeof (size_t))) -typedef struct -{ - size_t __val[_SIGSET_NWORDS]; -} sigset_t; - -typedef union epoll_data { - void* ptr; - int fd; - uint32_t u32; - uint64_t u64; - SOCKET sock; /* Windows specific */ - HANDLE hnd; /* Windows specific */ -} epoll_data_t; - -struct epoll_event { - uint32_t events; /* Epoll events and flags */ - epoll_data_t data; /* User data variable */ -}; - -#ifdef __cplusplus -extern "C" { -#endif - -WEPOLL_EXPORT HANDLE epoll_create(int size); -WEPOLL_EXPORT HANDLE epoll_create1(int flags); - -WEPOLL_EXPORT int epoll_close(HANDLE ephnd); - -WEPOLL_EXPORT int epoll_ctl(HANDLE ephnd, - int op, - SOCKET sock, - struct epoll_event* event); - -WEPOLL_EXPORT int epoll_wait(HANDLE ephnd, - struct epoll_event* events, - int maxevents, - int timeout); -WEPOLL_EXPORT int epoll_pwait(HANDLE ephnd, - struct epoll_event* events, - int maxevents, - int timeout, - const sigset_t* sigmask); -WEPOLL_EXPORT int epoll_pwait2(HANDLE ephnd, - struct epoll_event* events, - int maxevents, - const struct timespec* timeout, - const sigset_t* sigmask); - -#ifdef __cplusplus -} /* extern "C" */ -#endif -#endif - #include #include @@ -200,31 +87,31 @@ typedef NTSTATUS* PNTSTATUS; #endif typedef struct _IO_STATUS_BLOCK { - NTSTATUS Status; - ULONG_PTR Information; -} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + NTSTATUS Status; + ULONG_PTR Information; +} IO_STATUS_BLOCK, * PIO_STATUS_BLOCK; typedef VOID(NTAPI* PIO_APC_ROUTINE)(PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - ULONG Reserved); + PIO_STATUS_BLOCK IoStatusBlock, + ULONG Reserved); typedef struct _UNICODE_STRING { - USHORT Length; - USHORT MaximumLength; - PWSTR Buffer; -} UNICODE_STRING, *PUNICODE_STRING; + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, * PUNICODE_STRING; #define RTL_CONSTANT_STRING(s) \ { sizeof(s) - sizeof((s)[0]), sizeof(s), s } typedef struct _OBJECT_ATTRIBUTES { - ULONG Length; - HANDLE RootDirectory; - PUNICODE_STRING ObjectName; - ULONG Attributes; - PVOID SecurityDescriptor; - PVOID SecurityQualityOfService; -} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; #define RTL_CONSTANT_OBJECT_ATTRIBUTES(ObjectName, Attributes) \ { sizeof(OBJECT_ATTRIBUTES), NULL, ObjectName, Attributes, NULL, NULL } @@ -316,26 +203,26 @@ NT_NTDLL_IMPORT_LIST(X) #define AFD_POLL_CONNECT_FAIL 0x0100 typedef struct _AFD_POLL_HANDLE_INFO { - HANDLE Handle; - ULONG Events; - NTSTATUS Status; -} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO; + HANDLE Handle; + ULONG Events; + NTSTATUS Status; +} AFD_POLL_HANDLE_INFO, * PAFD_POLL_HANDLE_INFO; typedef struct _AFD_POLL_INFO { - LARGE_INTEGER Timeout; - ULONG NumberOfHandles; - ULONG Exclusive; - AFD_POLL_HANDLE_INFO Handles[1]; -} AFD_POLL_INFO, *PAFD_POLL_INFO; + LARGE_INTEGER Timeout; + ULONG NumberOfHandles; + ULONG Exclusive; + AFD_POLL_HANDLE_INFO Handles[1]; +} AFD_POLL_INFO, * PAFD_POLL_INFO; WEPOLL_INTERNAL int afd_create_device_handle(HANDLE iocp_handle, - HANDLE* afd_device_handle_out); + HANDLE* afd_device_handle_out); WEPOLL_INTERNAL int afd_poll(HANDLE afd_device_handle, - AFD_POLL_INFO* poll_info, - IO_STATUS_BLOCK* io_status_block); + AFD_POLL_INFO* poll_info, + IO_STATUS_BLOCK* io_status_block); WEPOLL_INTERNAL int afd_cancel_poll(HANDLE afd_device_handle, - IO_STATUS_BLOCK* io_status_block); + IO_STATUS_BLOCK* io_status_block); #define return_map_error(value) \ do { \ @@ -356,96 +243,96 @@ WEPOLL_INTERNAL int err_check_handle(HANDLE handle); #define IOCTL_AFD_POLL 0x00012024 static UNICODE_STRING afd__device_name = - RTL_CONSTANT_STRING(L"\\Device\\Afd\\Wepoll"); +RTL_CONSTANT_STRING(L"\\Device\\Afd\\Wepoll"); static OBJECT_ATTRIBUTES afd__device_attributes = - RTL_CONSTANT_OBJECT_ATTRIBUTES(&afd__device_name, 0); +RTL_CONSTANT_OBJECT_ATTRIBUTES(&afd__device_name, 0); int afd_create_device_handle(HANDLE iocp_handle, - HANDLE* afd_device_handle_out) { - HANDLE afd_device_handle; - IO_STATUS_BLOCK iosb; - NTSTATUS status; + HANDLE* afd_device_handle_out) { + HANDLE afd_device_handle; + IO_STATUS_BLOCK iosb; + NTSTATUS status; - /* By opening \Device\Afd without specifying any extended attributes, we'll - * get a handle that lets us talk to the AFD driver, but that doesn't have an - * associated endpoint (so it's not a socket). */ - status = NtCreateFile(&afd_device_handle, - SYNCHRONIZE, - &afd__device_attributes, - &iosb, - NULL, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN, - 0, - NULL, - 0); - if (status != STATUS_SUCCESS) - return_set_error(-1, RtlNtStatusToDosError(status)); + /* By opening \Device\Afd without specifying any extended attributes, we'll + * get a handle that lets us talk to the AFD driver, but that doesn't have an + * associated endpoint (so it's not a socket). */ + status = NtCreateFile(&afd_device_handle, + SYNCHRONIZE, + &afd__device_attributes, + &iosb, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + 0, + NULL, + 0); + if (status != STATUS_SUCCESS) + return_set_error(-1, RtlNtStatusToDosError(status)); - if (CreateIoCompletionPort(afd_device_handle, iocp_handle, 0, 0) == NULL) - goto error; + if (CreateIoCompletionPort(afd_device_handle, iocp_handle, 0, 0) == NULL) + goto error; - if (!SetFileCompletionNotificationModes(afd_device_handle, - FILE_SKIP_SET_EVENT_ON_HANDLE)) - goto error; + if (!SetFileCompletionNotificationModes(afd_device_handle, + FILE_SKIP_SET_EVENT_ON_HANDLE)) + goto error; - *afd_device_handle_out = afd_device_handle; - return 0; + *afd_device_handle_out = afd_device_handle; + return 0; error: - CloseHandle(afd_device_handle); - return_map_error(-1); + CloseHandle(afd_device_handle); + return_map_error(-1); } int afd_poll(HANDLE afd_device_handle, - AFD_POLL_INFO* poll_info, - IO_STATUS_BLOCK* io_status_block) { - NTSTATUS status; + AFD_POLL_INFO* poll_info, + IO_STATUS_BLOCK* io_status_block) { + NTSTATUS status; - /* Blocking operation is not supported. */ - assert(io_status_block != NULL); + /* Blocking operation is not supported. */ + assert(io_status_block != NULL); - io_status_block->Status = STATUS_PENDING; - status = NtDeviceIoControlFile(afd_device_handle, - NULL, - NULL, - io_status_block, - io_status_block, - IOCTL_AFD_POLL, - poll_info, - sizeof *poll_info, - poll_info, - sizeof *poll_info); + io_status_block->Status = STATUS_PENDING; + status = NtDeviceIoControlFile(afd_device_handle, + NULL, + NULL, + io_status_block, + io_status_block, + IOCTL_AFD_POLL, + poll_info, + sizeof * poll_info, + poll_info, + sizeof * poll_info); - if (status == STATUS_SUCCESS) - return 0; - else if (status == STATUS_PENDING) - return_set_error(-1, ERROR_IO_PENDING); - else - return_set_error(-1, RtlNtStatusToDosError(status)); + if (status == STATUS_SUCCESS) + return 0; + else if (status == STATUS_PENDING) + return_set_error(-1, ERROR_IO_PENDING); + else + return_set_error(-1, RtlNtStatusToDosError(status)); } int afd_cancel_poll(HANDLE afd_device_handle, - IO_STATUS_BLOCK* io_status_block) { - NTSTATUS cancel_status; - IO_STATUS_BLOCK cancel_iosb; + IO_STATUS_BLOCK* io_status_block) { + NTSTATUS cancel_status; + IO_STATUS_BLOCK cancel_iosb; - /* If the poll operation has already completed or has been cancelled earlier, - * there's nothing left for us to do. */ - if (io_status_block->Status != STATUS_PENDING) - return 0; + /* If the poll operation has already completed or has been cancelled earlier, + * there's nothing left for us to do. */ + if (io_status_block->Status != STATUS_PENDING) + return 0; - cancel_status = - NtCancelIoFileEx(afd_device_handle, io_status_block, &cancel_iosb); + cancel_status = + NtCancelIoFileEx(afd_device_handle, io_status_block, &cancel_iosb); - /* NtCancelIoFileEx() may return STATUS_NOT_FOUND if the operation completed - * just before calling NtCancelIoFileEx(). This is not an error. */ - if (cancel_status == STATUS_SUCCESS || cancel_status == STATUS_NOT_FOUND) - return 0; - else - return_set_error(-1, RtlNtStatusToDosError(cancel_status)); + /* NtCancelIoFileEx() may return STATUS_NOT_FOUND if the operation completed + * just before calling NtCancelIoFileEx(). This is not an error. */ + if (cancel_status == STATUS_SUCCESS || cancel_status == STATUS_NOT_FOUND) + return 0; + else + return_set_error(-1, RtlNtStatusToDosError(cancel_status)); } WEPOLL_INTERNAL int epoll_global_init(void); @@ -462,40 +349,40 @@ WEPOLL_INTERNAL int port_close(port_state_t* port_state); WEPOLL_INTERNAL int port_delete(port_state_t* port_state); WEPOLL_INTERNAL int port_wait(port_state_t* port_state, - struct epoll_event* events, - int maxevents, - int timeout); + struct epoll_event* events, + int maxevents, + int timeout); WEPOLL_INTERNAL int port_ctl(port_state_t* port_state, - int op, - SOCKET sock, - struct epoll_event* ev); + int op, + SOCKET sock, + struct epoll_event* ev); WEPOLL_INTERNAL int port_register_socket(port_state_t* port_state, - sock_state_t* sock_state, - SOCKET socket); + sock_state_t* sock_state, + SOCKET socket); WEPOLL_INTERNAL void port_unregister_socket(port_state_t* port_state, - sock_state_t* sock_state); + sock_state_t* sock_state); WEPOLL_INTERNAL sock_state_t* port_find_socket(port_state_t* port_state, - SOCKET socket); + SOCKET socket); WEPOLL_INTERNAL void port_request_socket_update(port_state_t* port_state, - sock_state_t* sock_state); + sock_state_t* sock_state); WEPOLL_INTERNAL void port_cancel_socket_update(port_state_t* port_state, - sock_state_t* sock_state); + sock_state_t* sock_state); WEPOLL_INTERNAL void port_add_deleted_socket(port_state_t* port_state, - sock_state_t* sock_state); + sock_state_t* sock_state); WEPOLL_INTERNAL void port_remove_deleted_socket(port_state_t* port_state, - sock_state_t* sock_state); + sock_state_t* sock_state); WEPOLL_INTERNAL HANDLE port_get_iocp_handle(port_state_t* port_state); WEPOLL_INTERNAL queue_t* port_get_poll_group_queue(port_state_t* port_state); WEPOLL_INTERNAL port_state_t* port_state_from_handle_tree_node( - ts_tree_node_t* tree_node); + ts_tree_node_t* tree_node); WEPOLL_INTERNAL ts_tree_node_t* port_state_to_handle_tree_node( - port_state_t* port_state); + port_state_t* port_state); /* The reflock is a special kind of lock that normally prevents a chunk of * memory from being freed, but does allow the chunk of memory to eventually be @@ -516,7 +403,7 @@ WEPOLL_INTERNAL ts_tree_node_t* port_state_to_handle_tree_node( */ typedef struct reflock { - volatile long state; /* 32-bit Interlocked APIs operate on `long` values. */ + volatile long state; /* 32-bit Interlocked APIs operate on `long` values. */ } reflock_t; WEPOLL_INTERNAL int reflock_global_init(void); @@ -536,15 +423,15 @@ typedef struct tree tree_t; typedef struct tree_node tree_node_t; typedef struct tree { - tree_node_t* root; + tree_node_t* root; } tree_t; typedef struct tree_node { - tree_node_t* left; - tree_node_t* right; - tree_node_t* parent; - uintptr_t key; - bool red; + tree_node_t* left; + tree_node_t* right; + tree_node_t* parent; + uintptr_t key; + bool red; } tree_node_t; WEPOLL_INTERNAL void tree_init(tree_t* tree); @@ -557,26 +444,26 @@ WEPOLL_INTERNAL tree_node_t* tree_find(const tree_t* tree, uintptr_t key); WEPOLL_INTERNAL tree_node_t* tree_root(const tree_t* tree); typedef struct ts_tree { - tree_t tree; - SRWLOCK lock; + tree_t tree; + SRWLOCK lock; } ts_tree_t; typedef struct ts_tree_node { - tree_node_t tree_node; - reflock_t reflock; + tree_node_t tree_node; + reflock_t reflock; } ts_tree_node_t; WEPOLL_INTERNAL void ts_tree_init(ts_tree_t* rtl); WEPOLL_INTERNAL void ts_tree_node_init(ts_tree_node_t* node); WEPOLL_INTERNAL int ts_tree_add(ts_tree_t* ts_tree, - ts_tree_node_t* node, - uintptr_t key); + ts_tree_node_t* node, + uintptr_t key); WEPOLL_INTERNAL ts_tree_node_t* ts_tree_del_and_ref(ts_tree_t* ts_tree, - uintptr_t key); + uintptr_t key); WEPOLL_INTERNAL ts_tree_node_t* ts_tree_find_and_ref(ts_tree_t* ts_tree, - uintptr_t key); + uintptr_t key); WEPOLL_INTERNAL void ts_tree_node_unref(ts_tree_node_t* node); WEPOLL_INTERNAL void ts_tree_node_unref_and_destroy(ts_tree_node_t* node); @@ -584,174 +471,174 @@ WEPOLL_INTERNAL void ts_tree_node_unref_and_destroy(ts_tree_node_t* node); static ts_tree_t epoll__handle_tree; int epoll_global_init(void) { - ts_tree_init(&epoll__handle_tree); - return 0; + ts_tree_init(&epoll__handle_tree); + return 0; } static HANDLE epoll__create(void) { - port_state_t* port_state; - HANDLE ephnd; - ts_tree_node_t* tree_node; + port_state_t* port_state; + HANDLE ephnd; + ts_tree_node_t* tree_node; - if (init() < 0) - return INVALID_HANDLE_VALUE; + if (init() < 0) + return INVALID_HANDLE_VALUE; - port_state = port_new(&ephnd); - if (port_state == NULL) - return INVALID_HANDLE_VALUE; + port_state = port_new(&ephnd); + if (port_state == NULL) + return INVALID_HANDLE_VALUE; - tree_node = port_state_to_handle_tree_node(port_state); - if (ts_tree_add(&epoll__handle_tree, tree_node, (uintptr_t) ephnd) < 0) { - /* This should never happen. */ - port_delete(port_state); - return_set_error(INVALID_HANDLE_VALUE, ERROR_ALREADY_EXISTS); - } + tree_node = port_state_to_handle_tree_node(port_state); + if (ts_tree_add(&epoll__handle_tree, tree_node, (uintptr_t)ephnd) < 0) { + /* This should never happen. */ + port_delete(port_state); + return_set_error(INVALID_HANDLE_VALUE, ERROR_ALREADY_EXISTS); + } - return ephnd; + return ephnd; } HANDLE epoll_create(int size) { - if (size <= 0) - return_set_error(INVALID_HANDLE_VALUE, ERROR_INVALID_PARAMETER); + if (size <= 0) + return_set_error(INVALID_HANDLE_VALUE, ERROR_INVALID_PARAMETER); - return epoll__create(); + return epoll__create(); } #include HANDLE epoll_create1(int flags) { - if (flags & ~EPOLL_CLOEXEC) - return_set_error(INVALID_HANDLE_VALUE, ERROR_INVALID_PARAMETER); + if (flags & ~EPOLL_CLOEXEC) + return_set_error(INVALID_HANDLE_VALUE, ERROR_INVALID_PARAMETER); - HANDLE ephnd = epoll__create(); - if (ephnd == INVALID_HANDLE_VALUE) { - return INVALID_HANDLE_VALUE; - } + HANDLE ephnd = epoll__create(); + if (ephnd == INVALID_HANDLE_VALUE) { + return INVALID_HANDLE_VALUE; + } - if (flags & EPOLL_CLOEXEC) { - if (!SetHandleInformation((HANDLE)ephnd, HANDLE_FLAG_INHERIT, 0)) { - DWORD error = GetLastError(); - epoll_close(ephnd); - err_set_win_error(error); - return INVALID_HANDLE_VALUE; - } - } + if (flags & EPOLL_CLOEXEC) { + if (!SetHandleInformation((HANDLE)ephnd, HANDLE_FLAG_INHERIT, 0)) { + DWORD error = GetLastError(); + epoll_close(ephnd); + err_set_win_error(error); + return INVALID_HANDLE_VALUE; + } + } - return ephnd; + return ephnd; } int epoll_close(HANDLE ephnd) { - ts_tree_node_t* tree_node; - port_state_t* port_state; + ts_tree_node_t* tree_node; + port_state_t* port_state; - if (init() < 0) - return -1; + if (init() < 0) + return -1; - tree_node = ts_tree_del_and_ref(&epoll__handle_tree, (uintptr_t) ephnd); - if (tree_node == NULL) { - err_set_win_error(ERROR_INVALID_PARAMETER); - goto err; - } + tree_node = ts_tree_del_and_ref(&epoll__handle_tree, (uintptr_t)ephnd); + if (tree_node == NULL) { + err_set_win_error(ERROR_INVALID_PARAMETER); + goto err; + } - port_state = port_state_from_handle_tree_node(tree_node); - port_close(port_state); + port_state = port_state_from_handle_tree_node(tree_node); + port_close(port_state); - ts_tree_node_unref_and_destroy(tree_node); + ts_tree_node_unref_and_destroy(tree_node); - return port_delete(port_state); + return port_delete(port_state); err: - err_check_handle(ephnd); - return -1; + err_check_handle(ephnd); + return -1; } int epoll_ctl(HANDLE ephnd, int op, SOCKET sock, struct epoll_event* ev) { - ts_tree_node_t* tree_node; - port_state_t* port_state; - int r; + ts_tree_node_t* tree_node; + port_state_t* port_state; + int r; - if (init() < 0) - return -1; + if (init() < 0) + return -1; - tree_node = ts_tree_find_and_ref(&epoll__handle_tree, (uintptr_t) ephnd); - if (tree_node == NULL) { - err_set_win_error(ERROR_INVALID_PARAMETER); - goto err; - } + tree_node = ts_tree_find_and_ref(&epoll__handle_tree, (uintptr_t)ephnd); + if (tree_node == NULL) { + err_set_win_error(ERROR_INVALID_PARAMETER); + goto err; + } - port_state = port_state_from_handle_tree_node(tree_node); - r = port_ctl(port_state, op, sock, ev); + port_state = port_state_from_handle_tree_node(tree_node); + r = port_ctl(port_state, op, sock, ev); - ts_tree_node_unref(tree_node); + ts_tree_node_unref(tree_node); - if (r < 0) - goto err; + if (r < 0) + goto err; - return 0; + return 0; err: - /* On Linux, in the case of epoll_ctl(), EBADF takes priority over other - * errors. Wepoll mimics this behavior. */ - err_check_handle(ephnd); - err_check_handle((HANDLE) sock); - return -1; + /* On Linux, in the case of epoll_ctl(), EBADF takes priority over other + * errors. Wepoll mimics this behavior. */ + err_check_handle(ephnd); + err_check_handle((HANDLE)sock); + return -1; } int epoll_wait(HANDLE ephnd, - struct epoll_event* events, - int maxevents, - int timeout) { - ts_tree_node_t* tree_node; - port_state_t* port_state; - int num_events; + struct epoll_event* events, + int maxevents, + int timeout) { + ts_tree_node_t* tree_node; + port_state_t* port_state; + int num_events; - if (maxevents <= 0) - return_set_error(-1, ERROR_INVALID_PARAMETER); + if (maxevents <= 0) + return_set_error(-1, ERROR_INVALID_PARAMETER); - if (init() < 0) - return -1; + if (init() < 0) + return -1; - tree_node = ts_tree_find_and_ref(&epoll__handle_tree, (uintptr_t) ephnd); - if (tree_node == NULL) { - err_set_win_error(ERROR_INVALID_PARAMETER); - goto err; - } + tree_node = ts_tree_find_and_ref(&epoll__handle_tree, (uintptr_t)ephnd); + if (tree_node == NULL) { + err_set_win_error(ERROR_INVALID_PARAMETER); + goto err; + } - port_state = port_state_from_handle_tree_node(tree_node); - num_events = port_wait(port_state, events, maxevents, timeout); + port_state = port_state_from_handle_tree_node(tree_node); + num_events = port_wait(port_state, events, maxevents, timeout); - ts_tree_node_unref(tree_node); + ts_tree_node_unref(tree_node); - if (num_events < 0) - goto err; + if (num_events < 0) + goto err; - return num_events; + return num_events; err: - err_check_handle(ephnd); - return -1; + err_check_handle(ephnd); + return -1; } int epoll_pwait(HANDLE ephnd, - struct epoll_event* events, - int maxevents, - int timeout, - const sigset_t* sigmask) { - (void)sigmask; - return epoll_wait(ephnd, events, maxevents, timeout); + struct epoll_event* events, + int maxevents, + int timeout, + const sigset_t* sigmask) { + (void)sigmask; + return epoll_wait(ephnd, events, maxevents, timeout); } int epoll_pwait2(HANDLE ephnd, - struct epoll_event* events, - int maxevents, - const struct timespec* timeout, - const sigset_t* sigmask) { - int timeout_ms = -1; - if (timeout != NULL) { - timeout_ms = (int)timeout->tv_sec * 1000; - timeout_ms += ((int)timeout->tv_nsec + 1000000 - 1) % 1000000; - } + struct epoll_event* events, + int maxevents, + const struct timespec* timeout, + const sigset_t* sigmask) { + int timeout_ms = -1; + if (timeout != NULL) { + timeout_ms = (int)timeout->tv_sec * 1000; + timeout_ms += ((int)timeout->tv_nsec + 1000000 - 1) % 1000000; + } - return epoll_pwait(ephnd, events, maxevents, timeout_ms, sigmask); + return epoll_pwait(ephnd, events, maxevents, timeout_ms, sigmask); } #include @@ -860,37 +747,37 @@ int epoll_pwait2(HANDLE ephnd, X(WSAVERNOTSUPPORTED, ENOSYS) static errno_t err__map_win_error_to_errno(DWORD error) { - switch (error) { + switch (error) { #define X(error_sym, errno_sym) \ case error_sym: \ return errno_sym; - ERR__ERRNO_MAPPINGS(X) + ERR__ERRNO_MAPPINGS(X) #undef X - } - return EINVAL; + } + return EINVAL; } void err_map_win_error(void) { - errno = err__map_win_error_to_errno(GetLastError()); + errno = err__map_win_error_to_errno(GetLastError()); } void err_set_win_error(DWORD error) { - SetLastError(error); - errno = err__map_win_error_to_errno(error); + SetLastError(error); + errno = err__map_win_error_to_errno(error); } int err_check_handle(HANDLE handle) { - DWORD flags; + DWORD flags; - /* GetHandleInformation() succeeds when passed INVALID_HANDLE_VALUE, so check - * for this condition explicitly. */ - if (handle == INVALID_HANDLE_VALUE) - return_set_error(-1, ERROR_INVALID_HANDLE); + /* GetHandleInformation() succeeds when passed INVALID_HANDLE_VALUE, so check + * for this condition explicitly. */ + if (handle == INVALID_HANDLE_VALUE) + return_set_error(-1, ERROR_INVALID_HANDLE); - if (!GetHandleInformation(handle, &flags)) - return_map_error(-1); + if (!GetHandleInformation(handle, &flags)) + return_map_error(-1); - return 0; + return 0; } #include @@ -914,31 +801,31 @@ static bool init__done = false; static INIT_ONCE init__once = INIT_ONCE_STATIC_INIT; static BOOL CALLBACK init__once_callback(INIT_ONCE* once, - void* parameter, - void** context) { - unused_var(once); - unused_var(parameter); - unused_var(context); + void* parameter, + void** context) { + unused_var(once); + unused_var(parameter); + unused_var(context); - /* N.b. that initialization order matters here. */ - if (ws_global_init() < 0 || nt_global_init() < 0 || - reflock_global_init() < 0 || epoll_global_init() < 0) - return FALSE; + /* N.b. that initialization order matters here. */ + if (ws_global_init() < 0 || nt_global_init() < 0 || + reflock_global_init() < 0 || epoll_global_init() < 0) + return FALSE; - init__done = true; - return TRUE; + init__done = true; + return TRUE; } int init(void) { - if (!init__done && - !InitOnceExecuteOnce(&init__once, init__once_callback, NULL, NULL)) - /* `InitOnceExecuteOnce()` itself is infallible, and it doesn't set any - * error code when the once-callback returns FALSE. We return -1 here to - * indicate that global initialization failed; the failing init function is - * resposible for setting `errno` and calling `SetLastError()`. */ - return -1; + if (!init__done && + !InitOnceExecuteOnce(&init__once, init__once_callback, NULL, NULL)) + /* `InitOnceExecuteOnce()` itself is infallible, and it doesn't set any + * error code when the once-callback returns FALSE. We return -1 here to + * indicate that global initialization failed; the failing init function is + * resposible for setting `errno` and calling `SetLastError()`. */ + return -1; - return 0; + return 0; } /* Set up a workaround for the following problem: @@ -959,22 +846,22 @@ NT_NTDLL_IMPORT_LIST(X) #undef X int nt_global_init(void) { - HMODULE ntdll; - FARPROC fn_ptr; + HMODULE ntdll; + FARPROC fn_ptr; - ntdll = GetModuleHandleW(L"ntdll.dll"); - if (ntdll == NULL) - return -1; + ntdll = GetModuleHandleW(L"ntdll.dll"); + if (ntdll == NULL) + return -1; #define X(return_type, attributes, name, parameters) \ fn_ptr = GetProcAddress(ntdll, #name); \ if (fn_ptr == NULL) \ return -1; \ name = (return_type(attributes*) parameters)(nt__fn_ptr_cast_t) fn_ptr; - NT_NTDLL_IMPORT_LIST(X) + NT_NTDLL_IMPORT_LIST(X) #undef X - return 0; + return 0; } #include @@ -989,17 +876,17 @@ WEPOLL_INTERNAL void poll_group_release(poll_group_t* poll_group); WEPOLL_INTERNAL void poll_group_delete(poll_group_t* poll_group); WEPOLL_INTERNAL poll_group_t* poll_group_from_queue_node( - queue_node_t* queue_node); + queue_node_t* queue_node); WEPOLL_INTERNAL HANDLE - poll_group_get_afd_device_handle(poll_group_t* poll_group); +poll_group_get_afd_device_handle(poll_group_t* poll_group); typedef struct queue_node { - queue_node_t* prev; - queue_node_t* next; + queue_node_t* prev; + queue_node_t* next; } queue_node_t; typedef struct queue { - queue_node_t head; + queue_node_t head; } queue_t; WEPOLL_INTERNAL void queue_init(queue_t* queue); @@ -1020,575 +907,578 @@ WEPOLL_INTERNAL bool queue_is_enqueued(const queue_node_t* node); #define POLL_GROUP__MAX_GROUP_SIZE 32 typedef struct poll_group { - port_state_t* port_state; - queue_node_t queue_node; - HANDLE afd_device_handle; - size_t group_size; + port_state_t* port_state; + queue_node_t queue_node; + HANDLE afd_device_handle; + size_t group_size; } poll_group_t; static poll_group_t* poll_group__new(port_state_t* port_state) { - HANDLE iocp_handle = port_get_iocp_handle(port_state); - queue_t* poll_group_queue = port_get_poll_group_queue(port_state); + HANDLE iocp_handle = port_get_iocp_handle(port_state); + queue_t* poll_group_queue = port_get_poll_group_queue(port_state); - poll_group_t* poll_group = malloc(sizeof *poll_group); - if (poll_group == NULL) - return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); + poll_group_t* poll_group = malloc(sizeof * poll_group); + if (poll_group == NULL) + return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); - memset(poll_group, 0, sizeof *poll_group); + memset(poll_group, 0, sizeof * poll_group); - queue_node_init(&poll_group->queue_node); - poll_group->port_state = port_state; + queue_node_init(&poll_group->queue_node); + poll_group->port_state = port_state; - if (afd_create_device_handle(iocp_handle, &poll_group->afd_device_handle) < - 0) { - free(poll_group); - return NULL; - } + if (afd_create_device_handle(iocp_handle, &poll_group->afd_device_handle) < + 0) { + free(poll_group); + return NULL; + } - queue_append(poll_group_queue, &poll_group->queue_node); + queue_append(poll_group_queue, &poll_group->queue_node); - return poll_group; + return poll_group; } void poll_group_delete(poll_group_t* poll_group) { - assert(poll_group->group_size == 0); - CloseHandle(poll_group->afd_device_handle); - queue_remove(&poll_group->queue_node); - free(poll_group); + assert(poll_group->group_size == 0); + CloseHandle(poll_group->afd_device_handle); + queue_remove(&poll_group->queue_node); + free(poll_group); } poll_group_t* poll_group_from_queue_node(queue_node_t* queue_node) { - return container_of(queue_node, poll_group_t, queue_node); + return container_of(queue_node, poll_group_t, queue_node); } HANDLE poll_group_get_afd_device_handle(poll_group_t* poll_group) { - return poll_group->afd_device_handle; + return poll_group->afd_device_handle; } poll_group_t* poll_group_acquire(port_state_t* port_state) { - queue_t* poll_group_queue = port_get_poll_group_queue(port_state); - poll_group_t* poll_group = - !queue_is_empty(poll_group_queue) - ? container_of( - queue_last(poll_group_queue), poll_group_t, queue_node) - : NULL; + queue_t* poll_group_queue = port_get_poll_group_queue(port_state); + poll_group_t* poll_group = + !queue_is_empty(poll_group_queue) + ? container_of( + queue_last(poll_group_queue), poll_group_t, queue_node) + : NULL; - if (poll_group == NULL || - poll_group->group_size >= POLL_GROUP__MAX_GROUP_SIZE) - poll_group = poll_group__new(port_state); - if (poll_group == NULL) - return NULL; + if (poll_group == NULL || + poll_group->group_size >= POLL_GROUP__MAX_GROUP_SIZE) + poll_group = poll_group__new(port_state); + if (poll_group == NULL) + return NULL; - if (++poll_group->group_size == POLL_GROUP__MAX_GROUP_SIZE) - queue_move_to_start(poll_group_queue, &poll_group->queue_node); + if (++poll_group->group_size == POLL_GROUP__MAX_GROUP_SIZE) + queue_move_to_start(poll_group_queue, &poll_group->queue_node); - return poll_group; + return poll_group; } void poll_group_release(poll_group_t* poll_group) { - port_state_t* port_state = poll_group->port_state; - queue_t* poll_group_queue = port_get_poll_group_queue(port_state); + port_state_t* port_state = poll_group->port_state; + queue_t* poll_group_queue = port_get_poll_group_queue(port_state); - poll_group->group_size--; - assert(poll_group->group_size < POLL_GROUP__MAX_GROUP_SIZE); + poll_group->group_size--; + assert(poll_group->group_size < POLL_GROUP__MAX_GROUP_SIZE); - queue_move_to_end(poll_group_queue, &poll_group->queue_node); + queue_move_to_end(poll_group_queue, &poll_group->queue_node); - /* Poll groups are currently only freed when the epoll port is closed. */ + /* Poll groups are currently only freed when the epoll port is closed. */ } WEPOLL_INTERNAL sock_state_t* sock_new(port_state_t* port_state, - SOCKET socket); + SOCKET socket); WEPOLL_INTERNAL void sock_delete(port_state_t* port_state, - sock_state_t* sock_state); + sock_state_t* sock_state); WEPOLL_INTERNAL void sock_force_delete(port_state_t* port_state, - sock_state_t* sock_state); + sock_state_t* sock_state); WEPOLL_INTERNAL int sock_set_event(port_state_t* port_state, - sock_state_t* sock_state, - const struct epoll_event* ev); + sock_state_t* sock_state, + const struct epoll_event* ev); WEPOLL_INTERNAL int sock_update(port_state_t* port_state, - sock_state_t* sock_state); + sock_state_t* sock_state); WEPOLL_INTERNAL int sock_feed_event(port_state_t* port_state, - IO_STATUS_BLOCK* io_status_block, - struct epoll_event* ev); + IO_STATUS_BLOCK* io_status_block, + struct epoll_event* ev); WEPOLL_INTERNAL sock_state_t* sock_state_from_queue_node( - queue_node_t* queue_node); + queue_node_t* queue_node); WEPOLL_INTERNAL queue_node_t* sock_state_to_queue_node( - sock_state_t* sock_state); + sock_state_t* sock_state); WEPOLL_INTERNAL sock_state_t* sock_state_from_tree_node( - tree_node_t* tree_node); + tree_node_t* tree_node); WEPOLL_INTERNAL tree_node_t* sock_state_to_tree_node(sock_state_t* sock_state); #define PORT__MAX_ON_STACK_COMPLETIONS 256 typedef struct port_state { - HANDLE iocp_handle; - tree_t sock_tree; - queue_t sock_update_queue; - queue_t sock_deleted_queue; - queue_t poll_group_queue; - ts_tree_node_t handle_tree_node; - CRITICAL_SECTION lock; - size_t active_poll_count; + HANDLE iocp_handle; + tree_t sock_tree; + queue_t sock_update_queue; + queue_t sock_deleted_queue; + queue_t poll_group_queue; + ts_tree_node_t handle_tree_node; + CRITICAL_SECTION lock; + size_t active_poll_count; } port_state_t; static inline port_state_t* port__alloc(void) { - port_state_t* port_state = malloc(sizeof *port_state); - if (port_state == NULL) - return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); + port_state_t* port_state = malloc(sizeof * port_state); + if (port_state == NULL) + return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); - return port_state; + return port_state; } static inline void port__free(port_state_t* port) { - assert(port != NULL); - free(port); + assert(port != NULL); + free(port); } static inline HANDLE port__create_iocp(void) { - HANDLE iocp_handle = - CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); - if (iocp_handle == NULL) - return_map_error(NULL); + HANDLE iocp_handle = + CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); + if (iocp_handle == NULL) + return_map_error(NULL); - return iocp_handle; + return iocp_handle; } port_state_t* port_new(HANDLE* iocp_handle_out) { - port_state_t* port_state; - HANDLE iocp_handle; + port_state_t* port_state; + HANDLE iocp_handle; - port_state = port__alloc(); - if (port_state == NULL) - goto err1; + port_state = port__alloc(); + if (port_state == NULL) + goto err1; - iocp_handle = port__create_iocp(); - if (iocp_handle == NULL) - goto err2; + iocp_handle = port__create_iocp(); + if (iocp_handle == NULL) + goto err2; - memset(port_state, 0, sizeof *port_state); + memset(port_state, 0, sizeof * port_state); - port_state->iocp_handle = iocp_handle; - tree_init(&port_state->sock_tree); - queue_init(&port_state->sock_update_queue); - queue_init(&port_state->sock_deleted_queue); - queue_init(&port_state->poll_group_queue); - ts_tree_node_init(&port_state->handle_tree_node); - InitializeCriticalSection(&port_state->lock); + port_state->iocp_handle = iocp_handle; + tree_init(&port_state->sock_tree); + queue_init(&port_state->sock_update_queue); + queue_init(&port_state->sock_deleted_queue); + queue_init(&port_state->poll_group_queue); + ts_tree_node_init(&port_state->handle_tree_node); + InitializeCriticalSection(&port_state->lock); - *iocp_handle_out = iocp_handle; - return port_state; + *iocp_handle_out = iocp_handle; + return port_state; err2: - port__free(port_state); + port__free(port_state); err1: - return NULL; + return NULL; } static inline int port__close_iocp(port_state_t* port_state) { - HANDLE iocp_handle = port_state->iocp_handle; - port_state->iocp_handle = NULL; + HANDLE iocp_handle = port_state->iocp_handle; + port_state->iocp_handle = NULL; - if (!CloseHandle(iocp_handle)) - return_map_error(-1); + if (!CloseHandle(iocp_handle)) + return_map_error(-1); - return 0; + return 0; } int port_close(port_state_t* port_state) { - int result; + int result; - EnterCriticalSection(&port_state->lock); - result = port__close_iocp(port_state); - LeaveCriticalSection(&port_state->lock); + EnterCriticalSection(&port_state->lock); + result = port__close_iocp(port_state); + LeaveCriticalSection(&port_state->lock); - return result; + return result; } int port_delete(port_state_t* port_state) { - tree_node_t* tree_node; - queue_node_t* queue_node; + tree_node_t* tree_node; + queue_node_t* queue_node; - /* At this point the IOCP port should have been closed. */ - assert(port_state->iocp_handle == NULL); + /* At this point the IOCP port should have been closed. */ + assert(port_state->iocp_handle == NULL); - while ((tree_node = tree_root(&port_state->sock_tree)) != NULL) { - sock_state_t* sock_state = sock_state_from_tree_node(tree_node); - sock_force_delete(port_state, sock_state); - } + while ((tree_node = tree_root(&port_state->sock_tree)) != NULL) { + sock_state_t* sock_state = sock_state_from_tree_node(tree_node); + sock_force_delete(port_state, sock_state); + } - while ((queue_node = queue_first(&port_state->sock_deleted_queue)) != NULL) { - sock_state_t* sock_state = sock_state_from_queue_node(queue_node); - sock_force_delete(port_state, sock_state); - } + while ((queue_node = queue_first(&port_state->sock_deleted_queue)) != NULL) { + sock_state_t* sock_state = sock_state_from_queue_node(queue_node); + sock_force_delete(port_state, sock_state); + } - while ((queue_node = queue_first(&port_state->poll_group_queue)) != NULL) { - poll_group_t* poll_group = poll_group_from_queue_node(queue_node); - poll_group_delete(poll_group); - } + while ((queue_node = queue_first(&port_state->poll_group_queue)) != NULL) { + poll_group_t* poll_group = poll_group_from_queue_node(queue_node); + poll_group_delete(poll_group); + } - assert(queue_is_empty(&port_state->sock_update_queue)); + assert(queue_is_empty(&port_state->sock_update_queue)); - DeleteCriticalSection(&port_state->lock); + DeleteCriticalSection(&port_state->lock); - port__free(port_state); + port__free(port_state); - return 0; + return 0; } static int port__update_events(port_state_t* port_state) { - queue_t* sock_update_queue = &port_state->sock_update_queue; + queue_t* sock_update_queue = &port_state->sock_update_queue; - /* Walk the queue, submitting new poll requests for every socket that needs - * it. */ - while (!queue_is_empty(sock_update_queue)) { - queue_node_t* queue_node = queue_first(sock_update_queue); - sock_state_t* sock_state = sock_state_from_queue_node(queue_node); + /* Walk the queue, submitting new poll requests for every socket that needs + * it. */ + while (!queue_is_empty(sock_update_queue)) { + queue_node_t* queue_node = queue_first(sock_update_queue); + sock_state_t* sock_state = sock_state_from_queue_node(queue_node); - if (sock_update(port_state, sock_state) < 0) - return -1; + if (sock_update(port_state, sock_state) < 0) + return -1; - /* sock_update() removes the socket from the update queue. */ - } + /* sock_update() removes the socket from the update queue. */ + } - return 0; + return 0; } static inline void port__update_events_if_polling(port_state_t* port_state) { - if (port_state->active_poll_count > 0) - port__update_events(port_state); + if (port_state->active_poll_count > 0) + port__update_events(port_state); } static inline int port__feed_events(port_state_t* port_state, - struct epoll_event* epoll_events, - OVERLAPPED_ENTRY* iocp_events, - DWORD iocp_event_count) { - int epoll_event_count = 0; - DWORD i; + struct epoll_event* epoll_events, + OVERLAPPED_ENTRY* iocp_events, + DWORD iocp_event_count) { + int epoll_event_count = 0; + DWORD i; - for (i = 0; i < iocp_event_count; i++) { - IO_STATUS_BLOCK* io_status_block = - (IO_STATUS_BLOCK*) iocp_events[i].lpOverlapped; - struct epoll_event* ev = &epoll_events[epoll_event_count]; + for (i = 0; i < iocp_event_count; i++) { + IO_STATUS_BLOCK* io_status_block = + (IO_STATUS_BLOCK*)iocp_events[i].lpOverlapped; + struct epoll_event* ev = &epoll_events[epoll_event_count]; - epoll_event_count += sock_feed_event(port_state, io_status_block, ev); - } + epoll_event_count += sock_feed_event(port_state, io_status_block, ev); + } - return epoll_event_count; + return epoll_event_count; } static inline int port__poll(port_state_t* port_state, - struct epoll_event* epoll_events, - OVERLAPPED_ENTRY* iocp_events, - DWORD maxevents, - DWORD timeout) { - DWORD completion_count; + struct epoll_event* epoll_events, + OVERLAPPED_ENTRY* iocp_events, + DWORD maxevents, + DWORD timeout) { + DWORD completion_count; - if (port__update_events(port_state) < 0) - return -1; + if (port__update_events(port_state) < 0) + return -1; - port_state->active_poll_count++; + port_state->active_poll_count++; - LeaveCriticalSection(&port_state->lock); + LeaveCriticalSection(&port_state->lock); - BOOL r = GetQueuedCompletionStatusEx(port_state->iocp_handle, - iocp_events, - maxevents, - &completion_count, - timeout, - FALSE); + BOOL r = GetQueuedCompletionStatusEx(port_state->iocp_handle, + iocp_events, + maxevents, + &completion_count, + timeout, + FALSE); - EnterCriticalSection(&port_state->lock); + EnterCriticalSection(&port_state->lock); - port_state->active_poll_count--; + port_state->active_poll_count--; - if (!r) - return_map_error(-1); + if (!r) + return_map_error(-1); - return port__feed_events( - port_state, epoll_events, iocp_events, completion_count); + return port__feed_events( + port_state, epoll_events, iocp_events, completion_count); } int port_wait(port_state_t* port_state, - struct epoll_event* events, - int maxevents, - int timeout) { - OVERLAPPED_ENTRY stack_iocp_events[PORT__MAX_ON_STACK_COMPLETIONS]; - OVERLAPPED_ENTRY* iocp_events; - uint64_t due = 0; - DWORD gqcs_timeout; - int result; + struct epoll_event* events, + int maxevents, + int timeout) { + OVERLAPPED_ENTRY stack_iocp_events[PORT__MAX_ON_STACK_COMPLETIONS]; + OVERLAPPED_ENTRY* iocp_events; + uint64_t due = 0; + DWORD gqcs_timeout; + int result; - /* Check whether `maxevents` is in range. */ - if (maxevents <= 0) - return_set_error(-1, ERROR_INVALID_PARAMETER); + /* Check whether `maxevents` is in range. */ + if (maxevents <= 0) + return_set_error(-1, ERROR_INVALID_PARAMETER); - /* Decide whether the IOCP completion list can live on the stack, or allocate - * memory for it on the heap. */ - if ((size_t) maxevents <= array_count(stack_iocp_events)) { - iocp_events = stack_iocp_events; - } else if ((iocp_events = - malloc((size_t) maxevents * sizeof *iocp_events)) == NULL) { - iocp_events = stack_iocp_events; - maxevents = array_count(stack_iocp_events); - } + /* Decide whether the IOCP completion list can live on the stack, or allocate + * memory for it on the heap. */ + if ((size_t)maxevents <= array_count(stack_iocp_events)) { + iocp_events = stack_iocp_events; + } + else if ((iocp_events = + malloc((size_t)maxevents * sizeof * iocp_events)) == NULL) { + iocp_events = stack_iocp_events; + maxevents = array_count(stack_iocp_events); + } - /* Compute the timeout for GetQueuedCompletionStatus, and the wait end - * time, if the user specified a timeout other than zero or infinite. */ - if (timeout > 0) { - due = GetTickCount64() + (uint64_t) timeout; - gqcs_timeout = (DWORD) timeout; - } else if (timeout == 0) { - gqcs_timeout = 0; - } else { - gqcs_timeout = INFINITE; - } + /* Compute the timeout for GetQueuedCompletionStatus, and the wait end + * time, if the user specified a timeout other than zero or infinite. */ + if (timeout > 0) { + due = GetTickCount64() + (uint64_t)timeout; + gqcs_timeout = (DWORD)timeout; + } + else if (timeout == 0) { + gqcs_timeout = 0; + } + else { + gqcs_timeout = INFINITE; + } - EnterCriticalSection(&port_state->lock); + EnterCriticalSection(&port_state->lock); - /* Dequeue completion packets until either at least one interesting event - * has been discovered, or the timeout is reached. */ - for (;;) { - uint64_t now; + /* Dequeue completion packets until either at least one interesting event + * has been discovered, or the timeout is reached. */ + for (;;) { + uint64_t now; - result = port__poll( - port_state, events, iocp_events, (DWORD) maxevents, gqcs_timeout); - if (result < 0 || result > 0) - break; /* Result, error, or time-out. */ + result = port__poll( + port_state, events, iocp_events, (DWORD)maxevents, gqcs_timeout); + if (result < 0 || result > 0) + break; /* Result, error, or time-out. */ - if (timeout < 0) - continue; /* When timeout is negative, never time out. */ + if (timeout < 0) + continue; /* When timeout is negative, never time out. */ - /* Update time. */ - now = GetTickCount64(); + /* Update time. */ + now = GetTickCount64(); - /* Do not allow the due time to be in the past. */ - if (now >= due) { - SetLastError(WAIT_TIMEOUT); - break; - } + /* Do not allow the due time to be in the past. */ + if (now >= due) { + SetLastError(WAIT_TIMEOUT); + break; + } - /* Recompute time-out argument for GetQueuedCompletionStatus. */ - gqcs_timeout = (DWORD)(due - now); - } + /* Recompute time-out argument for GetQueuedCompletionStatus. */ + gqcs_timeout = (DWORD)(due - now); + } - port__update_events_if_polling(port_state); + port__update_events_if_polling(port_state); - LeaveCriticalSection(&port_state->lock); + LeaveCriticalSection(&port_state->lock); - if (iocp_events != stack_iocp_events) - free(iocp_events); + if (iocp_events != stack_iocp_events) + free(iocp_events); - if (result >= 0) - return result; - else if (GetLastError() == WAIT_TIMEOUT) - return 0; - else - return -1; + if (result >= 0) + return result; + else if (GetLastError() == WAIT_TIMEOUT) + return 0; + else + return -1; } static inline int port__ctl_add(port_state_t* port_state, - SOCKET sock, - struct epoll_event* ev) { - sock_state_t* sock_state = sock_new(port_state, sock); - if (sock_state == NULL) - return -1; + SOCKET sock, + struct epoll_event* ev) { + sock_state_t* sock_state = sock_new(port_state, sock); + if (sock_state == NULL) + return -1; - if (sock_set_event(port_state, sock_state, ev) < 0) { - sock_delete(port_state, sock_state); - return -1; - } + if (sock_set_event(port_state, sock_state, ev) < 0) { + sock_delete(port_state, sock_state); + return -1; + } - port__update_events_if_polling(port_state); + port__update_events_if_polling(port_state); - return 0; + return 0; } static inline int port__ctl_mod(port_state_t* port_state, - SOCKET sock, - struct epoll_event* ev) { - sock_state_t* sock_state = port_find_socket(port_state, sock); - if (sock_state == NULL) - return -1; + SOCKET sock, + struct epoll_event* ev) { + sock_state_t* sock_state = port_find_socket(port_state, sock); + if (sock_state == NULL) + return -1; - if (sock_set_event(port_state, sock_state, ev) < 0) - return -1; + if (sock_set_event(port_state, sock_state, ev) < 0) + return -1; - port__update_events_if_polling(port_state); + port__update_events_if_polling(port_state); - return 0; + return 0; } static inline int port__ctl_del(port_state_t* port_state, SOCKET sock) { - sock_state_t* sock_state = port_find_socket(port_state, sock); - if (sock_state == NULL) - return -1; + sock_state_t* sock_state = port_find_socket(port_state, sock); + if (sock_state == NULL) + return -1; - sock_delete(port_state, sock_state); + sock_delete(port_state, sock_state); - return 0; + return 0; } static inline int port__ctl_op(port_state_t* port_state, - int op, - SOCKET sock, - struct epoll_event* ev) { - switch (op) { - case EPOLL_CTL_ADD: - return port__ctl_add(port_state, sock, ev); - case EPOLL_CTL_MOD: - return port__ctl_mod(port_state, sock, ev); - case EPOLL_CTL_DEL: - return port__ctl_del(port_state, sock); - default: - return_set_error(-1, ERROR_INVALID_PARAMETER); - } + int op, + SOCKET sock, + struct epoll_event* ev) { + switch (op) { + case EPOLL_CTL_ADD: + return port__ctl_add(port_state, sock, ev); + case EPOLL_CTL_MOD: + return port__ctl_mod(port_state, sock, ev); + case EPOLL_CTL_DEL: + return port__ctl_del(port_state, sock); + default: + return_set_error(-1, ERROR_INVALID_PARAMETER); + } } int port_ctl(port_state_t* port_state, - int op, - SOCKET sock, - struct epoll_event* ev) { - int result; + int op, + SOCKET sock, + struct epoll_event* ev) { + int result; - EnterCriticalSection(&port_state->lock); - result = port__ctl_op(port_state, op, sock, ev); - LeaveCriticalSection(&port_state->lock); + EnterCriticalSection(&port_state->lock); + result = port__ctl_op(port_state, op, sock, ev); + LeaveCriticalSection(&port_state->lock); - return result; + return result; } int port_register_socket(port_state_t* port_state, - sock_state_t* sock_state, - SOCKET socket) { - if (tree_add(&port_state->sock_tree, - sock_state_to_tree_node(sock_state), - socket) < 0) - return_set_error(-1, ERROR_ALREADY_EXISTS); - return 0; + sock_state_t* sock_state, + SOCKET socket) { + if (tree_add(&port_state->sock_tree, + sock_state_to_tree_node(sock_state), + socket) < 0) + return_set_error(-1, ERROR_ALREADY_EXISTS); + return 0; } void port_unregister_socket(port_state_t* port_state, - sock_state_t* sock_state) { - tree_del(&port_state->sock_tree, sock_state_to_tree_node(sock_state)); + sock_state_t* sock_state) { + tree_del(&port_state->sock_tree, sock_state_to_tree_node(sock_state)); } sock_state_t* port_find_socket(port_state_t* port_state, SOCKET socket) { - tree_node_t* tree_node = tree_find(&port_state->sock_tree, socket); - if (tree_node == NULL) - return_set_error(NULL, ERROR_NOT_FOUND); - return sock_state_from_tree_node(tree_node); + tree_node_t* tree_node = tree_find(&port_state->sock_tree, socket); + if (tree_node == NULL) + return_set_error(NULL, ERROR_NOT_FOUND); + return sock_state_from_tree_node(tree_node); } void port_request_socket_update(port_state_t* port_state, - sock_state_t* sock_state) { - if (queue_is_enqueued(sock_state_to_queue_node(sock_state))) - return; - queue_append(&port_state->sock_update_queue, - sock_state_to_queue_node(sock_state)); + sock_state_t* sock_state) { + if (queue_is_enqueued(sock_state_to_queue_node(sock_state))) + return; + queue_append(&port_state->sock_update_queue, + sock_state_to_queue_node(sock_state)); } void port_cancel_socket_update(port_state_t* port_state, - sock_state_t* sock_state) { - unused_var(port_state); - if (!queue_is_enqueued(sock_state_to_queue_node(sock_state))) - return; - queue_remove(sock_state_to_queue_node(sock_state)); + sock_state_t* sock_state) { + unused_var(port_state); + if (!queue_is_enqueued(sock_state_to_queue_node(sock_state))) + return; + queue_remove(sock_state_to_queue_node(sock_state)); } void port_add_deleted_socket(port_state_t* port_state, - sock_state_t* sock_state) { - if (queue_is_enqueued(sock_state_to_queue_node(sock_state))) - return; - queue_append(&port_state->sock_deleted_queue, - sock_state_to_queue_node(sock_state)); + sock_state_t* sock_state) { + if (queue_is_enqueued(sock_state_to_queue_node(sock_state))) + return; + queue_append(&port_state->sock_deleted_queue, + sock_state_to_queue_node(sock_state)); } void port_remove_deleted_socket(port_state_t* port_state, - sock_state_t* sock_state) { - unused_var(port_state); - if (!queue_is_enqueued(sock_state_to_queue_node(sock_state))) - return; - queue_remove(sock_state_to_queue_node(sock_state)); + sock_state_t* sock_state) { + unused_var(port_state); + if (!queue_is_enqueued(sock_state_to_queue_node(sock_state))) + return; + queue_remove(sock_state_to_queue_node(sock_state)); } HANDLE port_get_iocp_handle(port_state_t* port_state) { - assert(port_state->iocp_handle != NULL); - return port_state->iocp_handle; + assert(port_state->iocp_handle != NULL); + return port_state->iocp_handle; } queue_t* port_get_poll_group_queue(port_state_t* port_state) { - return &port_state->poll_group_queue; + return &port_state->poll_group_queue; } port_state_t* port_state_from_handle_tree_node(ts_tree_node_t* tree_node) { - return container_of(tree_node, port_state_t, handle_tree_node); + return container_of(tree_node, port_state_t, handle_tree_node); } ts_tree_node_t* port_state_to_handle_tree_node(port_state_t* port_state) { - return &port_state->handle_tree_node; + return &port_state->handle_tree_node; } void queue_init(queue_t* queue) { - queue_node_init(&queue->head); + queue_node_init(&queue->head); } void queue_node_init(queue_node_t* node) { - node->prev = node; - node->next = node; + node->prev = node; + node->next = node; } static inline void queue__detach_node(queue_node_t* node) { - node->prev->next = node->next; - node->next->prev = node->prev; + node->prev->next = node->next; + node->next->prev = node->prev; } queue_node_t* queue_first(const queue_t* queue) { - return !queue_is_empty(queue) ? queue->head.next : NULL; + return !queue_is_empty(queue) ? queue->head.next : NULL; } queue_node_t* queue_last(const queue_t* queue) { - return !queue_is_empty(queue) ? queue->head.prev : NULL; + return !queue_is_empty(queue) ? queue->head.prev : NULL; } void queue_prepend(queue_t* queue, queue_node_t* node) { - node->next = queue->head.next; - node->prev = &queue->head; - node->next->prev = node; - queue->head.next = node; + node->next = queue->head.next; + node->prev = &queue->head; + node->next->prev = node; + queue->head.next = node; } void queue_append(queue_t* queue, queue_node_t* node) { - node->next = &queue->head; - node->prev = queue->head.prev; - node->prev->next = node; - queue->head.prev = node; + node->next = &queue->head; + node->prev = queue->head.prev; + node->prev->next = node; + queue->head.prev = node; } void queue_move_to_start(queue_t* queue, queue_node_t* node) { - queue__detach_node(node); - queue_prepend(queue, node); + queue__detach_node(node); + queue_prepend(queue, node); } void queue_move_to_end(queue_t* queue, queue_node_t* node) { - queue__detach_node(node); - queue_append(queue, node); + queue__detach_node(node); + queue_append(queue, node); } void queue_remove(queue_node_t* node) { - queue__detach_node(node); - queue_node_init(node); + queue__detach_node(node); + queue_node_init(node); } bool queue_is_empty(const queue_t* queue) { - return !queue_is_enqueued(&queue->head); + return !queue_is_enqueued(&queue->head); } bool queue_is_enqueued(const queue_node_t* node) { - return node->prev != node; + return node->prev != node; } #define REFLOCK__REF ((long) 0x00000001UL) @@ -1600,62 +1490,62 @@ bool queue_is_enqueued(const queue_node_t* node) { static HANDLE reflock__keyed_event = NULL; int reflock_global_init(void) { - NTSTATUS status = NtCreateKeyedEvent( - &reflock__keyed_event, KEYEDEVENT_ALL_ACCESS, NULL, 0); - if (status != STATUS_SUCCESS) - return_set_error(-1, RtlNtStatusToDosError(status)); - return 0; + NTSTATUS status = NtCreateKeyedEvent( + &reflock__keyed_event, KEYEDEVENT_ALL_ACCESS, NULL, 0); + if (status != STATUS_SUCCESS) + return_set_error(-1, RtlNtStatusToDosError(status)); + return 0; } void reflock_init(reflock_t* reflock) { - reflock->state = 0; + reflock->state = 0; } static void reflock__signal_event(void* address) { - NTSTATUS status = - NtReleaseKeyedEvent(reflock__keyed_event, address, FALSE, NULL); - if (status != STATUS_SUCCESS) - abort(); + NTSTATUS status = + NtReleaseKeyedEvent(reflock__keyed_event, address, FALSE, NULL); + if (status != STATUS_SUCCESS) + abort(); } static void reflock__await_event(void* address) { - NTSTATUS status = - NtWaitForKeyedEvent(reflock__keyed_event, address, FALSE, NULL); - if (status != STATUS_SUCCESS) - abort(); + NTSTATUS status = + NtWaitForKeyedEvent(reflock__keyed_event, address, FALSE, NULL); + if (status != STATUS_SUCCESS) + abort(); } void reflock_ref(reflock_t* reflock) { - long state = InterlockedAdd(&reflock->state, REFLOCK__REF); + long state = InterlockedAdd(&reflock->state, REFLOCK__REF); - /* Verify that the counter didn't overflow and the lock isn't destroyed. */ - assert((state & REFLOCK__DESTROY_MASK) == 0); - unused_var(state); + /* Verify that the counter didn't overflow and the lock isn't destroyed. */ + assert((state & REFLOCK__DESTROY_MASK) == 0); + unused_var(state); } void reflock_unref(reflock_t* reflock) { - long state = InterlockedAdd(&reflock->state, -REFLOCK__REF); + long state = InterlockedAdd(&reflock->state, -REFLOCK__REF); - /* Verify that the lock was referenced and not already destroyed. */ - assert((state & REFLOCK__DESTROY_MASK & ~REFLOCK__DESTROY) == 0); + /* Verify that the lock was referenced and not already destroyed. */ + assert((state & REFLOCK__DESTROY_MASK & ~REFLOCK__DESTROY) == 0); - if (state == REFLOCK__DESTROY) - reflock__signal_event(reflock); + if (state == REFLOCK__DESTROY) + reflock__signal_event(reflock); } void reflock_unref_and_destroy(reflock_t* reflock) { - long state = - InterlockedAdd(&reflock->state, REFLOCK__DESTROY - REFLOCK__REF); - long ref_count = state & REFLOCK__REF_MASK; + long state = + InterlockedAdd(&reflock->state, REFLOCK__DESTROY - REFLOCK__REF); + long ref_count = state & REFLOCK__REF_MASK; - /* Verify that the lock was referenced and not already destroyed. */ - assert((state & REFLOCK__DESTROY_MASK) == REFLOCK__DESTROY); + /* Verify that the lock was referenced and not already destroyed. */ + assert((state & REFLOCK__DESTROY_MASK) == REFLOCK__DESTROY); - if (ref_count != 0) - reflock__await_event(reflock); + if (ref_count != 0) + reflock__await_event(reflock); - state = InterlockedExchange(&reflock->state, REFLOCK__POISON); - assert(state == REFLOCK__DESTROY); + state = InterlockedExchange(&reflock->state, REFLOCK__POISON); + assert(state == REFLOCK__DESTROY); } #define SOCK__KNOWN_EPOLL_EVENTS \ @@ -1663,392 +1553,402 @@ void reflock_unref_and_destroy(reflock_t* reflock) { EPOLLRDBAND | EPOLLWRNORM | EPOLLWRBAND | EPOLLMSG | EPOLLRDHUP) typedef enum sock__poll_status { - SOCK__POLL_IDLE = 0, - SOCK__POLL_PENDING, - SOCK__POLL_CANCELLED + SOCK__POLL_IDLE = 0, + SOCK__POLL_PENDING, + SOCK__POLL_CANCELLED } sock__poll_status_t; typedef struct sock_state { - IO_STATUS_BLOCK io_status_block; - AFD_POLL_INFO poll_info; - queue_node_t queue_node; - tree_node_t tree_node; - poll_group_t* poll_group; - SOCKET base_socket; - epoll_data_t user_data; - uint32_t user_events; - uint32_t pending_events; - sock__poll_status_t poll_status; - bool delete_pending; + IO_STATUS_BLOCK io_status_block; + AFD_POLL_INFO poll_info; + queue_node_t queue_node; + tree_node_t tree_node; + poll_group_t* poll_group; + SOCKET base_socket; + epoll_data_t user_data; + uint32_t user_events; + uint32_t pending_events; + sock__poll_status_t poll_status; + bool delete_pending; } sock_state_t; static inline sock_state_t* sock__alloc(void) { - sock_state_t* sock_state = malloc(sizeof *sock_state); - if (sock_state == NULL) - return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); - return sock_state; + sock_state_t* sock_state = malloc(sizeof * sock_state); + if (sock_state == NULL) + return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); + return sock_state; } static inline void sock__free(sock_state_t* sock_state) { - assert(sock_state != NULL); - free(sock_state); + assert(sock_state != NULL); + free(sock_state); } static inline int sock__cancel_poll(sock_state_t* sock_state) { - assert(sock_state->poll_status == SOCK__POLL_PENDING); + assert(sock_state->poll_status == SOCK__POLL_PENDING); - if (afd_cancel_poll(poll_group_get_afd_device_handle(sock_state->poll_group), - &sock_state->io_status_block) < 0) - return -1; + if (afd_cancel_poll(poll_group_get_afd_device_handle(sock_state->poll_group), + &sock_state->io_status_block) < 0) + return -1; - sock_state->poll_status = SOCK__POLL_CANCELLED; - sock_state->pending_events = 0; - return 0; + sock_state->poll_status = SOCK__POLL_CANCELLED; + sock_state->pending_events = 0; + return 0; } sock_state_t* sock_new(port_state_t* port_state, SOCKET socket) { - SOCKET base_socket; - poll_group_t* poll_group; - sock_state_t* sock_state; + SOCKET base_socket; + poll_group_t* poll_group; + sock_state_t* sock_state; - if (socket == 0 || socket == INVALID_SOCKET) - return_set_error(NULL, ERROR_INVALID_HANDLE); + if (socket == 0 || socket == INVALID_SOCKET) + return_set_error(NULL, ERROR_INVALID_HANDLE); - base_socket = ws_get_base_socket(socket); - if (base_socket == INVALID_SOCKET) - return NULL; + base_socket = ws_get_base_socket(socket); + if (base_socket == INVALID_SOCKET) + return NULL; - poll_group = poll_group_acquire(port_state); - if (poll_group == NULL) - return NULL; + poll_group = poll_group_acquire(port_state); + if (poll_group == NULL) + return NULL; - sock_state = sock__alloc(); - if (sock_state == NULL) - goto err1; + sock_state = sock__alloc(); + if (sock_state == NULL) + goto err1; - memset(sock_state, 0, sizeof *sock_state); + memset(sock_state, 0, sizeof * sock_state); - sock_state->base_socket = base_socket; - sock_state->poll_group = poll_group; + sock_state->base_socket = base_socket; + sock_state->poll_group = poll_group; - tree_node_init(&sock_state->tree_node); - queue_node_init(&sock_state->queue_node); + tree_node_init(&sock_state->tree_node); + queue_node_init(&sock_state->queue_node); - if (port_register_socket(port_state, sock_state, socket) < 0) - goto err2; + if (port_register_socket(port_state, sock_state, socket) < 0) + goto err2; - return sock_state; + return sock_state; err2: - sock__free(sock_state); + sock__free(sock_state); err1: - poll_group_release(poll_group); + poll_group_release(poll_group); - return NULL; + return NULL; } static int sock__delete(port_state_t* port_state, - sock_state_t* sock_state, - bool force) { - if (!sock_state->delete_pending) { - if (sock_state->poll_status == SOCK__POLL_PENDING) - sock__cancel_poll(sock_state); + sock_state_t* sock_state, + bool force) { + if (!sock_state->delete_pending) { + if (sock_state->poll_status == SOCK__POLL_PENDING) + sock__cancel_poll(sock_state); - port_cancel_socket_update(port_state, sock_state); - port_unregister_socket(port_state, sock_state); + port_cancel_socket_update(port_state, sock_state); + port_unregister_socket(port_state, sock_state); - sock_state->delete_pending = true; - } + sock_state->delete_pending = true; + } - /* If the poll request still needs to complete, the sock_state object can't - * be free()d yet. `sock_feed_event()` or `port_close()` will take care - * of this later. */ - if (force || sock_state->poll_status == SOCK__POLL_IDLE) { - /* Free the sock_state now. */ - port_remove_deleted_socket(port_state, sock_state); - poll_group_release(sock_state->poll_group); - sock__free(sock_state); - } else { - /* Free the socket later. */ - port_add_deleted_socket(port_state, sock_state); - } + /* If the poll request still needs to complete, the sock_state object can't + * be free()d yet. `sock_feed_event()` or `port_close()` will take care + * of this later. */ + if (force || sock_state->poll_status == SOCK__POLL_IDLE) { + /* Free the sock_state now. */ + port_remove_deleted_socket(port_state, sock_state); + poll_group_release(sock_state->poll_group); + sock__free(sock_state); + } + else { + /* Free the socket later. */ + port_add_deleted_socket(port_state, sock_state); + } - return 0; + return 0; } void sock_delete(port_state_t* port_state, sock_state_t* sock_state) { - sock__delete(port_state, sock_state, false); + sock__delete(port_state, sock_state, false); } void sock_force_delete(port_state_t* port_state, sock_state_t* sock_state) { - sock__delete(port_state, sock_state, true); + sock__delete(port_state, sock_state, true); } int sock_set_event(port_state_t* port_state, - sock_state_t* sock_state, - const struct epoll_event* ev) { - /* EPOLLERR and EPOLLHUP are always reported, even when not requested by the - * caller. However they are disabled after a event has been reported for a - * socket for which the EPOLLONESHOT flag was set. */ - uint32_t events = ev->events | EPOLLERR | EPOLLHUP; + sock_state_t* sock_state, + const struct epoll_event* ev) { + /* EPOLLERR and EPOLLHUP are always reported, even when not requested by the + * caller. However they are disabled after a event has been reported for a + * socket for which the EPOLLONESHOT flag was set. */ + uint32_t events = ev->events | EPOLLERR | EPOLLHUP; - sock_state->user_events = events; - sock_state->user_data = ev->data; + sock_state->user_events = events; + sock_state->user_data = ev->data; - if ((events & SOCK__KNOWN_EPOLL_EVENTS & ~sock_state->pending_events) != 0) - port_request_socket_update(port_state, sock_state); + if ((events & SOCK__KNOWN_EPOLL_EVENTS & ~sock_state->pending_events) != 0) + port_request_socket_update(port_state, sock_state); - return 0; + return 0; } static inline DWORD sock__epoll_events_to_afd_events(uint32_t epoll_events) { - /* Always monitor for AFD_POLL_LOCAL_CLOSE, which is triggered when the - * socket is closed with closesocket() or CloseHandle(). */ - DWORD afd_events = AFD_POLL_LOCAL_CLOSE; + /* Always monitor for AFD_POLL_LOCAL_CLOSE, which is triggered when the + * socket is closed with closesocket() or CloseHandle(). */ + DWORD afd_events = AFD_POLL_LOCAL_CLOSE; - if (epoll_events & (EPOLLIN | EPOLLRDNORM)) - afd_events |= AFD_POLL_RECEIVE | AFD_POLL_ACCEPT; - if (epoll_events & (EPOLLPRI | EPOLLRDBAND)) - afd_events |= AFD_POLL_RECEIVE_EXPEDITED; - if (epoll_events & (EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND)) - afd_events |= AFD_POLL_SEND; - if (epoll_events & (EPOLLIN | EPOLLRDNORM | EPOLLRDHUP)) - afd_events |= AFD_POLL_DISCONNECT; - if (epoll_events & EPOLLHUP) - afd_events |= AFD_POLL_ABORT; - if (epoll_events & EPOLLERR) - afd_events |= AFD_POLL_CONNECT_FAIL; + if (epoll_events & (EPOLLIN | EPOLLRDNORM)) + afd_events |= AFD_POLL_RECEIVE | AFD_POLL_ACCEPT; + if (epoll_events & (EPOLLPRI | EPOLLRDBAND)) + afd_events |= AFD_POLL_RECEIVE_EXPEDITED; + if (epoll_events & (EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND)) + afd_events |= AFD_POLL_SEND; + if (epoll_events & (EPOLLIN | EPOLLRDNORM | EPOLLRDHUP)) + afd_events |= AFD_POLL_DISCONNECT; + if (epoll_events & EPOLLHUP) + afd_events |= AFD_POLL_ABORT; + if (epoll_events & EPOLLERR) + afd_events |= AFD_POLL_CONNECT_FAIL; - return afd_events; + return afd_events; } static inline uint32_t sock__afd_events_to_epoll_events(DWORD afd_events) { - uint32_t epoll_events = 0; + uint32_t epoll_events = 0; - if (afd_events & (AFD_POLL_RECEIVE | AFD_POLL_ACCEPT)) - epoll_events |= EPOLLIN | EPOLLRDNORM; - if (afd_events & AFD_POLL_RECEIVE_EXPEDITED) - epoll_events |= EPOLLPRI | EPOLLRDBAND; - if (afd_events & AFD_POLL_SEND) - epoll_events |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND; - if (afd_events & AFD_POLL_DISCONNECT) - epoll_events |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP; - if (afd_events & AFD_POLL_ABORT) - epoll_events |= EPOLLHUP; - if (afd_events & AFD_POLL_CONNECT_FAIL) - /* Linux reports all these events after connect() has failed. */ - epoll_events |= - EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLRDNORM | EPOLLWRNORM | EPOLLRDHUP; + if (afd_events & (AFD_POLL_RECEIVE | AFD_POLL_ACCEPT)) + epoll_events |= EPOLLIN | EPOLLRDNORM; + if (afd_events & AFD_POLL_RECEIVE_EXPEDITED) + epoll_events |= EPOLLPRI | EPOLLRDBAND; + if (afd_events & AFD_POLL_SEND) + epoll_events |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND; + if (afd_events & AFD_POLL_DISCONNECT) + epoll_events |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP; + if (afd_events & AFD_POLL_ABORT) + epoll_events |= EPOLLHUP; + if (afd_events & AFD_POLL_CONNECT_FAIL) + /* Linux reports all these events after connect() has failed. */ + epoll_events |= + EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLRDNORM | EPOLLWRNORM | EPOLLRDHUP; - return epoll_events; + return epoll_events; } int sock_update(port_state_t* port_state, sock_state_t* sock_state) { - assert(!sock_state->delete_pending); + assert(!sock_state->delete_pending); - if ((sock_state->poll_status == SOCK__POLL_PENDING) && - (sock_state->user_events & SOCK__KNOWN_EPOLL_EVENTS & - ~sock_state->pending_events) == 0) { - /* All the events the user is interested in are already being monitored by - * the pending poll operation. It might spuriously complete because of an - * event that we're no longer interested in; when that happens we'll submit - * a new poll operation with the updated event mask. */ + if ((sock_state->poll_status == SOCK__POLL_PENDING) && + (sock_state->user_events & SOCK__KNOWN_EPOLL_EVENTS & + ~sock_state->pending_events) == 0) { + /* All the events the user is interested in are already being monitored by + * the pending poll operation. It might spuriously complete because of an + * event that we're no longer interested in; when that happens we'll submit + * a new poll operation with the updated event mask. */ - } else if (sock_state->poll_status == SOCK__POLL_PENDING) { - /* A poll operation is already pending, but it's not monitoring for all the - * events that the user is interested in. Therefore, cancel the pending - * poll operation; when we receive it's completion package, a new poll - * operation will be submitted with the correct event mask. */ - if (sock__cancel_poll(sock_state) < 0) - return -1; + } + else if (sock_state->poll_status == SOCK__POLL_PENDING) { + /* A poll operation is already pending, but it's not monitoring for all the + * events that the user is interested in. Therefore, cancel the pending + * poll operation; when we receive it's completion package, a new poll + * operation will be submitted with the correct event mask. */ + if (sock__cancel_poll(sock_state) < 0) + return -1; - } else if (sock_state->poll_status == SOCK__POLL_CANCELLED) { - /* The poll operation has already been cancelled, we're still waiting for - * it to return. For now, there's nothing that needs to be done. */ + } + else if (sock_state->poll_status == SOCK__POLL_CANCELLED) { + /* The poll operation has already been cancelled, we're still waiting for + * it to return. For now, there's nothing that needs to be done. */ - } else if (sock_state->poll_status == SOCK__POLL_IDLE) { - /* No poll operation is pending; start one. */ - sock_state->poll_info.Exclusive = FALSE; - sock_state->poll_info.NumberOfHandles = 1; - sock_state->poll_info.Timeout.QuadPart = INT64_MAX; - sock_state->poll_info.Handles[0].Handle = (HANDLE) sock_state->base_socket; - sock_state->poll_info.Handles[0].Status = 0; - sock_state->poll_info.Handles[0].Events = - sock__epoll_events_to_afd_events(sock_state->user_events); + } + else if (sock_state->poll_status == SOCK__POLL_IDLE) { + /* No poll operation is pending; start one. */ + sock_state->poll_info.Exclusive = FALSE; + sock_state->poll_info.NumberOfHandles = 1; + sock_state->poll_info.Timeout.QuadPart = INT64_MAX; + sock_state->poll_info.Handles[0].Handle = (HANDLE)sock_state->base_socket; + sock_state->poll_info.Handles[0].Status = 0; + sock_state->poll_info.Handles[0].Events = + sock__epoll_events_to_afd_events(sock_state->user_events); - if (afd_poll(poll_group_get_afd_device_handle(sock_state->poll_group), - &sock_state->poll_info, - &sock_state->io_status_block) < 0) { - switch (GetLastError()) { - case ERROR_IO_PENDING: - /* Overlapped poll operation in progress; this is expected. */ - break; - case ERROR_INVALID_HANDLE: - /* Socket closed; it'll be dropped from the epoll set. */ - return sock__delete(port_state, sock_state, false); - default: - /* Other errors are propagated to the caller. */ - return_map_error(-1); - } - } + if (afd_poll(poll_group_get_afd_device_handle(sock_state->poll_group), + &sock_state->poll_info, + &sock_state->io_status_block) < 0) { + switch (GetLastError()) { + case ERROR_IO_PENDING: + /* Overlapped poll operation in progress; this is expected. */ + break; + case ERROR_INVALID_HANDLE: + /* Socket closed; it'll be dropped from the epoll set. */ + return sock__delete(port_state, sock_state, false); + default: + /* Other errors are propagated to the caller. */ + return_map_error(-1); + } + } - /* The poll request was successfully submitted. */ - sock_state->poll_status = SOCK__POLL_PENDING; - sock_state->pending_events = sock_state->user_events; + /* The poll request was successfully submitted. */ + sock_state->poll_status = SOCK__POLL_PENDING; + sock_state->pending_events = sock_state->user_events; - } else { - /* Unreachable. */ - assert(false); - } + } + else { + /* Unreachable. */ + assert(false); + } - port_cancel_socket_update(port_state, sock_state); - return 0; + port_cancel_socket_update(port_state, sock_state); + return 0; } int sock_feed_event(port_state_t* port_state, - IO_STATUS_BLOCK* io_status_block, - struct epoll_event* ev) { - sock_state_t* sock_state = - container_of(io_status_block, sock_state_t, io_status_block); - AFD_POLL_INFO* poll_info = &sock_state->poll_info; - uint32_t epoll_events = 0; + IO_STATUS_BLOCK* io_status_block, + struct epoll_event* ev) { + sock_state_t* sock_state = + container_of(io_status_block, sock_state_t, io_status_block); + AFD_POLL_INFO* poll_info = &sock_state->poll_info; + uint32_t epoll_events = 0; - sock_state->poll_status = SOCK__POLL_IDLE; - sock_state->pending_events = 0; + sock_state->poll_status = SOCK__POLL_IDLE; + sock_state->pending_events = 0; - if (sock_state->delete_pending) { - /* Socket has been deleted earlier and can now be freed. */ - return sock__delete(port_state, sock_state, false); + if (sock_state->delete_pending) { + /* Socket has been deleted earlier and can now be freed. */ + return sock__delete(port_state, sock_state, false); - } else if (io_status_block->Status == STATUS_CANCELLED) { - /* The poll request was cancelled by CancelIoEx. */ + } + else if (io_status_block->Status == STATUS_CANCELLED) { + /* The poll request was cancelled by CancelIoEx. */ - } else if (!NT_SUCCESS(io_status_block->Status)) { - /* The overlapped request itself failed in an unexpected way. */ - epoll_events = EPOLLERR; + } + else if (!NT_SUCCESS(io_status_block->Status)) { + /* The overlapped request itself failed in an unexpected way. */ + epoll_events = EPOLLERR; - } else if (poll_info->NumberOfHandles < 1) { - /* This poll operation succeeded but didn't report any socket events. */ + } + else if (poll_info->NumberOfHandles < 1) { + /* This poll operation succeeded but didn't report any socket events. */ - } else if (poll_info->Handles[0].Events & AFD_POLL_LOCAL_CLOSE) { - /* The poll operation reported that the socket was closed. */ - return sock__delete(port_state, sock_state, false); + } + else if (poll_info->Handles[0].Events & AFD_POLL_LOCAL_CLOSE) { + /* The poll operation reported that the socket was closed. */ + return sock__delete(port_state, sock_state, false); - } else { - /* Events related to our socket were reported. */ - epoll_events = - sock__afd_events_to_epoll_events(poll_info->Handles[0].Events); - } + } + else { + /* Events related to our socket were reported. */ + epoll_events = + sock__afd_events_to_epoll_events(poll_info->Handles[0].Events); + } - /* Requeue the socket so a new poll request will be submitted. */ - port_request_socket_update(port_state, sock_state); + /* Requeue the socket so a new poll request will be submitted. */ + port_request_socket_update(port_state, sock_state); - /* Filter out events that the user didn't ask for. */ - epoll_events &= sock_state->user_events; + /* Filter out events that the user didn't ask for. */ + epoll_events &= sock_state->user_events; - /* Return if there are no epoll events to report. */ - if (epoll_events == 0) - return 0; + /* Return if there are no epoll events to report. */ + if (epoll_events == 0) + return 0; - /* If the the socket has the EPOLLONESHOT flag set, unmonitor all events, - * even EPOLLERR and EPOLLHUP. But always keep looking for closed sockets. */ - if (sock_state->user_events & EPOLLONESHOT) - sock_state->user_events = 0; + /* If the the socket has the EPOLLONESHOT flag set, unmonitor all events, + * even EPOLLERR and EPOLLHUP. But always keep looking for closed sockets. */ + if (sock_state->user_events & EPOLLONESHOT) + sock_state->user_events = 0; - ev->data = sock_state->user_data; - ev->events = epoll_events; - return 1; + ev->data = sock_state->user_data; + ev->events = epoll_events; + return 1; } sock_state_t* sock_state_from_queue_node(queue_node_t* queue_node) { - return container_of(queue_node, sock_state_t, queue_node); + return container_of(queue_node, sock_state_t, queue_node); } queue_node_t* sock_state_to_queue_node(sock_state_t* sock_state) { - return &sock_state->queue_node; + return &sock_state->queue_node; } sock_state_t* sock_state_from_tree_node(tree_node_t* tree_node) { - return container_of(tree_node, sock_state_t, tree_node); + return container_of(tree_node, sock_state_t, tree_node); } tree_node_t* sock_state_to_tree_node(sock_state_t* sock_state) { - return &sock_state->tree_node; + return &sock_state->tree_node; } void ts_tree_init(ts_tree_t* ts_tree) { - tree_init(&ts_tree->tree); - InitializeSRWLock(&ts_tree->lock); + tree_init(&ts_tree->tree); + InitializeSRWLock(&ts_tree->lock); } void ts_tree_node_init(ts_tree_node_t* node) { - tree_node_init(&node->tree_node); - reflock_init(&node->reflock); + tree_node_init(&node->tree_node); + reflock_init(&node->reflock); } int ts_tree_add(ts_tree_t* ts_tree, ts_tree_node_t* node, uintptr_t key) { - int r; + int r; - AcquireSRWLockExclusive(&ts_tree->lock); - r = tree_add(&ts_tree->tree, &node->tree_node, key); - ReleaseSRWLockExclusive(&ts_tree->lock); + AcquireSRWLockExclusive(&ts_tree->lock); + r = tree_add(&ts_tree->tree, &node->tree_node, key); + ReleaseSRWLockExclusive(&ts_tree->lock); - return r; + return r; } static inline ts_tree_node_t* ts_tree__find_node(ts_tree_t* ts_tree, - uintptr_t key) { - tree_node_t* tree_node = tree_find(&ts_tree->tree, key); - if (tree_node == NULL) - return NULL; + uintptr_t key) { + tree_node_t* tree_node = tree_find(&ts_tree->tree, key); + if (tree_node == NULL) + return NULL; - return container_of(tree_node, ts_tree_node_t, tree_node); + return container_of(tree_node, ts_tree_node_t, tree_node); } ts_tree_node_t* ts_tree_del_and_ref(ts_tree_t* ts_tree, uintptr_t key) { - ts_tree_node_t* ts_tree_node; + ts_tree_node_t* ts_tree_node; - AcquireSRWLockExclusive(&ts_tree->lock); + AcquireSRWLockExclusive(&ts_tree->lock); - ts_tree_node = ts_tree__find_node(ts_tree, key); - if (ts_tree_node != NULL) { - tree_del(&ts_tree->tree, &ts_tree_node->tree_node); - reflock_ref(&ts_tree_node->reflock); - } + ts_tree_node = ts_tree__find_node(ts_tree, key); + if (ts_tree_node != NULL) { + tree_del(&ts_tree->tree, &ts_tree_node->tree_node); + reflock_ref(&ts_tree_node->reflock); + } - ReleaseSRWLockExclusive(&ts_tree->lock); + ReleaseSRWLockExclusive(&ts_tree->lock); - return ts_tree_node; + return ts_tree_node; } ts_tree_node_t* ts_tree_find_and_ref(ts_tree_t* ts_tree, uintptr_t key) { - ts_tree_node_t* ts_tree_node; + ts_tree_node_t* ts_tree_node; - AcquireSRWLockShared(&ts_tree->lock); + AcquireSRWLockShared(&ts_tree->lock); - ts_tree_node = ts_tree__find_node(ts_tree, key); - if (ts_tree_node != NULL) - reflock_ref(&ts_tree_node->reflock); + ts_tree_node = ts_tree__find_node(ts_tree, key); + if (ts_tree_node != NULL) + reflock_ref(&ts_tree_node->reflock); - ReleaseSRWLockShared(&ts_tree->lock); + ReleaseSRWLockShared(&ts_tree->lock); - return ts_tree_node; + return ts_tree_node; } void ts_tree_node_unref(ts_tree_node_t* node) { - reflock_unref(&node->reflock); + reflock_unref(&node->reflock); } void ts_tree_node_unref_and_destroy(ts_tree_node_t* node) { - reflock_unref_and_destroy(&node->reflock); + reflock_unref_and_destroy(&node->reflock); } void tree_init(tree_t* tree) { - memset(tree, 0, sizeof *tree); + memset(tree, 0, sizeof * tree); } void tree_node_init(tree_node_t* node) { - memset(node, 0, sizeof *node); + memset(node, 0, sizeof * node); } #define TREE__ROTATE(cis, trans) \ @@ -2073,11 +1973,11 @@ void tree_node_init(tree_node_t* node) { q->cis = p; static inline void tree__rotate_left(tree_t* tree, tree_node_t* node) { - TREE__ROTATE(left, right) + TREE__ROTATE(left, right) } static inline void tree__rotate_right(tree_t* tree, tree_node_t* node) { - TREE__ROTATE(right, left) + TREE__ROTATE(right, left) } #define TREE__INSERT_OR_DESCEND(side) \ @@ -2108,38 +2008,42 @@ static inline void tree__rotate_right(tree_t* tree, tree_node_t* node) { } int tree_add(tree_t* tree, tree_node_t* node, uintptr_t key) { - tree_node_t* parent; + tree_node_t* parent; - parent = tree->root; - if (parent) { - for (;;) { - if (key < parent->key) { - TREE__INSERT_OR_DESCEND(left) - } else if (key > parent->key) { - TREE__INSERT_OR_DESCEND(right) - } else { - return -1; - } - } - } else { - tree->root = node; - } + parent = tree->root; + if (parent) { + for (;;) { + if (key < parent->key) { + TREE__INSERT_OR_DESCEND(left) + } + else if (key > parent->key) { + TREE__INSERT_OR_DESCEND(right) + } + else { + return -1; + } + } + } + else { + tree->root = node; + } - node->key = key; - node->left = node->right = NULL; - node->parent = parent; - node->red = true; + node->key = key; + node->left = node->right = NULL; + node->parent = parent; + node->red = true; - for (; parent && parent->red; parent = node->parent) { - if (parent == parent->parent->left) { - TREE__REBALANCE_AFTER_INSERT(left, right) - } else { - TREE__REBALANCE_AFTER_INSERT(right, left) - } - } - tree->root->red = false; + for (; parent && parent->red; parent = node->parent) { + if (parent == parent->parent->left) { + TREE__REBALANCE_AFTER_INSERT(left, right) + } + else { + TREE__REBALANCE_AFTER_INSERT(right, left) + } + } + tree->root->red = false; - return 0; + return 0; } #define TREE__REBALANCE_AFTER_REMOVE(cis, trans) \ @@ -2168,93 +2072,99 @@ int tree_add(tree_t* tree, tree_node_t* node, uintptr_t key) { sibling->red = true; void tree_del(tree_t* tree, tree_node_t* node) { - tree_node_t* parent = node->parent; - tree_node_t* left = node->left; - tree_node_t* right = node->right; - tree_node_t* next; - bool red; + tree_node_t* parent = node->parent; + tree_node_t* left = node->left; + tree_node_t* right = node->right; + tree_node_t* next; + bool red; - if (!left) { - next = right; - } else if (!right) { - next = left; - } else { - next = right; - while (next->left) - next = next->left; - } + if (!left) { + next = right; + } + else if (!right) { + next = left; + } + else { + next = right; + while (next->left) + next = next->left; + } - if (parent) { - if (parent->left == node) - parent->left = next; - else - parent->right = next; - } else { - tree->root = next; - } + if (parent) { + if (parent->left == node) + parent->left = next; + else + parent->right = next; + } + else { + tree->root = next; + } - if (left && right) { - red = next->red; - next->red = node->red; - next->left = left; - left->parent = next; - if (next != right) { - parent = next->parent; - next->parent = node->parent; - node = next->right; - parent->left = node; - next->right = right; - right->parent = next; - } else { - next->parent = parent; - parent = next; - node = next->right; - } - } else { - red = node->red; - node = next; - } + if (left && right) { + red = next->red; + next->red = node->red; + next->left = left; + left->parent = next; + if (next != right) { + parent = next->parent; + next->parent = node->parent; + node = next->right; + parent->left = node; + next->right = right; + right->parent = next; + } + else { + next->parent = parent; + parent = next; + node = next->right; + } + } + else { + red = node->red; + node = next; + } - if (node) - node->parent = parent; - if (red) - return; - if (node && node->red) { - node->red = false; - return; - } + if (node) + node->parent = parent; + if (red) + return; + if (node && node->red) { + node->red = false; + return; + } - do { - if (node == tree->root) - break; - if (node == parent->left) { - TREE__REBALANCE_AFTER_REMOVE(left, right) - } else { - TREE__REBALANCE_AFTER_REMOVE(right, left) - } - node = parent; - parent = parent->parent; - } while (!node->red); + do { + if (node == tree->root) + break; + if (node == parent->left) { + TREE__REBALANCE_AFTER_REMOVE(left, right) + } + else { + TREE__REBALANCE_AFTER_REMOVE(right, left) + } + node = parent; + parent = parent->parent; + } while (!node->red); - if (node) - node->red = false; + if (node) + node->red = false; } tree_node_t* tree_find(const tree_t* tree, uintptr_t key) { - tree_node_t* node = tree->root; - while (node) { - if (key < node->key) - node = node->left; - else if (key > node->key) - node = node->right; - else - return node; - } - return NULL; + tree_node_t* node = tree->root; + while (node) { + if (key < node->key) + node = node->left; + else if (key > node->key) + node = node->right; + else + return node; + } + return NULL; } tree_node_t* tree_root(const tree_t* tree) { - return tree->root; + return tree->root; } #ifndef SIO_BSP_HANDLE_POLL @@ -2266,62 +2176,62 @@ tree_node_t* tree_root(const tree_t* tree) { #endif int ws_global_init(void) { - int r; - WSADATA wsa_data; + int r; + WSADATA wsa_data; - r = WSAStartup(MAKEWORD(2, 2), &wsa_data); - if (r != 0) - return_set_error(-1, (DWORD) r); + r = WSAStartup(MAKEWORD(2, 2), &wsa_data); + if (r != 0) + return_set_error(-1, (DWORD)r); - return 0; + return 0; } static inline SOCKET ws__ioctl_get_bsp_socket(SOCKET socket, DWORD ioctl) { - SOCKET bsp_socket; - DWORD bytes; + SOCKET bsp_socket; + DWORD bytes; - if (WSAIoctl(socket, - ioctl, - NULL, - 0, - &bsp_socket, - sizeof bsp_socket, - &bytes, - NULL, - NULL) != SOCKET_ERROR) - return bsp_socket; - else - return INVALID_SOCKET; + if (WSAIoctl(socket, + ioctl, + NULL, + 0, + &bsp_socket, + sizeof bsp_socket, + &bytes, + NULL, + NULL) != SOCKET_ERROR) + return bsp_socket; + else + return INVALID_SOCKET; } SOCKET ws_get_base_socket(SOCKET socket) { - SOCKET base_socket; - DWORD error; + SOCKET base_socket; + DWORD error; - for (;;) { - base_socket = ws__ioctl_get_bsp_socket(socket, SIO_BASE_HANDLE); - if (base_socket != INVALID_SOCKET) - return base_socket; + for (;;) { + base_socket = ws__ioctl_get_bsp_socket(socket, SIO_BASE_HANDLE); + if (base_socket != INVALID_SOCKET) + return base_socket; - error = GetLastError(); - if (error == WSAENOTSOCK) - return_set_error(INVALID_SOCKET, error); + error = GetLastError(); + if (error == WSAENOTSOCK) + return_set_error(INVALID_SOCKET, error); - /* Even though Microsoft documentation clearly states that LSPs should - * never intercept the `SIO_BASE_HANDLE` ioctl [1], Komodia based LSPs do - * so anyway, breaking it, with the apparent intention of preventing LSP - * bypass [2]. Fortunately they don't handle `SIO_BSP_HANDLE_POLL`, which - * will at least let us obtain the socket associated with the next winsock - * protocol chain entry. If this succeeds, loop around and call - * `SIO_BASE_HANDLE` again with the returned BSP socket, to make sure that - * we unwrap all layers and retrieve the actual base socket. - * [1] https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls - * [2] https://www.komodia.com/newwiki/index.php?title=Komodia%27s_Redirector_bug_fixes#Version_2.2.2.6 - */ - base_socket = ws__ioctl_get_bsp_socket(socket, SIO_BSP_HANDLE_POLL); - if (base_socket != INVALID_SOCKET && base_socket != socket) - socket = base_socket; - else - return_set_error(INVALID_SOCKET, error); - } + /* Even though Microsoft documentation clearly states that LSPs should + * never intercept the `SIO_BASE_HANDLE` ioctl [1], Komodia based LSPs do + * so anyway, breaking it, with the apparent intention of preventing LSP + * bypass [2]. Fortunately they don't handle `SIO_BSP_HANDLE_POLL`, which + * will at least let us obtain the socket associated with the next winsock + * protocol chain entry. If this succeeds, loop around and call + * `SIO_BASE_HANDLE` again with the returned BSP socket, to make sure that + * we unwrap all layers and retrieve the actual base socket. + * [1] https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls + * [2] https://www.komodia.com/newwiki/index.php?title=Komodia%27s_Redirector_bug_fixes#Version_2.2.2.6 + */ + base_socket = ws__ioctl_get_bsp_socket(socket, SIO_BSP_HANDLE_POLL); + if (base_socket != INVALID_SOCKET && base_socket != socket) + socket = base_socket; + else + return_set_error(INVALID_SOCKET, error); + } } diff --git a/wepoll.h b/wepoll.h index 5a179ab..6224a84 100644 --- a/wepoll.h +++ b/wepoll.h @@ -41,39 +41,39 @@ #include enum EPOLL_EVENTS { - EPOLLIN = 0x0001, + EPOLLIN = 0x0001, #define EPOLLIN EPOLLIN - EPOLLPRI = 0x0002, + EPOLLPRI = 0x0002, #define EPOLLPRI EPOLLPRI - EPOLLOUT = 0x0004, + EPOLLOUT = 0x0004, #define EPOLLOUT EPOLLOUT - EPOLLERR = 0x0008, + EPOLLERR = 0x0008, #define EPOLLERR EPOLLERR - EPOLLHUP = 0x0010, + EPOLLHUP = 0x0010, #define EPOLLHUP EPOLLHUP - EPOLLNVAL = 0x0020, + EPOLLNVAL = 0x0020, #define EPOLLNVAL EPOLLNVAL - EPOLLRDNORM = 0x0040, + EPOLLRDNORM = 0x0040, #define EPOLLRDNORM EPOLLRDNORM - EPOLLRDBAND = 0x0080, + EPOLLRDBAND = 0x0080, #define EPOLLRDBAND EPOLLRDBAND - EPOLLWRNORM = 0x0100, + EPOLLWRNORM = 0x0100, #define EPOLLWRNORM EPOLLWRNORM - EPOLLWRBAND = 0x0200, + EPOLLWRBAND = 0x0200, #define EPOLLWRBAND EPOLLWRBAND - EPOLLMSG = 0x0400, /* Never reported. */ + EPOLLMSG = 0x0400, /* Never reported. */ #define EPOLLMSG EPOLLMSG - EPOLLRDHUP = 0x2000, + EPOLLRDHUP = 0x2000, #define EPOLLRDHUP EPOLLRDHUP - EPOLL_URING_WAKE = (unsigned)(1U << 27), + EPOLL_URING_WAKE = (unsigned)(1U << 27), #define EPOLL_URING_WAKE EPOLL_URING_WAKE - EPOLLEXCLUSIVE = (unsigned)(1U << 28), + EPOLLEXCLUSIVE = (unsigned)(1U << 28), #define EPOLLEXCLUSIVE EPOLLEXCLUSIVE - EPOLLWAKEUP = (unsigned)(1U << 29), + EPOLLWAKEUP = (unsigned)(1U << 29), #define EPOLLWAKEUP EPOLLWAKEUP - EPOLLONESHOT = (unsigned)(1U << 30), + EPOLLONESHOT = (unsigned)(1U << 30), #define EPOLLONESHOT EPOLLONESHOT - EPOLLET = (unsigned)(1U << 31) + EPOLLET = (unsigned)(1U << 31) #define EPOLLET EPOLLET }; @@ -82,7 +82,7 @@ enum EPOLL_EVENTS { #define EPOLL_CTL_MOD 3 enum { - EPOLL_CLOEXEC = 02000000 /*O_CLOEXEC*/ + EPOLL_CLOEXEC = 02000000 /*O_CLOEXEC*/ #define EPOLL_CLOEXEC EPOLL_CLOEXEC }; @@ -92,51 +92,53 @@ typedef uintptr_t SOCKET; #define _SIGSET_NWORDS (1024 / (8 * sizeof (size_t))) typedef struct { - size_t __val[_SIGSET_NWORDS]; + size_t __val[_SIGSET_NWORDS]; } sigset_t; typedef union epoll_data { - void* ptr; - int fd; - uint32_t u32; - uint64_t u64; - SOCKET sock; /* Windows specific */ - HANDLE hnd; /* Windows specific */ + void* ptr; + int fd; + uint32_t u32; + uint64_t u64; + SOCKET sock; /* Windows specific */ + HANDLE hnd; /* Windows specific */ } epoll_data_t; +#pragma pack(push, 1) struct epoll_event { - uint32_t events; /* Epoll events and flags */ - epoll_data_t data; /* User data variable */ + uint32_t events; /* Epoll events and flags */ + epoll_data_t data; /* User data variable */ }; +#pragma pack(pop) #ifdef __cplusplus extern "C" { #endif -WEPOLL_EXPORT HANDLE epoll_create(int size); -WEPOLL_EXPORT HANDLE epoll_create1(int flags); + WEPOLL_EXPORT HANDLE epoll_create(int size); + WEPOLL_EXPORT HANDLE epoll_create1(int flags); -WEPOLL_EXPORT int epoll_close(HANDLE ephnd); + WEPOLL_EXPORT int epoll_close(HANDLE ephnd); -WEPOLL_EXPORT int epoll_ctl(HANDLE ephnd, - int op, - SOCKET sock, - struct epoll_event* event); + WEPOLL_EXPORT int epoll_ctl(HANDLE ephnd, + int op, + SOCKET sock, + struct epoll_event* event); -WEPOLL_EXPORT int epoll_wait(HANDLE ephnd, - struct epoll_event* events, - int maxevents, - int timeout); -WEPOLL_EXPORT int epoll_pwait(HANDLE ephnd, - struct epoll_event* events, - int maxevents, - int timeout, - const sigset_t* sigmask); -WEPOLL_EXPORT int epoll_pwait2(HANDLE ephnd, - struct epoll_event* events, - int maxevents, - const struct timespec* timeout, - const sigset_t* sigmask); + WEPOLL_EXPORT int epoll_wait(HANDLE ephnd, + struct epoll_event* events, + int maxevents, + int timeout); + WEPOLL_EXPORT int epoll_pwait(HANDLE ephnd, + struct epoll_event* events, + int maxevents, + int timeout, + const sigset_t* sigmask); + WEPOLL_EXPORT int epoll_pwait2(HANDLE ephnd, + struct epoll_event* events, + int maxevents, + const struct timespec* timeout, + const sigset_t* sigmask); #ifdef __cplusplus } /* extern "C" */