diff --git a/include/epoll.h b/include/epoll.h index fe92845..e88e7bb 100644 --- a/include/epoll.h +++ b/include/epoll.h @@ -41,7 +41,6 @@ enum EPOLL_EVENTS { typedef void* HANDLE; typedef uintptr_t SOCKET; -typedef void* epoll_t; typedef union epoll_data { void* ptr; @@ -61,16 +60,16 @@ struct epoll_event { extern "C" { #endif -EPOLL_EXTERN epoll_t epoll_create(void); +EPOLL_EXTERN HANDLE epoll_create(void); -EPOLL_EXTERN int epoll_close(epoll_t epoll_hnd); +EPOLL_EXTERN int epoll_close(HANDLE ephnd); -EPOLL_EXTERN int epoll_ctl(epoll_t epoll_hnd, +EPOLL_EXTERN int epoll_ctl(HANDLE ephnd, int op, SOCKET sock, struct epoll_event* event); -EPOLL_EXTERN int epoll_wait(epoll_t epoll_hnd, +EPOLL_EXTERN int epoll_wait(HANDLE ephnd, struct epoll_event* events, int maxevents, int timeout); diff --git a/src/epoll.c b/src/epoll.c index ae88331..3a1083e 100644 --- a/src/epoll.c +++ b/src/epoll.c @@ -6,16 +6,25 @@ #include "error.h" #include "init.h" #include "port.h" +#include "reflock-tree.h" #include "util.h" #include "win.h" #define _EPOLL_MAX_COMPLETION_COUNT 64 +static reflock_tree_t _epoll_handle_tree; + +static inline ep_port_t* _handle_tree_node_to_port( + reflock_tree_node_t* tree_node) { + return container_of(tree_node, ep_port_t, handle_tree_node); +} + int epoll_global_init(void) { + reflock_tree_init(&_epoll_handle_tree); return 0; } -epoll_t epoll_create(void) { +HANDLE epoll_create(void) { ep_port_t* port_info; HANDLE iocp; @@ -32,19 +41,32 @@ epoll_t epoll_create(void) { return NULL; } - return (epoll_t) port_info; + if (reflock_tree_add(&_epoll_handle_tree, + &port_info->handle_tree_node, + (uintptr_t) iocp) < 0) { + ep_port_delete(port_info); + return_error(INVALID_HANDLE_VALUE, ERROR_ALREADY_EXISTS); + } + + return iocp; } -int epoll_close(epoll_t port_handle) { +int epoll_close(HANDLE ephnd) { + reflock_tree_node_t* tree_node; ep_port_t* port_info; if (init() < 0) return -1; - port_info = (ep_port_t*) port_handle; + tree_node = reflock_tree_del_and_ref(&_epoll_handle_tree, (uintptr_t) ephnd); + if (tree_node == NULL) + return_error(-1, ERROR_INVALID_HANDLE); + port_info = _handle_tree_node_to_port(tree_node); ep_port_close(port_info); + reflock_tree_node_unref_and_destroy(tree_node); + return ep_port_delete(port_info); } @@ -86,15 +108,10 @@ static int _ep_ctl_del(ep_port_t* port_info, SOCKET sock) { return 0; } -int epoll_ctl(epoll_t port_handle, - int op, - SOCKET sock, - struct epoll_event* ev) { - ep_port_t* port_info = (ep_port_t*) port_handle; - - if (init() < 0) - return -1; - +static int _ep_ctl(ep_port_t* port_info, + int op, + SOCKET sock, + struct epoll_event* ev) { switch (op) { case EPOLL_CTL_ADD: return _ep_ctl_add(port_info, sock, ev); @@ -102,23 +119,38 @@ int epoll_ctl(epoll_t port_handle, return _ep_ctl_mod(port_info, sock, ev); case EPOLL_CTL_DEL: return _ep_ctl_del(port_info, sock); + default: + return_error(-1, ERROR_INVALID_PARAMETER); } - - return_error(-1, ERROR_INVALID_PARAMETER); } -int epoll_wait(epoll_t port_handle, - struct epoll_event* events, - int maxevents, - int timeout) { +int epoll_ctl(HANDLE ephnd, int op, SOCKET sock, struct epoll_event* ev) { + reflock_tree_node_t* tree_node; ep_port_t* port_info; - ULONGLONG due = 0; - DWORD gqcs_timeout; + int result; if (init() < 0) return -1; - port_info = (ep_port_t*) port_handle; + tree_node = + reflock_tree_find_and_ref(&_epoll_handle_tree, (uintptr_t) ephnd); + if (tree_node == NULL) + return_error(-1, ERROR_INVALID_HANDLE); + port_info = _handle_tree_node_to_port(tree_node); + + result = _ep_ctl(port_info, op, sock, ev); + + reflock_tree_node_unref(tree_node); + + return result; +} + +static int _ep_wait(ep_port_t* port_info, + struct epoll_event* events, + int maxevents, + int timeout) { + ULONGLONG due = 0; + DWORD gqcs_timeout; /* Compute the timeout for GetQueuedCompletionStatus, and the wait end * time, if the user specified a timeout other than zero or infinite. @@ -174,3 +206,27 @@ int epoll_wait(epoll_t port_handle, return 0; } + +int epoll_wait(HANDLE ephnd, + struct epoll_event* events, + int maxevents, + int timeout) { + reflock_tree_node_t* tree_node; + ep_port_t* port_info; + int result; + + if (init() < 0) + return -1; + + tree_node = + reflock_tree_find_and_ref(&_epoll_handle_tree, (uintptr_t) ephnd); + if (tree_node == NULL) + return_error(-1, ERROR_INVALID_HANDLE); + port_info = _handle_tree_node_to_port(tree_node); + + result = _ep_wait(port_info, events, maxevents, timeout); + + reflock_tree_node_unref(tree_node); + + return result; +} diff --git a/src/port.c b/src/port.c index 96d419a..40eba47 100644 --- a/src/port.c +++ b/src/port.c @@ -37,6 +37,7 @@ ep_port_t* ep_port_new(HANDLE iocp) { port_info->iocp = iocp; queue_init(&port_info->update_queue); tree_init(&port_info->sock_tree); + reflock_tree_node_init(&port_info->handle_tree_node); return port_info; } diff --git a/src/port.h b/src/port.h index a42c150..b14730f 100644 --- a/src/port.h +++ b/src/port.h @@ -8,6 +8,7 @@ #include "poll-group.h" #include "queue.h" #include "rb.h" +#include "reflock-tree.h" #include "tree.h" #include "util.h" #include "win.h" @@ -21,6 +22,7 @@ typedef struct ep_port { poll_group_allocators[array_count(AFD_PROVIDER_GUID_LIST)]; tree_t sock_tree; queue_t update_queue; + reflock_tree_node_t handle_tree_node; } ep_port_t; EPOLL_INTERNAL ep_port_t* ep_port_new(HANDLE iocp); diff --git a/test/test-ctl-fuzz.c b/test/test-ctl-fuzz.c index 4a8cb56..9866503 100644 --- a/test/test-ctl-fuzz.c +++ b/test/test-ctl-fuzz.c @@ -15,7 +15,7 @@ #define RUN_TIME 10000 #define PRINT_INTERVAL 500 -static SOCKET create_and_add_socket(epoll_t epfd) { +static SOCKET create_and_add_socket(HANDLE epfd) { SOCKET sock; unsigned long one; int r; @@ -41,7 +41,7 @@ int main(void) { uint64_t start_time, last_print_time, now, total_time; SOCKET sockets[NUM_SOCKETS]; int r; - epoll_t epfd; + HANDLE epfd; r = init(); assert(r == 0); diff --git a/test/test-multi-poll.c b/test/test-multi-poll.c index 2cf7046..c41acec 100644 --- a/test/test-multi-poll.c +++ b/test/test-multi-poll.c @@ -62,7 +62,7 @@ static void send_message(SOCKET sock, unsigned short port) { } static unsigned int __stdcall poll_thread(void* arg) { - epoll_t epfd; + HANDLE epfd; SOCKET sock; struct epoll_event ev_in; struct epoll_event ev_out; diff --git a/test/test-udp-pings.c b/test/test-udp-pings.c index af3c244..9b9cf41 100644 --- a/test/test-udp-pings.c +++ b/test/test-udp-pings.c @@ -13,7 +13,7 @@ static const char PING[] = "PING"; int main(void) { - epoll_t epoll_hnd; + HANDLE epoll_hnd; int r; u_long one = 1; struct sockaddr_in address;