Statistics
| Branch: | Revision:

root / compatfd.c @ 09716e45

History | View | Annotate | Download (2.3 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 dcc38d1c Marcelo Tosatti
 */
13 dcc38d1c Marcelo Tosatti
14 dcc38d1c Marcelo Tosatti
#include "qemu-common.h"
15 dcc38d1c Marcelo Tosatti
#include "compatfd.h"
16 dcc38d1c Marcelo Tosatti
17 dcc38d1c Marcelo Tosatti
#include <sys/syscall.h>
18 dcc38d1c Marcelo Tosatti
#include <pthread.h>
19 dcc38d1c Marcelo Tosatti
20 dcc38d1c Marcelo Tosatti
struct sigfd_compat_info
21 dcc38d1c Marcelo Tosatti
{
22 dcc38d1c Marcelo Tosatti
    sigset_t mask;
23 dcc38d1c Marcelo Tosatti
    int fd;
24 dcc38d1c Marcelo Tosatti
};
25 dcc38d1c Marcelo Tosatti
26 dcc38d1c Marcelo Tosatti
static void *sigwait_compat(void *opaque)
27 dcc38d1c Marcelo Tosatti
{
28 dcc38d1c Marcelo Tosatti
    struct sigfd_compat_info *info = opaque;
29 dcc38d1c Marcelo Tosatti
    sigset_t all;
30 dcc38d1c Marcelo Tosatti
31 dcc38d1c Marcelo Tosatti
    sigfillset(&all);
32 09716e45 Alexander Graf
    pthread_sigmask(SIG_BLOCK, &all, NULL);
33 dcc38d1c Marcelo Tosatti
34 30faaf70 Tristan Gingold
    while (1) {
35 30faaf70 Tristan Gingold
        int sig;
36 30faaf70 Tristan Gingold
        int err;
37 dcc38d1c Marcelo Tosatti
38 30faaf70 Tristan Gingold
        err = sigwait(&info->mask, &sig);
39 30faaf70 Tristan Gingold
        if (err != 0) {
40 30faaf70 Tristan Gingold
            if (errno == EINTR) {
41 30faaf70 Tristan Gingold
                continue;
42 30faaf70 Tristan Gingold
            } else {
43 30faaf70 Tristan Gingold
                return NULL;
44 30faaf70 Tristan Gingold
            }
45 30faaf70 Tristan Gingold
        } else {
46 30faaf70 Tristan Gingold
            struct qemu_signalfd_siginfo buffer;
47 dcc38d1c Marcelo Tosatti
            size_t offset = 0;
48 dcc38d1c Marcelo Tosatti
49 30faaf70 Tristan Gingold
            memset(&buffer, 0, sizeof(buffer));
50 30faaf70 Tristan Gingold
            buffer.ssi_signo = sig;
51 30faaf70 Tristan Gingold
52 dcc38d1c Marcelo Tosatti
            while (offset < sizeof(buffer)) {
53 dcc38d1c Marcelo Tosatti
                ssize_t len;
54 dcc38d1c Marcelo Tosatti
55 30faaf70 Tristan Gingold
                len = write(info->fd, (char *)&buffer + offset,
56 dcc38d1c Marcelo Tosatti
                            sizeof(buffer) - offset);
57 dcc38d1c Marcelo Tosatti
                if (len == -1 && errno == EINTR)
58 dcc38d1c Marcelo Tosatti
                    continue;
59 dcc38d1c Marcelo Tosatti
60 dcc38d1c Marcelo Tosatti
                if (len <= 0) {
61 30faaf70 Tristan Gingold
                    return NULL;
62 dcc38d1c Marcelo Tosatti
                }
63 dcc38d1c Marcelo Tosatti
64 dcc38d1c Marcelo Tosatti
                offset += len;
65 dcc38d1c Marcelo Tosatti
            }
66 dcc38d1c Marcelo Tosatti
        }
67 30faaf70 Tristan Gingold
    }
68 dcc38d1c Marcelo Tosatti
}
69 dcc38d1c Marcelo Tosatti
70 dcc38d1c Marcelo Tosatti
static int qemu_signalfd_compat(const sigset_t *mask)
71 dcc38d1c Marcelo Tosatti
{
72 dcc38d1c Marcelo Tosatti
    pthread_attr_t attr;
73 dcc38d1c Marcelo Tosatti
    pthread_t tid;
74 dcc38d1c Marcelo Tosatti
    struct sigfd_compat_info *info;
75 dcc38d1c Marcelo Tosatti
    int fds[2];
76 dcc38d1c Marcelo Tosatti
77 dcc38d1c Marcelo Tosatti
    info = malloc(sizeof(*info));
78 dcc38d1c Marcelo Tosatti
    if (info == NULL) {
79 dcc38d1c Marcelo Tosatti
        errno = ENOMEM;
80 dcc38d1c Marcelo Tosatti
        return -1;
81 dcc38d1c Marcelo Tosatti
    }
82 dcc38d1c Marcelo Tosatti
83 dcc38d1c Marcelo Tosatti
    if (pipe(fds) == -1) {
84 dcc38d1c Marcelo Tosatti
        free(info);
85 dcc38d1c Marcelo Tosatti
        return -1;
86 dcc38d1c Marcelo Tosatti
    }
87 dcc38d1c Marcelo Tosatti
88 dcc38d1c Marcelo Tosatti
    qemu_set_cloexec(fds[0]);
89 dcc38d1c Marcelo Tosatti
    qemu_set_cloexec(fds[1]);
90 dcc38d1c Marcelo Tosatti
91 dcc38d1c Marcelo Tosatti
    memcpy(&info->mask, mask, sizeof(*mask));
92 dcc38d1c Marcelo Tosatti
    info->fd = fds[1];
93 dcc38d1c Marcelo Tosatti
94 dcc38d1c Marcelo Tosatti
    pthread_attr_init(&attr);
95 dcc38d1c Marcelo Tosatti
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
96 dcc38d1c Marcelo Tosatti
97 dcc38d1c Marcelo Tosatti
    pthread_create(&tid, &attr, sigwait_compat, info);
98 dcc38d1c Marcelo Tosatti
99 dcc38d1c Marcelo Tosatti
    pthread_attr_destroy(&attr);
100 dcc38d1c Marcelo Tosatti
101 dcc38d1c Marcelo Tosatti
    return fds[0];
102 dcc38d1c Marcelo Tosatti
}
103 dcc38d1c Marcelo Tosatti
104 dcc38d1c Marcelo Tosatti
int qemu_signalfd(const sigset_t *mask)
105 dcc38d1c Marcelo Tosatti
{
106 dcc38d1c Marcelo Tosatti
#if defined(CONFIG_SIGNALFD)
107 dcc38d1c Marcelo Tosatti
    int ret;
108 dcc38d1c Marcelo Tosatti
109 dcc38d1c Marcelo Tosatti
    ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8);
110 dcc38d1c Marcelo Tosatti
    if (ret != -1) {
111 dcc38d1c Marcelo Tosatti
        qemu_set_cloexec(ret);
112 dcc38d1c Marcelo Tosatti
        return ret;
113 dcc38d1c Marcelo Tosatti
    }
114 dcc38d1c Marcelo Tosatti
#endif
115 dcc38d1c Marcelo Tosatti
116 dcc38d1c Marcelo Tosatti
    return qemu_signalfd_compat(mask);
117 dcc38d1c Marcelo Tosatti
}