Interrupt io thread in qemu_set_fd_handler2
[qemu-kvm/fedora.git] / kvm-compatfd.c
blobb1311e27ee9fbf04cb2f9559d4e93ae50aa9fdee
1 /*
2 * signalfd/eventfd compatibility
4 * Copyright IBM, Corp. 2008
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
14 #include "qemu-common.h"
15 #include "qemu-kvm.h"
17 #include <sys/syscall.h>
18 #include <pthread.h>
20 struct sigfd_compat_info
22 sigset_t mask;
23 int fd;
26 static void *sigwait_compat(void *opaque)
28 struct sigfd_compat_info *info = opaque;
29 int err;
31 sigprocmask(SIG_BLOCK, &info->mask, NULL);
33 do {
34 siginfo_t siginfo;
36 err = sigwaitinfo(&info->mask, &siginfo);
37 if (err == -1 && errno == EINTR)
38 continue;
40 if (err > 0) {
41 char buffer[128];
42 size_t offset = 0;
44 memcpy(buffer, &err, sizeof(err));
45 while (offset < sizeof(buffer)) {
46 ssize_t len;
48 len = write(info->fd, buffer + offset,
49 sizeof(buffer) - offset);
50 if (len == -1 && errno == EINTR)
51 continue;
53 if (len <= 0) {
54 err = -1;
55 break;
58 offset += len;
61 } while (err >= 0);
63 return NULL;
66 static int kvm_signalfd_compat(const sigset_t *mask)
68 pthread_attr_t attr;
69 pthread_t tid;
70 struct sigfd_compat_info *info;
71 int fds[2];
73 info = malloc(sizeof(*info));
74 if (info == NULL) {
75 errno = ENOMEM;
76 return -1;
79 if (pipe(fds) == -1) {
80 free(info);
81 return -1;
84 memcpy(&info->mask, mask, sizeof(*mask));
85 info->fd = fds[1];
87 pthread_attr_init(&attr);
88 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
90 pthread_create(&tid, &attr, sigwait_compat, info);
92 pthread_attr_destroy(&attr);
94 return fds[0];
97 int kvm_signalfd(const sigset_t *mask)
99 #if defined(SYS_signalfd)
100 int ret;
102 ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8);
103 if (!(ret == -1 && errno == ENOSYS))
104 return ret;
105 #endif
107 return kvm_signalfd_compat(mask);
110 int kvm_eventfd(int *fds)
112 #if defined(SYS_eventfd)
113 int ret;
115 ret = syscall(SYS_eventfd, 0);
116 if (ret >= 0) {
117 fds[0] = fds[1] = ret;
118 return 0;
119 } else if (!(ret == -1 && errno == ENOSYS))
120 return ret;
121 #endif
123 return pipe(fds);