Statistics
| Branch: | Revision:

root / compatfd.c @ bcdf9b4d

History | View | Annotate | Download (2.2 kB)

1 bcdf9b4d aliguori
/*
2 bcdf9b4d aliguori
 * signalfd/eventfd compatibility
3 bcdf9b4d aliguori
 *
4 bcdf9b4d aliguori
 * Copyright IBM, Corp. 2008
5 bcdf9b4d aliguori
 *
6 bcdf9b4d aliguori
 * Authors:
7 bcdf9b4d aliguori
 *  Anthony Liguori   <aliguori@us.ibm.com>
8 bcdf9b4d aliguori
 *
9 bcdf9b4d aliguori
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10 bcdf9b4d aliguori
 * the COPYING file in the top-level directory.
11 bcdf9b4d aliguori
 *
12 bcdf9b4d aliguori
 */
13 bcdf9b4d aliguori
14 bcdf9b4d aliguori
#include "qemu-common.h"
15 bcdf9b4d aliguori
#include "compatfd.h"
16 bcdf9b4d aliguori
17 bcdf9b4d aliguori
#include <sys/syscall.h>
18 bcdf9b4d aliguori
#include <pthread.h>
19 bcdf9b4d aliguori
20 bcdf9b4d aliguori
struct sigfd_compat_info
21 bcdf9b4d aliguori
{
22 bcdf9b4d aliguori
    sigset_t mask;
23 bcdf9b4d aliguori
    int fd;
24 bcdf9b4d aliguori
};
25 bcdf9b4d aliguori
26 bcdf9b4d aliguori
static void *sigwait_compat(void *opaque)
27 bcdf9b4d aliguori
{
28 bcdf9b4d aliguori
    struct sigfd_compat_info *info = opaque;
29 bcdf9b4d aliguori
    int err;
30 bcdf9b4d aliguori
    sigset_t all;
31 bcdf9b4d aliguori
32 bcdf9b4d aliguori
    sigfillset(&all);
33 bcdf9b4d aliguori
    sigprocmask(SIG_BLOCK, &all, NULL);
34 bcdf9b4d aliguori
35 bcdf9b4d aliguori
    do {
36 bcdf9b4d aliguori
        siginfo_t siginfo;
37 bcdf9b4d aliguori
38 bcdf9b4d aliguori
        err = sigwaitinfo(&info->mask, &siginfo);
39 bcdf9b4d aliguori
        if (err == -1 && errno == EINTR) {
40 bcdf9b4d aliguori
            err = 0;
41 bcdf9b4d aliguori
            continue;
42 bcdf9b4d aliguori
        }
43 bcdf9b4d aliguori
44 bcdf9b4d aliguori
        if (err > 0) {
45 bcdf9b4d aliguori
            char buffer[128];
46 bcdf9b4d aliguori
            size_t offset = 0;
47 bcdf9b4d aliguori
48 bcdf9b4d aliguori
            memcpy(buffer, &err, sizeof(err));
49 bcdf9b4d aliguori
            while (offset < sizeof(buffer)) {
50 bcdf9b4d aliguori
                ssize_t len;
51 bcdf9b4d aliguori
52 bcdf9b4d aliguori
                len = write(info->fd, buffer + offset,
53 bcdf9b4d aliguori
                            sizeof(buffer) - offset);
54 bcdf9b4d aliguori
                if (len == -1 && errno == EINTR)
55 bcdf9b4d aliguori
                    continue;
56 bcdf9b4d aliguori
57 bcdf9b4d aliguori
                if (len <= 0) {
58 bcdf9b4d aliguori
                    err = -1;
59 bcdf9b4d aliguori
                    break;
60 bcdf9b4d aliguori
                }
61 bcdf9b4d aliguori
62 bcdf9b4d aliguori
                offset += len;
63 bcdf9b4d aliguori
            }
64 bcdf9b4d aliguori
        }
65 bcdf9b4d aliguori
    } while (err >= 0);
66 bcdf9b4d aliguori
67 bcdf9b4d aliguori
    return NULL;
68 bcdf9b4d aliguori
}
69 bcdf9b4d aliguori
70 bcdf9b4d aliguori
static int qemu_signalfd_compat(const sigset_t *mask)
71 bcdf9b4d aliguori
{
72 bcdf9b4d aliguori
    pthread_attr_t attr;
73 bcdf9b4d aliguori
    pthread_t tid;
74 bcdf9b4d aliguori
    struct sigfd_compat_info *info;
75 bcdf9b4d aliguori
    int fds[2];
76 bcdf9b4d aliguori
77 bcdf9b4d aliguori
    info = malloc(sizeof(*info));
78 bcdf9b4d aliguori
    if (info == NULL) {
79 bcdf9b4d aliguori
        errno = ENOMEM;
80 bcdf9b4d aliguori
        return -1;
81 bcdf9b4d aliguori
    }
82 bcdf9b4d aliguori
83 bcdf9b4d aliguori
    if (pipe(fds) == -1) {
84 bcdf9b4d aliguori
        free(info);
85 bcdf9b4d aliguori
        return -1;
86 bcdf9b4d aliguori
    }
87 bcdf9b4d aliguori
88 bcdf9b4d aliguori
    memcpy(&info->mask, mask, sizeof(*mask));
89 bcdf9b4d aliguori
    info->fd = fds[1];
90 bcdf9b4d aliguori
91 bcdf9b4d aliguori
    pthread_attr_init(&attr);
92 bcdf9b4d aliguori
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
93 bcdf9b4d aliguori
94 bcdf9b4d aliguori
    pthread_create(&tid, &attr, sigwait_compat, info);
95 bcdf9b4d aliguori
96 bcdf9b4d aliguori
    pthread_attr_destroy(&attr);
97 bcdf9b4d aliguori
98 bcdf9b4d aliguori
    return fds[0];
99 bcdf9b4d aliguori
}
100 bcdf9b4d aliguori
101 bcdf9b4d aliguori
int qemu_signalfd(const sigset_t *mask)
102 bcdf9b4d aliguori
{
103 bcdf9b4d aliguori
#if defined(SYS_signalfd)
104 bcdf9b4d aliguori
    int ret;
105 bcdf9b4d aliguori
106 bcdf9b4d aliguori
    ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8);
107 bcdf9b4d aliguori
    if (!(ret == -1 && errno == ENOSYS))
108 bcdf9b4d aliguori
        return ret;
109 bcdf9b4d aliguori
#endif
110 bcdf9b4d aliguori
111 bcdf9b4d aliguori
    return qemu_signalfd_compat(mask);
112 bcdf9b4d aliguori
}
113 bcdf9b4d aliguori
114 bcdf9b4d aliguori
int qemu_eventfd(int *fds)
115 bcdf9b4d aliguori
{
116 bcdf9b4d aliguori
#if defined(SYS_eventfd)
117 bcdf9b4d aliguori
    int ret;
118 bcdf9b4d aliguori
119 bcdf9b4d aliguori
    ret = syscall(SYS_eventfd, 0);
120 bcdf9b4d aliguori
    if (ret >= 0) {
121 bcdf9b4d aliguori
        fds[0] = fds[1] = ret;
122 bcdf9b4d aliguori
        return 0;
123 bcdf9b4d aliguori
    } else if (!(ret == -1 && errno == ENOSYS))
124 bcdf9b4d aliguori
        return ret;
125 bcdf9b4d aliguori
#endif
126 bcdf9b4d aliguori
127 bcdf9b4d aliguori
    return pipe(fds);
128 bcdf9b4d aliguori
}