Another copy of my dotfiles. Because I don't completely trust GitHub.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
3.6 KiB

  1. /* See LICENSE file for copyright and license details. */
  2. #include <stddef.h>
  3. #ifdef __linux__
  4. #include <sys/epoll.h>
  5. #else
  6. #include <sys/types.h>
  7. #include <sys/event.h>
  8. #include <sys/time.h>
  9. #endif
  10. #include "queue.h"
  11. #include "util.h"
  12. int
  13. queue_create(void)
  14. {
  15. int qfd;
  16. #ifdef __linux__
  17. if ((qfd = epoll_create1(0)) < 0) {
  18. warn("epoll_create1:");
  19. }
  20. #else
  21. if ((qfd = kqueue()) < 0) {
  22. warn("kqueue:");
  23. }
  24. #endif
  25. return qfd;
  26. }
  27. int
  28. queue_add_fd(int qfd, int fd, enum queue_event_type t, int shared,
  29. const void *data)
  30. {
  31. #ifdef __linux__
  32. struct epoll_event e;
  33. /* set event flag */
  34. if (shared) {
  35. /*
  36. * if the fd is shared, "exclusive" is the only
  37. * way to avoid spurious wakeups and "blocking"
  38. * accept()'s.
  39. */
  40. e.events = EPOLLEXCLUSIVE;
  41. } else {
  42. /*
  43. * if we have the fd for ourselves (i.e. only
  44. * within the thread), we want to be
  45. * edge-triggered, as our logic makes sure
  46. * that the buffers are drained when we return
  47. * to epoll_wait()
  48. */
  49. e.events = EPOLLET;
  50. }
  51. switch (t) {
  52. case QUEUE_EVENT_IN:
  53. e.events |= EPOLLIN;
  54. break;
  55. case QUEUE_EVENT_OUT:
  56. e.events |= EPOLLOUT;
  57. break;
  58. }
  59. /* set data pointer */
  60. e.data.ptr = (void *)data;
  61. /* register fd in the interest list */
  62. if (epoll_ctl(qfd, EPOLL_CTL_ADD, fd, &e) < 0) {
  63. warn("epoll_ctl:");
  64. return -1;
  65. }
  66. #else
  67. struct kevent e;
  68. int events;
  69. /* prepare event flag */
  70. events = (shared) ? 0 : EV_CLEAR;
  71. switch (t) {
  72. case QUEUE_EVENT_IN:
  73. events |= EVFILT_READ;
  74. break;
  75. case QUEUE_EVENT_OUT:
  76. events |= EVFILT_WRITE;
  77. break;
  78. }
  79. EV_SET(&e, fd, events, EV_ADD, 0, 0, (void *)data);
  80. if (kevent(qfd, &e, 1, NULL, 0, NULL) < 0) {
  81. warn("kevent:");
  82. return -1;
  83. }
  84. #endif
  85. return 0;
  86. }
  87. int
  88. queue_mod_fd(int qfd, int fd, enum queue_event_type t, const void *data)
  89. {
  90. #ifdef __linux__
  91. struct epoll_event e;
  92. /* set event flag (only for non-shared fd's) */
  93. e.events = EPOLLET;
  94. switch (t) {
  95. case QUEUE_EVENT_IN:
  96. e.events |= EPOLLIN;
  97. break;
  98. case QUEUE_EVENT_OUT:
  99. e.events |= EPOLLOUT;
  100. break;
  101. }
  102. /* set data pointer */
  103. e.data.ptr = (void *)data;
  104. /* register fd in the interest list */
  105. if (epoll_ctl(qfd, EPOLL_CTL_MOD, fd, &e) < 0) {
  106. warn("epoll_ctl:");
  107. return -1;
  108. }
  109. #else
  110. struct kevent e;
  111. int events;
  112. events = EV_CLEAR;
  113. switch (t) {
  114. case QUEUE_EVENT_IN:
  115. events |= EVFILT_READ;
  116. break;
  117. case QUEUE_EVENT_OUT:
  118. events |= EVFILT_WRITE;
  119. break;
  120. }
  121. EV_SET(&e, fd, events, EV_ADD, 0, 0, (void *)data);
  122. if (kevent(qfd, &e, 1, NULL, 0, NULL) < 0) {
  123. warn("kevent:");
  124. return -1;
  125. }
  126. #endif
  127. return 0;
  128. }
  129. int
  130. queue_rem_fd(int qfd, int fd)
  131. {
  132. #ifdef __linux__
  133. struct epoll_event e;
  134. if (epoll_ctl(qfd, EPOLL_CTL_DEL, fd, &e) < 0) {
  135. warn("epoll_ctl:");
  136. return -1;
  137. }
  138. #else
  139. struct kevent e;
  140. EV_SET(&e, fd, 0, EV_DELETE, 0, 0, 0);
  141. if (kevent(qfd, &e, 1, NULL, 0, NULL) < 0) {
  142. warn("kevent:");
  143. return -1;
  144. }
  145. #endif
  146. return 0;
  147. }
  148. ssize_t
  149. queue_wait(int qfd, queue_event *e, size_t elen)
  150. {
  151. ssize_t nready;
  152. #ifdef __linux__
  153. if ((nready = epoll_wait(qfd, e, elen, -1)) < 0) {
  154. warn("epoll_wait:");
  155. return -1;
  156. }
  157. #else
  158. if ((nready = kevent(qfd, NULL, 0, e, elen, NULL)) < 0) {
  159. warn("kevent:");
  160. return -1;
  161. }
  162. #endif
  163. return nready;
  164. }
  165. void *
  166. queue_event_get_data(const queue_event *e)
  167. {
  168. #ifdef __linux__
  169. return e->data.ptr;
  170. #else
  171. return e->udata;
  172. #endif
  173. }
  174. int
  175. queue_event_is_error(const queue_event *e)
  176. {
  177. #ifdef __linux__
  178. return (e->events & ~(EPOLLIN | EPOLLOUT)) ? 1 : 0;
  179. #else
  180. return (e->flags & EV_EOF) ? 1 : 0;
  181. #endif
  182. }