From 3d1bae50738b44db5259046ce1d763dc4b20c535 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Thu, 7 Sep 2017 19:19:07 +0200 Subject: [PATCH] epoll: move the socket lookup tree to it's own file --- src/epoll-socket.c | 32 +++++++++--------- src/epoll-socket.h | 11 ++----- src/epoll.c | 43 +++++++++++++++--------- src/handle-tree.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++ src/handle-tree.h | 24 ++++++++++++++ src/port-data.c | 1 + src/port-data.h | 9 +++++- src/tree.h | 2 +- 8 files changed, 161 insertions(+), 42 deletions(-) create mode 100644 src/handle-tree.c create mode 100644 src/handle-tree.h create mode 100644 src/port-data.c diff --git a/src/epoll-socket.c b/src/epoll-socket.c index 1e17091..8faa219 100644 --- a/src/epoll-socket.c +++ b/src/epoll-socket.c @@ -44,17 +44,18 @@ ep_sock_t* ep_sock_new(_ep_port_data_t* port_data) { (void) port_data; memset(sock_info, 0, sizeof *sock_info); + handle_tree_entry_init(&sock_info->tree_entry); QUEUE_INIT(&sock_info->queue_entry); return sock_info; } int ep_sock_delete(_ep_port_data_t* port_data, ep_sock_t* sock_info) { - /* Remove from lookup tree. */ - if (sock_info->socket != 0 && !(sock_info->flags & _EP_SOCK_DELETED)) { - RB_REMOVE(ep_sock_tree, &port_data->sock_data_tree, sock_info); - sock_info->flags |= _EP_SOCK_DELETED; - } + /* Remove SOCKET -> ep_sock mapping from port. */ + if (!(sock_info->flags & _EP_SOCK_DELETED)) + _ep_port_del_socket(port_data, &sock_info->tree_entry); + + sock_info->flags |= _EP_SOCK_DELETED; /* Remove from attention list. */ if (sock_info->flags & _EP_SOCK_LISTED) { @@ -72,10 +73,6 @@ int ep_sock_delete(_ep_port_data_t* port_data, ep_sock_t* sock_info) { return 0; } -int ep_sock_compare(ep_sock_t* a, ep_sock_t* b) { - return a->socket - b->socket; -} - static inline bool _ep_sock_delete_pending(ep_sock_t* sock_info) { return sock_info->flags & _EP_SOCK_DELETED; } @@ -135,8 +132,8 @@ int ep_sock_set_socket(_ep_port_data_t* port_data, SOCKET socket) { if (socket == 0 || socket == INVALID_SOCKET) return_error(-1, ERROR_INVALID_HANDLE); - if (sock_info->socket != 0) - return_error(-1, ERROR_INVALID_PARAMETER); + if (sock_info->afd_socket != 0) + return_error(-1, ERROR_ALREADY_ASSIGNED); if (_get_related_sockets(port_data, socket, @@ -144,12 +141,8 @@ int ep_sock_set_socket(_ep_port_data_t* port_data, &sock_info->driver_socket) < 0) return -1; - sock_info->socket = socket; - - if (RB_INSERT(ep_sock_tree, &port_data->sock_data_tree, sock_info) != NULL) { - sock_info->socket = 0; - return_error(-1, ERROR_ALREADY_EXISTS); /* Socket already in epoll set. */ - } + if (_ep_port_add_socket(port_data, &sock_info->tree_entry, socket) < 0) + return -1; return 0; } @@ -297,3 +290,8 @@ int ep_sock_feed_event(_ep_port_data_t* port_data, return ev_count; } + +ep_sock_t* ep_sock_from_tree_entry(handle_tree_entry_t* tree_entry) { + assert(tree_entry != NULL); + return container_of(tree_entry, ep_sock_t, tree_entry); +} diff --git a/src/epoll-socket.h b/src/epoll-socket.h index 3a00162..ba1c050 100644 --- a/src/epoll-socket.h +++ b/src/epoll-socket.h @@ -4,6 +4,7 @@ #include #include "epoll.h" +#include "handle-tree.h" #include "queue.h" #include "tree.h" #include "util.h" @@ -12,14 +13,10 @@ typedef struct _ep_port_data _ep_port_data_t; typedef struct poll_req poll_req_t; -typedef RB_HEAD(ep_sock_tree, ep_sock) ep_sock_tree_head_t; -typedef RB_ENTRY(ep_sock) ep_sock_tree_entry_t; - typedef struct ep_sock { - SOCKET socket; SOCKET afd_socket; SOCKET driver_socket; - ep_sock_tree_entry_t tree_entry; + handle_tree_entry_t tree_entry; QUEUE queue_entry; epoll_data_t user_data; poll_req_t* latest_poll_req; @@ -49,8 +46,6 @@ void ep_sock_register_poll_req(_ep_port_data_t* port_data, void ep_sock_unregister_poll_req(_ep_port_data_t* port_data, ep_sock_t* sock_info); -int ep_sock_compare(ep_sock_t* a, ep_sock_t* b); - -RB_GENERATE_STATIC(ep_sock_tree, ep_sock, tree_entry, ep_sock_compare) +ep_sock_t* ep_sock_from_tree_entry(handle_tree_entry_t* tree_entry); #endif /* EPOLL_SOCK_DATA_H_ */ diff --git a/src/epoll.c b/src/epoll.c index 86f2224..aae7898 100644 --- a/src/epoll.c +++ b/src/epoll.c @@ -50,13 +50,14 @@ static int _ep_ctl_add(_ep_port_data_t* port_data, static int _ep_ctl_mod(_ep_port_data_t* port_data, uintptr_t socket, struct epoll_event* ev) { - ep_sock_t lookup; + handle_tree_entry_t* tree_entry; ep_sock_t* sock_info; - lookup.socket = socket; - sock_info = RB_FIND(ep_sock_tree, &port_data->sock_data_tree, &lookup); - if (sock_info == NULL) - return_error(-1, ERROR_BAD_NETPATH); /* Socket not in epoll set. */ + tree_entry = handle_tree_find(&port_data->sock_tree, socket); + if (tree_entry == NULL) + return -1; + + sock_info = ep_sock_from_tree_entry(tree_entry); if (ep_sock_set_event(port_data, sock_info, ev) < 0) return -1; @@ -65,13 +66,14 @@ static int _ep_ctl_mod(_ep_port_data_t* port_data, } static int _ep_ctl_del(_ep_port_data_t* port_data, uintptr_t socket) { - ep_sock_t lookup; + handle_tree_entry_t* tree_entry; ep_sock_t* sock_info; - lookup.socket = socket; - sock_info = RB_FIND(ep_sock_tree, &port_data->sock_data_tree, &lookup); - if (sock_info == NULL) - return_error(-1, ERROR_NOT_FOUND); /* Socket not in epoll set. */ + tree_entry = handle_tree_find(&port_data->sock_tree, socket); + if (tree_entry == NULL) + return -1; + + sock_info = ep_sock_from_tree_entry(tree_entry); if (ep_sock_delete(port_data, sock_info) < 0) return -1; @@ -230,14 +232,14 @@ epoll_t epoll_create(void) { QUEUE_INIT(&port_data->update_queue); memset(&port_data->driver_sockets, 0, sizeof port_data->driver_sockets); - RB_INIT(&port_data->sock_data_tree); + handle_tree_init(&port_data->sock_tree); return (epoll_t) port_data; } int epoll_close(epoll_t port_handle) { _ep_port_data_t* port_data; - ep_sock_t* sock_info; + handle_tree_entry_t* tree_entry; port_data = (_ep_port_data_t*) port_handle; @@ -279,9 +281,9 @@ int epoll_close(epoll_t port_handle) { } /* Remove all entries from the socket_state tree. */ - while ((sock_info = RB_ROOT(&port_data->sock_data_tree))) { - RB_REMOVE(ep_sock_tree, &port_data->sock_data_tree, sock_info); - free(sock_info); + while ((tree_entry = handle_tree_root(&port_data->sock_tree))) { + ep_sock_t* sock_info = ep_sock_from_tree_entry(tree_entry); + ep_sock_delete(port_data, sock_info); } /* Close the I/O completion port. */ @@ -308,6 +310,17 @@ static int _ep_initialize(void) { return 0; } +int _ep_port_add_socket(_ep_port_data_t* port_data, + handle_tree_entry_t* tree_entry, + SOCKET socket) { + return handle_tree_add(&port_data->sock_tree, tree_entry, socket); +} + +int _ep_port_del_socket(_ep_port_data_t* port_data, + handle_tree_entry_t* tree_entry) { + return handle_tree_del(&port_data->sock_tree, tree_entry); +} + SOCKET _ep_get_driver_socket(_ep_port_data_t* port_data, SOCKET socket) { ssize_t index; size_t i; diff --git a/src/handle-tree.c b/src/handle-tree.c new file mode 100644 index 0000000..1d49627 --- /dev/null +++ b/src/handle-tree.c @@ -0,0 +1,81 @@ +#include + +#include "error.h" +#include "handle-tree.h" +#include "tree.h" + +static inline int _handle_tree_compare(handle_tree_entry_t* a, + handle_tree_entry_t* b) { + return a->key - b->key; +} + +RB_GENERATE_STATIC(handle_tree, + handle_tree_entry, + entry, + _handle_tree_compare); + +void handle_tree_init(handle_tree_t* tree) { + RB_INIT(tree); +} + +void handle_tree_entry_init(handle_tree_entry_t* entry) { + memset(entry, 0, sizeof *entry); +} + +int handle_tree_add(handle_tree_t* tree, + handle_tree_entry_t* entry, + uintptr_t key) { + handle_tree_entry_t* existing_entry; + + if (key == 0) + return_error(-1, ERROR_INVALID_PARAMETER); + if (entry->key != 0) + return_error(-1, ERROR_ALREADY_EXISTS); + + entry->key = key; + existing_entry = RB_INSERT(handle_tree, tree, entry); + + if (existing_entry != NULL) { + entry->key = 0; + return_error(-1, ERROR_ALREADY_EXISTS); + } + + return 0; +} + +int handle_tree_del(handle_tree_t* tree, handle_tree_entry_t* entry) { + handle_tree_entry_t* removed_entry; + + if (entry->key == 0) + return_error(-1, ERROR_NOT_FOUND); + + removed_entry = RB_REMOVE(handle_tree, tree, entry); + + if (removed_entry == NULL) + return_error(-1, ERROR_NOT_FOUND); + else + assert(removed_entry == entry); + + entry->key = 0; + + return 0; +} + +handle_tree_entry_t* handle_tree_find(handle_tree_t* tree, uintptr_t key) { + handle_tree_entry_t* entry; + handle_tree_entry_t lookup = {0}; + lookup.key = key; + + if (key == 0) + return_error(NULL, ERROR_INVALID_PARAMETER); + + entry = RB_FIND(handle_tree, tree, &lookup); + if (entry == NULL) + return_error(NULL, ERROR_NOT_FOUND); + + return entry; +} + +handle_tree_entry_t* handle_tree_root(handle_tree_t* tree) { + return RB_ROOT(tree); +} diff --git a/src/handle-tree.h b/src/handle-tree.h new file mode 100644 index 0000000..4b1281f --- /dev/null +++ b/src/handle-tree.h @@ -0,0 +1,24 @@ +#ifndef EPOLL_HANDLE_TREE_H_ +#define EPOLL_HANDLE_TREE_H_ + +#include "tree.h" + +typedef RB_HEAD(handle_tree, handle_tree_entry) handle_tree_t; + +typedef struct handle_tree_entry { + RB_ENTRY(handle_tree_entry) entry; + uintptr_t key; +} handle_tree_entry_t; + +void handle_tree_init(handle_tree_t* tree); +void handle_tree_entry_init(handle_tree_entry_t* entry); + +int handle_tree_add(handle_tree_t* tree, + handle_tree_entry_t* entry, + uintptr_t key); +int handle_tree_del(handle_tree_t* tree, handle_tree_entry_t* entry); + +handle_tree_entry_t* handle_tree_find(handle_tree_t* tree, uintptr_t key); +handle_tree_entry_t* handle_tree_root(handle_tree_t* tree); + +#endif /* EPOLL_HANDLE_TREE_H_ */ diff --git a/src/port-data.c b/src/port-data.c new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/port-data.c @@ -0,0 +1 @@ + diff --git a/src/port-data.h b/src/port-data.h index f771490..33f6542 100644 --- a/src/port-data.h +++ b/src/port-data.h @@ -3,6 +3,7 @@ #include "afd.h" #include "epoll-socket.h" +#include "handle-tree.h" #include "queue.h" #include "tree.h" #include "util.h" @@ -14,11 +15,17 @@ typedef struct ep_sock ep_sock_t; typedef struct _ep_port_data { HANDLE iocp; SOCKET driver_sockets[array_count(AFD_PROVIDER_GUID_LIST)]; - ep_sock_tree_head_t sock_data_tree; + handle_tree_t sock_tree; QUEUE update_queue; size_t poll_req_count; } _ep_port_data_t; SOCKET _ep_get_driver_socket(_ep_port_data_t* port_data, SOCKET socket); +int _ep_port_add_socket(_ep_port_data_t* port_data, + handle_tree_entry_t* tree_entry, + SOCKET socket); +int _ep_port_del_socket(_ep_port_data_t* port_data, + handle_tree_entry_t* tree_entry); + #endif /* EPOLL_PORT_DATA_H_ */ diff --git a/src/tree.h b/src/tree.h index 8d7a4f4..a62dde5 100644 --- a/src/tree.h +++ b/src/tree.h @@ -39,7 +39,7 @@ #define EPOLL_TREE_H_ #ifdef __clang__ -#define TREE_UNUSED __attribute__((__unused__)) +//#define TREE_UNUSED __attribute__((__unused__)) #else #define TREE_UNUSED /* empty */ #endif