select.cpp 2.3 KB

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