epoll.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2. * contributor license agreements. See the NOTICE file distributed with
  3. * this work for additional information regarding copyright ownership.
  4. * The ASF licenses this file to You under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "apr_arch_poll_private.h"
  17. #ifdef POLLSET_USES_EPOLL
  18. static apr_int16_t get_epoll_event(apr_int16_t event)
  19. {
  20. apr_int16_t rv = 0;
  21. if (event & APR_POLLIN)
  22. rv |= EPOLLIN;
  23. if (event & APR_POLLPRI)
  24. rv |= EPOLLPRI;
  25. if (event & APR_POLLOUT)
  26. rv |= EPOLLOUT;
  27. if (event & APR_POLLERR)
  28. rv |= EPOLLERR;
  29. if (event & APR_POLLHUP)
  30. rv |= EPOLLHUP;
  31. /* APR_POLLNVAL is not handled by epoll. */
  32. return rv;
  33. }
  34. static apr_int16_t get_epoll_revent(apr_int16_t event)
  35. {
  36. apr_int16_t rv = 0;
  37. if (event & EPOLLIN)
  38. rv |= APR_POLLIN;
  39. if (event & EPOLLPRI)
  40. rv |= APR_POLLPRI;
  41. if (event & EPOLLOUT)
  42. rv |= APR_POLLOUT;
  43. if (event & EPOLLERR)
  44. rv |= APR_POLLERR;
  45. if (event & EPOLLHUP)
  46. rv |= APR_POLLHUP;
  47. /* APR_POLLNVAL is not handled by epoll. */
  48. return rv;
  49. }
  50. struct apr_pollset_t
  51. {
  52. apr_pool_t *pool;
  53. apr_uint32_t nelts;
  54. apr_uint32_t nalloc;
  55. int epoll_fd;
  56. struct epoll_event *pollset;
  57. apr_pollfd_t *result_set;
  58. apr_uint32_t flags;
  59. #if APR_HAS_THREADS
  60. /* A thread mutex to protect operations on the rings */
  61. apr_thread_mutex_t *ring_lock;
  62. #endif
  63. /* A ring containing all of the pollfd_t that are active */
  64. APR_RING_HEAD(pfd_query_ring_t, pfd_elem_t) query_ring;
  65. /* A ring of pollfd_t that have been used, and then _remove()'d */
  66. APR_RING_HEAD(pfd_free_ring_t, pfd_elem_t) free_ring;
  67. /* A ring of pollfd_t where rings that have been _remove()`ed but
  68. might still be inside a _poll() */
  69. APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring;
  70. };
  71. static apr_status_t backend_cleanup(void *p_)
  72. {
  73. apr_pollset_t *pollset = (apr_pollset_t *) p_;
  74. close(pollset->epoll_fd);
  75. return APR_SUCCESS;
  76. }
  77. APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
  78. apr_uint32_t size,
  79. apr_pool_t *p,
  80. apr_uint32_t flags)
  81. {
  82. apr_status_t rv;
  83. int fd;
  84. fd = epoll_create(size);
  85. if (fd < 0) {
  86. *pollset = NULL;
  87. return errno;
  88. }
  89. *pollset = apr_palloc(p, sizeof(**pollset));
  90. #if APR_HAS_THREADS
  91. if (flags & APR_POLLSET_THREADSAFE &&
  92. ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock,
  93. APR_THREAD_MUTEX_DEFAULT,
  94. p) != APR_SUCCESS))) {
  95. *pollset = NULL;
  96. return rv;
  97. }
  98. #else
  99. if (flags & APR_POLLSET_THREADSAFE) {
  100. *pollset = NULL;
  101. return APR_ENOTIMPL;
  102. }
  103. #endif
  104. (*pollset)->nelts = 0;
  105. (*pollset)->nalloc = size;
  106. (*pollset)->flags = flags;
  107. (*pollset)->pool = p;
  108. (*pollset)->epoll_fd = fd;
  109. (*pollset)->pollset = apr_palloc(p, size * sizeof(struct epoll_event));
  110. apr_pool_cleanup_register(p, *pollset, backend_cleanup, backend_cleanup);
  111. (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
  112. APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link);
  113. APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link);
  114. APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link);
  115. return APR_SUCCESS;
  116. }
  117. APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset)
  118. {
  119. return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup);
  120. }
  121. APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
  122. const apr_pollfd_t *descriptor)
  123. {
  124. struct epoll_event ev;
  125. int ret = -1;
  126. pfd_elem_t *elem;
  127. apr_status_t rv = APR_SUCCESS;
  128. pollset_lock_rings();
  129. if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) {
  130. elem = APR_RING_FIRST(&(pollset->free_ring));
  131. APR_RING_REMOVE(elem, link);
  132. }
  133. else {
  134. elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t));
  135. APR_RING_ELEM_INIT(elem, link);
  136. }
  137. elem->pfd = *descriptor;
  138. ev.events = get_epoll_event(descriptor->reqevents);
  139. ev.data.ptr = elem;
  140. if (descriptor->desc_type == APR_POLL_SOCKET) {
  141. ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD,
  142. descriptor->desc.s->socketdes, &ev);
  143. }
  144. else {
  145. ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD,
  146. descriptor->desc.f->filedes, &ev);
  147. }
  148. if (0 != ret) {
  149. rv = APR_EBADF;
  150. APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link);
  151. }
  152. else {
  153. pollset->nelts++;
  154. APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link);
  155. }
  156. pollset_unlock_rings();
  157. return rv;
  158. }
  159. APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
  160. const apr_pollfd_t *descriptor)
  161. {
  162. pfd_elem_t *ep;
  163. apr_status_t rv = APR_SUCCESS;
  164. struct epoll_event ev;
  165. int ret = -1;
  166. pollset_lock_rings();
  167. ev.events = get_epoll_event(descriptor->reqevents);
  168. if (descriptor->desc_type == APR_POLL_SOCKET) {
  169. ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL,
  170. descriptor->desc.s->socketdes, &ev);
  171. }
  172. else {
  173. ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL,
  174. descriptor->desc.f->filedes, &ev);
  175. }
  176. if (ret < 0) {
  177. rv = APR_NOTFOUND;
  178. }
  179. if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) {
  180. for (ep = APR_RING_FIRST(&(pollset->query_ring));
  181. ep != APR_RING_SENTINEL(&(pollset->query_ring),
  182. pfd_elem_t, link);
  183. ep = APR_RING_NEXT(ep, link)) {
  184. if (descriptor->desc.s == ep->pfd.desc.s) {
  185. APR_RING_REMOVE(ep, link);
  186. APR_RING_INSERT_TAIL(&(pollset->dead_ring),
  187. ep, pfd_elem_t, link);
  188. break;
  189. }
  190. }
  191. }
  192. pollset_unlock_rings();
  193. return rv;
  194. }
  195. APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
  196. apr_interval_time_t timeout,
  197. apr_int32_t *num,
  198. const apr_pollfd_t **descriptors)
  199. {
  200. int ret, i;
  201. apr_status_t rv = APR_SUCCESS;
  202. if (timeout > 0) {
  203. timeout /= 1000;
  204. }
  205. ret = epoll_wait(pollset->epoll_fd, pollset->pollset, pollset->nalloc,
  206. timeout);
  207. (*num) = ret;
  208. if (ret < 0) {
  209. rv = apr_get_netos_error();
  210. }
  211. else if (ret == 0) {
  212. rv = APR_TIMEUP;
  213. }
  214. else {
  215. for (i = 0; i < ret; i++) {
  216. pollset->result_set[i] =
  217. (((pfd_elem_t *) (pollset->pollset[i].data.ptr))->pfd);
  218. pollset->result_set[i].rtnevents =
  219. get_epoll_revent(pollset->pollset[i].events);
  220. }
  221. if (descriptors) {
  222. *descriptors = pollset->result_set;
  223. }
  224. }
  225. pollset_lock_rings();
  226. /* Shift all PFDs in the Dead Ring to be Free Ring */
  227. APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link);
  228. pollset_unlock_rings();
  229. return rv;
  230. }
  231. #endif /* POLLSET_USES_EPOLL */