qemu/util/event_notifier-posix.c
<<
>>
Prefs
   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-common.h"
  15#include "qemu/cutils.h"
  16#include "qemu/event_notifier.h"
  17#include "qemu/main-loop.h"
  18
  19#ifdef CONFIG_EVENTFD
  20#include <sys/eventfd.h>
  21#endif
  22
  23#ifdef CONFIG_EVENTFD
  24/*
  25 * Initialize @e with existing file descriptor @fd.
  26 * @fd must be a genuine eventfd object, emulation with pipe won't do.
  27 */
  28void event_notifier_init_fd(EventNotifier *e, int fd)
  29{
  30    e->rfd = fd;
  31    e->wfd = fd;
  32}
  33#endif
  34
  35int 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 (qemu_pipe(fds) < 0) {
  53            return -errno;
  54        }
  55        ret = fcntl_setfl(fds[0], O_NONBLOCK);
  56        if (ret < 0) {
  57            ret = -errno;
  58            goto fail;
  59        }
  60        ret = fcntl_setfl(fds[1], O_NONBLOCK);
  61        if (ret < 0) {
  62            ret = -errno;
  63            goto fail;
  64        }
  65        e->rfd = fds[0];
  66        e->wfd = fds[1];
  67    }
  68    if (active) {
  69        event_notifier_set(e);
  70    }
  71    return 0;
  72
  73fail:
  74    close(fds[0]);
  75    close(fds[1]);
  76    return ret;
  77}
  78
  79void event_notifier_cleanup(EventNotifier *e)
  80{
  81    if (e->rfd != e->wfd) {
  82        close(e->rfd);
  83        e->rfd = -1;
  84    }
  85    close(e->wfd);
  86    e->wfd = -1;
  87}
  88
  89int event_notifier_get_fd(const EventNotifier *e)
  90{
  91    return e->rfd;
  92}
  93
  94int event_notifier_set(EventNotifier *e)
  95{
  96    static const uint64_t value = 1;
  97    ssize_t ret;
  98
  99    do {
 100        ret = write(e->wfd, &value, sizeof(value));
 101    } while (ret < 0 && errno == EINTR);
 102
 103    /* EAGAIN is fine, a read must be pending.  */
 104    if (ret < 0 && errno != EAGAIN) {
 105        return -errno;
 106    }
 107    return 0;
 108}
 109
 110int event_notifier_test_and_clear(EventNotifier *e)
 111{
 112    int value;
 113    ssize_t len;
 114    char buffer[512];
 115
 116    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
 117    value = 0;
 118    do {
 119        len = read(e->rfd, buffer, sizeof(buffer));
 120        value |= (len > 0);
 121    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
 122
 123    return value;
 124}
 125