Statistics
| Branch: | Revision:

root / compatfd.c @ 9a78eead

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
    int err;
30 dcc38d1c Marcelo Tosatti
    sigset_t all;
31 dcc38d1c Marcelo Tosatti
32 dcc38d1c Marcelo Tosatti
    sigfillset(&all);
33 dcc38d1c Marcelo Tosatti
    sigprocmask(SIG_BLOCK, &all, NULL);
34 dcc38d1c Marcelo Tosatti
35 dcc38d1c Marcelo Tosatti
    do {
36 dcc38d1c Marcelo Tosatti
        siginfo_t siginfo;
37 dcc38d1c Marcelo Tosatti
38 dcc38d1c Marcelo Tosatti
        err = sigwaitinfo(&info->mask, &siginfo);
39 dcc38d1c Marcelo Tosatti
        if (err == -1 && errno == EINTR) {
40 dcc38d1c Marcelo Tosatti
            err = 0;
41 dcc38d1c Marcelo Tosatti
            continue;
42 dcc38d1c Marcelo Tosatti
        }
43 dcc38d1c Marcelo Tosatti
44 dcc38d1c Marcelo Tosatti
        if (err > 0) {
45 dcc38d1c Marcelo Tosatti
            char buffer[128];
46 dcc38d1c Marcelo Tosatti
            size_t offset = 0;
47 dcc38d1c Marcelo Tosatti
48 dcc38d1c Marcelo Tosatti
            memcpy(buffer, &err, sizeof(err));
49 dcc38d1c Marcelo Tosatti
            while (offset < sizeof(buffer)) {
50 dcc38d1c Marcelo Tosatti
                ssize_t len;
51 dcc38d1c Marcelo Tosatti
52 dcc38d1c Marcelo Tosatti
                len = write(info->fd, buffer + offset,
53 dcc38d1c Marcelo Tosatti
                            sizeof(buffer) - offset);
54 dcc38d1c Marcelo Tosatti
                if (len == -1 && errno == EINTR)
55 dcc38d1c Marcelo Tosatti
                    continue;
56 dcc38d1c Marcelo Tosatti
57 dcc38d1c Marcelo Tosatti
                if (len <= 0) {
58 dcc38d1c Marcelo Tosatti
                    err = -1;
59 dcc38d1c Marcelo Tosatti
                    break;
60 dcc38d1c Marcelo Tosatti
                }
61 dcc38d1c Marcelo Tosatti
62 dcc38d1c Marcelo Tosatti
                offset += len;
63 dcc38d1c Marcelo Tosatti
            }
64 dcc38d1c Marcelo Tosatti
        }
65 dcc38d1c Marcelo Tosatti
    } while (err >= 0);
66 dcc38d1c Marcelo Tosatti
67 dcc38d1c Marcelo Tosatti
    return NULL;
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
}