A clone of btpd with my configuration changes.
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

371 строка
8.8 KiB

  1. /* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
  2. /*
  3. * Copyright 2000-2002 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 <signal.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <unistd.h>
  44. #include <errno.h>
  45. #ifdef CHECK_INVARIANTS
  46. #include <assert.h>
  47. #endif
  48. #include "event.h"
  49. #include "event-internal.h"
  50. #include "evsignal.h"
  51. #include "log.h"
  52. #ifndef howmany
  53. #define howmany(x, y) (((x)+((y)-1))/(y))
  54. #endif
  55. extern volatile sig_atomic_t evsignal_caught;
  56. struct selectop {
  57. int event_fds; /* Highest fd in fd set */
  58. int event_fdsz;
  59. fd_set *event_readset_in;
  60. fd_set *event_writeset_in;
  61. fd_set *event_readset_out;
  62. fd_set *event_writeset_out;
  63. struct event **event_r_by_fd;
  64. struct event **event_w_by_fd;
  65. };
  66. void *select_init (void);
  67. int select_add (void *, struct event *);
  68. int select_del (void *, struct event *);
  69. int select_recalc (struct event_base *, void *, int);
  70. int select_dispatch (struct event_base *, void *, struct timeval *);
  71. void select_dealloc (void *);
  72. const struct eventop selectops = {
  73. "select",
  74. select_init,
  75. select_add,
  76. select_del,
  77. select_recalc,
  78. select_dispatch,
  79. select_dealloc
  80. };
  81. static int select_resize(struct selectop *sop, int fdsz);
  82. void *
  83. select_init(void)
  84. {
  85. struct selectop *sop;
  86. /* Disable select when this environment variable is set */
  87. if (getenv("EVENT_NOSELECT"))
  88. return (NULL);
  89. if (!(sop = calloc(1, sizeof(struct selectop))))
  90. return (NULL);
  91. select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask));
  92. evsignal_init();
  93. return (sop);
  94. }
  95. #ifdef CHECK_INVARIANTS
  96. static void
  97. check_selectop(struct selectop *sop)
  98. {
  99. int i;
  100. for (i=0;i<=sop->event_fds;++i) {
  101. if (FD_ISSET(i, sop->event_readset_in)) {
  102. assert(sop->event_r_by_fd[i]);
  103. assert(sop->event_r_by_fd[i]->ev_events & EV_READ);
  104. assert(sop->event_r_by_fd[i]->ev_fd == i);
  105. } else {
  106. assert(! sop->event_r_by_fd[i]);
  107. }
  108. if (FD_ISSET(i, sop->event_writeset_in)) {
  109. assert(sop->event_w_by_fd[i]);
  110. assert(sop->event_w_by_fd[i]->ev_events & EV_WRITE);
  111. assert(sop->event_w_by_fd[i]->ev_fd == i);
  112. } else {
  113. assert(! sop->event_w_by_fd[i]);
  114. }
  115. }
  116. }
  117. #else
  118. #define check_selectop(sop) do { (void) sop; } while (0)
  119. #endif
  120. /*
  121. * Called with the highest fd that we know about. If it is 0, completely
  122. * recalculate everything.
  123. */
  124. int
  125. select_recalc(struct event_base *base, void *arg, int max)
  126. {
  127. struct selectop *sop = arg;
  128. check_selectop(sop);
  129. return (0);
  130. }
  131. int
  132. select_dispatch(struct event_base *base, void *arg, struct timeval *tv)
  133. {
  134. int res, i;
  135. struct selectop *sop = arg;
  136. check_selectop(sop);
  137. memcpy(sop->event_readset_out, sop->event_readset_in,
  138. sop->event_fdsz);
  139. memcpy(sop->event_writeset_out, sop->event_writeset_in,
  140. sop->event_fdsz);
  141. res = select(sop->event_fds + 1, sop->event_readset_out,
  142. sop->event_writeset_out, NULL, tv);
  143. check_selectop(sop);
  144. if (res == -1) {
  145. if (errno != EINTR) {
  146. event_warn("select");
  147. return (-1);
  148. }
  149. evsignal_process();
  150. return (0);
  151. } else if (evsignal_caught)
  152. evsignal_process();
  153. event_debug(("%s: select reports %d", __func__, res));
  154. check_selectop(sop);
  155. for (i = 0; i <= sop->event_fds; ++i) {
  156. struct event *r_ev = NULL, *w_ev = NULL;
  157. res = 0;
  158. if (FD_ISSET(i, sop->event_readset_out)) {
  159. r_ev = sop->event_r_by_fd[i];
  160. res |= EV_READ;
  161. }
  162. if (FD_ISSET(i, sop->event_writeset_out)) {
  163. w_ev = sop->event_w_by_fd[i];
  164. res |= EV_WRITE;
  165. }
  166. if (r_ev && (res & r_ev->ev_events)) {
  167. if (!(r_ev->ev_events & EV_PERSIST))
  168. event_del(r_ev);
  169. event_active(r_ev, res & r_ev->ev_events, 1);
  170. }
  171. if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) {
  172. if (!(w_ev->ev_events & EV_PERSIST))
  173. event_del(w_ev);
  174. event_active(w_ev, res & w_ev->ev_events, 1);
  175. }
  176. }
  177. check_selectop(sop);
  178. return (0);
  179. }
  180. static int
  181. select_resize(struct selectop *sop, int fdsz)
  182. {
  183. int n_events, n_events_old;
  184. fd_set *readset_in = NULL;
  185. fd_set *writeset_in = NULL;
  186. fd_set *readset_out = NULL;
  187. fd_set *writeset_out = NULL;
  188. struct event **r_by_fd = NULL;
  189. struct event **w_by_fd = NULL;
  190. n_events = (fdsz/sizeof(fd_mask)) * NFDBITS;
  191. n_events_old = (sop->event_fdsz/sizeof(fd_mask)) * NFDBITS;
  192. if (sop->event_readset_in)
  193. check_selectop(sop);
  194. if ((readset_in = realloc(sop->event_readset_in, fdsz)) == NULL)
  195. goto error;
  196. sop->event_readset_in = readset_in;
  197. if ((readset_out = realloc(sop->event_readset_out, fdsz)) == NULL)
  198. goto error;
  199. sop->event_readset_out = readset_out;
  200. if ((writeset_in = realloc(sop->event_writeset_in, fdsz)) == NULL)
  201. goto error;
  202. sop->event_writeset_in = writeset_in;
  203. if ((writeset_out = realloc(sop->event_writeset_out, fdsz)) == NULL)
  204. goto error;
  205. sop->event_writeset_out = writeset_out;
  206. if ((r_by_fd = realloc(sop->event_r_by_fd,
  207. n_events*sizeof(struct event*))) == NULL)
  208. goto error;
  209. sop->event_r_by_fd = r_by_fd;
  210. if ((w_by_fd = realloc(sop->event_w_by_fd,
  211. n_events * sizeof(struct event*))) == NULL)
  212. goto error;
  213. sop->event_w_by_fd = w_by_fd;
  214. memset((char *)sop->event_readset_in + sop->event_fdsz, 0,
  215. fdsz - sop->event_fdsz);
  216. memset((char *)sop->event_writeset_in + sop->event_fdsz, 0,
  217. fdsz - sop->event_fdsz);
  218. memset(sop->event_r_by_fd + n_events_old, 0,
  219. (n_events-n_events_old) * sizeof(struct event*));
  220. memset(sop->event_w_by_fd + n_events_old, 0,
  221. (n_events-n_events_old) * sizeof(struct event*));
  222. sop->event_fdsz = fdsz;
  223. check_selectop(sop);
  224. return (0);
  225. error:
  226. event_warn("malloc");
  227. return (-1);
  228. }
  229. int
  230. select_add(void *arg, struct event *ev)
  231. {
  232. struct selectop *sop = arg;
  233. if (ev->ev_events & EV_SIGNAL)
  234. return (evsignal_add(ev));
  235. check_selectop(sop);
  236. /*
  237. * Keep track of the highest fd, so that we can calculate the size
  238. * of the fd_sets for select(2)
  239. */
  240. if (sop->event_fds < ev->ev_fd) {
  241. int fdsz = sop->event_fdsz;
  242. if (fdsz < sizeof(fd_mask))
  243. fdsz = sizeof(fd_mask);
  244. while (fdsz <
  245. (howmany(ev->ev_fd + 1, NFDBITS) * sizeof(fd_mask)))
  246. fdsz *= 2;
  247. if (fdsz != sop->event_fdsz) {
  248. if (select_resize(sop, fdsz)) {
  249. check_selectop(sop);
  250. return (-1);
  251. }
  252. }
  253. sop->event_fds = ev->ev_fd;
  254. }
  255. if (ev->ev_events & EV_READ) {
  256. FD_SET(ev->ev_fd, sop->event_readset_in);
  257. sop->event_r_by_fd[ev->ev_fd] = ev;
  258. }
  259. if (ev->ev_events & EV_WRITE) {
  260. FD_SET(ev->ev_fd, sop->event_writeset_in);
  261. sop->event_w_by_fd[ev->ev_fd] = ev;
  262. }
  263. check_selectop(sop);
  264. return (0);
  265. }
  266. /*
  267. * Nothing to be done here.
  268. */
  269. int
  270. select_del(void *arg, struct event *ev)
  271. {
  272. struct selectop *sop = arg;
  273. check_selectop(sop);
  274. if (ev->ev_events & EV_SIGNAL)
  275. return (evsignal_del(ev));
  276. if (sop->event_fds < ev->ev_fd) {
  277. check_selectop(sop);
  278. return (0);
  279. }
  280. if (ev->ev_events & EV_READ) {
  281. FD_CLR(ev->ev_fd, sop->event_readset_in);
  282. sop->event_r_by_fd[ev->ev_fd] = NULL;
  283. }
  284. if (ev->ev_events & EV_WRITE) {
  285. FD_CLR(ev->ev_fd, sop->event_writeset_in);
  286. sop->event_w_by_fd[ev->ev_fd] = NULL;
  287. }
  288. check_selectop(sop);
  289. return (0);
  290. }
  291. void
  292. select_dealloc(void *arg)
  293. {
  294. struct selectop *sop = arg;
  295. if (sop->event_readset_in)
  296. free(sop->event_readset_in);
  297. if (sop->event_writeset_in)
  298. free(sop->event_writeset_in);
  299. if (sop->event_readset_out)
  300. free(sop->event_readset_out);
  301. if (sop->event_writeset_out)
  302. free(sop->event_writeset_out);
  303. if (sop->event_r_by_fd)
  304. free(sop->event_r_by_fd);
  305. if (sop->event_w_by_fd)
  306. free(sop->event_w_by_fd);
  307. memset(sop, 0, sizeof(struct selectop));
  308. free(sop);
  309. }