select.cpp 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <errno.h>
  7. #include <stdio.h>
  8. #include <sys/poll.h>
  9. #include <sys/select.h>
  10. #include <sys/time.h>
  11. #include <syscall.h>
  12. #include <AK/Vector.h>
  13. extern "C" {
  14. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html
  15. int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, timeval* timeout_tv)
  16. {
  17. timespec* timeout_ts = nullptr;
  18. timespec timeout;
  19. if (timeout_tv) {
  20. timeout_ts = &timeout;
  21. TIMEVAL_TO_TIMESPEC(timeout_tv, timeout_ts);
  22. }
  23. return pselect(nfds, readfds, writefds, exceptfds, timeout_ts, nullptr);
  24. }
  25. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html
  26. int pselect(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, timespec const* timeout, sigset_t const* sigmask)
  27. {
  28. Vector<pollfd, FD_SETSIZE> fds;
  29. if (nfds < 0 || static_cast<size_t>(nfds) >= fds.capacity())
  30. return EINVAL;
  31. for (int fd = 0; fd < nfds; fd++) {
  32. short events = 0;
  33. if (readfds && FD_ISSET(fd, readfds))
  34. events |= POLLIN;
  35. if (writefds && FD_ISSET(fd, writefds))
  36. events |= POLLOUT;
  37. if (exceptfds && FD_ISSET(fd, exceptfds))
  38. events |= POLLPRI;
  39. if (!events)
  40. continue;
  41. fds.unchecked_append({ fd, events, 0 });
  42. }
  43. if (ppoll(fds.data(), fds.size(), timeout, sigmask) < 0)
  44. return -1;
  45. if (readfds)
  46. FD_ZERO(readfds);
  47. if (writefds)
  48. FD_ZERO(writefds);
  49. if (exceptfds)
  50. FD_ZERO(exceptfds);
  51. int marked_fd_count = 0;
  52. for (auto& fd_entry : fds) {
  53. if (fd_entry.revents == 0)
  54. continue;
  55. if (readfds && (fd_entry.revents & POLLIN)) {
  56. FD_SET(fd_entry.fd, readfds);
  57. marked_fd_count++;
  58. }
  59. if (writefds && (fd_entry.revents & POLLOUT)) {
  60. FD_SET(fd_entry.fd, writefds);
  61. marked_fd_count++;
  62. }
  63. if (exceptfds && (fd_entry.revents & (POLLPRI | POLLERR | POLLHUP))) {
  64. FD_SET(fd_entry.fd, exceptfds);
  65. marked_fd_count++;
  66. }
  67. }
  68. return marked_fd_count;
  69. }
  70. }