+static void set_signo(uint64_t *signums, int signo)
+{
+ if (signo >= 1 && signo <= 64)
+ *signums |= (1u << (signo - 1));
+}
+
+static bool get_signo(uint64_t signums, int signo)
+{
+ return (signo >= 1) && (signo <= 64) && (signums & (1u << (signo - 1)));
+}
+
+static void signal_consume(struct uloop_fd *fd, unsigned int events)
+{
+ struct uloop_signal *usig, *usig_next;
+ uint64_t signums = 0;
+ uint8_t buf[32];
+ ssize_t nsigs;
+
+ do {
+ nsigs = read(fd->fd, buf, sizeof(buf));
+
+ for (ssize_t i = 0; i < nsigs; i++)
+ set_signo(&signums, buf[i]);
+ }
+ while (nsigs > 0);
+
+ list_for_each_entry_safe(usig, usig_next, &signals, list)
+ if (get_signo(signums, usig->signo))
+ usig->cb(usig);
+}
+
+static int waker_pipe = -1;
+static struct uloop_fd waker_fd = {
+ .fd = -1,
+ .cb = signal_consume,
+};
+
+static void waker_init_fd(int fd)
+{
+ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
+}
+
+static int waker_init(void)
+{
+ int fds[2];
+
+ if (waker_pipe >= 0)
+ return 0;
+
+ if (pipe(fds) < 0)
+ return -1;
+
+ waker_init_fd(fds[0]);
+ waker_init_fd(fds[1]);
+ waker_pipe = fds[1];
+
+ waker_fd.fd = fds[0];
+ waker_fd.cb = signal_consume;
+ uloop_fd_add(&waker_fd, ULOOP_READ);
+
+ return 0;
+}
+
+static void uloop_setup_signals(bool add);
+
+int uloop_init(void)
+{
+ if (uloop_init_pollfd() < 0)
+ return -1;
+
+ if (waker_init() < 0) {
+ uloop_done();
+ return -1;
+ }
+
+ uloop_setup_signals(true);
+
+ return 0;
+}
+