func: bool aio_poll(AioContext *ctx, bool blocking)
  
  {
  
      AioHandler *node;
  
      int i, ret;
  
      bool progress;
  
      int64_t timeout;
  
  
  
      aio_context_acquire(ctx);
  
      progress = false;
  
  
  
      /* aio_notify can avoid the expensive event_notifier_set if
  
       * everything (file descriptors, bottom halves, timers) will
  
       * be re-evaluated before the next blocking poll().  This is
  
       * already true when aio_poll is called with blocking == false;
  
       * if blocking == true, it is only true after poll() returns,
  
       * so disable the optimization now.
  
       */
  
      if (blocking) {
  
          atomic_add(&ctx->notify_me, 2);
  
      }
  
  
  
      ctx->walking_handlers++;
  
  
  
      assert(npfd == 0);
  
  
  
      /* fill pollfds */
  
  
  
      if (!aio_epoll_enabled(ctx)) {
  
          QLIST_FOREACH(node, &ctx->aio_handlers, node) {
  
              if (!node->deleted && node->pfd.events
  
                  && aio_node_check(ctx, node->is_external)) {
  
                  add_pollfd(node);
  
              }
  
          }
  
      }
  
  
  
      timeout = blocking ? aio_compute_timeout(ctx) : 0;
  
  
  
      /* wait until next event */
  
      if (timeout) {
  
          aio_context_release(ctx);
  
      }
  
      if (aio_epoll_check_poll(ctx, pollfds, npfd, timeout)) {
  
          AioHandler epoll_handler;
  
  
  
          epoll_handler.pfd.fd = ctx->epollfd;
  
          epoll_handler.pfd.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR;
  
          npfd = 0;
  
          add_pollfd(&epoll_handler);
  
          ret = aio_epoll(ctx, pollfds, npfd, timeout);
  
      } else  {
  
          ret = qemu_poll_ns(pollfds, npfd, timeout);
  
      }
  
      if (blocking) {
  
          atomic_sub(&ctx->notify_me, 2);
  
      }
  
      if (timeout) {
  
          aio_context_acquire(ctx);
  
      }
  
  
  
      aio_notify_accept(ctx);
  
  
  
      /* if we have any readable fds, dispatch event */
  
      if (ret > 0) {
  
          for (i = 0; i < npfd; i++) {
  
              nodes[i]->pfd.revents = pollfds[i].revents;
  
          }
  
      }
  
  
  
      npfd = 0;
  
      ctx->walking_handlers--;
  
  
  
      /* Run dispatch even if there were no readable fds to run timers */
  
      if (aio_dispatch(ctx, ret > 0)) {
  
          progress = true;
  
      }
  
  
  
      aio_context_release(ctx);
  
  
  
      return progress;
  
  }
  