]> PatchyGit - patchyircd.git/commitdiff
netpoll: add libuv implementation
authorEgor <egor@patchysicp.xyz>
Sat, 1 Mar 2025 19:47:03 +0000 (21:47 +0200)
committerEgor <egor@patchysicp.xyz>
Sat, 1 Mar 2025 19:47:03 +0000 (21:47 +0200)
Makefile
src/job.cpp
src/job.h
src/main.cpp
src/netpoll.cpp

index 78268cb..39d2f40 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -29,6 +29,11 @@ HEADERS := \
 
 -include config.mk
 
+ifdef USE_UV
+CXXFLAGS += -DHAS_UV
+WANTLIBS += libuv
+endif
+
 ifdef USE_TLS
 CXXFLAGS += -DHAS_TLS
 WANTLIBS += libtls
index 1fef031..9323da4 100644 (file)
@@ -31,14 +31,34 @@ static void job_child(int signum)
        }
        errno = old_errno;
 }
+#ifdef NETPOLL_USE_LIBUV
+#include <uv.h>
+static uv_signal_t uvsig;
+static void job_child_cb(uv_signal_t *handle, int signum)
+{
+       (void)handle;
+       job_child(signum);
+}
+#endif
 void job_init(void)
 {
+#ifndef NETPOLL_USE_LIBUV
        struct sigaction sa;
        sa.sa_handler = job_child;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = SA_RESTART;
        if (sigaction(SIGCHLD, &sa, NULL) == -1)
                perror("sigaction");
+#else
+       uv_signal_init(uv_default_loop(), &uvsig);
+       uv_signal_start(&uvsig, job_child_cb, SIGCHLD);
+#endif
+}
+void job_fini(void)
+{
+#ifndef NETPOLL_USE_LIBUV
+       uv_signal_stop(&uvsig);
+#endif
 }
 static void job_process(void)
 {
@@ -67,19 +87,23 @@ static void job_process(void)
 }
 void job_process_begin(void)
 {
+#ifndef NETPOLL_USE_LIBUV
        sigset_t mask;
        sigemptyset(&mask);
        sigaddset(&mask, SIGCHLD);
        sigprocmask(SIG_BLOCK, &mask, 0);
+#endif
        job_process();
 }
 void job_process_end(void)
 {
        job_process();
+#ifndef NETPOLL_USE_LIBUV
        sigset_t mask;
        sigemptyset(&mask);
        sigaddset(&mask, SIGCHLD);
        sigprocmask(SIG_UNBLOCK, &mask, 0);
+#endif
 }
 
 void job_add(struct client_data *cl, jobproc_t job, contproc_t then, char *data, size_t len)
index 562f7ee..609def5 100644 (file)
--- a/src/job.h
+++ b/src/job.h
@@ -3,6 +3,7 @@
 typedef int (*jobproc_t)(struct client_data *cl, const char *data, size_t len);
 typedef void (*contproc_t)(struct client_data *cl, int res);
 void job_init(void);
+void job_fini(void);
 void job_process_begin(void);
 void job_process_end(void);
 void job_add(struct client_data *client, jobproc_t job, contproc_t then, char *data, size_t len);
index ecb0a19..68be53e 100644 (file)
@@ -395,6 +395,7 @@ int main(int argc, char *argv[])
 #ifdef HAS_LUA
        admin_fini();
 #endif
+       job_fini();
        net_poll_fini();
        net_cleanup();
 #ifdef HAS_TLS
index 0a09e58..7b98a73 100644 (file)
@@ -220,6 +220,91 @@ int net_poll_get(struct net_pollfd *out)
        *out = *(struct net_pollfd *)events[lastptr-1].data.ptr;
        return ev;
 }
+#elif defined(NETPOLL_USE_LIBUV)
+#include <uv.h>
+#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member)))
+struct polldata {
+       uv_poll_t uv;
+       int events, revents, fd;
+};
+static polldata uvpollbuf[NETPOLL_MAXFDS] = {};
+static polldata *uvpoll[NETPOLL_MAXFDS] = {};
+static uv_loop_t *uvloop = 0;
+static int lastptr = 0;
+void net_poll_init(void)
+{
+       for (int i = 0; i < NETPOLL_MAXFDS; i++)
+               uvpoll[i] = &uvpollbuf[i];
+       uvloop = uv_default_loop();
+}
+void net_poll_fini(void)
+{
+       uv_loop_close(uvloop);
+}
+static void net_poll_add_impl(int i)
+{
+       struct polldata *poll = uvpoll[nfds-1];
+       memmove(uvpoll+i+1, uvpoll+i, sizeof(uvpoll[0])*(nfds-1-i));
+       uvpoll[i] = poll;
+       poll->events = 0;
+       poll->revents = 0;
+       poll->fd = fds[i].fd;
+       uv_poll_init_socket(uvloop, &poll->uv, fds[i].fd);
+       if (lastptr >= i)
+               lastptr++;
+}
+static void net_poll_del_impl(int i)
+{
+       struct polldata *poll = uvpoll[i];
+       memmove(uvpoll+i, uvpoll+i+1, sizeof(uvpoll[0])*(nfds-(i+1)));
+       uvpoll[nfds-1] = poll;
+       uv_poll_stop(&poll->uv);
+       if (lastptr > i)
+               lastptr--;
+}
+static void net_poll_cb(uv_poll_t *handle, int status, int events)
+{
+       struct polldata *poll = container_of(handle, struct polldata, uv);
+       if (status == 0) {
+               poll->revents = events;
+       }
+       uv_poll_stop(handle);
+       lastptr = 0;
+}
+static void net_poll_reg_impl(int i, int ev)
+{
+       int events = 0;
+       if (ev & NETPOLL_IN)
+               events |= UV_READABLE;
+       if (ev & NETPOLL_OUT)
+               events |= UV_WRITABLE;
+       uvpoll[i]->events = events;
+}
+int net_poll_begin(void)
+{
+       for (int i = 0; i < nfds; i++) {
+               uv_poll_start(&uvpoll[i]->uv, uvpoll[i]->events, net_poll_cb);
+               uvpoll[i]->revents = 0;
+       }
+       uv_run(uvloop, UV_RUN_ONCE);
+       return 0;
+}
+int net_poll_get(struct net_pollfd *out)
+{
+       int ev = 0;
+       while (!ev) {
+               if (lastptr == nfds)
+                       return 0;
+               int pev = uvpoll[lastptr]->revents;
+               if (pev & UV_READABLE)
+                       ev |= NETPOLL_IN;
+               if (pev & UV_WRITABLE)
+                       ev |= NETPOLL_OUT;
+               lastptr++;
+       }
+       *out = fds[lastptr-1];
+       return ev;
+}
 #else
 #error pick a netpoll implementation
 #endif