summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-10-30 02:35:32 +0100
committerDirk Engling <erdgeist@erdgeist.org>2026-10-30 02:35:32 +0100
commit95fd9a4ae2717a73bc446b29a87ad5bc9f00317e (patch)
tree36b0a0accb4da8269faf0c8e80455b83d04a6456
parente3efacd05d8a74b2f753dd8afbfe62baa1e0770e (diff)
Reduce number of per connection sys calls
-rw-r--r--ot_event.c14
-rw-r--r--ot_event.h5
-rw-r--r--ot_http.c3
-rw-r--r--ot_socket.c13
4 files changed, 30 insertions, 5 deletions
diff --git a/ot_event.c b/ot_event.c
index 1542bf5..8f55817 100644
--- a/ot_event.c
+++ b/ot_event.c
@@ -71,6 +71,10 @@ int event_add(int fd, int what, uint32_t generation) { return event_ctl(EPOLL_CT
71int event_modify(int fd, int what, uint32_t generation) { return event_ctl(EPOLL_CTL_MOD, fd, what, generation); } 71int event_modify(int fd, int what, uint32_t generation) { return event_ctl(EPOLL_CTL_MOD, fd, what, generation); }
72int event_del(int fd) { return epoll_ctl(g_epoll, EPOLL_CTL_DEL, fd, NULL); } 72int event_del(int fd) { return epoll_ctl(g_epoll, EPOLL_CTL_DEL, fd, NULL); }
73 73
74/* A descriptor leaves the interest list when the last reference to its open
75 file description is closed, and the tracker never duplicates one */
76int event_close(int fd) { return close(fd); }
77
74int event_wait(ot_event *out, int max, int timeout_ms) { 78int event_wait(ot_event *out, int max, int timeout_ms) {
75 int count, i; 79 int count, i;
76 80
@@ -171,6 +175,9 @@ int event_add(int fd, int what, uint32_t generation) { return event_change(fd, w
171int event_modify(int fd, int what, uint32_t generation) { return event_change(fd, what, generation, 0); } 175int event_modify(int fd, int what, uint32_t generation) { return event_change(fd, what, generation, 0); }
172int event_del(int fd) { return event_change(fd, 0, 0, 1); } 176int event_del(int fd) { return event_change(fd, 0, 0, 1); }
173 177
178/* Closing a descriptor removes every kevent that references it */
179int event_close(int fd) { return close(fd); }
180
174int event_wait(ot_event *out, int max, int timeout_ms) { 181int event_wait(ot_event *out, int max, int timeout_ms) {
175 struct timespec timeout; 182 struct timespec timeout;
176 struct timespec *deadline = NULL; 183 struct timespec *deadline = NULL;
@@ -311,6 +318,13 @@ int event_del(int fd) {
311 return 0; 318 return 0;
312} 319}
313 320
321/* Nothing here lives in the kernel, so the entry has to come out by hand
322 before the descriptor goes, or poll reports POLLNVAL for it forever */
323int event_close(int fd) {
324 event_del(fd);
325 return close(fd);
326}
327
314int event_wait(ot_event *out, int max, int timeout_ms) { 328int event_wait(ot_event *out, int max, int timeout_ms) {
315 int ready, found = 0, i; 329 int ready, found = 0, i;
316 330
diff --git a/ot_event.h b/ot_event.h
index 6023134..aa007d0 100644
--- a/ot_event.h
+++ b/ot_event.h
@@ -29,6 +29,11 @@ int event_add(int fd, int what, uint32_t generation);
29int event_modify(int fd, int what, uint32_t generation); 29int event_modify(int fd, int what, uint32_t generation);
30int event_del(int fd); 30int event_del(int fd);
31 31
32/* Stop watching a descriptor and close it. Where the kernel drops a closed
33 descriptor from its set by itself, this is one system call where doing the
34 two separately would be two. */
35int event_close(int fd);
36
32/* Waits at most timeout_ms, or indefinitely when that is negative, and fills 37/* Waits at most timeout_ms, or indefinitely when that is negative, and fills
33 out with up to max ready descriptors. Returns how many, or -1. */ 38 out with up to max ready descriptors. Returns how many, or -1. */
34int event_wait(ot_event *out, int max, int timeout_ms); 39int event_wait(ot_event *out, int max, int timeout_ms);
diff --git a/ot_http.c b/ot_http.c
index c2f7e5e..d4c7363 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -56,8 +56,7 @@ void http_close(const int64_t sock) {
56 free(cookie); 56 free(cookie);
57 } 57 }
58 58
59 event_del((int)sock); 59 event_close((int)sock);
60 close((int)sock);
61} 60}
62 61
63static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { 62static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
diff --git a/ot_socket.c b/ot_socket.c
index 158459f..47ed26d 100644
--- a/ot_socket.c
+++ b/ot_socket.c
@@ -4,6 +4,7 @@
4 $id$ */ 4 $id$ */
5 5
6/* System */ 6/* System */
7#define _GNU_SOURCE /* accept4 on glibc */
7#include <errno.h> 8#include <errno.h>
8#include <fcntl.h> 9#include <fcntl.h>
9#include <netinet/in.h> 10#include <netinet/in.h>
@@ -170,19 +171,25 @@ int socket_is_connected(int s) {
170 return 1; 171 return 1;
171} 172}
172 173
174/* Linux hands over a blocking socket whatever the listening socket was, the
175 BSDs and macOS inherit the listener's flags, so the accepted socket has to
176 be told either way. accept4 carries the flag itself, which saves the two
177 fcntl calls it otherwise takes. Darwin has neither accept4 nor the flag. */
173int socket_accept(int s, ot_ip6 ip, uint16_t *port) { 178int socket_accept(int s, ot_ip6 ip, uint16_t *port) {
174 struct sockaddr_storage ss; 179 struct sockaddr_storage ss;
175 socklen_t len = sizeof(ss); 180 socklen_t len = sizeof(ss);
176 int fd; 181 int fd;
177 182
178 memset(&ss, 0, sizeof(ss)); 183 memset(&ss, 0, sizeof(ss));
184#ifdef SOCK_NONBLOCK
185 if ((fd = accept4(s, (struct sockaddr *)&ss, &len, SOCK_NONBLOCK)) == -1)
186 return -1;
187#else
179 if ((fd = accept(s, (struct sockaddr *)&ss, &len)) == -1) 188 if ((fd = accept(s, (struct sockaddr *)&ss, &len)) == -1)
180 return -1; 189 return -1;
181
182 /* Linux hands over a blocking socket whatever the listening socket was, the
183 BSDs and macOS inherit the listener's flags, so say which one we want. */
184 if (set_nonblocking(fd) == -1) 190 if (set_nonblocking(fd) == -1)
185 return close_and_fail(fd); 191 return close_and_fail(fd);
192#endif
186 193
187 ip_from_sockaddr(ip, port, &ss); 194 ip_from_sockaddr(ip, port, &ss);
188 return fd; 195 return fd;