blob: 2e30e74bd63f800dbd520b37cbf64d1ca016d08f [file] [log] [blame]
Michael S. Tsirkin2292b332010-03-17 13:07:58 +02001/*
2 * event notifier support
3 *
4 * Copyright Red Hat, Inc. 2010
5 *
6 * Authors:
7 * Michael S. Tsirkin <mst@redhat.com>
8 *
Paolo Bonzini6b620ca2012-01-13 17:44:23 +01009 * 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.
Michael S. Tsirkin2292b332010-03-17 13:07:58 +020011 */
12
Peter Maydellaafd7582016-01-29 17:49:55 +000013#include "qemu/osdep.h"
Paolo Bonzinie80c2622012-07-05 17:16:24 +020014#include "qemu-common.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010015#include "qemu/event_notifier.h"
Paolo Bonzinidccfcd02013-04-08 16:55:25 +020016#include "sysemu/char.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010017#include "qemu/main-loop.h"
Paolo Bonzinie80c2622012-07-05 17:16:24 +020018
Michael S. Tsirkin2292b332010-03-17 13:07:58 +020019#ifdef CONFIG_EVENTFD
20#include <sys/eventfd.h>
21#endif
22
Paolo Bonzinie80c2622012-07-05 17:16:24 +020023void event_notifier_init_fd(EventNotifier *e, int fd)
24{
Paolo Bonzinid0cc2fb2010-05-24 17:17:04 +020025 e->rfd = fd;
26 e->wfd = fd;
Paolo Bonzinie80c2622012-07-05 17:16:24 +020027}
28
Michael S. Tsirkin2292b332010-03-17 13:07:58 +020029int event_notifier_init(EventNotifier *e, int active)
30{
Paolo Bonzinid0cc2fb2010-05-24 17:17:04 +020031 int fds[2];
32 int ret;
33
Michael S. Tsirkin2292b332010-03-17 13:07:58 +020034#ifdef CONFIG_EVENTFD
Paolo Bonzinid0cc2fb2010-05-24 17:17:04 +020035 ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
Michael S. Tsirkin2292b332010-03-17 13:07:58 +020036#else
Paolo Bonzinid0cc2fb2010-05-24 17:17:04 +020037 ret = -1;
38 errno = ENOSYS;
Michael S. Tsirkin2292b332010-03-17 13:07:58 +020039#endif
Paolo Bonzinid0cc2fb2010-05-24 17:17:04 +020040 if (ret >= 0) {
41 e->rfd = e->wfd = ret;
42 } else {
43 if (errno != ENOSYS) {
44 return -errno;
45 }
46 if (qemu_pipe(fds) < 0) {
47 return -errno;
48 }
49 ret = fcntl_setfl(fds[0], O_NONBLOCK);
50 if (ret < 0) {
51 ret = -errno;
52 goto fail;
53 }
54 ret = fcntl_setfl(fds[1], O_NONBLOCK);
55 if (ret < 0) {
56 ret = -errno;
57 goto fail;
58 }
59 e->rfd = fds[0];
60 e->wfd = fds[1];
61 }
62 if (active) {
63 event_notifier_set(e);
64 }
65 return 0;
66
67fail:
68 close(fds[0]);
69 close(fds[1]);
70 return ret;
Michael S. Tsirkin2292b332010-03-17 13:07:58 +020071}
72
73void event_notifier_cleanup(EventNotifier *e)
74{
Paolo Bonzinid0cc2fb2010-05-24 17:17:04 +020075 if (e->rfd != e->wfd) {
76 close(e->rfd);
77 }
78 close(e->wfd);
Michael S. Tsirkin2292b332010-03-17 13:07:58 +020079}
80
Marc-André Lureau12f0b682015-10-13 12:12:16 +020081int event_notifier_get_fd(const EventNotifier *e)
Michael S. Tsirkin2292b332010-03-17 13:07:58 +020082{
Paolo Bonzinid0cc2fb2010-05-24 17:17:04 +020083 return e->rfd;
Michael S. Tsirkin2292b332010-03-17 13:07:58 +020084}
85
Paolo Bonzini6bf819f2012-07-05 17:16:28 +020086int event_notifier_set_handler(EventNotifier *e,
87 EventNotifierHandler *handler)
88{
Fam Zheng1e354522015-06-04 14:45:23 +080089 qemu_set_fd_handler(e->rfd, (IOHandler *)handler, NULL, e);
90 return 0;
Paolo Bonzini6bf819f2012-07-05 17:16:28 +020091}
92
Paolo Bonzini2ec10b92012-07-05 17:16:22 +020093int event_notifier_set(EventNotifier *e)
94{
Paolo Bonzinid0cc2fb2010-05-24 17:17:04 +020095 static const uint64_t value = 1;
96 ssize_t ret;
97
98 do {
99 ret = write(e->wfd, &value, sizeof(value));
100 } while (ret < 0 && errno == EINTR);
101
102 /* EAGAIN is fine, a read must be pending. */
103 if (ret < 0 && errno != EAGAIN) {
104 return -errno;
105 }
106 return 0;
Paolo Bonzini2ec10b92012-07-05 17:16:22 +0200107}
108
Michael S. Tsirkin2292b332010-03-17 13:07:58 +0200109int event_notifier_test_and_clear(EventNotifier *e)
110{
Paolo Bonzinid0cc2fb2010-05-24 17:17:04 +0200111 int value;
112 ssize_t len;
113 char buffer[512];
114
115 /* Drain the notify pipe. For eventfd, only 8 bytes will be read. */
116 value = 0;
117 do {
118 len = read(e->rfd, buffer, sizeof(buffer));
119 value |= (len > 0);
120 } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
121
122 return value;
Michael S. Tsirkin2292b332010-03-17 13:07:58 +0200123}