api: reference the epoll port by windows HANDLE

This commit is contained in:
Bert Belder 2017-09-25 18:14:26 +02:00
parent fd83d12648
commit 45728a1e90
7 changed files with 89 additions and 31 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;