|  | /* | 
|  | * signalfd/eventfd compatibility | 
|  | * | 
|  | * Copyright IBM, Corp. 2008 | 
|  | * | 
|  | * Authors: | 
|  | *  Anthony Liguori   <aliguori@us.ibm.com> | 
|  | * | 
|  | * 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 <sys/signalfd.h> | 
|  | #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 (!g_unix_open_pipe(fds, FD_CLOEXEC, NULL)) { | 
|  | g_free(info); | 
|  | return -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); | 
|  | } |