A clone of btpd with my configuration changes.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

378 行
8.9 KiB

  1. /* $OpenBSD: poll.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
  2. /*
  3. * Copyright 2000-2003 Niels Provos <provos@citi.umich.edu>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. The name of the author may not be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #ifdef HAVE_CONFIG_H
  29. #include "config.h"
  30. #endif
  31. #include <sys/types.h>
  32. #ifdef HAVE_SYS_TIME_H
  33. #include <sys/time.h>
  34. #else
  35. #include <sys/_time.h>
  36. #endif
  37. #include <sys/queue.h>
  38. #include <sys/tree.h>
  39. #include <poll.h>
  40. #include <signal.h>
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <unistd.h>
  45. #include <errno.h>
  46. #ifdef CHECK_INVARIANTS
  47. #include <assert.h>
  48. #endif
  49. #include "event.h"
  50. #include "event-internal.h"
  51. #include "evsignal.h"
  52. #include "log.h"
  53. extern volatile sig_atomic_t evsignal_caught;
  54. struct pollop {
  55. int event_count; /* Highest number alloc */
  56. int nfds; /* Size of event_* */
  57. int fd_count; /* Size of idxplus1_by_fd */
  58. struct pollfd *event_set;
  59. struct event **event_r_back;
  60. struct event **event_w_back;
  61. int *idxplus1_by_fd; /* Index into event_set by fd; we add 1 so
  62. * that 0 (which is easy to memset) can mean
  63. * "no entry." */
  64. sigset_t evsigmask;
  65. };
  66. void *poll_init (void);
  67. int poll_add (void *, struct event *);
  68. int poll_del (void *, struct event *);
  69. int poll_recalc (struct event_base *, void *, int);
  70. int poll_dispatch (struct event_base *, void *, struct timeval *);
  71. void poll_dealloc (void *);
  72. const struct eventop pollops = {
  73. "poll",
  74. poll_init,
  75. poll_add,
  76. poll_del,
  77. poll_recalc,
  78. poll_dispatch,
  79. poll_dealloc
  80. };
  81. void *
  82. poll_init(void)
  83. {
  84. struct pollop *pollop;
  85. /* Disable poll when this environment variable is set */
  86. if (getenv("EVENT_NOPOLL"))
  87. return (NULL);
  88. if (!(pollop = calloc(1, sizeof(struct pollop))))
  89. return (NULL);
  90. evsignal_init(&pollop->evsigmask);
  91. return (pollop);
  92. }
  93. /*
  94. * Called with the highest fd that we know about. If it is 0, completely
  95. * recalculate everything.
  96. */
  97. int
  98. poll_recalc(struct event_base *base, void *arg, int max)
  99. {
  100. struct pollop *pop = arg;
  101. return (evsignal_recalc(&pop->evsigmask));
  102. }
  103. #ifdef CHECK_INVARIANTS
  104. static void
  105. poll_check_ok(struct pollop *pop)
  106. {
  107. int i, idx;
  108. struct event *ev;
  109. for (i = 0; i < pop->fd_count; ++i) {
  110. idx = pop->idxplus1_by_fd[i]-1;
  111. if (idx < 0)
  112. continue;
  113. assert(pop->event_set[idx].fd == i);
  114. if (pop->event_set[idx].events & POLLIN) {
  115. ev = pop->event_r_back[idx];
  116. assert(ev);
  117. assert(ev->ev_events & EV_READ);
  118. assert(ev->ev_fd == i);
  119. }
  120. if (pop->event_set[idx].events & POLLOUT) {
  121. ev = pop->event_w_back[idx];
  122. assert(ev);
  123. assert(ev->ev_events & EV_WRITE);
  124. assert(ev->ev_fd == i);
  125. }
  126. }
  127. for (i = 0; i < pop->nfds; ++i) {
  128. struct pollfd *pfd = &pop->event_set[i];
  129. assert(pop->idxplus1_by_fd[pfd->fd] == i+1);
  130. }
  131. }
  132. #else
  133. #define poll_check_ok(pop)
  134. #endif
  135. int
  136. poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
  137. {
  138. int res, i, sec, nfds;
  139. struct pollop *pop = arg;
  140. if (evsignal_deliver(&pop->evsigmask) == -1)
  141. return (-1);
  142. poll_check_ok(pop);
  143. sec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
  144. nfds = pop->nfds;
  145. res = poll(pop->event_set, nfds, sec);
  146. if (evsignal_recalc(&pop->evsigmask) == -1)
  147. return (-1);
  148. if (res == -1) {
  149. if (errno != EINTR) {
  150. event_warn("poll");
  151. return (-1);
  152. }
  153. evsignal_process();
  154. return (0);
  155. } else if (evsignal_caught)
  156. evsignal_process();
  157. event_debug(("%s: poll reports %d", __func__, res));
  158. if (res == 0)
  159. return (0);
  160. for (i = 0; i < nfds; i++) {
  161. int what = pop->event_set[i].revents;
  162. struct event *r_ev = NULL, *w_ev = NULL;
  163. if (!what)
  164. continue;
  165. res = 0;
  166. /* If the file gets closed notify */
  167. if (what & (POLLHUP|POLLERR))
  168. what |= POLLIN|POLLOUT;
  169. if (what & POLLIN) {
  170. res |= EV_READ;
  171. r_ev = pop->event_r_back[i];
  172. }
  173. if (what & POLLOUT) {
  174. res |= EV_WRITE;
  175. w_ev = pop->event_w_back[i];
  176. }
  177. if (res == 0)
  178. continue;
  179. if (r_ev && (res & r_ev->ev_events)) {
  180. if (!(r_ev->ev_events & EV_PERSIST))
  181. event_del(r_ev);
  182. event_active(r_ev, res & r_ev->ev_events, 1);
  183. }
  184. if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) {
  185. if (!(w_ev->ev_events & EV_PERSIST))
  186. event_del(w_ev);
  187. event_active(w_ev, res & w_ev->ev_events, 1);
  188. }
  189. }
  190. return (0);
  191. }
  192. int
  193. poll_add(void *arg, struct event *ev)
  194. {
  195. struct pollop *pop = arg;
  196. struct pollfd *pfd = NULL;
  197. int i;
  198. if (ev->ev_events & EV_SIGNAL)
  199. return (evsignal_add(&pop->evsigmask, ev));
  200. if (!(ev->ev_events & (EV_READ|EV_WRITE)))
  201. return (0);
  202. poll_check_ok(pop);
  203. if (pop->nfds + 1 >= pop->event_count) {
  204. if (pop->event_count < 32)
  205. pop->event_count = 32;
  206. else
  207. pop->event_count *= 2;
  208. /* We need more file descriptors */
  209. pop->event_set = realloc(pop->event_set,
  210. pop->event_count * sizeof(struct pollfd));
  211. if (pop->event_set == NULL) {
  212. event_warn("realloc");
  213. return (-1);
  214. }
  215. pop->event_r_back = realloc(pop->event_r_back,
  216. pop->event_count * sizeof(struct event *));
  217. pop->event_w_back = realloc(pop->event_w_back,
  218. pop->event_count * sizeof(struct event *));
  219. if (pop->event_r_back == NULL ||
  220. pop->event_w_back == NULL) {
  221. event_warn("realloc");
  222. return (-1);
  223. }
  224. }
  225. if (ev->ev_fd >= pop->fd_count) {
  226. int new_count;
  227. if (pop->fd_count < 32)
  228. new_count = 32;
  229. else
  230. new_count = pop->fd_count * 2;
  231. while (new_count <= ev->ev_fd)
  232. new_count *= 2;
  233. pop->idxplus1_by_fd =
  234. realloc(pop->idxplus1_by_fd, new_count*sizeof(int));
  235. if (pop->idxplus1_by_fd == NULL) {
  236. event_warn("realloc");
  237. return (-1);
  238. }
  239. memset(pop->idxplus1_by_fd + pop->fd_count,
  240. 0, sizeof(int)*(new_count - pop->fd_count));
  241. pop->fd_count = new_count;
  242. }
  243. i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
  244. if (i >= 0) {
  245. pfd = &pop->event_set[i];
  246. } else {
  247. i = pop->nfds++;
  248. pfd = &pop->event_set[i];
  249. pfd->events = 0;
  250. pfd->fd = ev->ev_fd;
  251. pop->event_w_back[i] = pop->event_r_back[i] = NULL;
  252. pop->idxplus1_by_fd[ev->ev_fd] = i + 1;
  253. }
  254. pfd->revents = 0;
  255. if (ev->ev_events & EV_WRITE) {
  256. pfd->events |= POLLOUT;
  257. pop->event_w_back[i] = ev;
  258. }
  259. if (ev->ev_events & EV_READ) {
  260. pfd->events |= POLLIN;
  261. pop->event_r_back[i] = ev;
  262. }
  263. poll_check_ok(pop);
  264. return (0);
  265. }
  266. /*
  267. * Nothing to be done here.
  268. */
  269. int
  270. poll_del(void *arg, struct event *ev)
  271. {
  272. struct pollop *pop = arg;
  273. struct pollfd *pfd = NULL;
  274. int i;
  275. if (ev->ev_events & EV_SIGNAL)
  276. return (evsignal_del(&pop->evsigmask, ev));
  277. if (!(ev->ev_events & (EV_READ|EV_WRITE)))
  278. return (0);
  279. poll_check_ok(pop);
  280. i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
  281. if (i < 0)
  282. return (-1);
  283. /* Do we still want to read or write? */
  284. pfd = &pop->event_set[i];
  285. if (ev->ev_events & EV_READ) {
  286. pfd->events &= ~POLLIN;
  287. pop->event_r_back[i] = NULL;
  288. }
  289. if (ev->ev_events & EV_WRITE) {
  290. pfd->events &= ~POLLOUT;
  291. pop->event_w_back[i] = NULL;
  292. }
  293. poll_check_ok(pop);
  294. if (pfd->events)
  295. /* Another event cares about that fd. */
  296. return (0);
  297. /* Okay, so we aren't interested in that fd anymore. */
  298. pop->idxplus1_by_fd[ev->ev_fd] = 0;
  299. --pop->nfds;
  300. if (i != pop->nfds) {
  301. /*
  302. * Shift the last pollfd down into the now-unoccupied
  303. * position.
  304. */
  305. memcpy(&pop->event_set[i], &pop->event_set[pop->nfds],
  306. sizeof(struct pollfd));
  307. pop->event_r_back[i] = pop->event_r_back[pop->nfds];
  308. pop->event_w_back[i] = pop->event_w_back[pop->nfds];
  309. pop->idxplus1_by_fd[pop->event_set[i].fd] = i + 1;
  310. }
  311. poll_check_ok(pop);
  312. return (0);
  313. }
  314. void
  315. poll_dealloc(void *arg)
  316. {
  317. struct pollop *pop = arg;
  318. if (pop->event_set)
  319. free(pop->event_set);
  320. if (pop->event_r_back)
  321. free(pop->event_r_back);
  322. if (pop->event_w_back)
  323. free(pop->event_w_back);
  324. if (pop->idxplus1_by_fd)
  325. free(pop->idxplus1_by_fd);
  326. memset(pop, 0, sizeof(struct pollop));
  327. free(pop);
  328. }