]>
Commit | Line | Data |
---|---|---|
b842bc97 SK |
1 | /* dnsmasq is Copyright (c) 2000-2015 Simon Kelley |
2 | ||
3 | This program is free software; you can redistribute it and/or modify | |
4 | it under the terms of the GNU General Public License as published by | |
5 | the Free Software Foundation; version 2 dated June, 1991, or | |
6 | (at your option) version 3 dated 29 June, 2007. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "dnsmasq.h" | |
18 | ||
19 | /* Wrapper for poll(). Allocates and extends array of struct pollfds, | |
20 | keeps them in fd order so that we can set and test conditions on | |
21 | fd using a simple but efficient binary chop. */ | |
22 | ||
23 | /* poll_reset() | |
24 | poll_listen(fd, event) | |
25 | . | |
26 | . | |
27 | poll_listen(fd, event); | |
28 | ||
29 | hits = do_poll(timeout); | |
30 | ||
31 | if (poll_check(fd, event) | |
32 | . | |
33 | . | |
34 | ||
35 | if (poll_check(fd, event) | |
36 | . | |
37 | . | |
38 | ||
39 | event is OR of POLLIN, POLLOUT, POLLERR, etc | |
40 | */ | |
41 | ||
42 | static struct pollfd *pollfds = NULL; | |
43 | static nfds_t nfds, arrsize = 0; | |
44 | ||
45 | /* Binary search. Returns either the pollfd with fd, or | |
46 | if the fd doesn't match, or return equals nfds, the entry | |
47 | to the left of which a new record should be inserted. */ | |
48 | static nfds_t fd_search(int fd) | |
49 | { | |
50 | nfds_t left, right, mid; | |
51 | ||
52 | if ((right = nfds) == 0) | |
53 | return 0; | |
54 | ||
55 | left = 0; | |
56 | ||
57 | while (1) | |
58 | { | |
59 | if (right == left + 1) | |
60 | return (pollfds[left].fd >= fd) ? left : right; | |
61 | ||
62 | mid = (left + right)/2; | |
63 | ||
64 | if (pollfds[mid].fd > fd) | |
65 | right = mid; | |
66 | else | |
67 | left = mid; | |
68 | } | |
69 | } | |
70 | ||
71 | void poll_reset(void) | |
72 | { | |
73 | nfds = 0; | |
74 | } | |
75 | ||
76 | int do_poll(int timeout) | |
77 | { | |
78 | return poll(pollfds, nfds, timeout); | |
79 | } | |
80 | ||
81 | int poll_check(int fd, short event) | |
82 | { | |
83 | nfds_t i = fd_search(fd); | |
84 | ||
85 | if (i < nfds && pollfds[i].fd == fd) | |
86 | return pollfds[i].revents & event; | |
87 | ||
88 | return 0; | |
89 | } | |
90 | ||
91 | void poll_listen(int fd, short event) | |
92 | { | |
93 | nfds_t i = fd_search(fd); | |
94 | ||
95 | if (i < nfds && pollfds[i].fd == fd) | |
96 | pollfds[i].events |= event; | |
97 | else | |
98 | { | |
99 | if (arrsize != nfds) | |
100 | memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd)); | |
101 | else | |
102 | { | |
103 | /* Array too small, extend. */ | |
104 | struct pollfd *new; | |
90c3822b SK |
105 | |
106 | arrsize = (arrsize == 0) ? 64 : arrsize * 2; | |
107 | ||
b842bc97 SK |
108 | if (!(new = whine_malloc(arrsize * sizeof(struct pollfd)))) |
109 | return; | |
110 | ||
111 | if (pollfds) | |
112 | { | |
113 | memcpy(new, pollfds, i * sizeof(struct pollfd)); | |
114 | memcpy(&new[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd)); | |
115 | free(pollfds); | |
116 | } | |
117 | ||
118 | pollfds = new; | |
119 | } | |
120 | ||
121 | pollfds[i].fd = fd; | |
122 | pollfds[i].events = event; | |
123 | nfds++; | |
124 | } | |
125 | } |