]>
Commit | Line | Data |
---|---|---|
dcc38d1c MT |
1 | /* |
2 | * signalfd/eventfd compatibility | |
3 | * | |
4 | * Copyright IBM, Corp. 2008 | |
5 | * | |
6 | * Authors: | |
7 | * Anthony Liguori <aliguori@us.ibm.com> | |
8 | * | |
9 | * This work is licensed under the terms of the GNU GPL, version 2. See | |
10 | * the COPYING file in the top-level directory. | |
11 | * | |
6b620ca3 PB |
12 | * Contributions after 2012-01-13 are licensed under the terms of the |
13 | * GNU GPL, version 2 or (at your option) any later version. | |
dcc38d1c MT |
14 | */ |
15 | ||
aafd7584 | 16 | #include "qemu/osdep.h" |
518420df | 17 | #include "qemu/thread.h" |
dcc38d1c | 18 | |
81b7b1e2 | 19 | #if defined(CONFIG_SIGNALFD) |
6bd17dcc | 20 | #include <sys/signalfd.h> |
81b7b1e2 | 21 | #endif |
dcc38d1c | 22 | |
7e3a61ce | 23 | struct sigfd_compat_info { |
dcc38d1c MT |
24 | sigset_t mask; |
25 | int fd; | |
26 | }; | |
27 | ||
28 | static void *sigwait_compat(void *opaque) | |
29 | { | |
30 | struct sigfd_compat_info *info = opaque; | |
dcc38d1c | 31 | |
30faaf70 TG |
32 | while (1) { |
33 | int sig; | |
34 | int err; | |
dcc38d1c | 35 | |
30faaf70 TG |
36 | err = sigwait(&info->mask, &sig); |
37 | if (err != 0) { | |
38 | if (errno == EINTR) { | |
39 | continue; | |
40 | } else { | |
41 | return NULL; | |
42 | } | |
43 | } else { | |
44 | struct qemu_signalfd_siginfo buffer; | |
30faaf70 TG |
45 | memset(&buffer, 0, sizeof(buffer)); |
46 | buffer.ssi_signo = sig; | |
47 | ||
d0dedf2f MAL |
48 | if (qemu_write_full(info->fd, &buffer, sizeof(buffer)) != sizeof(buffer)) { |
49 | return NULL; | |
dcc38d1c MT |
50 | } |
51 | } | |
30faaf70 | 52 | } |
dcc38d1c MT |
53 | } |
54 | ||
55 | static int qemu_signalfd_compat(const sigset_t *mask) | |
56 | { | |
dcc38d1c | 57 | struct sigfd_compat_info *info; |
518420df | 58 | QemuThread thread; |
dcc38d1c MT |
59 | int fds[2]; |
60 | ||
e0c5a18e | 61 | info = g_malloc(sizeof(*info)); |
dcc38d1c | 62 | |
81badab3 | 63 | if (!g_unix_open_pipe(fds, FD_CLOEXEC, NULL)) { |
e0c5a18e | 64 | g_free(info); |
dcc38d1c MT |
65 | return -1; |
66 | } | |
67 | ||
dcc38d1c MT |
68 | memcpy(&info->mask, mask, sizeof(*mask)); |
69 | info->fd = fds[1]; | |
70 | ||
4900116e DDAG |
71 | qemu_thread_create(&thread, "signalfd_compat", sigwait_compat, info, |
72 | QEMU_THREAD_DETACHED); | |
dcc38d1c MT |
73 | |
74 | return fds[0]; | |
75 | } | |
76 | ||
77 | int qemu_signalfd(const sigset_t *mask) | |
78 | { | |
79 | #if defined(CONFIG_SIGNALFD) | |
80 | int ret; | |
81 | ||
6bd17dcc | 82 | ret = signalfd(-1, mask, SFD_CLOEXEC); |
dcc38d1c | 83 | if (ret != -1) { |
dcc38d1c MT |
84 | return ret; |
85 | } | |
86 | #endif | |
87 | ||
88 | return qemu_signalfd_compat(mask); | |
89 | } |