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 "sysemu/char.h"
  18#include "qemu/main-loop.h"
  19
  20#ifdef CONFIG_EVENTFD
  21#include <sys/eventfd.h>
  22#endif
  23
  24#ifdef CONFIG_EVENTFD
  25/*
  26 * Initialize @e with existing file descriptor @fd.
  27 * @fd must be a genuine eventfd object, emulation with pipe won't do.
  28 */
  29void event_notifier_init_fd(EventNotifier *e, int fd)
  30{
  31    e->rfd = fd;
  32    e->wfd = fd;
  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    if (active) {
  70        event_notifier_set(e);
  71    }
  72    return 0;
  73
  74fail:
  75    close(fds[0]);
  76    close(fds[1]);
  77    return ret;
  78}
  79
  80void event_notifier_cleanup(EventNotifier *e)
  81{
  82    if (e->rfd != e->wfd) {
  83        close(e->rfd);
  84    }
  85    close(e->wfd);
  86}
  87
  88int event_notifier_get_fd(const EventNotifier *e)
  89{
  90    return e->rfd;
  91}
  92
  93int event_notifier_set_handler(EventNotifier *e,
  94                               bool is_external,
  95                               EventNotifierHandler *handler)
  96{
  97    aio_set_fd_handler(iohandler_get_aio_context(), e->rfd, is_external,
  98                       (IOHandler *)handler, NULL, e);
  99    return 0;
 100}
 101
 102int event_notifier_set(EventNotifier *e)
 103{
 104    static const uint64_t value = 1;
 105    ssize_t ret;
 106
 107    do {
 108        ret = write(e->wfd, &value, sizeof(value));
 109    } while (ret < 0 && errno == EINTR);
 110
 111    /* EAGAIN is fine, a read must be pending.  */
 112    if (ret < 0 && errno != EAGAIN) {
 113        return -errno;
 114    }
 115    return 0;
 116}
 117
 118int event_notifier_test_and_clear(EventNotifier *e)
 119{
 120    int value;
 121    ssize_t len;
 122    char buffer[512];
 123
 124    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
 125    value = 0;
 126    do {
 127        len = read(e->rfd, buffer, sizeof(buffer));
 128        value |= (len > 0);
 129    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
 130
 131    return value;
 132}
 133