A clone of btpd with my configuration changes.
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.

пре 18 година
пре 17 година
пре 18 година
пре 17 година
пре 18 година
пре 17 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 17 година
пре 18 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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. };
  65. void *poll_init (void);
  66. int poll_add (void *, struct event *);
  67. int poll_del (void *, struct event *);
  68. int poll_recalc (struct event_base *, void *, int);
  69. int poll_dispatch (struct event_base *, void *, struct timeval *);
  70. void poll_dealloc (void *);
  71. const struct eventop pollops = {
  72. "poll",
  73. poll_init,
  74. poll_add,
  75. poll_del,
  76. poll_recalc,
  77. poll_dispatch,
  78. poll_dealloc
  79. };
  80. void *
  81. poll_init(void)
  82. {
  83. struct pollop *pollop;
  84. /* Disable poll when this environment variable is set */
  85. if (getenv("EVENT_NOPOLL"))
  86. return (NULL);
  87. if (!(pollop = calloc(1, sizeof(struct pollop))))
  88. return (NULL);
  89. evsignal_init();
  90. return (pollop);
  91. }
  92. /*
  93. * Called with the highest fd that we know about. If it is 0, completely
  94. * recalculate everything.
  95. */
  96. int
  97. poll_recalc(struct event_base *base, void *arg, int max)
  98. {
  99. return (0);
  100. }
  101. #ifdef CHECK_INVARIANTS
  102. static void
  103. poll_check_ok(struct pollop *pop)
  104. {
  105. int i, idx;
  106. struct event *ev;
  107. for (i = 0; i < pop->fd_count; ++i) {
  108. idx = pop->idxplus1_by_fd[i]-1;
  109. if (idx < 0)
  110. continue;
  111. assert(pop->event_set[idx].fd == i);
  112. if (pop->event_set[idx].events & POLLIN) {
  113. ev = pop->event_r_back[idx];
  114. assert(ev);
  115. assert(ev->ev_events & EV_READ);
  116. assert(ev->ev_fd == i);
  117. }
  118. if (pop->event_set[idx].events & POLLOUT) {
  119. ev = pop->event_w_back[idx];
  120. assert(ev);
  121. assert(ev->ev_events & EV_WRITE);
  122. assert(ev->ev_fd == i);
  123. }
  124. }
  125. for (i = 0; i < pop->nfds; ++i) {
  126. struct pollfd *pfd = &pop->event_set[i];
  127. assert(pop->idxplus1_by_fd[pfd->fd] == i+1);
  128. }
  129. }
  130. #else
  131. #define poll_check_ok(pop)
  132. #endif
  133. int
  134. poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
  135. {
  136. int res, i, sec, nfds;
  137. struct pollop *pop = arg;
  138. poll_check_ok(pop);
  139. sec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
  140. nfds = pop->nfds;
  141. res = poll(pop->event_set, nfds, sec);
  142. if (res == -1) {
  143. if (errno != EINTR) {
  144. event_warn("poll");
  145. return (-1);
  146. }
  147. evsignal_process();
  148. return (0);
  149. } else if (evsignal_caught)
  150. evsignal_process();
  151. event_debug(("%s: poll reports %d", __func__, res));
  152. if (res == 0)
  153. return (0);
  154. for (i = 0; i < nfds; i++) {
  155. int what = pop->event_set[i].revents;
  156. struct event *r_ev = NULL, *w_ev = NULL;
  157. if (!what)
  158. continue;
  159. res = 0;
  160. /* If the file gets closed notify */
  161. if (what & (POLLHUP|POLLERR))
  162. what |= POLLIN|POLLOUT;
  163. if (what & POLLIN) {
  164. res |= EV_READ;
  165. r_ev = pop->event_r_back[i];
  166. }
  167. if (what & POLLOUT) {
  168. res |= EV_WRITE;
  169. w_ev = pop->event_w_back[i];
  170. }
  171. if (res == 0)
  172. continue;
  173. if (r_ev && (res & r_ev->ev_events)) {
  174. if (!(r_ev->ev_events & EV_PERSIST))
  175. event_del(r_ev);
  176. event_active(r_ev, res & r_ev->ev_events, 1);
  177. }
  178. if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) {
  179. if (!(w_ev->ev_events & EV_PERSIST))
  180. event_del(w_ev);
  181. event_active(w_ev, res & w_ev->ev_events, 1);
  182. }
  183. }
  184. return (0);
  185. }
  186. int
  187. poll_add(void *arg, struct event *ev)
  188. {
  189. struct pollop *pop = arg;
  190. struct pollfd *pfd = NULL;
  191. int i;
  192. if (ev->ev_events & EV_SIGNAL)
  193. return (evsignal_add(ev));
  194. if (!(ev->ev_events & (EV_READ|EV_WRITE)))
  195. return (0);
  196. poll_check_ok(pop);
  197. if (pop->nfds + 1 >= pop->event_count) {
  198. struct pollfd *tmp_event_set;
  199. struct event **tmp_event_r_back;
  200. struct event **tmp_event_w_back;
  201. int tmp_event_count;
  202. if (pop->event_count < 32)
  203. tmp_event_count = 32;
  204. else
  205. tmp_event_count = pop->event_count * 2;
  206. /* We need more file descriptors */
  207. tmp_event_set = realloc(pop->event_set,
  208. tmp_event_count * sizeof(struct pollfd));
  209. if (tmp_event_set == NULL) {
  210. event_warn("realloc");
  211. return (-1);
  212. }
  213. pop->event_set = tmp_event_set;
  214. tmp_event_r_back = realloc(pop->event_r_back,
  215. tmp_event_count * sizeof(struct event *));
  216. if (tmp_event_r_back == NULL) {
  217. /* event_set overallocated; that's okay. */
  218. event_warn("realloc");
  219. return (-1);
  220. }
  221. pop->event_r_back = tmp_event_r_back;
  222. tmp_event_w_back = realloc(pop->event_w_back,
  223. tmp_event_count * sizeof(struct event *));
  224. if (tmp_event_w_back == NULL) {
  225. /* event_set and event_r_back overallocated; that's
  226. * okay. */
  227. event_warn("realloc");
  228. return (-1);
  229. }
  230. pop->event_w_back = tmp_event_w_back;
  231. pop->event_count = tmp_event_count;
  232. }
  233. if (ev->ev_fd >= pop->fd_count) {
  234. int *tmp_idxplus1_by_fd;
  235. int new_count;
  236. if (pop->fd_count < 32)
  237. new_count = 32;
  238. else
  239. new_count = pop->fd_count * 2;
  240. while (new_count <= ev->ev_fd)
  241. new_count *= 2;
  242. tmp_idxplus1_by_fd =
  243. realloc(pop->idxplus1_by_fd, new_count * sizeof(int));
  244. if (tmp_idxplus1_by_fd == NULL) {
  245. event_warn("realloc");
  246. return (-1);
  247. }
  248. pop->idxplus1_by_fd = tmp_idxplus1_by_fd;
  249. memset(pop->idxplus1_by_fd + pop->fd_count,
  250. 0, sizeof(int)*(new_count - pop->fd_count));
  251. pop->fd_count = new_count;
  252. }
  253. i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
  254. if (i >= 0) {
  255. pfd = &pop->event_set[i];
  256. } else {
  257. i = pop->nfds++;
  258. pfd = &pop->event_set[i];
  259. pfd->events = 0;
  260. pfd->fd = ev->ev_fd;
  261. pop->event_w_back[i] = pop->event_r_back[i] = NULL;
  262. pop->idxplus1_by_fd[ev->ev_fd] = i + 1;
  263. }
  264. pfd->revents = 0;
  265. if (ev->ev_events & EV_WRITE) {
  266. pfd->events |= POLLOUT;
  267. pop->event_w_back[i] = ev;
  268. }
  269. if (ev->ev_events & EV_READ) {
  270. pfd->events |= POLLIN;
  271. pop->event_r_back[i] = ev;
  272. }
  273. poll_check_ok(pop);
  274. return (0);
  275. }
  276. /*
  277. * Nothing to be done here.
  278. */
  279. int
  280. poll_del(void *arg, struct event *ev)
  281. {
  282. struct pollop *pop = arg;
  283. struct pollfd *pfd = NULL;
  284. int i;
  285. if (ev->ev_events & EV_SIGNAL)
  286. return (evsignal_del(ev));
  287. if (!(ev->ev_events & (EV_READ|EV_WRITE)))
  288. return (0);
  289. poll_check_ok(pop);
  290. i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
  291. if (i < 0)
  292. return (-1);
  293. /* Do we still want to read or write? */
  294. pfd = &pop->event_set[i];
  295. if (ev->ev_events & EV_READ) {
  296. pfd->events &= ~POLLIN;
  297. pop->event_r_back[i] = NULL;
  298. }
  299. if (ev->ev_events & EV_WRITE) {
  300. pfd->events &= ~POLLOUT;
  301. pop->event_w_back[i] = NULL;
  302. }
  303. poll_check_ok(pop);
  304. if (pfd->events)
  305. /* Another event cares about that fd. */
  306. return (0);
  307. /* Okay, so we aren't interested in that fd anymore. */
  308. pop->idxplus1_by_fd[ev->ev_fd] = 0;
  309. --pop->nfds;
  310. if (i != pop->nfds) {
  311. /*
  312. * Shift the last pollfd down into the now-unoccupied
  313. * position.
  314. */
  315. memcpy(&pop->event_set[i], &pop->event_set[pop->nfds],
  316. sizeof(struct pollfd));
  317. pop->event_r_back[i] = pop->event_r_back[pop->nfds];
  318. pop->event_w_back[i] = pop->event_w_back[pop->nfds];
  319. pop->idxplus1_by_fd[pop->event_set[i].fd] = i + 1;
  320. }
  321. poll_check_ok(pop);
  322. return (0);
  323. }
  324. void
  325. poll_dealloc(void *arg)
  326. {
  327. struct pollop *pop = arg;
  328. if (pop->event_set)
  329. free(pop->event_set);
  330. if (pop->event_r_back)
  331. free(pop->event_r_back);
  332. if (pop->event_w_back)
  333. free(pop->event_w_back);
  334. if (pop->idxplus1_by_fd)
  335. free(pop->idxplus1_by_fd);
  336. memset(pop, 0, sizeof(struct pollop));
  337. free(pop);
  338. }