text: // Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/
  //
  // SPDX-License-Identifier: BSD-2-Clause
  
  #include <wasi/api.h>
  #include <errno.h>
  #include <poll.h>
  #include <stdbool.h>
  
  int poll(struct pollfd *fds, size_t nfds, int timeout) {
    // Construct events for poll().
    size_t maxevents = 2 * nfds + 1;
    __wasi_subscription_t subscriptions[maxevents];
    size_t nsubscriptions = 0;
    for (size_t i = 0; i < nfds; ++i) {
      struct pollfd *pollfd = &fds[i];
      if (pollfd->fd < 0)
        continue;
      bool created_events = false;
      if ((pollfd->events & POLLRDNORM) != 0) {
        __wasi_subscription_t *subscription = &subscriptions[nsubscriptions++];
        *subscription = (__wasi_subscription_t){
            .userdata = (uintptr_t)pollfd,
            .u.tag = __WASI_EVENTTYPE_FD_READ,
            .u.u.fd_read.file_descriptor = pollfd->fd,
        };
        created_events = true;
      }
      if ((pollfd->events & POLLWRNORM) != 0) {
        __wasi_subscription_t *subscription = &subscriptions[nsubscriptions++];
        *subscription = (__wasi_subscription_t){
            .userdata = (uintptr_t)pollfd,
            .u.tag = __WASI_EVENTTYPE_FD_WRITE,
            .u.u.fd_write.file_descriptor = pollfd->fd,
        };
        created_events = true;
      }
  
      // As entries are decomposed into separate read/write subscriptions,
      // we cannot detect POLLERR, POLLHUP and POLLNVAL if POLLRDNORM and
      // POLLWRNORM are not specified. Disallow this for now.
      if (!created_events) {
        errno = ENOSYS;
        return -1;
      }
    }
  
    // Create extra event for the timeout.
    if (timeout >= 0) {
      __wasi_subscription_t *subscription = &subscriptions[nsubscriptions++];
      *subscription = (__wasi_subscription_t){
          .u.tag = __WASI_EVENTTYPE_CLOCK,
          .u.u.clock.id = __WASI_CLOCKID_REALTIME,
          .u.u.clock.timeout = (__wasi_timestamp_t)timeout * 1000000,
      };
    }
  
    // Execute poll().
    size_t nevents;
    __wasi_event_t events[nsubscriptions];
    __wasi_errno_t error =
        __wasi_poll_oneoff(subscriptions, events, nsubscriptions, &nevents);
    if (error != 0) {
      // WASI's poll requires at least one subscription, or else it returns
      // `EINVAL`. Since a `poll` with nothing to wait for is valid in POSIX,
      // return `ENOTSUP` to indicate that we don't support that case.
      //
      // Wasm has no signal handling, so if none of the user-provided `pollfd`
      // elements, nor the timeout, led us to producing even one subscription
      // to wait for, there would be no way for the poll to wake up. WASI
      // returns `EINVAL` in this case, but for users of `poll`, `ENOTSUP` is
      // more likely to be understood.
      if (nsubscriptions == 0)
        errno = ENOTSUP;
      else
        errno = error;
      return -1;
    }
  
    // Clear revents fields.
    for (size_t i = 0; i < nfds; ++i) {
      struct pollfd *pollfd = &fds[i];
      pollfd->revents = 0;
    }
  
    // Set revents fields.
    for (size_t i = 0; i < nevents; ++i) {
      const __wasi_event_t *event = &events[i];
      if (event->type == __WASI_EVENTTYPE_FD_READ ||
          event->type == __WASI_EVENTTYPE_FD_WRITE) {
        struct pollfd *pollfd = (struct pollfd *)(uintptr_t)event->userdata;
        if (event->error == __WASI_ERRNO_BADF) {
          // Invalid file descriptor.
          pollfd->revents |= POLLNVAL;
        } else if (event->error == __WASI_ERRNO_PIPE) {
          // Hangup on write side of pipe.
          pollfd->revents |= POLLHUP;
        } else if (event->error != 0) {
          // Another error occurred.
          pollfd->revents |= POLLERR;
        } else {
          // Data can be read or written.
          if (event->type == __WASI_EVENTTYPE_FD_READ) {
              pollfd->revents |= POLLRDNORM;
              if (event->fd_readwrite.flags & __WASI_EVENTRWFLAGS_FD_READWRITE_HANGUP) {
                pollfd->revents |= POLLHUP;
              }
          } else if (event->type == __WASI_EVENTTYPE_FD_WRITE) {
              pollfd->revents |= POLLWRNORM;
              if (event->fd_readwrite.flags & __WASI_EVENTRWFLAGS_FD_READWRITE_HANGUP) {
                pollfd->revents |= POLLHUP;
              }
          }
        }
      }
    }
  
    // Return the number of events with a non-zero revents value.
    int retval = 0;
    for (size_t i = 0; i < nfds; ++i) {
      struct pollfd *pollfd = &fds[i];
      // POLLHUP contradicts with POLLWRNORM.
      if ((pollfd->revents & POLLHUP) != 0)
        pollfd->revents &= ~POLLWRNORM;
      if (pollfd->revents != 0)
        ++retval;
    }
    return retval;
  }
  