}
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)
{
}
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)
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);
*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