Poller.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * Copyright (C) 2016 Intel Corporation. All rights reserved.
  3. *
  4. * This file is free software: you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This file is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. * See the GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <errno.h>
  18. #include <fcntl.h>
  19. #include <inttypes.h>
  20. #include <stdio.h>
  21. #include <sys/epoll.h>
  22. #include <sys/eventfd.h>
  23. #include <sys/types.h>
  24. #include <sys/uio.h>
  25. #include <unistd.h>
  26. #include "Poller.h"
  27. extern const AP_HAL::HAL &hal;
  28. namespace Linux {
  29. void WakeupPollable::on_can_read()
  30. {
  31. ssize_t r;
  32. uint64_t val;
  33. do {
  34. r = read(_fd, &val, sizeof(val));
  35. } while (!(r == -1 && errno == EAGAIN));
  36. }
  37. Poller::Poller()
  38. {
  39. _epfd = epoll_create1(EPOLL_CLOEXEC);
  40. if (_epfd == -1) {
  41. fprintf(stderr, "Failed to create epoll: %m\n");
  42. return;
  43. }
  44. _wakeup._fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
  45. if (_wakeup._fd == -1) {
  46. fprintf(stderr, "Failed to create wakeup fd: %m\n");
  47. goto fail_eventfd;
  48. }
  49. if (!register_pollable(&_wakeup, EPOLLIN)) {
  50. fprintf(stderr, "Failed to add wakeup fd\n");
  51. goto fail_register;
  52. }
  53. return;
  54. fail_register:
  55. close(_wakeup._fd);
  56. _wakeup._fd = -1;
  57. fail_eventfd:
  58. close(_epfd);
  59. _epfd = -1;
  60. }
  61. bool Poller::register_pollable(Pollable *p, uint32_t events)
  62. {
  63. /*
  64. * EPOLLWAKEUP prevents the system from hibernating or suspending when
  65. * inside epoll_wait() for this particular event. It is silently
  66. * ignored if the process does not have the CAP_BLOCK_SUSPEND
  67. * capability.
  68. */
  69. events |= EPOLLWAKEUP;
  70. if (_epfd < 0) {
  71. return false;
  72. }
  73. struct epoll_event epev = { };
  74. epev.events = events;
  75. epev.data.ptr = static_cast<void *>(p);
  76. return epoll_ctl(_epfd, EPOLL_CTL_ADD, p->get_fd(), &epev) == 0;
  77. }
  78. void Poller::unregister_pollable(const Pollable *p)
  79. {
  80. if (_epfd >= 0 && p->get_fd() >= 0) {
  81. epoll_ctl(_epfd, EPOLL_CTL_DEL, p->get_fd(), nullptr);
  82. }
  83. }
  84. int Poller::poll() const
  85. {
  86. const int max_events = 16;
  87. epoll_event events[max_events];
  88. int r;
  89. do {
  90. r = epoll_wait(_epfd, events, max_events, -1);
  91. } while (r < 0 && errno == EINTR);
  92. if (r < 0) {
  93. return -errno;
  94. }
  95. for (int i = 0; i < r; i++) {
  96. Pollable *p = static_cast<Pollable *>(events[i].data.ptr);
  97. if (events[i].events & EPOLLIN) {
  98. p->on_can_read();
  99. }
  100. if (events[i].events & EPOLLOUT) {
  101. p->on_can_write();
  102. }
  103. if (events[i].events & EPOLLERR) {
  104. p->on_error();
  105. }
  106. if (events[i].events & EPOLLHUP) {
  107. p->on_hang_up();
  108. }
  109. }
  110. return r;
  111. }
  112. void Poller::wakeup() const
  113. {
  114. ssize_t r;
  115. uint64_t val = 1;
  116. do {
  117. r = write(_wakeup.get_fd(), &val, sizeof(val));
  118. } while (r == -1 && errno == EINTR);
  119. if (r == -1) {
  120. fprintf(stderr, "Failed to wakeup poller: %m\n");
  121. }
  122. }
  123. Pollable::~Pollable()
  124. {
  125. /*
  126. * Make sure to remove the file descriptor from epoll since events could
  127. * continue to be reported if the file descriptor was dup()'ed. However
  128. * we rely on user unregistering it rather than taking a reference to the
  129. * Poller. Here we just close our file descriptor.
  130. */
  131. if (_fd >= 0) {
  132. close(_fd);
  133. }
  134. }
  135. }