epoll: move the socket lookup tree to it's own file

This commit is contained in:
Bert Belder 2017-09-07 19:19:07 +02:00
parent 0d941fd52a
commit 3d1bae5073
8 changed files with 161 additions and 42 deletions

View File

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

View File

@ -4,6 +4,7 @@
#include <stdint.h>
#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_ */

View File

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

81
src/handle-tree.c Normal file
View File

@ -0,0 +1,81 @@
#include <assert.h>
#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);
}

24
src/handle-tree.h Normal file
View File

@ -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_ */

1
src/port-data.c Normal file
View File

@ -0,0 +1 @@

View File

@ -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_ */

View File

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