1baacf047SPaolo Bonzini /*
2baacf047SPaolo Bonzini * signalfd/eventfd compatibility
3baacf047SPaolo Bonzini *
4baacf047SPaolo Bonzini * Copyright IBM, Corp. 2008
5baacf047SPaolo Bonzini *
6baacf047SPaolo Bonzini * Authors:
7baacf047SPaolo Bonzini * Anthony Liguori <aliguori@us.ibm.com>
8baacf047SPaolo Bonzini *
9baacf047SPaolo Bonzini * This work is licensed under the terms of the GNU GPL, version 2. See
10baacf047SPaolo Bonzini * the COPYING file in the top-level directory.
11baacf047SPaolo Bonzini *
12baacf047SPaolo Bonzini * Contributions after 2012-01-13 are licensed under the terms of the
13baacf047SPaolo Bonzini * GNU GPL, version 2 or (at your option) any later version.
14baacf047SPaolo Bonzini */
15baacf047SPaolo Bonzini
16aafd7584SPeter Maydell #include "qemu/osdep.h"
17518420dfSJan Kiszka #include "qemu/thread.h"
18baacf047SPaolo Bonzini
1981b7b1e2SDavid CARLIER #if defined(CONFIG_SIGNALFD)
206bd17dccSKacper Słomiński #include <sys/signalfd.h>
2181b7b1e2SDavid CARLIER #endif
22baacf047SPaolo Bonzini
237e3a61ceSMahmoud Mandour struct sigfd_compat_info {
24baacf047SPaolo Bonzini sigset_t mask;
25baacf047SPaolo Bonzini int fd;
26baacf047SPaolo Bonzini };
27baacf047SPaolo Bonzini
sigwait_compat(void * opaque)28baacf047SPaolo Bonzini static void *sigwait_compat(void *opaque)
29baacf047SPaolo Bonzini {
30baacf047SPaolo Bonzini struct sigfd_compat_info *info = opaque;
31baacf047SPaolo Bonzini
32baacf047SPaolo Bonzini while (1) {
33baacf047SPaolo Bonzini int sig;
34baacf047SPaolo Bonzini int err;
35baacf047SPaolo Bonzini
36baacf047SPaolo Bonzini err = sigwait(&info->mask, &sig);
37baacf047SPaolo Bonzini if (err != 0) {
38baacf047SPaolo Bonzini if (errno == EINTR) {
39baacf047SPaolo Bonzini continue;
40baacf047SPaolo Bonzini } else {
41baacf047SPaolo Bonzini return NULL;
42baacf047SPaolo Bonzini }
43baacf047SPaolo Bonzini } else {
44baacf047SPaolo Bonzini struct qemu_signalfd_siginfo buffer;
45baacf047SPaolo Bonzini memset(&buffer, 0, sizeof(buffer));
46baacf047SPaolo Bonzini buffer.ssi_signo = sig;
47baacf047SPaolo Bonzini
48d0dedf2fSMarc-André Lureau if (qemu_write_full(info->fd, &buffer, sizeof(buffer)) != sizeof(buffer)) {
49baacf047SPaolo Bonzini return NULL;
50baacf047SPaolo Bonzini }
51baacf047SPaolo Bonzini }
52baacf047SPaolo Bonzini }
53baacf047SPaolo Bonzini }
54baacf047SPaolo Bonzini
qemu_signalfd_compat(const sigset_t * mask)55baacf047SPaolo Bonzini static int qemu_signalfd_compat(const sigset_t *mask)
56baacf047SPaolo Bonzini {
57baacf047SPaolo Bonzini struct sigfd_compat_info *info;
58518420dfSJan Kiszka QemuThread thread;
59baacf047SPaolo Bonzini int fds[2];
60baacf047SPaolo Bonzini
61e0c5a18eSMahmoud Mandour info = g_malloc(sizeof(*info));
62baacf047SPaolo Bonzini
63*81badab3SMarc-André Lureau if (!g_unix_open_pipe(fds, FD_CLOEXEC, NULL)) {
64e0c5a18eSMahmoud Mandour g_free(info);
65baacf047SPaolo Bonzini return -1;
66baacf047SPaolo Bonzini }
67baacf047SPaolo Bonzini
68baacf047SPaolo Bonzini memcpy(&info->mask, mask, sizeof(*mask));
69baacf047SPaolo Bonzini info->fd = fds[1];
70baacf047SPaolo Bonzini
714900116eSDr. David Alan Gilbert qemu_thread_create(&thread, "signalfd_compat", sigwait_compat, info,
724900116eSDr. David Alan Gilbert QEMU_THREAD_DETACHED);
73baacf047SPaolo Bonzini
74baacf047SPaolo Bonzini return fds[0];
75baacf047SPaolo Bonzini }
76baacf047SPaolo Bonzini
qemu_signalfd(const sigset_t * mask)77baacf047SPaolo Bonzini int qemu_signalfd(const sigset_t *mask)
78baacf047SPaolo Bonzini {
79baacf047SPaolo Bonzini #if defined(CONFIG_SIGNALFD)
80baacf047SPaolo Bonzini int ret;
81baacf047SPaolo Bonzini
826bd17dccSKacper Słomiński ret = signalfd(-1, mask, SFD_CLOEXEC);
83baacf047SPaolo Bonzini if (ret != -1) {
84baacf047SPaolo Bonzini return ret;
85baacf047SPaolo Bonzini }
86baacf047SPaolo Bonzini #endif
87baacf047SPaolo Bonzini
88baacf047SPaolo Bonzini return qemu_signalfd_compat(mask);
89baacf047SPaolo Bonzini }
90