async.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
  2. * Permission is hereby granted, free of charge, to any person obtaining a copy
  3. * of this software and associated documentation files (the "Software"), to
  4. * deal in the Software without restriction, including without limitation the
  5. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  6. * sell copies of the Software, and to permit persons to whom the Software is
  7. * furnished to do so, subject to the following conditions:
  8. *
  9. * The above copyright notice and this permission notice shall be included in
  10. * all copies or substantial portions of the Software.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  17. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  18. * IN THE SOFTWARE.
  19. */
  20. /* This file contains both the uv__async internal infrastructure and the
  21. * user-facing uv_async_t functions.
  22. */
  23. #include "uv.h"
  24. #include "internal.h"
  25. #include "atomic-ops.h"
  26. #include <errno.h>
  27. #include <stdio.h> /* snprintf() */
  28. #include <assert.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <unistd.h>
  32. static void uv__async_send(uv_loop_t* loop);
  33. static int uv__async_start(uv_loop_t* loop);
  34. static int uv__async_eventfd(void);
  35. int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
  36. int err;
  37. err = uv__async_start(loop);
  38. if (err)
  39. return err;
  40. uv__handle_init(loop, (uv_handle_t*)handle, UV_ASYNC);
  41. handle->async_cb = async_cb;
  42. handle->pending = 0;
  43. QUEUE_INSERT_TAIL(&loop->async_handles, &handle->queue);
  44. uv__handle_start(handle);
  45. return 0;
  46. }
  47. int uv_async_send(uv_async_t* handle) {
  48. /* Do a cheap read first. */
  49. if (ACCESS_ONCE(int, handle->pending) != 0)
  50. return 0;
  51. if (cmpxchgi(&handle->pending, 0, 1) == 0)
  52. uv__async_send(handle->loop);
  53. return 0;
  54. }
  55. void uv__async_close(uv_async_t* handle) {
  56. QUEUE_REMOVE(&handle->queue);
  57. uv__handle_stop(handle);
  58. }
  59. static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
  60. char buf[1024];
  61. ssize_t r;
  62. QUEUE queue;
  63. QUEUE* q;
  64. uv_async_t* h;
  65. assert(w == &loop->async_io_watcher);
  66. for (;;) {
  67. r = read(w->fd, buf, sizeof(buf));
  68. if (r == sizeof(buf))
  69. continue;
  70. if (r != -1)
  71. break;
  72. if (errno == EAGAIN || errno == EWOULDBLOCK)
  73. break;
  74. if (errno == EINTR)
  75. continue;
  76. abort();
  77. }
  78. QUEUE_MOVE(&loop->async_handles, &queue);
  79. while (!QUEUE_EMPTY(&queue)) {
  80. q = QUEUE_HEAD(&queue);
  81. h = QUEUE_DATA(q, uv_async_t, queue);
  82. QUEUE_REMOVE(q);
  83. QUEUE_INSERT_TAIL(&loop->async_handles, q);
  84. if (cmpxchgi(&h->pending, 1, 0) == 0)
  85. continue;
  86. if (h->async_cb == NULL)
  87. continue;
  88. h->async_cb(h);
  89. }
  90. }
  91. static void uv__async_send(uv_loop_t* loop) {
  92. const void* buf;
  93. ssize_t len;
  94. int fd;
  95. int r;
  96. buf = "";
  97. len = 1;
  98. fd = loop->async_wfd;
  99. #if defined(__linux__)
  100. if (fd == -1) {
  101. static const uint64_t val = 1;
  102. buf = &val;
  103. len = sizeof(val);
  104. fd = loop->async_io_watcher.fd; /* eventfd */
  105. }
  106. #endif
  107. do
  108. r = write(fd, buf, len);
  109. while (r == -1 && errno == EINTR);
  110. if (r == len)
  111. return;
  112. if (r == -1)
  113. if (errno == EAGAIN || errno == EWOULDBLOCK)
  114. return;
  115. abort();
  116. }
  117. static int uv__async_start(uv_loop_t* loop) {
  118. int pipefd[2];
  119. int err;
  120. if (loop->async_io_watcher.fd != -1)
  121. return 0;
  122. err = uv__async_eventfd();
  123. if (err >= 0) {
  124. pipefd[0] = err;
  125. pipefd[1] = -1;
  126. }
  127. else if (err == -ENOSYS) {
  128. err = uv__make_pipe(pipefd, UV__F_NONBLOCK);
  129. #if defined(__linux__)
  130. /* Save a file descriptor by opening one of the pipe descriptors as
  131. * read/write through the procfs. That file descriptor can then
  132. * function as both ends of the pipe.
  133. */
  134. if (err == 0) {
  135. char buf[32];
  136. int fd;
  137. snprintf(buf, sizeof(buf), "/proc/self/fd/%d", pipefd[0]);
  138. fd = uv__open_cloexec(buf, O_RDWR);
  139. if (fd >= 0) {
  140. uv__close(pipefd[0]);
  141. uv__close(pipefd[1]);
  142. pipefd[0] = fd;
  143. pipefd[1] = fd;
  144. }
  145. }
  146. #endif
  147. }
  148. if (err < 0)
  149. return err;
  150. uv__io_init(&loop->async_io_watcher, uv__async_io, pipefd[0]);
  151. uv__io_start(loop, &loop->async_io_watcher, POLLIN);
  152. loop->async_wfd = pipefd[1];
  153. return 0;
  154. }
  155. int uv__async_fork(uv_loop_t* loop) {
  156. if (loop->async_io_watcher.fd == -1) /* never started */
  157. return 0;
  158. uv__async_stop(loop);
  159. return uv__async_start(loop);
  160. }
  161. void uv__async_stop(uv_loop_t* loop) {
  162. if (loop->async_io_watcher.fd == -1)
  163. return;
  164. if (loop->async_wfd != -1) {
  165. if (loop->async_wfd != loop->async_io_watcher.fd)
  166. uv__close(loop->async_wfd);
  167. loop->async_wfd = -1;
  168. }
  169. uv__io_stop(loop, &loop->async_io_watcher, POLLIN);
  170. uv__close(loop->async_io_watcher.fd);
  171. loop->async_io_watcher.fd = -1;
  172. }
  173. static int uv__async_eventfd(void) {
  174. #if defined(__linux__)
  175. static int no_eventfd2;
  176. static int no_eventfd;
  177. int fd;
  178. if (no_eventfd2)
  179. goto skip_eventfd2;
  180. fd = uv__eventfd2(0, UV__EFD_CLOEXEC | UV__EFD_NONBLOCK);
  181. if (fd != -1)
  182. return fd;
  183. if (errno != ENOSYS)
  184. return -errno;
  185. no_eventfd2 = 1;
  186. skip_eventfd2:
  187. if (no_eventfd)
  188. goto skip_eventfd;
  189. fd = uv__eventfd(0);
  190. if (fd != -1) {
  191. uv__cloexec(fd, 1);
  192. uv__nonblock(fd, 1);
  193. return fd;
  194. }
  195. if (errno != ENOSYS)
  196. return -errno;
  197. no_eventfd = 1;
  198. skip_eventfd:
  199. #endif
  200. return -ENOSYS;
  201. }