summaryrefslogtreecommitdiff
path: root/src/poll.c
diff options
context:
space:
mode:
authorSeonah Moon <seonah1.moon@samsung.com>2016-04-07 14:01:07 +0900
committerSeonah Moon <seonah1.moon@samsung.com>2016-04-07 14:01:28 +0900
commit9acb9eb162ab31ca7d23350c508b207a775da79f (patch)
tree42dc00b1f72e043d48e274170275bbed32dcfa70 /src/poll.c
parent282cb37dd9a95cafc948b14cb782a229f6511f71 (diff)
downloaddnsmasq-9acb9eb162ab31ca7d23350c508b207a775da79f.tar.gz
dnsmasq-9acb9eb162ab31ca7d23350c508b207a775da79f.tar.bz2
dnsmasq-9acb9eb162ab31ca7d23350c508b207a775da79f.zip
Change-Id: Ic7e94612466be7786c3d2b0724d745c7720e01c9 Signed-off-by: Seonah Moon <seonah1.moon@samsung.com>
Diffstat (limited to 'src/poll.c')
-rw-r--r--src/poll.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/poll.c b/src/poll.c
new file mode 100644
index 0000000..d71b1b9
--- /dev/null
+++ b/src/poll.c
@@ -0,0 +1,125 @@
+/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 dated June, 1991, or
+ (at your option) version 3 dated 29 June, 2007.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+/* Wrapper for poll(). Allocates and extends array of struct pollfds,
+ keeps them in fd order so that we can set and test conditions on
+ fd using a simple but efficient binary chop. */
+
+/* poll_reset()
+ poll_listen(fd, event)
+ .
+ .
+ poll_listen(fd, event);
+
+ hits = do_poll(timeout);
+
+ if (poll_check(fd, event)
+ .
+ .
+
+ if (poll_check(fd, event)
+ .
+ .
+
+ event is OR of POLLIN, POLLOUT, POLLERR, etc
+*/
+
+static struct pollfd *pollfds = NULL;
+static nfds_t nfds, arrsize = 0;
+
+/* Binary search. Returns either the pollfd with fd, or
+ if the fd doesn't match, or return equals nfds, the entry
+ to the left of which a new record should be inserted. */
+static nfds_t fd_search(int fd)
+{
+ nfds_t left, right, mid;
+
+ if ((right = nfds) == 0)
+ return 0;
+
+ left = 0;
+
+ while (1)
+ {
+ if (right == left + 1)
+ return (pollfds[left].fd >= fd) ? left : right;
+
+ mid = (left + right)/2;
+
+ if (pollfds[mid].fd > fd)
+ right = mid;
+ else
+ left = mid;
+ }
+}
+
+void poll_reset(void)
+{
+ nfds = 0;
+}
+
+int do_poll(int timeout)
+{
+ return poll(pollfds, nfds, timeout);
+}
+
+int poll_check(int fd, short event)
+{
+ nfds_t i = fd_search(fd);
+
+ if (i < nfds && pollfds[i].fd == fd)
+ return pollfds[i].revents & event;
+
+ return 0;
+}
+
+void poll_listen(int fd, short event)
+{
+ nfds_t i = fd_search(fd);
+
+ if (i < nfds && pollfds[i].fd == fd)
+ pollfds[i].events |= event;
+ else
+ {
+ if (arrsize != nfds)
+ memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
+ else
+ {
+ /* Array too small, extend. */
+ struct pollfd *new;
+
+ arrsize = (arrsize == 0) ? 64 : arrsize * 2;
+
+ if (!(new = whine_malloc(arrsize * sizeof(struct pollfd))))
+ return;
+
+ if (pollfds)
+ {
+ memcpy(new, pollfds, i * sizeof(struct pollfd));
+ memcpy(&new[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
+ free(pollfds);
+ }
+
+ pollfds = new;
+ }
+
+ pollfds[i].fd = fd;
+ pollfds[i].events = event;
+ nfds++;
+ }
+}