A clone of btpd with my configuration changes.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

371 lignes
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. }