xref: /openbmc/qemu/util/compatfd.c (revision 81badab3)
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