Statistics
| Branch: | Revision:

root / compatfd.c @ 80465e80

History | View | Annotate | Download (2.8 kB)

1 dcc38d1c Marcelo Tosatti
/*
2 dcc38d1c Marcelo Tosatti
 * signalfd/eventfd compatibility
3 dcc38d1c Marcelo Tosatti
 *
4 dcc38d1c Marcelo Tosatti
 * Copyright IBM, Corp. 2008
5 dcc38d1c Marcelo Tosatti
 *
6 dcc38d1c Marcelo Tosatti
 * Authors:
7 dcc38d1c Marcelo Tosatti
 *  Anthony Liguori   <aliguori@us.ibm.com>
8 dcc38d1c Marcelo Tosatti
 *
9 dcc38d1c Marcelo Tosatti
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10 dcc38d1c Marcelo Tosatti
 * the COPYING file in the top-level directory.
11 dcc38d1c Marcelo Tosatti
 *
12 6b620ca3 Paolo Bonzini
 * Contributions after 2012-01-13 are licensed under the terms of the
13 6b620ca3 Paolo Bonzini
 * GNU GPL, version 2 or (at your option) any later version.
14 dcc38d1c Marcelo Tosatti
 */
15 dcc38d1c Marcelo Tosatti
16 dcc38d1c Marcelo Tosatti
#include "qemu-common.h"
17 dcc38d1c Marcelo Tosatti
#include "compatfd.h"
18 dcc38d1c Marcelo Tosatti
19 dcc38d1c Marcelo Tosatti
#include <sys/syscall.h>
20 dcc38d1c Marcelo Tosatti
#include <pthread.h>
21 dcc38d1c Marcelo Tosatti
22 dcc38d1c Marcelo Tosatti
struct sigfd_compat_info
23 dcc38d1c Marcelo Tosatti
{
24 dcc38d1c Marcelo Tosatti
    sigset_t mask;
25 dcc38d1c Marcelo Tosatti
    int fd;
26 dcc38d1c Marcelo Tosatti
};
27 dcc38d1c Marcelo Tosatti
28 dcc38d1c Marcelo Tosatti
static void *sigwait_compat(void *opaque)
29 dcc38d1c Marcelo Tosatti
{
30 dcc38d1c Marcelo Tosatti
    struct sigfd_compat_info *info = opaque;
31 dcc38d1c Marcelo Tosatti
    sigset_t all;
32 dcc38d1c Marcelo Tosatti
33 dcc38d1c Marcelo Tosatti
    sigfillset(&all);
34 09716e45 Alexander Graf
    pthread_sigmask(SIG_BLOCK, &all, NULL);
35 dcc38d1c Marcelo Tosatti
36 30faaf70 Tristan Gingold
    while (1) {
37 30faaf70 Tristan Gingold
        int sig;
38 30faaf70 Tristan Gingold
        int err;
39 dcc38d1c Marcelo Tosatti
40 30faaf70 Tristan Gingold
        err = sigwait(&info->mask, &sig);
41 30faaf70 Tristan Gingold
        if (err != 0) {
42 30faaf70 Tristan Gingold
            if (errno == EINTR) {
43 30faaf70 Tristan Gingold
                continue;
44 30faaf70 Tristan Gingold
            } else {
45 30faaf70 Tristan Gingold
                return NULL;
46 30faaf70 Tristan Gingold
            }
47 30faaf70 Tristan Gingold
        } else {
48 30faaf70 Tristan Gingold
            struct qemu_signalfd_siginfo buffer;
49 dcc38d1c Marcelo Tosatti
            size_t offset = 0;
50 dcc38d1c Marcelo Tosatti
51 30faaf70 Tristan Gingold
            memset(&buffer, 0, sizeof(buffer));
52 30faaf70 Tristan Gingold
            buffer.ssi_signo = sig;
53 30faaf70 Tristan Gingold
54 dcc38d1c Marcelo Tosatti
            while (offset < sizeof(buffer)) {
55 dcc38d1c Marcelo Tosatti
                ssize_t len;
56 dcc38d1c Marcelo Tosatti
57 30faaf70 Tristan Gingold
                len = write(info->fd, (char *)&buffer + offset,
58 dcc38d1c Marcelo Tosatti
                            sizeof(buffer) - offset);
59 dcc38d1c Marcelo Tosatti
                if (len == -1 && errno == EINTR)
60 dcc38d1c Marcelo Tosatti
                    continue;
61 dcc38d1c Marcelo Tosatti
62 dcc38d1c Marcelo Tosatti
                if (len <= 0) {
63 30faaf70 Tristan Gingold
                    return NULL;
64 dcc38d1c Marcelo Tosatti
                }
65 dcc38d1c Marcelo Tosatti
66 dcc38d1c Marcelo Tosatti
                offset += len;
67 dcc38d1c Marcelo Tosatti
            }
68 dcc38d1c Marcelo Tosatti
        }
69 30faaf70 Tristan Gingold
    }
70 dcc38d1c Marcelo Tosatti
}
71 dcc38d1c Marcelo Tosatti
72 dcc38d1c Marcelo Tosatti
static int qemu_signalfd_compat(const sigset_t *mask)
73 dcc38d1c Marcelo Tosatti
{
74 dcc38d1c Marcelo Tosatti
    pthread_attr_t attr;
75 dcc38d1c Marcelo Tosatti
    pthread_t tid;
76 dcc38d1c Marcelo Tosatti
    struct sigfd_compat_info *info;
77 dcc38d1c Marcelo Tosatti
    int fds[2];
78 dcc38d1c Marcelo Tosatti
79 dcc38d1c Marcelo Tosatti
    info = malloc(sizeof(*info));
80 dcc38d1c Marcelo Tosatti
    if (info == NULL) {
81 dcc38d1c Marcelo Tosatti
        errno = ENOMEM;
82 dcc38d1c Marcelo Tosatti
        return -1;
83 dcc38d1c Marcelo Tosatti
    }
84 dcc38d1c Marcelo Tosatti
85 dcc38d1c Marcelo Tosatti
    if (pipe(fds) == -1) {
86 dcc38d1c Marcelo Tosatti
        free(info);
87 dcc38d1c Marcelo Tosatti
        return -1;
88 dcc38d1c Marcelo Tosatti
    }
89 dcc38d1c Marcelo Tosatti
90 dcc38d1c Marcelo Tosatti
    qemu_set_cloexec(fds[0]);
91 dcc38d1c Marcelo Tosatti
    qemu_set_cloexec(fds[1]);
92 dcc38d1c Marcelo Tosatti
93 dcc38d1c Marcelo Tosatti
    memcpy(&info->mask, mask, sizeof(*mask));
94 dcc38d1c Marcelo Tosatti
    info->fd = fds[1];
95 dcc38d1c Marcelo Tosatti
96 dcc38d1c Marcelo Tosatti
    pthread_attr_init(&attr);
97 dcc38d1c Marcelo Tosatti
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
98 dcc38d1c Marcelo Tosatti
99 dcc38d1c Marcelo Tosatti
    pthread_create(&tid, &attr, sigwait_compat, info);
100 dcc38d1c Marcelo Tosatti
101 dcc38d1c Marcelo Tosatti
    pthread_attr_destroy(&attr);
102 dcc38d1c Marcelo Tosatti
103 dcc38d1c Marcelo Tosatti
    return fds[0];
104 dcc38d1c Marcelo Tosatti
}
105 dcc38d1c Marcelo Tosatti
106 dcc38d1c Marcelo Tosatti
int qemu_signalfd(const sigset_t *mask)
107 dcc38d1c Marcelo Tosatti
{
108 dcc38d1c Marcelo Tosatti
#if defined(CONFIG_SIGNALFD)
109 dcc38d1c Marcelo Tosatti
    int ret;
110 dcc38d1c Marcelo Tosatti
111 dcc38d1c Marcelo Tosatti
    ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8);
112 dcc38d1c Marcelo Tosatti
    if (ret != -1) {
113 dcc38d1c Marcelo Tosatti
        qemu_set_cloexec(ret);
114 dcc38d1c Marcelo Tosatti
        return ret;
115 dcc38d1c Marcelo Tosatti
    }
116 dcc38d1c Marcelo Tosatti
#endif
117 dcc38d1c Marcelo Tosatti
118 dcc38d1c Marcelo Tosatti
    return qemu_signalfd_compat(mask);
119 dcc38d1c Marcelo Tosatti
}
120 d25f89c9 Jan Kiszka
121 d25f89c9 Jan Kiszka
bool qemu_signalfd_available(void)
122 d25f89c9 Jan Kiszka
{
123 d25f89c9 Jan Kiszka
#ifdef CONFIG_SIGNALFD
124 7f84c127 Peter Maydell
    sigset_t mask;
125 7f84c127 Peter Maydell
    int fd;
126 7f84c127 Peter Maydell
    bool ok;
127 7f84c127 Peter Maydell
    sigemptyset(&mask);
128 d25f89c9 Jan Kiszka
    errno = 0;
129 7f84c127 Peter Maydell
    fd = syscall(SYS_signalfd, -1, &mask, _NSIG / 8);
130 7f84c127 Peter Maydell
    ok = (errno != ENOSYS);
131 7f84c127 Peter Maydell
    if (fd >= 0) {
132 7f84c127 Peter Maydell
        close(fd);
133 7f84c127 Peter Maydell
    }
134 7f84c127 Peter Maydell
    return ok;
135 d25f89c9 Jan Kiszka
#else
136 d25f89c9 Jan Kiszka
    return false;
137 d25f89c9 Jan Kiszka
#endif
138 d25f89c9 Jan Kiszka
}