qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

event_notifier-posix.c (2798B)


      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  */
     27 void 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 
     35 int 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 
     72 fail:
     73     close(fds[0]);
     74     close(fds[1]);
     75     return ret;
     76 }
     77 
     78 void 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 
     94 int event_notifier_get_fd(const EventNotifier *e)
     95 {
     96     return e->rfd;
     97 }
     98 
     99 int event_notifier_get_wfd(const EventNotifier *e)
    100 {
    101     return e->wfd;
    102 }
    103 
    104 int 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 
    124 int 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 }