From: Egor Date: Sat, 1 Mar 2025 19:47:03 +0000 (+0200) Subject: netpoll: add libuv implementation X-Git-Url: https://git.patchysicp.xyz/?a=commitdiff_plain;h=9efabae56249d95f9994e2beaa002d68db663da4;p=patchyircd.git netpoll: add libuv implementation --- diff --git a/Makefile b/Makefile index 78268cb..39d2f40 100644 --- 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 diff --git a/src/job.cpp b/src/job.cpp index 1fef031..9323da4 100644 --- a/src/job.cpp +++ b/src/job.cpp @@ -31,14 +31,34 @@ static void job_child(int signum) } errno = old_errno; } +#ifdef NETPOLL_USE_LIBUV +#include +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) diff --git a/src/job.h b/src/job.h index 562f7ee..609def5 100644 --- 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); diff --git a/src/main.cpp b/src/main.cpp index ecb0a19..68be53e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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 diff --git a/src/netpoll.cpp b/src/netpoll.cpp index 0a09e58..7b98a73 100644 --- a/src/netpoll.cpp +++ b/src/netpoll.cpp @@ -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 +#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