1baacf047SPaolo Bonzini /*
2baacf047SPaolo Bonzini * event notifier support
3baacf047SPaolo Bonzini *
4baacf047SPaolo Bonzini * Copyright Red Hat, Inc. 2010
5baacf047SPaolo Bonzini *
6baacf047SPaolo Bonzini * Authors:
7baacf047SPaolo Bonzini * Michael S. Tsirkin <mst@redhat.com>
8baacf047SPaolo Bonzini *
9baacf047SPaolo Bonzini * This work is licensed under the terms of the GNU GPL, version 2 or later.
10baacf047SPaolo Bonzini * See the COPYING file in the top-level directory.
11baacf047SPaolo Bonzini */
12baacf047SPaolo Bonzini
13aafd7584SPeter Maydell #include "qemu/osdep.h"
14f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
15baacf047SPaolo Bonzini #include "qemu/event_notifier.h"
16baacf047SPaolo Bonzini #include "qemu/main-loop.h"
17baacf047SPaolo Bonzini
18baacf047SPaolo Bonzini #ifdef CONFIG_EVENTFD
19baacf047SPaolo Bonzini #include <sys/eventfd.h>
20baacf047SPaolo Bonzini #endif
21baacf047SPaolo Bonzini
22330b5836SMarkus Armbruster #ifdef CONFIG_EVENTFD
23330b5836SMarkus Armbruster /*
24330b5836SMarkus Armbruster * Initialize @e with existing file descriptor @fd.
25330b5836SMarkus Armbruster * @fd must be a genuine eventfd object, emulation with pipe won't do.
26330b5836SMarkus Armbruster */
event_notifier_init_fd(EventNotifier * e,int fd)27baacf047SPaolo Bonzini void event_notifier_init_fd(EventNotifier *e, int fd)
28baacf047SPaolo Bonzini {
29baacf047SPaolo Bonzini e->rfd = fd;
30baacf047SPaolo Bonzini e->wfd = fd;
31e34e47ebSMaxim Levitsky e->initialized = true;
32baacf047SPaolo Bonzini }
33330b5836SMarkus Armbruster #endif
34baacf047SPaolo Bonzini
event_notifier_init(EventNotifier * e,int active)35baacf047SPaolo Bonzini int event_notifier_init(EventNotifier *e, int active)
36baacf047SPaolo Bonzini {
37baacf047SPaolo Bonzini int fds[2];
38baacf047SPaolo Bonzini int ret;
39baacf047SPaolo Bonzini
40baacf047SPaolo Bonzini #ifdef CONFIG_EVENTFD
41baacf047SPaolo Bonzini ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
42baacf047SPaolo Bonzini #else
43baacf047SPaolo Bonzini ret = -1;
44baacf047SPaolo Bonzini errno = ENOSYS;
45baacf047SPaolo Bonzini #endif
46baacf047SPaolo Bonzini if (ret >= 0) {
47baacf047SPaolo Bonzini e->rfd = e->wfd = ret;
48baacf047SPaolo Bonzini } else {
49baacf047SPaolo Bonzini if (errno != ENOSYS) {
50baacf047SPaolo Bonzini return -errno;
51baacf047SPaolo Bonzini }
52*a7241974SMarc-André Lureau if (!g_unix_open_pipe(fds, FD_CLOEXEC, NULL)) {
53baacf047SPaolo Bonzini return -errno;
54baacf047SPaolo Bonzini }
554d14cb0cSMarc-André Lureau if (!g_unix_set_fd_nonblocking(fds[0], true, NULL)) {
56baacf047SPaolo Bonzini ret = -errno;
57baacf047SPaolo Bonzini goto fail;
58baacf047SPaolo Bonzini }
594d14cb0cSMarc-André Lureau if (!g_unix_set_fd_nonblocking(fds[1], true, NULL)) {
60baacf047SPaolo Bonzini ret = -errno;
61baacf047SPaolo Bonzini goto fail;
62baacf047SPaolo Bonzini }
63baacf047SPaolo Bonzini e->rfd = fds[0];
64baacf047SPaolo Bonzini e->wfd = fds[1];
65baacf047SPaolo Bonzini }
6682e27568SGreg Kurz e->initialized = true;
67baacf047SPaolo Bonzini if (active) {
68baacf047SPaolo Bonzini event_notifier_set(e);
69baacf047SPaolo Bonzini }
70baacf047SPaolo Bonzini return 0;
71baacf047SPaolo Bonzini
72baacf047SPaolo Bonzini fail:
73baacf047SPaolo Bonzini close(fds[0]);
74baacf047SPaolo Bonzini close(fds[1]);
75baacf047SPaolo Bonzini return ret;
76baacf047SPaolo Bonzini }
77baacf047SPaolo Bonzini
event_notifier_cleanup(EventNotifier * e)78baacf047SPaolo Bonzini void event_notifier_cleanup(EventNotifier *e)
79baacf047SPaolo Bonzini {
80e34e47ebSMaxim Levitsky if (!e->initialized) {
81e34e47ebSMaxim Levitsky return;
82e34e47ebSMaxim Levitsky }
83e34e47ebSMaxim Levitsky
84baacf047SPaolo Bonzini if (e->rfd != e->wfd) {
85baacf047SPaolo Bonzini close(e->rfd);
86baacf047SPaolo Bonzini }
87e34e47ebSMaxim Levitsky
88105e1023SFrediano Ziglio e->rfd = -1;
89baacf047SPaolo Bonzini close(e->wfd);
90aa262928SHalil Pasic e->wfd = -1;
91e34e47ebSMaxim Levitsky e->initialized = false;
92baacf047SPaolo Bonzini }
93baacf047SPaolo Bonzini
event_notifier_get_fd(const EventNotifier * e)9412f0b68cSMarc-André Lureau int event_notifier_get_fd(const EventNotifier *e)
95baacf047SPaolo Bonzini {
96baacf047SPaolo Bonzini return e->rfd;
97baacf047SPaolo Bonzini }
98baacf047SPaolo Bonzini
event_notifier_get_wfd(const EventNotifier * e)993bcf0fb3SSergio Lopez int event_notifier_get_wfd(const EventNotifier *e)
1003bcf0fb3SSergio Lopez {
1013bcf0fb3SSergio Lopez return e->wfd;
1023bcf0fb3SSergio Lopez }
1033bcf0fb3SSergio Lopez
event_notifier_set(EventNotifier * e)104baacf047SPaolo Bonzini int event_notifier_set(EventNotifier *e)
105baacf047SPaolo Bonzini {
106baacf047SPaolo Bonzini static const uint64_t value = 1;
107baacf047SPaolo Bonzini ssize_t ret;
108baacf047SPaolo Bonzini
109e34e47ebSMaxim Levitsky if (!e->initialized) {
110e34e47ebSMaxim Levitsky return -1;
111e34e47ebSMaxim Levitsky }
112e34e47ebSMaxim Levitsky
113baacf047SPaolo Bonzini do {
114baacf047SPaolo Bonzini ret = write(e->wfd, &value, sizeof(value));
115baacf047SPaolo Bonzini } while (ret < 0 && errno == EINTR);
116baacf047SPaolo Bonzini
117baacf047SPaolo Bonzini /* EAGAIN is fine, a read must be pending. */
118baacf047SPaolo Bonzini if (ret < 0 && errno != EAGAIN) {
119baacf047SPaolo Bonzini return -errno;
120baacf047SPaolo Bonzini }
121baacf047SPaolo Bonzini return 0;
122baacf047SPaolo Bonzini }
123baacf047SPaolo Bonzini
event_notifier_test_and_clear(EventNotifier * e)124baacf047SPaolo Bonzini int event_notifier_test_and_clear(EventNotifier *e)
125baacf047SPaolo Bonzini {
126baacf047SPaolo Bonzini int value;
127baacf047SPaolo Bonzini ssize_t len;
128baacf047SPaolo Bonzini char buffer[512];
129baacf047SPaolo Bonzini
130e34e47ebSMaxim Levitsky if (!e->initialized) {
131e34e47ebSMaxim Levitsky return 0;
132e34e47ebSMaxim Levitsky }
133e34e47ebSMaxim Levitsky
134baacf047SPaolo Bonzini /* Drain the notify pipe. For eventfd, only 8 bytes will be read. */
135baacf047SPaolo Bonzini value = 0;
136baacf047SPaolo Bonzini do {
137baacf047SPaolo Bonzini len = read(e->rfd, buffer, sizeof(buffer));
138baacf047SPaolo Bonzini value |= (len > 0);
139baacf047SPaolo Bonzini } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
140baacf047SPaolo Bonzini
141baacf047SPaolo Bonzini return value;
142baacf047SPaolo Bonzini }
143