qemu

Форк
0
/
event_notifier-posix.c 
142 строки · 2.7 Кб
1
/*
2
 * event notifier support
3
 *
4
 * Copyright Red Hat, Inc. 2010
5
 *
6
 * Authors:
7
 *  Michael S. Tsirkin <mst@redhat.com>
8
 *
9
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10
 * See the COPYING file in the top-level directory.
11
 */
12

13
#include "qemu/osdep.h"
14
#include "qemu/cutils.h"
15
#include "qemu/event_notifier.h"
16
#include "qemu/main-loop.h"
17

18
#ifdef CONFIG_EVENTFD
19
#include <sys/eventfd.h>
20
#endif
21

22
#ifdef CONFIG_EVENTFD
23
/*
24
 * Initialize @e with existing file descriptor @fd.
25
 * @fd must be a genuine eventfd object, emulation with pipe won't do.
26
 */
27
void event_notifier_init_fd(EventNotifier *e, int fd)
28
{
29
    e->rfd = fd;
30
    e->wfd = fd;
31
    e->initialized = true;
32
}
33
#endif
34

35
int event_notifier_init(EventNotifier *e, int active)
36
{
37
    int fds[2];
38
    int ret;
39

40
#ifdef CONFIG_EVENTFD
41
    ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
42
#else
43
    ret = -1;
44
    errno = ENOSYS;
45
#endif
46
    if (ret >= 0) {
47
        e->rfd = e->wfd = ret;
48
    } else {
49
        if (errno != ENOSYS) {
50
            return -errno;
51
        }
52
        if (!g_unix_open_pipe(fds, FD_CLOEXEC, NULL)) {
53
            return -errno;
54
        }
55
        if (!g_unix_set_fd_nonblocking(fds[0], true, NULL)) {
56
            ret = -errno;
57
            goto fail;
58
        }
59
        if (!g_unix_set_fd_nonblocking(fds[1], true, NULL)) {
60
            ret = -errno;
61
            goto fail;
62
        }
63
        e->rfd = fds[0];
64
        e->wfd = fds[1];
65
    }
66
    e->initialized = true;
67
    if (active) {
68
        event_notifier_set(e);
69
    }
70
    return 0;
71

72
fail:
73
    close(fds[0]);
74
    close(fds[1]);
75
    return ret;
76
}
77

78
void event_notifier_cleanup(EventNotifier *e)
79
{
80
    if (!e->initialized) {
81
        return;
82
    }
83

84
    if (e->rfd != e->wfd) {
85
        close(e->rfd);
86
    }
87

88
    e->rfd = -1;
89
    close(e->wfd);
90
    e->wfd = -1;
91
    e->initialized = false;
92
}
93

94
int event_notifier_get_fd(const EventNotifier *e)
95
{
96
    return e->rfd;
97
}
98

99
int event_notifier_get_wfd(const EventNotifier *e)
100
{
101
    return e->wfd;
102
}
103

104
int event_notifier_set(EventNotifier *e)
105
{
106
    static const uint64_t value = 1;
107
    ssize_t ret;
108

109
    if (!e->initialized) {
110
        return -1;
111
    }
112

113
    do {
114
        ret = write(e->wfd, &value, sizeof(value));
115
    } while (ret < 0 && errno == EINTR);
116

117
    /* EAGAIN is fine, a read must be pending.  */
118
    if (ret < 0 && errno != EAGAIN) {
119
        return -errno;
120
    }
121
    return 0;
122
}
123

124
int event_notifier_test_and_clear(EventNotifier *e)
125
{
126
    int value;
127
    ssize_t len;
128
    char buffer[512];
129

130
    if (!e->initialized) {
131
        return 0;
132
    }
133

134
    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
135
    value = 0;
136
    do {
137
        len = read(e->rfd, buffer, sizeof(buffer));
138
        value |= (len > 0);
139
    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
140

141
    return value;
142
}
143

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.