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-common.h"
  14#include "qemu/event_notifier.h"
  15#include "char/char.h"
  16#include "qemu/main-loop.h"
  17
  18#ifdef CONFIG_EVENTFD
  19#include <sys/eventfd.h>
  20#endif
  21
  22void event_notifier_init_fd(EventNotifier *e, int fd)
  23{
  24    e->rfd = fd;
  25    e->wfd = fd;
  26}
  27
  28int event_notifier_init(EventNotifier *e, int active)
  29{
  30    int fds[2];
  31    int ret;
  32
  33#ifdef CONFIG_EVENTFD
  34    ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
  35#else
  36    ret = -1;
  37    errno = ENOSYS;
  38#endif
  39    if (ret >= 0) {
  40        e->rfd = e->wfd = ret;
  41    } else {
  42        if (errno != ENOSYS) {
  43            return -errno;
  44        }
  45        if (qemu_pipe(fds) < 0) {
  46            return -errno;
  47        }
  48        ret = fcntl_setfl(fds[0], O_NONBLOCK);
  49        if (ret < 0) {
  50            ret = -errno;
  51            goto fail;
  52        }
  53        ret = fcntl_setfl(fds[1], O_NONBLOCK);
  54        if (ret < 0) {
  55            ret = -errno;
  56            goto fail;
  57        }
  58        e->rfd = fds[0];
  59        e->wfd = fds[1];
  60    }
  61    if (active) {
  62        event_notifier_set(e);
  63    }
  64    return 0;
  65
  66fail:
  67    close(fds[0]);
  68    close(fds[1]);
  69    return ret;
  70}
  71
  72void event_notifier_cleanup(EventNotifier *e)
  73{
  74    if (e->rfd != e->wfd) {
  75        close(e->rfd);
  76    }
  77    close(e->wfd);
  78}
  79
  80int event_notifier_get_fd(EventNotifier *e)
  81{
  82    return e->rfd;
  83}
  84
  85int event_notifier_set_handler(EventNotifier *e,
  86                               EventNotifierHandler *handler)
  87{
  88    return qemu_set_fd_handler(e->rfd, (IOHandler *)handler, NULL, e);
  89}
  90
  91int event_notifier_set(EventNotifier *e)
  92{
  93    static const uint64_t value = 1;
  94    ssize_t ret;
  95
  96    do {
  97        ret = write(e->wfd, &value, sizeof(value));
  98    } while (ret < 0 && errno == EINTR);
  99
 100    /* EAGAIN is fine, a read must be pending.  */
 101    if (ret < 0 && errno != EAGAIN) {
 102        return -errno;
 103    }
 104    return 0;
 105}
 106
 107int event_notifier_test_and_clear(EventNotifier *e)
 108{
 109    int value;
 110    ssize_t len;
 111    char buffer[512];
 112
 113    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
 114    value = 0;
 115    do {
 116        len = read(e->rfd, buffer, sizeof(buffer));
 117        value |= (len > 0);
 118    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
 119
 120    return value;
 121}
 122