qemu
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_EVENTFD19#include <sys/eventfd.h>20#endif21
22#ifdef CONFIG_EVENTFD23/*
24* Initialize @e with existing file descriptor @fd.
25* @fd must be a genuine eventfd object, emulation with pipe won't do.
26*/
27void event_notifier_init_fd(EventNotifier *e, int fd)28{
29e->rfd = fd;30e->wfd = fd;31e->initialized = true;32}
33#endif34
35int event_notifier_init(EventNotifier *e, int active)36{
37int fds[2];38int ret;39
40#ifdef CONFIG_EVENTFD41ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);42#else43ret = -1;44errno = ENOSYS;45#endif46if (ret >= 0) {47e->rfd = e->wfd = ret;48} else {49if (errno != ENOSYS) {50return -errno;51}52if (!g_unix_open_pipe(fds, FD_CLOEXEC, NULL)) {53return -errno;54}55if (!g_unix_set_fd_nonblocking(fds[0], true, NULL)) {56ret = -errno;57goto fail;58}59if (!g_unix_set_fd_nonblocking(fds[1], true, NULL)) {60ret = -errno;61goto fail;62}63e->rfd = fds[0];64e->wfd = fds[1];65}66e->initialized = true;67if (active) {68event_notifier_set(e);69}70return 0;71
72fail:73close(fds[0]);74close(fds[1]);75return ret;76}
77
78void event_notifier_cleanup(EventNotifier *e)79{
80if (!e->initialized) {81return;82}83
84if (e->rfd != e->wfd) {85close(e->rfd);86}87
88e->rfd = -1;89close(e->wfd);90e->wfd = -1;91e->initialized = false;92}
93
94int event_notifier_get_fd(const EventNotifier *e)95{
96return e->rfd;97}
98
99int event_notifier_get_wfd(const EventNotifier *e)100{
101return e->wfd;102}
103
104int event_notifier_set(EventNotifier *e)105{
106static const uint64_t value = 1;107ssize_t ret;108
109if (!e->initialized) {110return -1;111}112
113do {114ret = write(e->wfd, &value, sizeof(value));115} while (ret < 0 && errno == EINTR);116
117/* EAGAIN is fine, a read must be pending. */118if (ret < 0 && errno != EAGAIN) {119return -errno;120}121return 0;122}
123
124int event_notifier_test_and_clear(EventNotifier *e)125{
126int value;127ssize_t len;128char buffer[512];129
130if (!e->initialized) {131return 0;132}133
134/* Drain the notify pipe. For eventfd, only 8 bytes will be read. */135value = 0;136do {137len = read(e->rfd, buffer, sizeof(buffer));138value |= (len > 0);139} while ((len == -1 && errno == EINTR) || len == sizeof(buffer));140
141return value;142}
143