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    e->initialized = true;
  33}
  34#endif
  35
  36int event_notifier_init(EventNotifier *e, int active)
  37{
  38    int fds[2];
  39    int ret;
  40
  41#ifdef CONFIG_EVENTFD
  42    ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
  43#else
  44    ret = -1;
  45    errno = ENOSYS;
  46#endif
  47    if (ret >= 0) {
  48        e->rfd = e->wfd = ret;
  49    } else {
  50        if (errno != ENOSYS) {
  51            return -errno;
  52        }
  53        if (qemu_pipe(fds) < 0) {
  54            return -errno;
  55        }
  56        ret = fcntl_setfl(fds[0], O_NONBLOCK);
  57        if (ret < 0) {
  58            ret = -errno;
  59            goto fail;
  60        }
  61        ret = fcntl_setfl(fds[1], O_NONBLOCK);
  62        if (ret < 0) {
  63            ret = -errno;
  64            goto fail;
  65        }
  66        e->rfd = fds[0];
  67        e->wfd = fds[1];
  68    }
  69    e->initialized = true;
  70    if (active) {
  71        event_notifier_set(e);
  72    }
  73    return 0;
  74
  75fail:
  76    close(fds[0]);
  77    close(fds[1]);
  78    return ret;
  79}
  80
  81void event_notifier_cleanup(EventNotifier *e)
  82{
  83    if (!e->initialized) {
  84        return;
  85    }
  86
  87    if (e->rfd != e->wfd) {
  88        close(e->rfd);
  89    }
  90
  91    e->rfd = -1;
  92    close(e->wfd);
  93    e->wfd = -1;
  94    e->initialized = false;
  95}
  96
  97int event_notifier_get_fd(const EventNotifier *e)
  98{
  99    return e->rfd;
 100}
 101
 102int event_notifier_set(EventNotifier *e)
 103{
 104    static const uint64_t value = 1;
 105    ssize_t ret;
 106
 107    if (!e->initialized) {
 108        return -1;
 109    }
 110
 111    do {
 112        ret = write(e->wfd, &value, sizeof(value));
 113    } while (ret < 0 && errno == EINTR);
 114
 115    /* EAGAIN is fine, a read must be pending.  */
 116    if (ret < 0 && errno != EAGAIN) {
 117        return -errno;
 118    }
 119    return 0;
 120}
 121
 122int event_notifier_test_and_clear(EventNotifier *e)
 123{
 124    int value;
 125    ssize_t len;
 126    char buffer[512];
 127
 128    if (!e->initialized) {
 129        return 0;
 130    }
 131
 132    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
 133    value = 0;
 134    do {
 135        len = read(e->rfd, buffer, sizeof(buffer));
 136        value |= (len > 0);
 137    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
 138
 139    return value;
 140}
 141