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/cutils.h"
  15#include "qemu/event_notifier.h"
  16#include "qemu/main-loop.h"
  17
  18#ifdef CONFIG_EVENTFD
  19#include <sys/eventfd.h>
  20#endif
  21
  22#ifdef CONFIG_EVENTFD
  23/*
  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{
  29    e->rfd = fd;
  30    e->wfd = fd;
  31    e->initialized = true;
  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 (!g_unix_open_pipe(fds, FD_CLOEXEC, NULL)) {
  53            return -errno;
  54        }
  55        if (!g_unix_set_fd_nonblocking(fds[0], true, NULL)) {
  56            ret = -errno;
  57            goto fail;
  58        }
  59        if (!g_unix_set_fd_nonblocking(fds[1], true, NULL)) {
  60            ret = -errno;
  61            goto fail;
  62        }
  63        e->rfd = fds[0];
  64        e->wfd = fds[1];
  65    }
  66    e->initialized = true;
  67    if (active) {
  68        event_notifier_set(e);
  69    }
  70    return 0;
  71
  72fail:
  73    close(fds[0]);
  74    close(fds[1]);
  75    return ret;
  76}
  77
  78void event_notifier_cleanup(EventNotifier *e)
  79{
  80    if (!e->initialized) {
  81        return;
  82    }
  83
  84    if (e->rfd != e->wfd) {
  85        close(e->rfd);
  86    }
  87
  88    e->rfd = -1;
  89    close(e->wfd);
  90    e->wfd = -1;
  91    e->initialized = false;
  92}
  93
  94int event_notifier_get_fd(const EventNotifier *e)
  95{
  96    return e->rfd;
  97}
  98
  99int event_notifier_get_wfd(const EventNotifier *e)
 100{
 101    return e->wfd;
 102}
 103
 104int event_notifier_set(EventNotifier *e)
 105{
 106    static const uint64_t value = 1;
 107    ssize_t ret;
 108
 109    if (!e->initialized) {
 110        return -1;
 111    }
 112
 113    do {
 114        ret = write(e->wfd, &value, sizeof(value));
 115    } while (ret < 0 && errno == EINTR);
 116
 117    /* EAGAIN is fine, a read must be pending.  */
 118    if (ret < 0 && errno != EAGAIN) {
 119        return -errno;
 120    }
 121    return 0;
 122}
 123
 124int event_notifier_test_and_clear(EventNotifier *e)
 125{
 126    int value;
 127    ssize_t len;
 128    char buffer[512];
 129
 130    if (!e->initialized) {
 131        return 0;
 132    }
 133
 134    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
 135    value = 0;
 136    do {
 137        len = read(e->rfd, buffer, sizeof(buffer));
 138        value |= (len > 0);
 139    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
 140
 141    return value;
 142}
 143