/* * signalfd/eventfd compatibility * * Copyright IBM, Corp. 2008 * * Authors: * Anthony Liguori * * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. * * Contributions after 2012-01-13 are licensed under the terms of the * GNU GPL, version 2 or (at your option) any later version. */ #include "qemu/osdep.h" #include "qemu/thread.h" #if defined(CONFIG_SIGNALFD) #include #endif struct sigfd_compat_info { sigset_t mask; int fd; }; static void *sigwait_compat(void *opaque) { struct sigfd_compat_info *info = opaque; while (1) { int sig; int err; err = sigwait(&info->mask, &sig); if (err != 0) { if (errno == EINTR) { continue; } else { return NULL; } } else { struct qemu_signalfd_siginfo buffer; memset(&buffer, 0, sizeof(buffer)); buffer.ssi_signo = sig; if (qemu_write_full(info->fd, &buffer, sizeof(buffer)) != sizeof(buffer)) { return NULL; } } } } static int qemu_signalfd_compat(const sigset_t *mask) { struct sigfd_compat_info *info; QemuThread thread; int fds[2]; info = g_malloc(sizeof(*info)); if (pipe(fds) == -1) { g_free(info); return -1; } qemu_set_cloexec(fds[0]); qemu_set_cloexec(fds[1]); memcpy(&info->mask, mask, sizeof(*mask)); info->fd = fds[1]; qemu_thread_create(&thread, "signalfd_compat", sigwait_compat, info, QEMU_THREAD_DETACHED); return fds[0]; } int qemu_signalfd(const sigset_t *mask) { #if defined(CONFIG_SIGNALFD) int ret; ret = signalfd(-1, mask, SFD_CLOEXEC); if (ret != -1) { return ret; } #endif return qemu_signalfd_compat(mask); }