From 8b4c90eaf418a2a206c29ec5587f0f04afd0ec00 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Thu, 17 Nov 2016 17:21:04 +0000 Subject: [PATCH 01/26] move default eventloop from select to poll, make max fds dependent on value from getrlimit not FD_SETSIZE --- src/extension/default_eventloop.c | 117 +++++++++++++++++++++--------- src/extension/default_eventloop.h | 17 ++--- 2 files changed, 86 insertions(+), 48 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index c27dacde..ec1b1e19 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -27,10 +27,15 @@ #include "config.h" +#include +#include #include "extension/default_eventloop.h" #include "debug.h" #include "types-internal.h" +static int max_fds = 0; +static int max_timeouts = 0; + static uint64_t get_now_plus(uint64_t amount) { struct timeval tv; @@ -53,15 +58,15 @@ default_eventloop_schedule(getdns_eventloop *loop, _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; size_t i; - DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, FD_SETSIZE: %d)\n" - , __FUNCTION__, loop, fd, timeout, event, FD_SETSIZE); + DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, max_fds: %d)\n" + , __FUNCTION__, loop, fd, timeout, event, max_fds); if (!loop || !event) return GETDNS_RETURN_INVALID_PARAMETER; - if (fd >= (int)FD_SETSIZE) { - DEBUG_SCHED( "ERROR: fd %d >= FD_SETSIZE: %d!\n" - , fd, FD_SETSIZE); + if (fd >= (int)max_fds) { + DEBUG_SCHED( "ERROR: fd %d >= max_fds: %d!\n" + , fd, max_fds); return GETDNS_RETURN_GENERIC_ERROR; } if (fd >= 0 && !(event->read_cb || event->write_cb)) { @@ -101,7 +106,7 @@ default_eventloop_schedule(getdns_eventloop *loop, DEBUG_SCHED("ERROR: timeout event with write_cb! Clearing.\n"); event->write_cb = NULL; } - for (i = 0; i < MAX_TIMEOUTS; i++) { + for (i = 0; i < max_timeouts; i++) { if (default_loop->timeout_events[i] == NULL) { default_loop->timeout_events[i] = event; default_loop->timeout_times[i] = get_now_plus(timeout); @@ -126,7 +131,7 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNCTION__, loop, event); i = (intptr_t)event->ev - 1; - if (i < 0 || i >= FD_SETSIZE) { + if (i < 0 || i > max_fds) { return GETDNS_RETURN_GENERIC_ERROR; } if (event->timeout_cb && !event->read_cb && !event->write_cb) { @@ -153,7 +158,15 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) static void default_eventloop_cleanup(getdns_eventloop *loop) { - (void)loop; + _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + if (default_loop->fd_events) + free(default_loop->fd_events); + if (default_loop->fd_timeout_times) + free(default_loop->fd_timeout_times); + if (default_loop->timeout_events) + free(default_loop->timeout_events); + if (default_loop->timeout_times) + free(default_loop->timeout_times); } static void @@ -191,20 +204,19 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) { _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; - fd_set readfds, writefds; int fd, max_fd = -1; uint64_t now, timeout = TIMEOUT_FOREVER; size_t i; - struct timeval tv; - + int poll_timeout = 0; + struct pollfd* pfds = NULL; + int num_pfds = 0; + if (!loop) return; - - FD_ZERO(&readfds); - FD_ZERO(&writefds); + now = get_now_plus(0); - for (i = 0; i < MAX_TIMEOUTS; i++) { + for (i = 0; i < max_timeouts; i++) { if (!default_loop->timeout_events[i]) continue; if (now > default_loop->timeout_times[i]) @@ -212,50 +224,65 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) else if (default_loop->timeout_times[i] < timeout) timeout = default_loop->timeout_times[i]; } - for (fd = 0; fd < FD_SETSIZE; fd++) { + // first we count the number of fds that will be active + for (fd = 0; fd < max_fds; fd++) { if (!default_loop->fd_events[fd]) continue; - if (default_loop->fd_events[fd]->read_cb) - FD_SET(fd, &readfds); - if (default_loop->fd_events[fd]->write_cb) - FD_SET(fd, &writefds); + if (default_loop->fd_events[fd]->read_cb || + default_loop->fd_events[fd]->write_cb) + num_pfds++; if (fd > max_fd) max_fd = fd; if (default_loop->fd_timeout_times[fd] < timeout) timeout = default_loop->fd_timeout_times[fd]; } - if (max_fd == -1 && timeout == TIMEOUT_FOREVER) + + if ((max_fd == -1 && timeout == (uint64_t)-1) || (num_pfds == 0)) return; - if (! blocking || now > timeout) { - tv.tv_sec = 0; - tv.tv_usec = 0; - } else { - tv.tv_sec = (long)((timeout - now) / 1000000); - tv.tv_usec = (long)((timeout - now) % 1000000); + pfds = calloc(num_pfds, sizeof(struct pollfd)); + for (fd = 0, i=0; fd < max_fds; fd++) { + if (!default_loop->fd_events[fd]) + continue; + if (default_loop->fd_events[fd]->read_cb) { + pfds[i].fd = fd; + pfds[i].events |= POLLIN; + } + if (default_loop->fd_events[fd]->write_cb) { + pfds[i].fd = fd; + pfds[i].events |= POLLOUT; + } } - if (select(max_fd + 1, &readfds, &writefds, NULL, - (timeout == TIMEOUT_FOREVER ? NULL : &tv)) < 0) { - perror("select() failed"); + + if (! blocking || now > timeout) { + poll_timeout = 0; + } else { + poll_timeout = (timeout - now) * 1000; /* turn seconds in millseconds */ + } + if (poll(pfds, num_pfds, poll_timeout) < 0) { + perror("poll() failed"); exit(EXIT_FAILURE); } now = get_now_plus(0); - for (fd = 0; fd < FD_SETSIZE; fd++) { + for (int i = 0; i < num_pfds; i++) { + int fd = pfds[i].fd; if (default_loop->fd_events[fd] && default_loop->fd_events[fd]->read_cb && - FD_ISSET(fd, &readfds)) + (pfds[i].revents & POLLIN)) default_read_cb(fd, default_loop->fd_events[fd]); if (default_loop->fd_events[fd] && default_loop->fd_events[fd]->write_cb && - FD_ISSET(fd, &writefds)) + (pfds[i].revents & POLLOUT)) default_write_cb(fd, default_loop->fd_events[fd]); - + } + if (pfds) + free(pfds); + for (int fd=0; fd < max_fds; fd++) { if (default_loop->fd_events[fd] && default_loop->fd_events[fd]->timeout_cb && now > default_loop->fd_timeout_times[fd]) default_timeout_cb(fd, default_loop->fd_events[fd]); - i = fd; if (default_loop->timeout_events[i] && default_loop->timeout_events[i]->timeout_cb && @@ -274,7 +301,7 @@ default_eventloop_run(getdns_eventloop *loop) return; i = 0; - while (i < MAX_TIMEOUTS) { + while (i < max_timeouts) { if (default_loop->fd_events[i] || default_loop->timeout_events[i]) { default_eventloop_run_once(loop, 1); i = 0; @@ -297,4 +324,22 @@ _getdns_default_eventloop_init(_getdns_default_eventloop *loop) (void) memset(loop, 0, sizeof(_getdns_default_eventloop)); loop->loop.vmt = &default_eventloop_vmt; + + struct rlimit rl; + if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { + max_fds = rl.rlim_cur; + max_timeouts = max_fds; + } else { + DEBUG_SCHED("ERROR: could not obtain RLIMIT_NOFILE from getrlimit()\n"); + max_fds = 0; + max_timeouts = max_fds; + } + if (max_fds) { + loop->fd_events = calloc(max_fds, sizeof(getdns_eventloop_event *)); + loop->fd_timeout_times = calloc(max_fds, sizeof(uint64_t)); + } + if (max_timeouts) { + loop->timeout_events = calloc(max_timeouts, sizeof(getdns_eventloop_event *)); + loop->timeout_times = calloc(max_timeouts, sizeof(uint64_t)); + } } diff --git a/src/extension/default_eventloop.h b/src/extension/default_eventloop.h index 7f6b78f0..67b2eda8 100644 --- a/src/extension/default_eventloop.h +++ b/src/extension/default_eventloop.h @@ -35,20 +35,13 @@ #include "getdns/getdns.h" #include "getdns/getdns_extra.h" -/* No more than select's capability queries can be outstanding, - * The number of outstanding timeouts should be less or equal then - * the number of outstanding queries, so MAX_TIMEOUTS equal to - * FD_SETSIZE should be safe. - */ -#define MAX_TIMEOUTS FD_SETSIZE - -/* Eventloop based on select */ +/* Eventloop based on poll */ typedef struct _getdns_default_eventloop { getdns_eventloop loop; - getdns_eventloop_event *fd_events[FD_SETSIZE]; - uint64_t fd_timeout_times[FD_SETSIZE]; - getdns_eventloop_event *timeout_events[MAX_TIMEOUTS]; - uint64_t timeout_times[MAX_TIMEOUTS]; + getdns_eventloop_event **fd_events; + uint64_t *fd_timeout_times; + getdns_eventloop_event **timeout_events; + uint64_t *timeout_times; } _getdns_default_eventloop; From a9386e621af226a6b2dbc5d1c2b44573ecef2390 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Thu, 17 Nov 2016 18:26:11 +0000 Subject: [PATCH 02/26] max_fds and max_timeouts part of default eventloop structure --- src/extension/default_eventloop.c | 43 ++++++++++++++----------------- src/extension/default_eventloop.h | 2 ++ 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index ec1b1e19..83a1d956 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -33,9 +33,6 @@ #include "debug.h" #include "types-internal.h" -static int max_fds = 0; -static int max_timeouts = 0; - static uint64_t get_now_plus(uint64_t amount) { struct timeval tv; @@ -59,14 +56,14 @@ default_eventloop_schedule(getdns_eventloop *loop, size_t i; DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, max_fds: %d)\n" - , __FUNCTION__, loop, fd, timeout, event, max_fds); + , __FUNCTION__, loop, fd, timeout, event, default_loop->max_fds); if (!loop || !event) return GETDNS_RETURN_INVALID_PARAMETER; - if (fd >= (int)max_fds) { + if (fd >= (int)default_loop->max_fds) { DEBUG_SCHED( "ERROR: fd %d >= max_fds: %d!\n" - , fd, max_fds); + , fd, default_loop->max_fds); return GETDNS_RETURN_GENERIC_ERROR; } if (fd >= 0 && !(event->read_cb || event->write_cb)) { @@ -106,7 +103,7 @@ default_eventloop_schedule(getdns_eventloop *loop, DEBUG_SCHED("ERROR: timeout event with write_cb! Clearing.\n"); event->write_cb = NULL; } - for (i = 0; i < max_timeouts; i++) { + for (i = 0; i < default_loop->max_timeouts; i++) { if (default_loop->timeout_events[i] == NULL) { default_loop->timeout_events[i] = event; default_loop->timeout_times[i] = get_now_plus(timeout); @@ -131,7 +128,7 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNCTION__, loop, event); i = (intptr_t)event->ev - 1; - if (i < 0 || i > max_fds) { + if (i < 0 || i > default_loop->max_fds) { return GETDNS_RETURN_GENERIC_ERROR; } if (event->timeout_cb && !event->read_cb && !event->write_cb) { @@ -216,7 +213,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) now = get_now_plus(0); - for (i = 0; i < max_timeouts; i++) { + for (i = 0; i < default_loop->max_timeouts; i++) { if (!default_loop->timeout_events[i]) continue; if (now > default_loop->timeout_times[i]) @@ -225,7 +222,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) timeout = default_loop->timeout_times[i]; } // first we count the number of fds that will be active - for (fd = 0; fd < max_fds; fd++) { + for (fd = 0; fd < default_loop->max_fds; fd++) { if (!default_loop->fd_events[fd]) continue; if (default_loop->fd_events[fd]->read_cb || @@ -241,7 +238,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) return; pfds = calloc(num_pfds, sizeof(struct pollfd)); - for (fd = 0, i=0; fd < max_fds; fd++) { + for (fd = 0, i=0; fd < default_loop->max_fds; fd++) { if (!default_loop->fd_events[fd]) continue; if (default_loop->fd_events[fd]->read_cb) { @@ -278,7 +275,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) } if (pfds) free(pfds); - for (int fd=0; fd < max_fds; fd++) { + for (int fd=0; fd < default_loop->max_fds; fd++) { if (default_loop->fd_events[fd] && default_loop->fd_events[fd]->timeout_cb && now > default_loop->fd_timeout_times[fd]) @@ -301,7 +298,7 @@ default_eventloop_run(getdns_eventloop *loop) return; i = 0; - while (i < max_timeouts) { + while (i < default_loop->max_timeouts) { if (default_loop->fd_events[i] || default_loop->timeout_events[i]) { default_eventloop_run_once(loop, 1); i = 0; @@ -327,19 +324,19 @@ _getdns_default_eventloop_init(_getdns_default_eventloop *loop) struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { - max_fds = rl.rlim_cur; - max_timeouts = max_fds; + loop->max_fds = rl.rlim_cur; + loop->max_timeouts = loop->max_fds; } else { DEBUG_SCHED("ERROR: could not obtain RLIMIT_NOFILE from getrlimit()\n"); - max_fds = 0; - max_timeouts = max_fds; + loop->max_fds = 0; + loop->max_timeouts = loop->max_fds; } - if (max_fds) { - loop->fd_events = calloc(max_fds, sizeof(getdns_eventloop_event *)); - loop->fd_timeout_times = calloc(max_fds, sizeof(uint64_t)); + if (loop->max_fds) { + loop->fd_events = calloc(loop->max_fds, sizeof(getdns_eventloop_event *)); + loop->fd_timeout_times = calloc(loop->max_fds, sizeof(uint64_t)); } - if (max_timeouts) { - loop->timeout_events = calloc(max_timeouts, sizeof(getdns_eventloop_event *)); - loop->timeout_times = calloc(max_timeouts, sizeof(uint64_t)); + if (loop->max_timeouts) { + loop->timeout_events = calloc(loop->max_timeouts, sizeof(getdns_eventloop_event *)); + loop->timeout_times = calloc(loop->max_timeouts, sizeof(uint64_t)); } } diff --git a/src/extension/default_eventloop.h b/src/extension/default_eventloop.h index 67b2eda8..285bbc11 100644 --- a/src/extension/default_eventloop.h +++ b/src/extension/default_eventloop.h @@ -38,6 +38,8 @@ /* Eventloop based on poll */ typedef struct _getdns_default_eventloop { getdns_eventloop loop; + int max_fds; + int max_timeouts; getdns_eventloop_event **fd_events; uint64_t *fd_timeout_times; getdns_eventloop_event **timeout_events; From d3b097fffe11a8fc15ce92af63c0dfb227493057 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 14 Dec 2016 15:45:39 +0000 Subject: [PATCH 03/26] Rewrite default_eventloop to use hash tables instead of arrays --- src/extension/default_eventloop.c | 216 +++--- src/extension/default_eventloop.h | 16 +- src/util/uthash.h | 1074 +++++++++++++++++++++++++++++ 3 files changed, 1212 insertions(+), 94 deletions(-) create mode 100644 src/util/uthash.h diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 83a1d956..1ae37adc 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -27,12 +27,41 @@ #include "config.h" +#ifdef USE_WINSOCK + +#else #include +#endif #include #include "extension/default_eventloop.h" #include "debug.h" #include "types-internal.h" +_getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) +{ + _getdns_eventloop_info* ev; + + DEBUG_SCHED("finding event in events ptr %p with id %d", *events, id); + + HASH_FIND_INT(*events, &id, ev); + + DEBUG_SCHED("found event in events ptr %p with id %d and ptr %p", *events, id, ev); + + return ev; +} + +void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) +{ + DEBUG_SCHED("adding event in events ptr %p with id %d and ptr %p", *events, id, ev); + HASH_ADD_INT(*events, id, ev); +} + +void delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) +{ + DEBUG_SCHED("deleting event in events ptr %p and ptr %p", *events, ev); + HASH_DEL(*events, ev); +} + static uint64_t get_now_plus(uint64_t amount) { struct timeval tv; @@ -72,22 +101,33 @@ default_eventloop_schedule(getdns_eventloop *loop, fd = -1; } if (fd >= 0) { + DEBUG_SCHED("default_eventloop_schedule: find_event(default_loop->fd_events)"); + _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); #if defined(SCHED_DEBUG) && SCHED_DEBUG - if (default_loop->fd_events[fd]) { - if (default_loop->fd_events[fd] == event) { + if (fd_event) { + if (fd_event->event == event) { DEBUG_SCHED("WARNING: Event %p not cleared " "before being rescheduled!\n" - , default_loop->fd_events[fd]); + , fd_event->event); } else { DEBUG_SCHED("ERROR: A different event is " "already present at fd slot: %p!\n" - , default_loop->fd_events[fd]); + , fd_event->event); } } #endif - default_loop->fd_events[fd] = event; - default_loop->fd_timeout_times[fd] = get_now_plus(timeout); - event->ev = (void *)(intptr_t)(fd + 1); + /* cleanup the old event if it exists */ + if (fd_event) { + delete_event(&default_loop->fd_events, fd_event); + free(fd_event); + } + fd_event = calloc(1, sizeof(_getdns_eventloop_info)); + fd_event->id = fd; + fd_event->event = event; + fd_event->timeout_time = get_now_plus(timeout); + add_event(&default_loop->fd_events, fd, fd_event); + event->ev = (void *) (intptr_t) fd + 1; + DEBUG_SCHED( "scheduled read/write at %d\n", fd); return GETDNS_RETURN_GOOD; } @@ -104,10 +144,16 @@ default_eventloop_schedule(getdns_eventloop *loop, event->write_cb = NULL; } for (i = 0; i < default_loop->max_timeouts; i++) { - if (default_loop->timeout_events[i] == NULL) { - default_loop->timeout_events[i] = event; - default_loop->timeout_times[i] = get_now_plus(timeout); - event->ev = (void *)(intptr_t)(i + 1); + _getdns_eventloop_info* timeout_event = NULL; + DEBUG_SCHED("default_eventloop_schedule: find_event(default_loop->timeout_events)"); + if ((timeout_event = find_event(&default_loop->timeout_events, i)) == NULL) { + timeout_event = calloc(1, sizeof(_getdns_eventloop_info)); + timeout_event->id = i; + timeout_event->event = event; + timeout_event->timeout_time = get_now_plus(timeout); + add_event(&default_loop->timeout_events, i, timeout_event); + event->ev = (void *) (intptr_t) i + 1; + DEBUG_SCHED( "scheduled timeout at %d\n", (int)i); return GETDNS_RETURN_GOOD; } @@ -132,21 +178,31 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) return GETDNS_RETURN_GENERIC_ERROR; } if (event->timeout_cb && !event->read_cb && !event->write_cb) { + DEBUG_SCHED("default_eventloop_clear: find_event(default_loop->timeout_events)"); + _getdns_eventloop_info* timeout_event = find_event(&default_loop->timeout_events, i); #if defined(SCHED_DEBUG) && SCHED_DEBUG - if (default_loop->timeout_events[i] != event) + if (timeout_event && timeout_event->event != event) DEBUG_SCHED( "ERROR: Different/wrong event present at " "timeout slot: %p!\n" - , default_loop->timeout_events[i]); + , timeout_event); #endif - default_loop->timeout_events[i] = NULL; + if (timeout_event) { + delete_event(&default_loop->timeout_events, timeout_event); + free(timeout_event); + } } else { + DEBUG_SCHED("default_eventloop_clear: find_event(default_loop->fd_events)"); + _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, i); #if defined(SCHED_DEBUG) && SCHED_DEBUG - if (default_loop->fd_events[i] != event) + if (fd_event && fd_event->event != event) DEBUG_SCHED( "ERROR: Different/wrong event present at " "fd slot: %p!\n" - , default_loop->fd_events[i]); + , fd_event); #endif - default_loop->fd_events[i] = NULL; + if (fd_event) { + delete_event(&default_loop->fd_events, fd_event); + free(fd_event); + } } event->ev = NULL; return GETDNS_RETURN_GOOD; @@ -156,14 +212,8 @@ static void default_eventloop_cleanup(getdns_eventloop *loop) { _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; - if (default_loop->fd_events) - free(default_loop->fd_events); - if (default_loop->fd_timeout_times) - free(default_loop->fd_timeout_times); - if (default_loop->timeout_events) - free(default_loop->timeout_events); - if (default_loop->timeout_times) - free(default_loop->timeout_times); + HASH_CLEAR(hh, default_loop->fd_events); + HASH_CLEAR(hh, default_loop->timeout_events); } static void @@ -200,91 +250,93 @@ static void default_eventloop_run_once(getdns_eventloop *loop, int blocking) { _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; - - int fd, max_fd = -1; + _getdns_eventloop_info *s, *tmp; uint64_t now, timeout = TIMEOUT_FOREVER; - size_t i; + size_t i=0; int poll_timeout = 0; struct pollfd* pfds = NULL; int num_pfds = 0; - + if (!loop) return; now = get_now_plus(0); - for (i = 0; i < default_loop->max_timeouts; i++) { - if (!default_loop->timeout_events[i]) - continue; - if (now > default_loop->timeout_times[i]) - default_timeout_cb(-1, default_loop->timeout_events[i]); - else if (default_loop->timeout_times[i] < timeout) - timeout = default_loop->timeout_times[i]; + HASH_ITER(hh, default_loop->timeout_events, s, tmp) { + if (now > s->timeout_time) + default_timeout_cb(-1, s->event); + else if (s->timeout_time < timeout) + timeout = s->timeout_time; } // first we count the number of fds that will be active - for (fd = 0; fd < default_loop->max_fds; fd++) { - if (!default_loop->fd_events[fd]) - continue; - if (default_loop->fd_events[fd]->read_cb || - default_loop->fd_events[fd]->write_cb) + HASH_ITER(hh, default_loop->fd_events, s, tmp) { + if (s->event->read_cb || + s->event->write_cb) num_pfds++; - if (fd > max_fd) - max_fd = fd; - if (default_loop->fd_timeout_times[fd] < timeout) - timeout = default_loop->fd_timeout_times[fd]; + if (s->timeout_time < timeout) + timeout = s->timeout_time; } - if ((max_fd == -1 && timeout == (uint64_t)-1) || (num_pfds == 0)) + if ((timeout == (uint64_t)-1) && (num_pfds == 0)) return; pfds = calloc(num_pfds, sizeof(struct pollfd)); - for (fd = 0, i=0; fd < default_loop->max_fds; fd++) { - if (!default_loop->fd_events[fd]) - continue; - if (default_loop->fd_events[fd]->read_cb) { - pfds[i].fd = fd; + i = 0; + HASH_ITER(hh, default_loop->fd_events, s, tmp) { + if (s->event->read_cb) { + pfds[i].fd = s->id; pfds[i].events |= POLLIN; } - if (default_loop->fd_events[fd]->write_cb) { - pfds[i].fd = fd; + if (s->event->write_cb) { + pfds[i].fd = s->id; pfds[i].events |= POLLOUT; } + i++; } if (! blocking || now > timeout) { poll_timeout = 0; } else { - poll_timeout = (timeout - now) * 1000; /* turn seconds in millseconds */ + poll_timeout = (timeout - now) * 1000; /* turn seconds into millseconds */ } +#ifdef USE_WINSOCK + if (WSAPoll(pfds, num_pfds, poll_timeout) < 0) { +#else if (poll(pfds, num_pfds, poll_timeout) < 0) { +#endif perror("poll() failed"); exit(EXIT_FAILURE); } now = get_now_plus(0); - for (int i = 0; i < num_pfds; i++) { + for (i = 0; i < num_pfds; i++) { int fd = pfds[i].fd; - if (default_loop->fd_events[fd] && - default_loop->fd_events[fd]->read_cb && + DEBUG_SCHED("default_eventloop_runonce: find_event(default_loop->fd_events)"); + _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); + if (fd_event && + fd_event->event && + fd_event->event->read_cb && (pfds[i].revents & POLLIN)) - default_read_cb(fd, default_loop->fd_events[fd]); + default_read_cb(fd, fd_event->event); - if (default_loop->fd_events[fd] && - default_loop->fd_events[fd]->write_cb && + if (fd_event && + fd_event->event && + fd_event->event->write_cb && (pfds[i].revents & POLLOUT)) - default_write_cb(fd, default_loop->fd_events[fd]); + default_write_cb(fd, fd_event->event); } if (pfds) free(pfds); - for (int fd=0; fd < default_loop->max_fds; fd++) { - if (default_loop->fd_events[fd] && - default_loop->fd_events[fd]->timeout_cb && - now > default_loop->fd_timeout_times[fd]) - default_timeout_cb(fd, default_loop->fd_events[fd]); - i = fd; - if (default_loop->timeout_events[i] && - default_loop->timeout_events[i]->timeout_cb && - now > default_loop->timeout_times[i]) - default_timeout_cb(-1, default_loop->timeout_events[i]); + HASH_ITER(hh, default_loop->fd_events, s, tmp) { + if (s->event && + s->event->timeout_cb && + now > s->timeout_time) + default_timeout_cb(s->id, s->event); + } + HASH_ITER(hh, default_loop->timeout_events, s, tmp) { + if (s->event && + s->event->timeout_cb && + now > s->timeout_time) + default_timeout_cb(s->id, s->event); } } @@ -292,19 +344,13 @@ static void default_eventloop_run(getdns_eventloop *loop) { _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; - size_t i; if (!loop) return; - i = 0; - while (i < default_loop->max_timeouts) { - if (default_loop->fd_events[i] || default_loop->timeout_events[i]) { - default_eventloop_run_once(loop, 1); - i = 0; - } else { - i++; - } + /* keep going until all the events are cleared */ + while (default_loop->fd_events && default_loop->timeout_events) { + default_eventloop_run_once(loop, 1); } } @@ -325,18 +371,10 @@ _getdns_default_eventloop_init(_getdns_default_eventloop *loop) struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { loop->max_fds = rl.rlim_cur; - loop->max_timeouts = loop->max_fds; + loop->max_timeouts = loop->max_fds; /* this is somewhat arbitrary */ } else { DEBUG_SCHED("ERROR: could not obtain RLIMIT_NOFILE from getrlimit()\n"); loop->max_fds = 0; loop->max_timeouts = loop->max_fds; } - if (loop->max_fds) { - loop->fd_events = calloc(loop->max_fds, sizeof(getdns_eventloop_event *)); - loop->fd_timeout_times = calloc(loop->max_fds, sizeof(uint64_t)); - } - if (loop->max_timeouts) { - loop->timeout_events = calloc(loop->max_timeouts, sizeof(getdns_eventloop_event *)); - loop->timeout_times = calloc(loop->max_timeouts, sizeof(uint64_t)); - } } diff --git a/src/extension/default_eventloop.h b/src/extension/default_eventloop.h index 285bbc11..bc1d881b 100644 --- a/src/extension/default_eventloop.h +++ b/src/extension/default_eventloop.h @@ -34,19 +34,25 @@ #include "config.h" #include "getdns/getdns.h" #include "getdns/getdns_extra.h" +#include "util/uthash.h" /* Eventloop based on poll */ + +typedef struct _getdns_eventloop_info { + int id; + getdns_eventloop_event *event; + uint64_t timeout_time; + UT_hash_handle hh; +} _getdns_eventloop_info; + typedef struct _getdns_default_eventloop { getdns_eventloop loop; int max_fds; int max_timeouts; - getdns_eventloop_event **fd_events; - uint64_t *fd_timeout_times; - getdns_eventloop_event **timeout_events; - uint64_t *timeout_times; + _getdns_eventloop_info *fd_events; + _getdns_eventloop_info *timeout_events; } _getdns_default_eventloop; - void _getdns_default_eventloop_init(_getdns_default_eventloop *loop); diff --git a/src/util/uthash.h b/src/util/uthash.h new file mode 100644 index 00000000..45d1f9fc --- /dev/null +++ b/src/util/uthash.h @@ -0,0 +1,1074 @@ +/* +Copyright (c) 2003-2016, Troy D. Hanson http://troydhanson.github.com/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTHASH_H +#define UTHASH_H + +#define UTHASH_VERSION 2.0.1 + +#include /* memcmp,strlen */ +#include /* ptrdiff_t */ +#include /* exit() */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define DECLTYPE(x) (decltype(x)) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#define DECLTYPE(x) +#endif +#elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE +#define DECLTYPE(x) +#else /* GNU, Sun and other compilers */ +#define DECLTYPE(x) (__typeof(x)) +#endif + +#ifdef NO_DECLTYPE +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + char **_da_dst = (char**)(&(dst)); \ + *_da_dst = (char*)(src); \ +} while (0) +#else +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + (dst) = DECLTYPE(dst)(src); \ +} while (0) +#endif + +/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */ +#if defined(_WIN32) +#if defined(_MSC_VER) && _MSC_VER >= 1600 +#include +#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__) +#include +#else +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#endif +#elif defined(__GNUC__) && !defined(__VXWORKS__) +#include +#else +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#endif + +#ifndef uthash_fatal +#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ +#endif +#ifndef uthash_malloc +#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ +#endif +#ifndef uthash_free +#define uthash_free(ptr,sz) free(ptr) /* free fcn */ +#endif +#ifndef uthash_strlen +#define uthash_strlen(s) strlen(s) +#endif +#ifndef uthash_memcmp +#define uthash_memcmp(a,b,n) memcmp(a,b,n) +#endif + +#ifndef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ +#endif +#ifndef uthash_expand_fyi +#define uthash_expand_fyi(tbl) /* can be defined to log expands */ +#endif + +/* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ +#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ + +/* calculate the element whose hash handle address is hhp */ +#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) +/* calculate the hash handle from element address elp */ +#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(((char*)(elp)) + ((tbl)->hho))) + +#define HASH_VALUE(keyptr,keylen,hashv) \ +do { \ + HASH_FCN(keyptr, keylen, hashv); \ +} while (0) + +#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ +do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_bkt; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ + } \ + } \ +} while (0) + +#define HASH_FIND(hh,head,keyptr,keylen,out) \ +do { \ + unsigned _hf_hashv; \ + HASH_VALUE(keyptr, keylen, _hf_hashv); \ + HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ +} while (0) + +#ifdef HASH_BLOOM +#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) +#define HASH_BLOOM_MAKE(tbl) \ +do { \ + (tbl)->bloom_nbits = HASH_BLOOM; \ + (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ + if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ + memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ + (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ +} while (0) + +#define HASH_BLOOM_FREE(tbl) \ +do { \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ +} while (0) + +#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) +#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U))) + +#define HASH_BLOOM_ADD(tbl,hashv) \ + HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U))) + +#define HASH_BLOOM_TEST(tbl,hashv) \ + HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U))) + +#else +#define HASH_BLOOM_MAKE(tbl) +#define HASH_BLOOM_FREE(tbl) +#define HASH_BLOOM_ADD(tbl,hashv) +#define HASH_BLOOM_TEST(tbl,hashv) (1) +#define HASH_BLOOM_BYTELEN 0U +#endif + +#define HASH_MAKE_TABLE(hh,head) \ +do { \ + (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ + sizeof(UT_hash_table)); \ + if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ + memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ + (head)->hh.tbl->tail = &((head)->hh); \ + (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ + (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ + (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ + (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ + memset((head)->hh.tbl->buckets, 0, \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ +} while (0) + +#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ +} while (0) + +#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ +} while (0) + +#define HASH_APPEND_LIST(hh, head, add) \ +do { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail->next = (add); \ + (head)->hh.tbl->tail = &((add)->hh); \ +} while (0) + +#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ +do { \ + unsigned _ha_bkt; \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + (head) = (add); \ + HASH_MAKE_TABLE(hh, head); \ + } else { \ + struct UT_hash_handle *_hs_iter = &(head)->hh; \ + (add)->hh.tbl = (head)->hh.tbl; \ + do { \ + if (cmpfcn(DECLTYPE(head) ELMT_FROM_HH((head)->hh.tbl, _hs_iter), add) > 0) \ + break; \ + } while ((_hs_iter = _hs_iter->next)); \ + if (_hs_iter) { \ + (add)->hh.next = _hs_iter; \ + if (((add)->hh.prev = _hs_iter->prev)) { \ + HH_FROM_ELMT((head)->hh.tbl, _hs_iter->prev)->next = (add); \ + } else { \ + (head) = (add); \ + } \ + _hs_iter->prev = (add); \ + } else { \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + } \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], &(add)->hh); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + HASH_FSCK(hh, head); \ +} while (0) + +#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ +do { \ + unsigned _hs_hashv; \ + HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) + +#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ + HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) + +#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ +do { \ + unsigned _ha_bkt; \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + (head) = (add); \ + HASH_MAKE_TABLE(hh, head); \ + } else { \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], &(add)->hh); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + HASH_FSCK(hh, head); \ +} while (0) + +#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ +do { \ + unsigned _ha_hashv; \ + HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) + +#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ + HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) + +#define HASH_TO_BKT(hashv,num_bkts,bkt) \ +do { \ + bkt = ((hashv) & ((num_bkts) - 1U)); \ +} while (0) + +/* delete "delptr" from the hash table. + * "the usual" patch-up process for the app-order doubly-linked-list. + * The use of _hd_hh_del below deserves special explanation. + * These used to be expressed using (delptr) but that led to a bug + * if someone used the same symbol for the head and deletee, like + * HASH_DELETE(hh,users,users); + * We want that to work, but by changing the head (users) below + * we were forfeiting our ability to further refer to the deletee (users) + * in the patch-up process. Solution: use scratch space to + * copy the deletee pointer, then the latter references are via that + * scratch pointer rather than through the repointed (users) symbol. + */ +#define HASH_DELETE(hh,head,delptr) \ +do { \ + struct UT_hash_handle *_hd_hh_del; \ + if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + head = NULL; \ + } else { \ + unsigned _hd_bkt; \ + _hd_hh_del = &((delptr)->hh); \ + if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ + (head)->hh.tbl->tail = \ + (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ + (head)->hh.tbl->hho); \ + } \ + if ((delptr)->hh.prev != NULL) { \ + ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ + (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ + } else { \ + DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ + } \ + if (_hd_hh_del->next != NULL) { \ + ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \ + (head)->hh.tbl->hho))->prev = \ + _hd_hh_del->prev; \ + } \ + HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh,head); \ +} while (0) + + +/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ +#define HASH_FIND_STR(head,findstr,out) \ + HASH_FIND(hh,head,findstr,(unsigned)uthash_strlen(findstr),out) +#define HASH_ADD_STR(head,strfield,add) \ + HASH_ADD(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add) +#define HASH_REPLACE_STR(head,strfield,add,replaced) \ + HASH_REPLACE(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add,replaced) +#define HASH_FIND_INT(head,findint,out) \ + HASH_FIND(hh,head,findint,sizeof(int),out) +#define HASH_ADD_INT(head,intfield,add) \ + HASH_ADD(hh,head,intfield,sizeof(int),add) +#define HASH_REPLACE_INT(head,intfield,add,replaced) \ + HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) +#define HASH_FIND_PTR(head,findptr,out) \ + HASH_FIND(hh,head,findptr,sizeof(void *),out) +#define HASH_ADD_PTR(head,ptrfield,add) \ + HASH_ADD(hh,head,ptrfield,sizeof(void *),add) +#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ + HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) +#define HASH_DEL(head,delptr) \ + HASH_DELETE(hh,head,delptr) + +/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. + * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. + */ +#ifdef HASH_DEBUG +#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) +#define HASH_FSCK(hh,head) \ +do { \ + struct UT_hash_handle *_thh; \ + if (head) { \ + unsigned _bkt_i; \ + unsigned _count; \ + char *_prev; \ + _count = 0; \ + for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ + unsigned _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char*)(_thh->hh_prev)) { \ + HASH_OOPS("invalid hh_prev %p, actual %p\n", \ + _thh->hh_prev, _prev ); \ + } \ + _bkt_count++; \ + _prev = (char*)(_thh); \ + _thh = _thh->hh_next; \ + } \ + _count += _bkt_count; \ + if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ + HASH_OOPS("invalid bucket count %u, actual %u\n", \ + (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("invalid hh item count %u, actual %u\n", \ + (head)->hh.tbl->num_items, _count ); \ + } \ + /* traverse hh in app order; check next/prev integrity, count */ \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev !=(char*)(_thh->prev)) { \ + HASH_OOPS("invalid prev %p, actual %p\n", \ + _thh->prev, _prev ); \ + } \ + _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ + (head)->hh.tbl->hho) : NULL ); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("invalid app item count %u, actual %u\n", \ + (head)->hh.tbl->num_items, _count ); \ + } \ + } \ +} while (0) +#else +#define HASH_FSCK(hh,head) +#endif + +/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to + * the descriptor to which this macro is defined for tuning the hash function. + * The app can #include to get the prototype for write(2). */ +#ifdef HASH_EMIT_KEYS +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ +do { \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ +} while (0) +#else +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) +#endif + +/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ +#ifdef HASH_FUNCTION +#define HASH_FCN HASH_FUNCTION +#else +#define HASH_FCN HASH_JEN +#endif + +/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ +#define HASH_BER(key,keylen,hashv) \ +do { \ + unsigned _hb_keylen=(unsigned)keylen; \ + const unsigned char *_hb_key=(const unsigned char*)(key); \ + (hashv) = 0; \ + while (_hb_keylen-- != 0U) { \ + (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ + } \ +} while (0) + + +/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at + * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ +#define HASH_SAX(key,keylen,hashv) \ +do { \ + unsigned _sx_i; \ + const unsigned char *_hs_key=(const unsigned char*)(key); \ + hashv = 0; \ + for(_sx_i=0; _sx_i < keylen; _sx_i++) { \ + hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ + } \ +} while (0) +/* FNV-1a variation */ +#define HASH_FNV(key,keylen,hashv) \ +do { \ + unsigned _fn_i; \ + const unsigned char *_hf_key=(const unsigned char*)(key); \ + hashv = 2166136261U; \ + for(_fn_i=0; _fn_i < keylen; _fn_i++) { \ + hashv = hashv ^ _hf_key[_fn_i]; \ + hashv = hashv * 16777619U; \ + } \ +} while (0) + +#define HASH_OAT(key,keylen,hashv) \ +do { \ + unsigned _ho_i; \ + const unsigned char *_ho_key=(const unsigned char*)(key); \ + hashv = 0; \ + for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ + hashv += _ho_key[_ho_i]; \ + hashv += (hashv << 10); \ + hashv ^= (hashv >> 6); \ + } \ + hashv += (hashv << 3); \ + hashv ^= (hashv >> 11); \ + hashv += (hashv << 15); \ +} while (0) + +#define HASH_JEN_MIX(a,b,c) \ +do { \ + a -= b; a -= c; a ^= ( c >> 13 ); \ + b -= c; b -= a; b ^= ( a << 8 ); \ + c -= a; c -= b; c ^= ( b >> 13 ); \ + a -= b; a -= c; a ^= ( c >> 12 ); \ + b -= c; b -= a; b ^= ( a << 16 ); \ + c -= a; c -= b; c ^= ( b >> 5 ); \ + a -= b; a -= c; a ^= ( c >> 3 ); \ + b -= c; b -= a; b ^= ( a << 10 ); \ + c -= a; c -= b; c ^= ( b >> 15 ); \ +} while (0) + +#define HASH_JEN(key,keylen,hashv) \ +do { \ + unsigned _hj_i,_hj_j,_hj_k; \ + unsigned const char *_hj_key=(unsigned const char*)(key); \ + hashv = 0xfeedbeefu; \ + _hj_i = _hj_j = 0x9e3779b9u; \ + _hj_k = (unsigned)(keylen); \ + while (_hj_k >= 12U) { \ + _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + + ( (unsigned)_hj_key[2] << 16 ) \ + + ( (unsigned)_hj_key[3] << 24 ) ); \ + _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ + + ( (unsigned)_hj_key[6] << 16 ) \ + + ( (unsigned)_hj_key[7] << 24 ) ); \ + hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ + + ( (unsigned)_hj_key[10] << 16 ) \ + + ( (unsigned)_hj_key[11] << 24 ) ); \ + \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + \ + _hj_key += 12; \ + _hj_k -= 12U; \ + } \ + hashv += (unsigned)(keylen); \ + switch ( _hj_k ) { \ + case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ + case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ + case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ + case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ + case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ + case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ + case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ + case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ + case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ + case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ + case 1: _hj_i += _hj_key[0]; \ + } \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ +} while (0) + +/* The Paul Hsieh hash function */ +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif +#define HASH_SFH(key,keylen,hashv) \ +do { \ + unsigned const char *_sfh_key=(unsigned const char*)(key); \ + uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ + \ + unsigned _sfh_rem = _sfh_len & 3U; \ + _sfh_len >>= 2; \ + hashv = 0xcafebabeu; \ + \ + /* Main loop */ \ + for (;_sfh_len > 0U; _sfh_len--) { \ + hashv += get16bits (_sfh_key); \ + _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ + hashv = (hashv << 16) ^ _sfh_tmp; \ + _sfh_key += 2U*sizeof (uint16_t); \ + hashv += hashv >> 11; \ + } \ + \ + /* Handle end cases */ \ + switch (_sfh_rem) { \ + case 3: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 16; \ + hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ + hashv += hashv >> 11; \ + break; \ + case 2: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 11; \ + hashv += hashv >> 17; \ + break; \ + case 1: hashv += *_sfh_key; \ + hashv ^= hashv << 10; \ + hashv += hashv >> 1; \ + } \ + \ + /* Force "avalanching" of final 127 bits */ \ + hashv ^= hashv << 3; \ + hashv += hashv >> 5; \ + hashv ^= hashv << 4; \ + hashv += hashv >> 17; \ + hashv ^= hashv << 25; \ + hashv += hashv >> 6; \ +} while (0) + +#ifdef HASH_USING_NO_STRICT_ALIASING +/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. + * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. + * MurmurHash uses the faster approach only on CPU's where we know it's safe. + * + * Note the preprocessor built-in defines can be emitted using: + * + * gcc -m64 -dM -E - < /dev/null (on gcc) + * cc -## a.c (where a.c is a simple test file) (Sun Studio) + */ +#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) +#define MUR_GETBLOCK(p,i) p[i] +#else /* non intel */ +#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL) +#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL) +#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL) +#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL) +#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) +#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) +#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) +#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) +#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) +#else /* assume little endian non-intel */ +#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) +#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) +#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) +#endif +#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ + (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ + (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ + MUR_ONE_THREE(p)))) +#endif +#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) +#define MUR_FMIX(_h) \ +do { \ + _h ^= _h >> 16; \ + _h *= 0x85ebca6bu; \ + _h ^= _h >> 13; \ + _h *= 0xc2b2ae35u; \ + _h ^= _h >> 16; \ +} while (0) + +#define HASH_MUR(key,keylen,hashv) \ +do { \ + const uint8_t *_mur_data = (const uint8_t*)(key); \ + const int _mur_nblocks = (int)(keylen) / 4; \ + uint32_t _mur_h1 = 0xf88D5353u; \ + uint32_t _mur_c1 = 0xcc9e2d51u; \ + uint32_t _mur_c2 = 0x1b873593u; \ + uint32_t _mur_k1 = 0; \ + const uint8_t *_mur_tail; \ + const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \ + int _mur_i; \ + for(_mur_i = -_mur_nblocks; _mur_i!=0; _mur_i++) { \ + _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ + _mur_k1 *= _mur_c1; \ + _mur_k1 = MUR_ROTL32(_mur_k1,15); \ + _mur_k1 *= _mur_c2; \ + \ + _mur_h1 ^= _mur_k1; \ + _mur_h1 = MUR_ROTL32(_mur_h1,13); \ + _mur_h1 = (_mur_h1*5U) + 0xe6546b64u; \ + } \ + _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4)); \ + _mur_k1=0; \ + switch((keylen) & 3U) { \ + case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \ + case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8; /* FALLTHROUGH */ \ + case 1: _mur_k1 ^= (uint32_t)_mur_tail[0]; \ + _mur_k1 *= _mur_c1; \ + _mur_k1 = MUR_ROTL32(_mur_k1,15); \ + _mur_k1 *= _mur_c2; \ + _mur_h1 ^= _mur_k1; \ + } \ + _mur_h1 ^= (uint32_t)(keylen); \ + MUR_FMIX(_mur_h1); \ + hashv = _mur_h1; \ +} while (0) +#endif /* HASH_USING_NO_STRICT_ALIASING */ + +/* iterate over items in a known bucket to find desired item */ +#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ +do { \ + if ((head).hh_head != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ + } else { \ + (out) = NULL; \ + } \ + while ((out) != NULL) { \ + if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ + if (uthash_memcmp((out)->hh.key, keyptr, keylen_in) == 0) { \ + break; \ + } \ + } \ + if ((out)->hh.hh_next != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ + } else { \ + (out) = NULL; \ + } \ + } \ +} while (0) + +/* add an item to a bucket */ +#define HASH_ADD_TO_BKT(head,addhh) \ +do { \ + head.count++; \ + (addhh)->hh_next = head.hh_head; \ + (addhh)->hh_prev = NULL; \ + if (head.hh_head != NULL) { (head).hh_head->hh_prev = (addhh); } \ + (head).hh_head=addhh; \ + if ((head.count >= ((head.expand_mult+1U) * HASH_BKT_CAPACITY_THRESH)) \ + && ((addhh)->tbl->noexpand != 1U)) { \ + HASH_EXPAND_BUCKETS((addhh)->tbl); \ + } \ +} while (0) + +/* remove an item from a given bucket */ +#define HASH_DEL_IN_BKT(hh,head,hh_del) \ + (head).count--; \ + if ((head).hh_head == hh_del) { \ + (head).hh_head = hh_del->hh_next; \ + } \ + if (hh_del->hh_prev) { \ + hh_del->hh_prev->hh_next = hh_del->hh_next; \ + } \ + if (hh_del->hh_next) { \ + hh_del->hh_next->hh_prev = hh_del->hh_prev; \ + } + +/* Bucket expansion has the effect of doubling the number of buckets + * and redistributing the items into the new buckets. Ideally the + * items will distribute more or less evenly into the new buckets + * (the extent to which this is true is a measure of the quality of + * the hash function as it applies to the key domain). + * + * With the items distributed into more buckets, the chain length + * (item count) in each bucket is reduced. Thus by expanding buckets + * the hash keeps a bound on the chain length. This bounded chain + * length is the essence of how a hash provides constant time lookup. + * + * The calculation of tbl->ideal_chain_maxlen below deserves some + * explanation. First, keep in mind that we're calculating the ideal + * maximum chain length based on the *new* (doubled) bucket count. + * In fractions this is just n/b (n=number of items,b=new num buckets). + * Since the ideal chain length is an integer, we want to calculate + * ceil(n/b). We don't depend on floating point arithmetic in this + * hash, so to calculate ceil(n/b) with integers we could write + * + * ceil(n/b) = (n/b) + ((n%b)?1:0) + * + * and in fact a previous version of this hash did just that. + * But now we have improved things a bit by recognizing that b is + * always a power of two. We keep its base 2 log handy (call it lb), + * so now we can write this with a bit shift and logical AND: + * + * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) + * + */ +#define HASH_EXPAND_BUCKETS(tbl) \ +do { \ + unsigned _he_bkt; \ + unsigned _he_bkt_i; \ + struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ + UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ + _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ + 2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ + memset(_he_new_buckets, 0, \ + 2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + tbl->ideal_chain_maxlen = \ + (tbl->num_items >> (tbl->log2_num_buckets+1U)) + \ + (((tbl->num_items & ((tbl->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ + tbl->nonideal_items = 0; \ + for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ + { \ + _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ + while (_he_thh != NULL) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2U, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ + if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ + tbl->nonideal_items++; \ + _he_newbkt->expand_mult = _he_newbkt->count / \ + tbl->ideal_chain_maxlen; \ + } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head != NULL) { _he_newbkt->hh_head->hh_prev = \ + _he_thh; } \ + _he_newbkt->hh_head = _he_thh; \ + _he_thh = _he_hh_nxt; \ + } \ + } \ + uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ + tbl->num_buckets *= 2U; \ + tbl->log2_num_buckets++; \ + tbl->buckets = _he_new_buckets; \ + tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ + (tbl->ineff_expands+1U) : 0U; \ + if (tbl->ineff_expands > 1U) { \ + tbl->noexpand=1; \ + uthash_noexpand_fyi(tbl); \ + } \ + uthash_expand_fyi(tbl); \ +} while (0) + + +/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ +/* Note that HASH_SORT assumes the hash handle name to be hh. + * HASH_SRT was added to allow the hash handle name to be passed in. */ +#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) +#define HASH_SRT(hh,head,cmpfcn) \ +do { \ + unsigned _hs_i; \ + unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ + struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ + if (head != NULL) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping != 0U) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p != NULL) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ + _hs_psize++; \ + _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + if (! (_hs_q) ) { break; } \ + } \ + _hs_qsize = _hs_insize; \ + while ((_hs_psize > 0U) || ((_hs_qsize > 0U) && (_hs_q != NULL))) {\ + if (_hs_psize == 0U) { \ + _hs_e = _hs_q; \ + _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_qsize--; \ + } else if ( (_hs_qsize == 0U) || (_hs_q == NULL) ) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL){ \ + _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \ + ((void*)((char*)(_hs_p->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + } \ + _hs_psize--; \ + } else if (( \ + cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ + ) <= 0) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL){ \ + _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \ + ((void*)((char*)(_hs_p->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + } \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_qsize--; \ + } \ + if ( _hs_tail != NULL ) { \ + _hs_tail->next = ((_hs_e != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + if (_hs_e != NULL) { \ + _hs_e->prev = ((_hs_tail != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ + } \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ + } \ + if (_hs_tail != NULL){ \ + _hs_tail->next = NULL; \ + } \ + if ( _hs_nmerges <= 1U ) { \ + _hs_looping=0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2U; \ + } \ + HASH_FSCK(hh,head); \ + } \ +} while (0) + +/* This function selects items from one hash into another hash. + * The end result is that the selected items have dual presence + * in both hashes. There is no copy of the items made; rather + * they are added into the new hash through a secondary hash + * hash handle that must be present in the structure. */ +#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ +do { \ + unsigned _src_bkt, _dst_bkt; \ + void *_last_elt=NULL, *_elt; \ + UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ + ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ + if (src != NULL) { \ + for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ + for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ + _src_hh != NULL; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ + _dst_hh->key = _src_hh->key; \ + _dst_hh->keylen = _src_hh->keylen; \ + _dst_hh->hashv = _src_hh->hashv; \ + _dst_hh->prev = _last_elt; \ + _dst_hh->next = NULL; \ + if (_last_elt_hh != NULL) { _last_elt_hh->next = _elt; } \ + if (dst == NULL) { \ + DECLTYPE_ASSIGN(dst,_elt); \ + HASH_MAKE_TABLE(hh_dst,dst); \ + } else { \ + _dst_hh->tbl = (dst)->hh_dst.tbl; \ + } \ + HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ + HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ + (dst)->hh_dst.tbl->num_items++; \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ + } \ + } \ + } \ + HASH_FSCK(hh_dst,dst); \ +} while (0) + +#define HASH_CLEAR(hh,head) \ +do { \ + if (head != NULL) { \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head)=NULL; \ + } \ +} while (0) + +#define HASH_OVERHEAD(hh,head) \ + ((head != NULL) ? ( \ + (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ + ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ + sizeof(UT_hash_table) + \ + (HASH_BLOOM_BYTELEN))) : 0U) + +#ifdef NO_DECLTYPE +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#else +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#endif + +/* obtain a count of items in the hash */ +#define HASH_COUNT(head) HASH_CNT(hh,head) +#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) + +typedef struct UT_hash_bucket { + struct UT_hash_handle *hh_head; + unsigned count; + + /* expand_mult is normally set to 0. In this situation, the max chain length + * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If + * the bucket's chain exceeds this length, bucket expansion is triggered). + * However, setting expand_mult to a non-zero value delays bucket expansion + * (that would be triggered by additions to this particular bucket) + * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. + * (The multiplier is simply expand_mult+1). The whole idea of this + * multiplier is to reduce bucket expansions, since they are expensive, in + * situations where we know that a particular bucket tends to be overused. + * It is better to let its chain length grow to a longer yet-still-bounded + * value, than to do an O(n) bucket expansion too often. + */ + unsigned expand_mult; + +} UT_hash_bucket; + +/* random signature used only to find hash tables in external analysis */ +#define HASH_SIGNATURE 0xa0111fe1u +#define HASH_BLOOM_SIGNATURE 0xb12220f2u + +typedef struct UT_hash_table { + UT_hash_bucket *buckets; + unsigned num_buckets, log2_num_buckets; + unsigned num_items; + struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ + ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ + + /* in an ideal situation (all buckets used equally), no bucket would have + * more than ceil(#items/#buckets) items. that's the ideal chain length. */ + unsigned ideal_chain_maxlen; + + /* nonideal_items is the number of items in the hash whose chain position + * exceeds the ideal chain maxlen. these items pay the penalty for an uneven + * hash distribution; reaching them in a chain traversal takes >ideal steps */ + unsigned nonideal_items; + + /* ineffective expands occur when a bucket doubling was performed, but + * afterward, more than half the items in the hash had nonideal chain + * positions. If this happens on two consecutive expansions we inhibit any + * further expansion, as it's not helping; this happens when the hash + * function isn't a good fit for the key domain. When expansion is inhibited + * the hash will still work, albeit no longer in constant time. */ + unsigned ineff_expands, noexpand; + + uint32_t signature; /* used only to find hash tables in external analysis */ +#ifdef HASH_BLOOM + uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ + uint8_t *bloom_bv; + uint8_t bloom_nbits; +#endif + +} UT_hash_table; + +typedef struct UT_hash_handle { + struct UT_hash_table *tbl; + void *prev; /* prev element in app order */ + void *next; /* next element in app order */ + struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ + struct UT_hash_handle *hh_next; /* next hh in bucket order */ + void *key; /* ptr to enclosing struct's key */ + unsigned keylen; /* enclosing struct's key len */ + unsigned hashv; /* result of hash-fcn(key) */ +} UT_hash_handle; + +#endif /* UTHASH_H */ From 5cc4028d634b10500fab38a52531c6998b771767 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 14 Dec 2016 15:54:10 +0000 Subject: [PATCH 04/26] cleanup poll.h include for non-windows --- src/extension/default_eventloop.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 1ae37adc..4c6d8349 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -27,9 +27,7 @@ #include "config.h" -#ifdef USE_WINSOCK - -#else +#ifndef USE_WINSOCK #include #endif #include From 326b6bb410c4ddba46ea07129253da00ba3e43ac Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 14 Dec 2016 16:10:44 +0000 Subject: [PATCH 05/26] remove redundant debugging --- src/extension/default_eventloop.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 4c6d8349..6509af7f 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -39,24 +39,18 @@ _getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) { _getdns_eventloop_info* ev; - DEBUG_SCHED("finding event in events ptr %p with id %d", *events, id); - HASH_FIND_INT(*events, &id, ev); - DEBUG_SCHED("found event in events ptr %p with id %d and ptr %p", *events, id, ev); - return ev; } void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { - DEBUG_SCHED("adding event in events ptr %p with id %d and ptr %p", *events, id, ev); HASH_ADD_INT(*events, id, ev); } void delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) { - DEBUG_SCHED("deleting event in events ptr %p and ptr %p", *events, ev); HASH_DEL(*events, ev); } @@ -99,7 +93,6 @@ default_eventloop_schedule(getdns_eventloop *loop, fd = -1; } if (fd >= 0) { - DEBUG_SCHED("default_eventloop_schedule: find_event(default_loop->fd_events)"); _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); #if defined(SCHED_DEBUG) && SCHED_DEBUG if (fd_event) { @@ -143,7 +136,6 @@ default_eventloop_schedule(getdns_eventloop *loop, } for (i = 0; i < default_loop->max_timeouts; i++) { _getdns_eventloop_info* timeout_event = NULL; - DEBUG_SCHED("default_eventloop_schedule: find_event(default_loop->timeout_events)"); if ((timeout_event = find_event(&default_loop->timeout_events, i)) == NULL) { timeout_event = calloc(1, sizeof(_getdns_eventloop_info)); timeout_event->id = i; @@ -176,7 +168,6 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) return GETDNS_RETURN_GENERIC_ERROR; } if (event->timeout_cb && !event->read_cb && !event->write_cb) { - DEBUG_SCHED("default_eventloop_clear: find_event(default_loop->timeout_events)"); _getdns_eventloop_info* timeout_event = find_event(&default_loop->timeout_events, i); #if defined(SCHED_DEBUG) && SCHED_DEBUG if (timeout_event && timeout_event->event != event) @@ -189,7 +180,6 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) free(timeout_event); } } else { - DEBUG_SCHED("default_eventloop_clear: find_event(default_loop->fd_events)"); _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, i); #if defined(SCHED_DEBUG) && SCHED_DEBUG if (fd_event && fd_event->event != event) @@ -308,7 +298,6 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) now = get_now_plus(0); for (i = 0; i < num_pfds; i++) { int fd = pfds[i].fd; - DEBUG_SCHED("default_eventloop_runonce: find_event(default_loop->fd_events)"); _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); if (fd_event && fd_event->event && From e9e6ff013b60eb5f27460c8b8e2b8bfd4aab25f9 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 14 Dec 2016 16:49:24 +0000 Subject: [PATCH 06/26] Fix travis compiler warnings/errors --- src/extension/default_eventloop.c | 4 +++- src/extension/default_eventloop.h | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 6509af7f..72fd51ec 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -46,11 +46,13 @@ _getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { + DEBUG_SCHED("default_eventloop: add_event with id %d", id); HASH_ADD_INT(*events, id, ev); } void delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) { + DEBUG_SCHED("default_eventloop: delete_event with id %d", ev->id); HASH_DEL(*events, ev); } @@ -243,7 +245,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) size_t i=0; int poll_timeout = 0; struct pollfd* pfds = NULL; - int num_pfds = 0; + unsigned int num_pfds = 0; if (!loop) return; diff --git a/src/extension/default_eventloop.h b/src/extension/default_eventloop.h index bc1d881b..f4a7d2b6 100644 --- a/src/extension/default_eventloop.h +++ b/src/extension/default_eventloop.h @@ -47,8 +47,8 @@ typedef struct _getdns_eventloop_info { typedef struct _getdns_default_eventloop { getdns_eventloop loop; - int max_fds; - int max_timeouts; + unsigned int max_fds; + unsigned int max_timeouts; _getdns_eventloop_info *fd_events; _getdns_eventloop_info *timeout_events; } _getdns_default_eventloop; From c1d5ae9a2551a1873289f8b85b61cc78872426cd Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 14 Dec 2016 17:04:09 +0000 Subject: [PATCH 07/26] set event id in add_event rather than calling function --- src/extension/default_eventloop.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 72fd51ec..9b81f15d 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -47,6 +47,7 @@ _getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { DEBUG_SCHED("default_eventloop: add_event with id %d", id); + ev->id = id; HASH_ADD_INT(*events, id, ev); } @@ -115,7 +116,6 @@ default_eventloop_schedule(getdns_eventloop *loop, free(fd_event); } fd_event = calloc(1, sizeof(_getdns_eventloop_info)); - fd_event->id = fd; fd_event->event = event; fd_event->timeout_time = get_now_plus(timeout); add_event(&default_loop->fd_events, fd, fd_event); @@ -140,7 +140,6 @@ default_eventloop_schedule(getdns_eventloop *loop, _getdns_eventloop_info* timeout_event = NULL; if ((timeout_event = find_event(&default_loop->timeout_events, i)) == NULL) { timeout_event = calloc(1, sizeof(_getdns_eventloop_info)); - timeout_event->id = i; timeout_event->event = event; timeout_event->timeout_time = get_now_plus(timeout); add_event(&default_loop->timeout_events, i, timeout_event); From 0d395639781ff7adbcbc65daeafdc7db23ce1410 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 14 Dec 2016 17:50:39 +0000 Subject: [PATCH 08/26] Consisten use of TIMEOUT_FOREVER --- src/extension/default_eventloop.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 9b81f15d..2e20ca16 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -266,7 +266,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) timeout = s->timeout_time; } - if ((timeout == (uint64_t)-1) && (num_pfds == 0)) + if ((timeout == TIMEOUT_FOREVER) && (num_pfds == 0)) return; pfds = calloc(num_pfds, sizeof(struct pollfd)); @@ -283,7 +283,10 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) i++; } - if (! blocking || now > timeout) { + if (timeout == TIMEOUT_FOREVER) { + poll_timeout = -1; + } + else if (! blocking || now > timeout) { poll_timeout = 0; } else { poll_timeout = (timeout - now) * 1000; /* turn seconds into millseconds */ From 9b715d4743df221768f40632f9e6b4d51760cab2 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 15 Dec 2016 09:53:49 +0100 Subject: [PATCH 09/26] Suppress compile warnings --- src/extension/default_eventloop.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 8aeca8a2..342b63f8 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -102,7 +102,7 @@ default_eventloop_schedule(getdns_eventloop *loop, if (fd_event->event == event) { DEBUG_SCHED("WARNING: Event %p not cleared " "before being rescheduled!\n" - , fd_event->event); + , (void *)fd_event->event); } else { DEBUG_SCHED("ERROR: A different event is " "already present at fd slot: %p!\n" @@ -119,7 +119,7 @@ default_eventloop_schedule(getdns_eventloop *loop, fd_event->event = event; fd_event->timeout_time = get_now_plus(timeout); add_event(&default_loop->fd_events, fd, fd_event); - event->ev = (void *) (intptr_t) fd + 1; + event->ev = (void *) (intptr_t) (fd + 1); DEBUG_SCHED( "scheduled read/write at %d\n", fd); return GETDNS_RETURN_GOOD; @@ -143,7 +143,7 @@ default_eventloop_schedule(getdns_eventloop *loop, timeout_event->event = event; timeout_event->timeout_time = get_now_plus(timeout); add_event(&default_loop->timeout_events, i, timeout_event); - event->ev = (void *) (intptr_t) i + 1; + event->ev = (void *) (intptr_t) (i + 1); DEBUG_SCHED( "scheduled timeout at %d\n", (int)i); return GETDNS_RETURN_GOOD; From 5e26137eda2482acbfee7c6aad49daedfa1162e9 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Thu, 15 Dec 2016 13:40:40 +0000 Subject: [PATCH 10/26] Fix default_eventloop_run OR instead of AND and hash table iteration safety --- src/extension/default_eventloop.c | 35 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 342b63f8..21575e40 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -46,14 +46,14 @@ _getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { - DEBUG_SCHED("default_eventloop: add_event with id %d", id); + DEBUG_SCHED("default_eventloop: add_event with id %d\n", id); ev->id = id; HASH_ADD_INT(*events, id, ev); } void delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) { - DEBUG_SCHED("default_eventloop: delete_event with id %d", ev->id); + DEBUG_SCHED("default_eventloop: delete_event with id %d\n", ev->id); HASH_DEL(*events, ev); } @@ -121,7 +121,7 @@ default_eventloop_schedule(getdns_eventloop *loop, add_event(&default_loop->fd_events, fd, fd_event); event->ev = (void *) (intptr_t) (fd + 1); - DEBUG_SCHED( "scheduled read/write at %d\n", fd); + DEBUG_SCHED( "scheduled read/write at fd %d\n", fd); return GETDNS_RETURN_GOOD; } if (!event->timeout_cb) { @@ -145,7 +145,7 @@ default_eventloop_schedule(getdns_eventloop *loop, add_event(&default_loop->timeout_events, i, timeout_event); event->ev = (void *) (intptr_t) (i + 1); - DEBUG_SCHED( "scheduled timeout at %d\n", (int)i); + DEBUG_SCHED( "scheduled timeout at slot %d\n", (int)i); return GETDNS_RETURN_GOOD; } } @@ -249,7 +249,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) if (!loop) return; - + now = get_now_plus(0); HASH_ITER(hh, default_loop->timeout_events, s, tmp) { @@ -318,18 +318,37 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) } if (pfds) free(pfds); + _getdns_eventloop_info* fd_timeout_cbs = NULL; HASH_ITER(hh, default_loop->fd_events, s, tmp) { if (s->event && s->event->timeout_cb && now > s->timeout_time) - default_timeout_cb(s->id, s->event); + add_event(&fd_timeout_cbs, s->id, s); } + /* this is in case the timeout callback deletes the event + and thus messes with the iteration */ + HASH_ITER(hh, fd_timeout_cbs, s, tmp) { + int fd = s->id; + getdns_eventloop_event* event = s->event; + delete_event(&fd_timeout_cbs, s); + default_timeout_cb(fd, event); + } + _getdns_eventloop_info* timeout_timeout_cbs = NULL; HASH_ITER(hh, default_loop->timeout_events, s, tmp) { if (s->event && s->event->timeout_cb && now > s->timeout_time) - default_timeout_cb(s->id, s->event); + add_event(&timeout_timeout_cbs, s->id, s); } + /* this is in case the timeout callback deletes the event + and thus messes with the iteration */ + HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { + int fd = s->id; + getdns_eventloop_event* event = s->event; + delete_event(&timeout_timeout_cbs, s); + default_timeout_cb(fd, event); + } + } static void @@ -341,7 +360,7 @@ default_eventloop_run(getdns_eventloop *loop) return; /* keep going until all the events are cleared */ - while (default_loop->fd_events && default_loop->timeout_events) { + while (default_loop->fd_events || default_loop->timeout_events) { default_eventloop_run_once(loop, 1); } } From 7ebf3924b54b95bc9c3522ec110723e21d4755bf Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Fri, 16 Dec 2016 10:36:21 +0000 Subject: [PATCH 11/26] Copy event pointer out of event hash table before callbacks, because it might be deleted --- src/extension/default_eventloop.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 21575e40..6262e446 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -304,17 +304,16 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) for (i = 0; i < num_pfds; i++) { int fd = pfds[i].fd; _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); - if (fd_event && - fd_event->event && - fd_event->event->read_cb && - (pfds[i].revents & POLLIN)) - default_read_cb(fd, fd_event->event); + if (fd_event && fd_event->event) { + getdns_eventloop_event* event = fd_event->event; + if (event->read_cb && + (pfds[i].revents & POLLIN)) + default_read_cb(fd, event); - if (fd_event && - fd_event->event && - fd_event->event->write_cb && - (pfds[i].revents & POLLOUT)) - default_write_cb(fd, fd_event->event); + if (event->write_cb && + (pfds[i].revents & POLLOUT)) + default_write_cb(fd, event); + } } if (pfds) free(pfds); From 17da80a8285e17809f886424415073aa19ab1621 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 18 Jan 2017 14:29:32 +0100 Subject: [PATCH 12/26] Feed poll with millisecond timeout --- src/extension/default_eventloop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 6262e446..17bb2b99 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -290,7 +290,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) else if (! blocking || now > timeout) { poll_timeout = 0; } else { - poll_timeout = (timeout - now) * 1000; /* turn seconds into millseconds */ + poll_timeout = (timeout - now) / 1000; /* turn microseconds into milliseconds */ } #ifdef USE_WINSOCK if (WSAPoll(pfds, num_pfds, poll_timeout) < 0) { From fd3e0c01f7f6a3e1fac3de009b624ec15b4e4d0f Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 18 Jan 2017 15:12:56 +0000 Subject: [PATCH 13/26] call default_time_cb with -1 instead of index --- src/extension/default_eventloop.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 17bb2b99..61e04070 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -246,6 +246,8 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) int poll_timeout = 0; struct pollfd* pfds = NULL; unsigned int num_pfds = 0; + _getdns_eventloop_info* timeout_timeout_cbs = NULL; + _getdns_eventloop_info* fd_timeout_cbs = NULL; if (!loop) return; @@ -254,10 +256,17 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) HASH_ITER(hh, default_loop->timeout_events, s, tmp) { if (now > s->timeout_time) - default_timeout_cb(-1, s->event); + add_event(&timeout_timeout_cbs, s->id, s); else if (s->timeout_time < timeout) timeout = s->timeout_time; } + /* this is in case the timeout callback deletes the event + and thus messes with the iteration */ + HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { + getdns_eventloop_event* event = s->event; + delete_event(&timeout_timeout_cbs, s); + default_timeout_cb(-1, event); + } // first we count the number of fds that will be active HASH_ITER(hh, default_loop->fd_events, s, tmp) { if (s->event->read_cb || @@ -317,7 +326,6 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) } if (pfds) free(pfds); - _getdns_eventloop_info* fd_timeout_cbs = NULL; HASH_ITER(hh, default_loop->fd_events, s, tmp) { if (s->event && s->event->timeout_cb && @@ -332,7 +340,6 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) delete_event(&fd_timeout_cbs, s); default_timeout_cb(fd, event); } - _getdns_eventloop_info* timeout_timeout_cbs = NULL; HASH_ITER(hh, default_loop->timeout_events, s, tmp) { if (s->event && s->event->timeout_cb && @@ -342,10 +349,9 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) /* this is in case the timeout callback deletes the event and thus messes with the iteration */ HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { - int fd = s->id; getdns_eventloop_event* event = s->event; delete_event(&timeout_timeout_cbs, s); - default_timeout_cb(fd, event); + default_timeout_cb(-1, event); } } From dad4aaf6d8ae1784f107a5a883663d823bf9963e Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 18 Jan 2017 15:31:01 +0000 Subject: [PATCH 14/26] correctly allocate and free memory for eventloop hashes --- src/extension/default_eventloop.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 61e04070..f9c0e1b2 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -47,14 +47,18 @@ _getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { DEBUG_SCHED("default_eventloop: add_event with id %d\n", id); - ev->id = id; - HASH_ADD_INT(*events, id, ev); + _getdns_eventloop_info* myevent = calloc(1, sizeof(_getdns_eventloop_info)); + myevent->event = ev->event; + myevent->id = id; + myevent->timeout_time = ev->timeout_time; + HASH_ADD_INT(*events, id, myevent); } void delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) { DEBUG_SCHED("default_eventloop: delete_event with id %d\n", ev->id); HASH_DEL(*events, ev); + free(ev); } static uint64_t get_now_plus(uint64_t amount) @@ -113,13 +117,12 @@ default_eventloop_schedule(getdns_eventloop *loop, /* cleanup the old event if it exists */ if (fd_event) { delete_event(&default_loop->fd_events, fd_event); - free(fd_event); } - fd_event = calloc(1, sizeof(_getdns_eventloop_info)); - fd_event->event = event; - fd_event->timeout_time = get_now_plus(timeout); - add_event(&default_loop->fd_events, fd, fd_event); + _getdns_eventloop_info fd_ev; event->ev = (void *) (intptr_t) (fd + 1); + fd_ev.event = event; + fd_ev.timeout_time = get_now_plus(timeout); + add_event(&default_loop->fd_events, fd, &fd_ev); DEBUG_SCHED( "scheduled read/write at fd %d\n", fd); return GETDNS_RETURN_GOOD; @@ -137,12 +140,11 @@ default_eventloop_schedule(getdns_eventloop *loop, event->write_cb = NULL; } for (i = 0; i < default_loop->max_timeouts; i++) { - _getdns_eventloop_info* timeout_event = NULL; - if ((timeout_event = find_event(&default_loop->timeout_events, i)) == NULL) { - timeout_event = calloc(1, sizeof(_getdns_eventloop_info)); - timeout_event->event = event; - timeout_event->timeout_time = get_now_plus(timeout); - add_event(&default_loop->timeout_events, i, timeout_event); + if (find_event(&default_loop->timeout_events, i) == NULL) { + _getdns_eventloop_info timeout_ev; + timeout_ev.event = event; + timeout_ev.timeout_time = get_now_plus(timeout); + add_event(&default_loop->timeout_events, i, &timeout_ev); event->ev = (void *) (intptr_t) (i + 1); DEBUG_SCHED( "scheduled timeout at slot %d\n", (int)i); @@ -179,7 +181,6 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) #endif if (timeout_event) { delete_event(&default_loop->timeout_events, timeout_event); - free(timeout_event); } } else { _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, i); @@ -191,7 +192,6 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) #endif if (fd_event) { delete_event(&default_loop->fd_events, fd_event); - free(fd_event); } } event->ev = NULL; From 60443fb7fd482c696d624dbde6477b25987af444 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 13 Feb 2017 11:56:25 +0100 Subject: [PATCH 15/26] Choice of poll or select based default event loop --- configure.ac | 27 +- src/Makefile.in | 8 +- src/extension/default_eventloop.h | 36 +-- .../{default_eventloop.c => poll_eventloop.c} | 141 ++++---- src/extension/poll_eventloop.h | 60 ++++ src/extension/select_eventloop.c | 300 ++++++++++++++++++ src/extension/select_eventloop.h | 58 ++++ 7 files changed, 538 insertions(+), 92 deletions(-) rename src/extension/{default_eventloop.c => poll_eventloop.c} (72%) create mode 100644 src/extension/poll_eventloop.h create mode 100644 src/extension/select_eventloop.c create mode 100644 src/extension/select_eventloop.h diff --git a/configure.ac b/configure.ac index f3b35c98..74709630 100644 --- a/configure.ac +++ b/configure.ac @@ -214,6 +214,31 @@ case "$enable_debug_keep_connections_open" in ;; esac + +DEFAULT_EVENTLOOP=select_eventloop +AC_CHECK_HEADERS([sys/poll.h poll.h sys/resource.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_FUNCS([getrlimit]) +AC_ARG_ENABLE(poll-eventloop, AC_HELP_STRING([--disable-poll-eventloop], [Disable default eventloop based on poll (default=enabled if available)])) +case "$enable_poll_eventloop" in + no) + ;; + yes|*) +AC_MSG_CHECKING(for poll) +AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#ifdef HAVE_SYS_POLL_H +#include +#else +#include +#endif +], [int rc; rc = poll((struct pollfd *)(0), 0, 0);])], [ +AC_MSG_RESULT(yes) +AC_DEFINE_UNQUOTED([USE_POLL_DEFAULT_EVENTLOOP], [1], [Define this to enable a default eventloop based on poll().]) +DEFAULT_EVENTLOOP=poll_eventloop +],[AC_MSG_RESULT(no)]) + ;; +esac +AC_SUBST(DEFAULT_EVENTLOOP) + AC_ARG_ENABLE(tcp-fastopen, AC_HELP_STRING([--disable-tcp-fastopen], Disable TCP Fast Open (default=enabled if available)), enable_tcp_fastopen="$enableval", enable_tcp_fastopen=yes) if test "x$enable_tcp_fastopen" = xno; then @@ -1076,8 +1101,6 @@ if test "$ac_cv_func_arc4random" = "no"; then ]) fi -AC_DEFINE(USE_MINI_EVENT, 1, [Needed for sync stub resolver functions]) - AC_TYPE_SIGNAL case `uname` in diff --git a/src/Makefile.in b/src/Makefile.in index bcd858e2..94f1500b 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -65,6 +65,8 @@ EXTENSION_LIBUV_LDFLAGS=@EXTENSION_LIBUV_LDFLAGS@ C99COMPATFLAGS=@C99COMPATFLAGS@ +DEFAULT_EVENTLOOP_OBJ=@DEFAULT_EVENTLOOP@.lo + GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \ list.lo request-internal.lo pubkey-pinning.lo rr-dict.lo \ rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo \ @@ -81,7 +83,7 @@ UTIL_OBJ=rbtree.lo val_secalgo.lo JSMN_OBJ=jsmn.lo -EXTENSION_OBJ=default_eventloop.lo libevent.lo libev.lo +EXTENSION_OBJ=$(DEFAULT_EVENTLOOP_OBJ) libevent.lo libev.lo NON_C99_OBJS=context.lo libuv.lo @@ -152,8 +154,8 @@ libgetdns_ext_ev.la: libgetdns.la libev.lo $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols -libgetdns.la: $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) - $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols +libgetdns.la: $(GETDNS_OBJ) version.lo context.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) + $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols test: all cd test && $(MAKE) $@ diff --git a/src/extension/default_eventloop.h b/src/extension/default_eventloop.h index f4a7d2b6..7b611349 100644 --- a/src/extension/default_eventloop.h +++ b/src/extension/default_eventloop.h @@ -1,6 +1,6 @@ /* * \file default_eventloop.h - * @brief Build in default eventloop extension that uses select. + * @brief Build in default eventloop extension that uses either poll or select. * */ /* @@ -32,29 +32,13 @@ #ifndef DEFAULT_EVENTLOOP_H_ #define DEFAULT_EVENTLOOP_H_ #include "config.h" -#include "getdns/getdns.h" -#include "getdns/getdns_extra.h" -#include "util/uthash.h" - -/* Eventloop based on poll */ - -typedef struct _getdns_eventloop_info { - int id; - getdns_eventloop_event *event; - uint64_t timeout_time; - UT_hash_handle hh; -} _getdns_eventloop_info; - -typedef struct _getdns_default_eventloop { - getdns_eventloop loop; - unsigned int max_fds; - unsigned int max_timeouts; - _getdns_eventloop_info *fd_events; - _getdns_eventloop_info *timeout_events; -} _getdns_default_eventloop; - -void -_getdns_default_eventloop_init(_getdns_default_eventloop *loop); - +#ifdef USE_POLL_DEFAULT_EVENTLOOP +#include "extension/poll_eventloop.h" +#define _getdns_default_eventloop _getdns_poll_eventloop +#define _getdns_default_eventloop_init _getdns_poll_eventloop_init +#else +#include "extension/select_eventloop.h" +#define _getdns_default_eventloop _getdns_select_eventloop +#define _getdns_default_eventloop_init _getdns_select_eventloop_init +#endif #endif - diff --git a/src/extension/default_eventloop.c b/src/extension/poll_eventloop.c similarity index 72% rename from src/extension/default_eventloop.c rename to src/extension/poll_eventloop.c index f9c0e1b2..ede0f20a 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -27,15 +27,20 @@ #include "config.h" -#ifndef USE_WINSOCK +#ifdef HAVE_SYS_POLL_H +#include +#else #include #endif +#ifdef HAVE_SYS_RESOURCE_H #include -#include "extension/default_eventloop.h" +#endif +#include "extension/poll_eventloop.h" #include "debug.h" #include "types-internal.h" -_getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) +static _getdns_eventloop_info * +find_event(_getdns_eventloop_info** events, int id) { _getdns_eventloop_info* ev; @@ -44,9 +49,10 @@ _getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) return ev; } -void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) +static void +add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { - DEBUG_SCHED("default_eventloop: add_event with id %d\n", id); + DEBUG_SCHED("poll_eventloop: add_event with id %d\n", id); _getdns_eventloop_info* myevent = calloc(1, sizeof(_getdns_eventloop_info)); myevent->event = ev->event; myevent->id = id; @@ -54,9 +60,10 @@ void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* HASH_ADD_INT(*events, id, myevent); } -void delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) +static void +delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) { - DEBUG_SCHED("default_eventloop: delete_event with id %d\n", ev->id); + DEBUG_SCHED("poll_eventloop: delete_event with id %d\n", ev->id); HASH_DEL(*events, ev); free(ev); } @@ -77,30 +84,33 @@ static uint64_t get_now_plus(uint64_t amount) } static getdns_return_t -default_eventloop_schedule(getdns_eventloop *loop, +poll_eventloop_schedule(getdns_eventloop *loop, int fd, uint64_t timeout, getdns_eventloop_event *event) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; size_t i; DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, max_fds: %d)\n" - , __FUNC__, (void *)loop, fd, timeout, (void *)event, default_loop->max_fds); + , __FUNC__, (void *)loop, fd, timeout, (void *)event, poll_loop->max_fds); if (!loop || !event) return GETDNS_RETURN_INVALID_PARAMETER; - if (fd >= (int)default_loop->max_fds) { + +#ifdef HAVE_GETRLIMIT + if (fd >= (int)poll_loop->max_fds) { DEBUG_SCHED( "ERROR: fd %d >= max_fds: %d!\n" - , fd, default_loop->max_fds); + , fd, poll_loop->max_fds); return GETDNS_RETURN_GENERIC_ERROR; } +#endif if (fd >= 0 && !(event->read_cb || event->write_cb)) { DEBUG_SCHED("WARNING: fd event without " "read or write cb!\n"); fd = -1; } if (fd >= 0) { - _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); + _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, fd); #if defined(SCHED_DEBUG) && SCHED_DEBUG if (fd_event) { if (fd_event->event == event) { @@ -116,13 +126,13 @@ default_eventloop_schedule(getdns_eventloop *loop, #endif /* cleanup the old event if it exists */ if (fd_event) { - delete_event(&default_loop->fd_events, fd_event); + delete_event(&poll_loop->fd_events, fd_event); } _getdns_eventloop_info fd_ev; event->ev = (void *) (intptr_t) (fd + 1); fd_ev.event = event; fd_ev.timeout_time = get_now_plus(timeout); - add_event(&default_loop->fd_events, fd, &fd_ev); + add_event(&poll_loop->fd_events, fd, &fd_ev); DEBUG_SCHED( "scheduled read/write at fd %d\n", fd); return GETDNS_RETURN_GOOD; @@ -139,12 +149,12 @@ default_eventloop_schedule(getdns_eventloop *loop, DEBUG_SCHED("ERROR: timeout event with write_cb! Clearing.\n"); event->write_cb = NULL; } - for (i = 0; i < default_loop->max_timeouts; i++) { - if (find_event(&default_loop->timeout_events, i) == NULL) { + for (i = poll_loop->timeout_id + 1; i != poll_loop->timeout_id; i++) { + if (find_event(&poll_loop->timeout_events, i) == NULL) { _getdns_eventloop_info timeout_ev; timeout_ev.event = event; timeout_ev.timeout_time = get_now_plus(timeout); - add_event(&default_loop->timeout_events, i, &timeout_ev); + add_event(&poll_loop->timeout_events, i, &timeout_ev); event->ev = (void *) (intptr_t) (i + 1); DEBUG_SCHED( "scheduled timeout at slot %d\n", (int)i); @@ -156,9 +166,9 @@ default_eventloop_schedule(getdns_eventloop *loop, } static getdns_return_t -default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) +poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; ssize_t i; if (!loop || !event) @@ -167,11 +177,15 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNC__, (void *)loop, (void *)event); i = (intptr_t)event->ev - 1; - if (i < 0 || i > default_loop->max_fds) { + if (i < 0 +#ifdef HAVE_GETRLIMIT + || i > poll_loop->max_fds +#endif + ) { return GETDNS_RETURN_GENERIC_ERROR; } if (event->timeout_cb && !event->read_cb && !event->write_cb) { - _getdns_eventloop_info* timeout_event = find_event(&default_loop->timeout_events, i); + _getdns_eventloop_info* timeout_event = find_event(&poll_loop->timeout_events, i); #if defined(SCHED_DEBUG) && SCHED_DEBUG if (timeout_event && timeout_event->event != event) DEBUG_SCHED( "ERROR: Different/wrong event present at " @@ -180,10 +194,10 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) #endif if (timeout_event) { - delete_event(&default_loop->timeout_events, timeout_event); + delete_event(&poll_loop->timeout_events, timeout_event); } } else { - _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, i); + _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, i); #if defined(SCHED_DEBUG) && SCHED_DEBUG if (fd_event && fd_event->event != event) DEBUG_SCHED( "ERROR: Different/wrong event present at " @@ -191,7 +205,7 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) , (void *)fd_event); #endif if (fd_event) { - delete_event(&default_loop->fd_events, fd_event); + delete_event(&poll_loop->fd_events, fd_event); } } event->ev = NULL; @@ -199,15 +213,15 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) } static void -default_eventloop_cleanup(getdns_eventloop *loop) +poll_eventloop_cleanup(getdns_eventloop *loop) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; - HASH_CLEAR(hh, default_loop->fd_events); - HASH_CLEAR(hh, default_loop->timeout_events); + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + HASH_CLEAR(hh, poll_loop->fd_events); + HASH_CLEAR(hh, poll_loop->timeout_events); } static void -default_read_cb(int fd, getdns_eventloop_event *event) +poll_read_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG (void)fd; @@ -217,7 +231,7 @@ default_read_cb(int fd, getdns_eventloop_event *event) } static void -default_write_cb(int fd, getdns_eventloop_event *event) +poll_write_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG (void)fd; @@ -227,7 +241,7 @@ default_write_cb(int fd, getdns_eventloop_event *event) } static void -default_timeout_cb(int fd, getdns_eventloop_event *event) +poll_timeout_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG (void)fd; @@ -237,9 +251,9 @@ default_timeout_cb(int fd, getdns_eventloop_event *event) } static void -default_eventloop_run_once(getdns_eventloop *loop, int blocking) +poll_eventloop_run_once(getdns_eventloop *loop, int blocking) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; _getdns_eventloop_info *s, *tmp; uint64_t now, timeout = TIMEOUT_FOREVER; size_t i=0; @@ -254,7 +268,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) now = get_now_plus(0); - HASH_ITER(hh, default_loop->timeout_events, s, tmp) { + HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { if (now > s->timeout_time) add_event(&timeout_timeout_cbs, s->id, s); else if (s->timeout_time < timeout) @@ -265,10 +279,10 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { getdns_eventloop_event* event = s->event; delete_event(&timeout_timeout_cbs, s); - default_timeout_cb(-1, event); + poll_timeout_cb(-1, event); } // first we count the number of fds that will be active - HASH_ITER(hh, default_loop->fd_events, s, tmp) { + HASH_ITER(hh, poll_loop->fd_events, s, tmp) { if (s->event->read_cb || s->event->write_cb) num_pfds++; @@ -281,7 +295,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) pfds = calloc(num_pfds, sizeof(struct pollfd)); i = 0; - HASH_ITER(hh, default_loop->fd_events, s, tmp) { + HASH_ITER(hh, poll_loop->fd_events, s, tmp) { if (s->event->read_cb) { pfds[i].fd = s->id; pfds[i].events |= POLLIN; @@ -312,21 +326,21 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) now = get_now_plus(0); for (i = 0; i < num_pfds; i++) { int fd = pfds[i].fd; - _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); + _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, fd); if (fd_event && fd_event->event) { getdns_eventloop_event* event = fd_event->event; if (event->read_cb && (pfds[i].revents & POLLIN)) - default_read_cb(fd, event); + poll_read_cb(fd, event); if (event->write_cb && (pfds[i].revents & POLLOUT)) - default_write_cb(fd, event); + poll_write_cb(fd, event); } } if (pfds) free(pfds); - HASH_ITER(hh, default_loop->fd_events, s, tmp) { + HASH_ITER(hh, poll_loop->fd_events, s, tmp) { if (s->event && s->event->timeout_cb && now > s->timeout_time) @@ -338,9 +352,9 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) int fd = s->id; getdns_eventloop_event* event = s->event; delete_event(&fd_timeout_cbs, s); - default_timeout_cb(fd, event); + poll_timeout_cb(fd, event); } - HASH_ITER(hh, default_loop->timeout_events, s, tmp) { + HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { if (s->event && s->event->timeout_cb && now > s->timeout_time) @@ -351,46 +365,51 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { getdns_eventloop_event* event = s->event; delete_event(&timeout_timeout_cbs, s); - default_timeout_cb(-1, event); + poll_timeout_cb(-1, event); } } static void -default_eventloop_run(getdns_eventloop *loop) +poll_eventloop_run(getdns_eventloop *loop) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; if (!loop) return; /* keep going until all the events are cleared */ - while (default_loop->fd_events || default_loop->timeout_events) { - default_eventloop_run_once(loop, 1); + while (poll_loop->fd_events || poll_loop->timeout_events) { + poll_eventloop_run_once(loop, 1); } } void -_getdns_default_eventloop_init(_getdns_default_eventloop *loop) +_getdns_poll_eventloop_init(_getdns_poll_eventloop *loop) { - static getdns_eventloop_vmt default_eventloop_vmt = { - default_eventloop_cleanup, - default_eventloop_schedule, - default_eventloop_clear, - default_eventloop_run, - default_eventloop_run_once +#ifdef HAVE_GETRLIMIT + struct rlimit rl; +#endif + static getdns_eventloop_vmt poll_eventloop_vmt = { + poll_eventloop_cleanup, + poll_eventloop_schedule, + poll_eventloop_clear, + poll_eventloop_run, + poll_eventloop_run_once }; - (void) memset(loop, 0, sizeof(_getdns_default_eventloop)); - loop->loop.vmt = &default_eventloop_vmt; + (void) memset(loop, 0, sizeof(_getdns_poll_eventloop)); + loop->loop.vmt = &poll_eventloop_vmt; - struct rlimit rl; +#ifdef HAVE_GETRLIMIT if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { loop->max_fds = rl.rlim_cur; - loop->max_timeouts = loop->max_fds; /* this is somewhat arbitrary */ } else { DEBUG_SCHED("ERROR: could not obtain RLIMIT_NOFILE from getrlimit()\n"); +#endif loop->max_fds = 0; - loop->max_timeouts = loop->max_fds; +#if HAVE_GETRLIMIT } +#endif + loop->timeout_id = 0; } diff --git a/src/extension/poll_eventloop.h b/src/extension/poll_eventloop.h new file mode 100644 index 00000000..0c06aa4c --- /dev/null +++ b/src/extension/poll_eventloop.h @@ -0,0 +1,60 @@ +/* + * \file poll_eventloop.h + * @brief Build in default eventloop extension that uses select. + * + */ +/* + * Copyright (c) 2013, NLNet Labs, Verisign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef POLL_EVENTLOOP_H_ +#define POLL_EVENTLOOP_H_ +#include "config.h" +#include "getdns/getdns.h" +#include "getdns/getdns_extra.h" +#include "util/uthash.h" + +/* Eventloop based on poll */ + +typedef struct _getdns_eventloop_info { + int id; + getdns_eventloop_event *event; + uint64_t timeout_time; + UT_hash_handle hh; +} _getdns_eventloop_info; + +typedef struct _getdns_poll_eventloop { + getdns_eventloop loop; + unsigned int max_fds; + unsigned int timeout_id; + _getdns_eventloop_info *fd_events; + _getdns_eventloop_info *timeout_events; +} _getdns_poll_eventloop; + +void +_getdns_poll_eventloop_init(_getdns_poll_eventloop *loop); + +#endif + diff --git a/src/extension/select_eventloop.c b/src/extension/select_eventloop.c new file mode 100644 index 00000000..35aa64b7 --- /dev/null +++ b/src/extension/select_eventloop.c @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2013, NLNet Labs, Verisign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "extension/select_eventloop.h" +#include "debug.h" +#include "types-internal.h" + +static uint64_t get_now_plus(uint64_t amount) +{ + struct timeval tv; + uint64_t now; + + if (gettimeofday(&tv, NULL)) { + perror("gettimeofday() failed"); + exit(EXIT_FAILURE); + } + now = tv.tv_sec * 1000000 + tv.tv_usec; + + return (now + amount * 1000) >= now + ? now + amount * 1000 : TIMEOUT_FOREVER; +} + +static getdns_return_t +select_eventloop_schedule(getdns_eventloop *loop, + int fd, uint64_t timeout, getdns_eventloop_event *event) +{ + _getdns_select_eventloop *select_loop = (_getdns_select_eventloop *)loop; + size_t i; + + DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, FD_SETSIZE: %d)\n" + , __FUNC__, (void *)loop, fd, timeout, (void *)event, FD_SETSIZE); + + if (!loop || !event) + return GETDNS_RETURN_INVALID_PARAMETER; + + if (fd >= (int)FD_SETSIZE) { + DEBUG_SCHED( "ERROR: fd %d >= FD_SETSIZE: %d!\n" + , fd, FD_SETSIZE); + return GETDNS_RETURN_GENERIC_ERROR; + } + if (fd >= 0 && !(event->read_cb || event->write_cb)) { + DEBUG_SCHED("WARNING: fd event without " + "read or write cb!\n"); + fd = -1; + } + if (fd >= 0) { +#if defined(SCHED_DEBUG) && SCHED_DEBUG + if (select_loop->fd_events[fd]) { + if (select_loop->fd_events[fd] == event) { + DEBUG_SCHED("WARNING: Event %p not cleared " + "before being rescheduled!\n" + , (void *)select_loop->fd_events[fd]); + } else { + DEBUG_SCHED("ERROR: A different event is " + "already present at fd slot: %p!\n" + , (void *)select_loop->fd_events[fd]); + } + } +#endif + select_loop->fd_events[fd] = event; + select_loop->fd_timeout_times[fd] = get_now_plus(timeout); + event->ev = (void *)(intptr_t)(fd + 1); + DEBUG_SCHED( "scheduled read/write at %d\n", fd); + return GETDNS_RETURN_GOOD; + } + if (!event->timeout_cb) { + DEBUG_SCHED("ERROR: fd < 0 without timeout_cb!\n"); + return GETDNS_RETURN_GENERIC_ERROR; + } + if (event->read_cb) { + DEBUG_SCHED("ERROR: timeout event with read_cb! Clearing.\n"); + event->read_cb = NULL; + } + if (event->write_cb) { + DEBUG_SCHED("ERROR: timeout event with write_cb! Clearing.\n"); + event->write_cb = NULL; + } + for (i = 0; i < MAX_TIMEOUTS; i++) { + if (select_loop->timeout_events[i] == NULL) { + select_loop->timeout_events[i] = event; + select_loop->timeout_times[i] = get_now_plus(timeout); + event->ev = (void *)(intptr_t)(i + 1); + DEBUG_SCHED( "scheduled timeout at %d\n", (int)i); + return GETDNS_RETURN_GOOD; + } + } + DEBUG_SCHED("ERROR: Out of timeout slots!\n"); + return GETDNS_RETURN_GENERIC_ERROR; +} + +static getdns_return_t +select_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) +{ + _getdns_select_eventloop *select_loop = (_getdns_select_eventloop *)loop; + ssize_t i; + + if (!loop || !event) + return GETDNS_RETURN_INVALID_PARAMETER; + + DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNC__, (void *)loop, (void *)event); + + i = (intptr_t)event->ev - 1; + if (i < 0 || i >= FD_SETSIZE) { + return GETDNS_RETURN_GENERIC_ERROR; + } + if (event->timeout_cb && !event->read_cb && !event->write_cb) { +#if defined(SCHED_DEBUG) && SCHED_DEBUG + if (select_loop->timeout_events[i] != event) + DEBUG_SCHED( "ERROR: Different/wrong event present at " + "timeout slot: %p!\n" + , (void *)select_loop->timeout_events[i]); +#endif + select_loop->timeout_events[i] = NULL; + } else { +#if defined(SCHED_DEBUG) && SCHED_DEBUG + if (select_loop->fd_events[i] != event) + DEBUG_SCHED( "ERROR: Different/wrong event present at " + "fd slot: %p!\n" + , (void *)select_loop->fd_events[i]); +#endif + select_loop->fd_events[i] = NULL; + } + event->ev = NULL; + return GETDNS_RETURN_GOOD; +} + +static void +select_eventloop_cleanup(getdns_eventloop *loop) +{ + (void)loop; +} + +static void +select_read_cb(int fd, getdns_eventloop_event *event) +{ +#if !defined(SCHED_DEBUG) || !SCHED_DEBUG + (void)fd; +#endif + DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); + event->read_cb(event->userarg); +} + +static void +select_write_cb(int fd, getdns_eventloop_event *event) +{ +#if !defined(SCHED_DEBUG) || !SCHED_DEBUG + (void)fd; +#endif + DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); + event->write_cb(event->userarg); +} + +static void +select_timeout_cb(int fd, getdns_eventloop_event *event) +{ +#if !defined(SCHED_DEBUG) || !SCHED_DEBUG + (void)fd; +#endif + DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); + event->timeout_cb(event->userarg); +} + +static void +select_eventloop_run_once(getdns_eventloop *loop, int blocking) +{ + _getdns_select_eventloop *select_loop = (_getdns_select_eventloop *)loop; + + fd_set readfds, writefds; + int fd, max_fd = -1; + uint64_t now, timeout = TIMEOUT_FOREVER; + size_t i; + struct timeval tv; + + if (!loop) + return; + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + now = get_now_plus(0); + + for (i = 0; i < MAX_TIMEOUTS; i++) { + if (!select_loop->timeout_events[i]) + continue; + if (now > select_loop->timeout_times[i]) + select_timeout_cb(-1, select_loop->timeout_events[i]); + else if (select_loop->timeout_times[i] < timeout) + timeout = select_loop->timeout_times[i]; + } + for (fd = 0; fd < (int)FD_SETSIZE; fd++) { + if (!select_loop->fd_events[fd]) + continue; + if (select_loop->fd_events[fd]->read_cb) + FD_SET(fd, &readfds); + if (select_loop->fd_events[fd]->write_cb) + FD_SET(fd, &writefds); + if (fd > max_fd) + max_fd = fd; + if (select_loop->fd_timeout_times[fd] < timeout) + timeout = select_loop->fd_timeout_times[fd]; + } + if (max_fd == -1 && timeout == TIMEOUT_FOREVER) + return; + + if (! blocking || now > timeout) { + tv.tv_sec = 0; + tv.tv_usec = 0; + } else { + tv.tv_sec = (long)((timeout - now) / 1000000); + tv.tv_usec = (long)((timeout - now) % 1000000); + } + if (select(max_fd + 1, &readfds, &writefds, NULL, + (timeout == TIMEOUT_FOREVER ? NULL : &tv)) < 0) { + perror("select() failed"); + exit(EXIT_FAILURE); + } + now = get_now_plus(0); + for (fd = 0; fd < (int)FD_SETSIZE; fd++) { + if (select_loop->fd_events[fd] && + select_loop->fd_events[fd]->read_cb && + FD_ISSET(fd, &readfds)) + select_read_cb(fd, select_loop->fd_events[fd]); + + if (select_loop->fd_events[fd] && + select_loop->fd_events[fd]->write_cb && + FD_ISSET(fd, &writefds)) + select_write_cb(fd, select_loop->fd_events[fd]); + + if (select_loop->fd_events[fd] && + select_loop->fd_events[fd]->timeout_cb && + now > select_loop->fd_timeout_times[fd]) + select_timeout_cb(fd, select_loop->fd_events[fd]); + + i = fd; + if (select_loop->timeout_events[i] && + select_loop->timeout_events[i]->timeout_cb && + now > select_loop->timeout_times[i]) + select_timeout_cb(-1, select_loop->timeout_events[i]); + } +} + +static void +select_eventloop_run(getdns_eventloop *loop) +{ + _getdns_select_eventloop *select_loop = (_getdns_select_eventloop *)loop; + size_t i; + + if (!loop) + return; + + i = 0; + while (i < MAX_TIMEOUTS) { + if (select_loop->fd_events[i] || select_loop->timeout_events[i]) { + select_eventloop_run_once(loop, 1); + i = 0; + } else { + i++; + } + } +} + +void +_getdns_select_eventloop_init(_getdns_select_eventloop *loop) +{ + static getdns_eventloop_vmt select_eventloop_vmt = { + select_eventloop_cleanup, + select_eventloop_schedule, + select_eventloop_clear, + select_eventloop_run, + select_eventloop_run_once + }; + + (void) memset(loop, 0, sizeof(_getdns_select_eventloop)); + loop->loop.vmt = &select_eventloop_vmt; +} diff --git a/src/extension/select_eventloop.h b/src/extension/select_eventloop.h new file mode 100644 index 00000000..40dfb549 --- /dev/null +++ b/src/extension/select_eventloop.h @@ -0,0 +1,58 @@ +/* + * \file select_eventloop.h + * @brief Build in default eventloop extension that uses select. + * + */ +/* + * Copyright (c) 2013, NLNet Labs, Verisign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SELECT_EVENTLOOP_H_ +#define SELECT_EVENTLOOP_H_ +#include "config.h" +#include "getdns/getdns.h" +#include "getdns/getdns_extra.h" + +/* No more than select's capability queries can be outstanding, + * The number of outstanding timeouts should be less or equal then + * the number of outstanding queries, so MAX_TIMEOUTS equal to + * FD_SETSIZE should be safe. + */ +#define MAX_TIMEOUTS FD_SETSIZE + +/* Eventloop based on select */ +typedef struct _getdns_select_eventloop { + getdns_eventloop loop; + getdns_eventloop_event *fd_events[FD_SETSIZE]; + uint64_t fd_timeout_times[FD_SETSIZE]; + getdns_eventloop_event *timeout_events[MAX_TIMEOUTS]; + uint64_t timeout_times[MAX_TIMEOUTS]; +} _getdns_select_eventloop; + + +void +_getdns_select_eventloop_init(_getdns_select_eventloop *loop); + +#endif From 549de0de60549053c0109be0ed6653a3f9a49780 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 14 Feb 2017 13:41:58 +0100 Subject: [PATCH 16/26] Use of custom mem funcs by uthash --- src/extension/poll_eventloop.c | 34 ++++++++++++++++++++-------------- src/extension/poll_eventloop.h | 5 +++++ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index ede0f20a..17e51552 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -37,7 +37,6 @@ #endif #include "extension/poll_eventloop.h" #include "debug.h" -#include "types-internal.h" static _getdns_eventloop_info * find_event(_getdns_eventloop_info** events, int id) @@ -50,7 +49,8 @@ find_event(_getdns_eventloop_info** events, int id) } static void -add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) +add_event(struct mem_funcs *mf, + _getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { DEBUG_SCHED("poll_eventloop: add_event with id %d\n", id); _getdns_eventloop_info* myevent = calloc(1, sizeof(_getdns_eventloop_info)); @@ -61,7 +61,8 @@ add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) } static void -delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) +delete_event(struct mem_funcs *mf, + _getdns_eventloop_info** events,_getdns_eventloop_info* ev) { DEBUG_SCHED("poll_eventloop: delete_event with id %d\n", ev->id); HASH_DEL(*events, ev); @@ -88,6 +89,7 @@ poll_eventloop_schedule(getdns_eventloop *loop, int fd, uint64_t timeout, getdns_eventloop_event *event) { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + struct mem_funcs *mf = &poll_loop->mf; size_t i; DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, max_fds: %d)\n" @@ -126,13 +128,13 @@ poll_eventloop_schedule(getdns_eventloop *loop, #endif /* cleanup the old event if it exists */ if (fd_event) { - delete_event(&poll_loop->fd_events, fd_event); + delete_event(mf, &poll_loop->fd_events, fd_event); } _getdns_eventloop_info fd_ev; event->ev = (void *) (intptr_t) (fd + 1); fd_ev.event = event; fd_ev.timeout_time = get_now_plus(timeout); - add_event(&poll_loop->fd_events, fd, &fd_ev); + add_event(mf, &poll_loop->fd_events, fd, &fd_ev); DEBUG_SCHED( "scheduled read/write at fd %d\n", fd); return GETDNS_RETURN_GOOD; @@ -154,7 +156,7 @@ poll_eventloop_schedule(getdns_eventloop *loop, _getdns_eventloop_info timeout_ev; timeout_ev.event = event; timeout_ev.timeout_time = get_now_plus(timeout); - add_event(&poll_loop->timeout_events, i, &timeout_ev); + add_event(mf, &poll_loop->timeout_events, i, &timeout_ev); event->ev = (void *) (intptr_t) (i + 1); DEBUG_SCHED( "scheduled timeout at slot %d\n", (int)i); @@ -169,6 +171,7 @@ static getdns_return_t poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + struct mem_funcs *mf = &poll_loop->mf; ssize_t i; if (!loop || !event) @@ -194,7 +197,7 @@ poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) #endif if (timeout_event) { - delete_event(&poll_loop->timeout_events, timeout_event); + delete_event(mf, &poll_loop->timeout_events, timeout_event); } } else { _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, i); @@ -205,7 +208,7 @@ poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) , (void *)fd_event); #endif if (fd_event) { - delete_event(&poll_loop->fd_events, fd_event); + delete_event(mf, &poll_loop->fd_events, fd_event); } } event->ev = NULL; @@ -216,6 +219,8 @@ static void poll_eventloop_cleanup(getdns_eventloop *loop) { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + struct mem_funcs *mf = &poll_loop->mf; + HASH_CLEAR(hh, poll_loop->fd_events); HASH_CLEAR(hh, poll_loop->timeout_events); } @@ -254,6 +259,7 @@ static void poll_eventloop_run_once(getdns_eventloop *loop, int blocking) { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + struct mem_funcs *mf = &poll_loop->mf; _getdns_eventloop_info *s, *tmp; uint64_t now, timeout = TIMEOUT_FOREVER; size_t i=0; @@ -270,7 +276,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { if (now > s->timeout_time) - add_event(&timeout_timeout_cbs, s->id, s); + add_event(mf, &timeout_timeout_cbs, s->id, s); else if (s->timeout_time < timeout) timeout = s->timeout_time; } @@ -278,7 +284,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) and thus messes with the iteration */ HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { getdns_eventloop_event* event = s->event; - delete_event(&timeout_timeout_cbs, s); + delete_event(mf, &timeout_timeout_cbs, s); poll_timeout_cb(-1, event); } // first we count the number of fds that will be active @@ -344,27 +350,27 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if (s->event && s->event->timeout_cb && now > s->timeout_time) - add_event(&fd_timeout_cbs, s->id, s); + add_event(mf, &fd_timeout_cbs, s->id, s); } /* this is in case the timeout callback deletes the event and thus messes with the iteration */ HASH_ITER(hh, fd_timeout_cbs, s, tmp) { int fd = s->id; getdns_eventloop_event* event = s->event; - delete_event(&fd_timeout_cbs, s); + delete_event(mf, &fd_timeout_cbs, s); poll_timeout_cb(fd, event); } HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { if (s->event && s->event->timeout_cb && now > s->timeout_time) - add_event(&timeout_timeout_cbs, s->id, s); + add_event(mf, &timeout_timeout_cbs, s->id, s); } /* this is in case the timeout callback deletes the event and thus messes with the iteration */ HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { getdns_eventloop_event* event = s->event; - delete_event(&timeout_timeout_cbs, s); + delete_event(mf, &timeout_timeout_cbs, s); poll_timeout_cb(-1, event); } diff --git a/src/extension/poll_eventloop.h b/src/extension/poll_eventloop.h index 0c06aa4c..aef3a57d 100644 --- a/src/extension/poll_eventloop.h +++ b/src/extension/poll_eventloop.h @@ -34,6 +34,10 @@ #include "config.h" #include "getdns/getdns.h" #include "getdns/getdns_extra.h" +#include "types-internal.h" + +#define uthash_malloc(sz) ((void *)GETDNS_XMALLOC(*mf, unsigned char, sz)) +#define uthash_free(ptr,sz) GETDNS_FREE(*mf, ptr) #include "util/uthash.h" /* Eventloop based on poll */ @@ -47,6 +51,7 @@ typedef struct _getdns_eventloop_info { typedef struct _getdns_poll_eventloop { getdns_eventloop loop; + struct mem_funcs mf; unsigned int max_fds; unsigned int timeout_id; _getdns_eventloop_info *fd_events; From 7484b8c37b0ca4cb14efc04b5025172abf601f65 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 10:22:41 +0100 Subject: [PATCH 17/26] Initialize default eventloop with custom mem funcs --- src/Makefile.in | 92 +++++++++++++++++++------------- src/context.c | 6 +-- src/extension/poll_eventloop.c | 3 +- src/extension/poll_eventloop.h | 2 +- src/extension/select_eventloop.c | 4 +- src/extension/select_eventloop.h | 2 +- 6 files changed, 63 insertions(+), 46 deletions(-) diff --git a/src/Makefile.in b/src/Makefile.in index 94f1500b..77297c42 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -220,85 +220,97 @@ const-info.lo const-info.o: $(srcdir)/const-info.c getdns/getdns.h getdns/getdns context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \ getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h \ - $(srcdir)/pubkey-pinning.h + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ + $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \ getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ + $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h \ $(srcdir)/const-info.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ - $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h \ - $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h + $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h \ + $(srcdir)/gldns/wire2str.h dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h \ - $(srcdir)/list.h $(srcdir)/util/val_secalgo.h + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ + $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \ + $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h \ + $(srcdir)/util/val_secalgo.h general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/getdns.h $(srcdir)/types-internal.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/util/uthash.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h \ $(srcdir)/mdns.h list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/list.h $(srcdir)/dict.h + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ + $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h \ + $(srcdir)/dict.h mdns.lo mdns.o: $(srcdir)/mdns.c config.h $(srcdir)/debug.h $(srcdir)/context.h getdns/getdns.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ + $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/mdns.h pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \ $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h \ - $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \ getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h \ $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/getdns.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/util-internal.h $(srcdir)/context.h getdns/getdns_extra.h getdns/getdns.h \ $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h config.h getdns/getdns.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h server.lo server.o: $(srcdir)/server.c config.h getdns/getdns_extra.h getdns/getdns.h \ $(srcdir)/context.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ + $(srcdir)/server.h stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ + $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h getdns/getdns_extra.h \ getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \ - $(srcdir)/gldns/wire2str.h + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ + $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h config.h getdns/getdns.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ $(srcdir)/debug.h util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getdns.h $(srcdir)/dict.h \ $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \ $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h \ $(srcdir)/gldns/rrdef.h version.lo version.o: version.c @@ -331,10 +343,6 @@ rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcd val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \ $(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h -default_eventloop.lo default_eventloop.o: $(srcdir)/extension/default_eventloop.c config.h \ - $(srcdir)/extension/default_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/debug.h config.h $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h libev.lo libev.o: $(srcdir)/extension/libev.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ $(srcdir)/getdns/getdns_ext_libev.h getdns/getdns_extra.h @@ -344,3 +352,11 @@ libevent.lo libevent.o: $(srcdir)/extension/libevent.c config.h $(srcdir)/types- libuv.lo libuv.o: $(srcdir)/extension/libuv.c config.h $(srcdir)/debug.h config.h $(srcdir)/types-internal.h \ getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ $(srcdir)/getdns/getdns_ext_libuv.h getdns/getdns_extra.h +poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c config.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ + $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/util/rbtree.h \ + $(srcdir)/util/uthash.h $(srcdir)/debug.h config.h +select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c config.h \ + $(srcdir)/extension/select_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ + $(srcdir)/debug.h config.h $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h diff --git a/src/context.c b/src/context.c index c4f5d0f7..7dab4ecf 100644 --- a/src/context.c +++ b/src/context.c @@ -1388,8 +1388,8 @@ getdns_context_create_with_extended_memory_functions( result->tls_ctx = NULL; result->extension = &result->default_eventloop.loop; - _getdns_default_eventloop_init(&result->default_eventloop); - _getdns_default_eventloop_init(&result->sync_eventloop); + _getdns_default_eventloop_init(&result->mf, &result->default_eventloop); + _getdns_default_eventloop_init(&result->mf, &result->sync_eventloop); /* request extension defaults */ @@ -3403,7 +3403,7 @@ getdns_context_detach_eventloop(struct getdns_context* context) cancel_outstanding_requests(context, 1); context->extension->vmt->cleanup(context->extension); context->extension = &context->default_eventloop.loop; - _getdns_default_eventloop_init(&context->default_eventloop); + _getdns_default_eventloop_init(&context->mf, &context->default_eventloop); #ifdef HAVE_UNBOUND_EVENT_API if (_getdns_ub_loop_enabled(&context->ub_loop)) context->ub_loop.extension = context->extension; diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index 17e51552..b5c95c85 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -391,7 +391,7 @@ poll_eventloop_run(getdns_eventloop *loop) } void -_getdns_poll_eventloop_init(_getdns_poll_eventloop *loop) +_getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) { #ifdef HAVE_GETRLIMIT struct rlimit rl; @@ -406,6 +406,7 @@ _getdns_poll_eventloop_init(_getdns_poll_eventloop *loop) (void) memset(loop, 0, sizeof(_getdns_poll_eventloop)); loop->loop.vmt = &poll_eventloop_vmt; + loop->mf = *mf; #ifdef HAVE_GETRLIMIT if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { diff --git a/src/extension/poll_eventloop.h b/src/extension/poll_eventloop.h index aef3a57d..9c58b042 100644 --- a/src/extension/poll_eventloop.h +++ b/src/extension/poll_eventloop.h @@ -59,7 +59,7 @@ typedef struct _getdns_poll_eventloop { } _getdns_poll_eventloop; void -_getdns_poll_eventloop_init(_getdns_poll_eventloop *loop); +_getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop); #endif diff --git a/src/extension/select_eventloop.c b/src/extension/select_eventloop.c index 35aa64b7..1b889fc1 100644 --- a/src/extension/select_eventloop.c +++ b/src/extension/select_eventloop.c @@ -285,7 +285,7 @@ select_eventloop_run(getdns_eventloop *loop) } void -_getdns_select_eventloop_init(_getdns_select_eventloop *loop) +_getdns_select_eventloop_init(struct mem_funcs *mf, _getdns_select_eventloop *loop) { static getdns_eventloop_vmt select_eventloop_vmt = { select_eventloop_cleanup, @@ -294,7 +294,7 @@ _getdns_select_eventloop_init(_getdns_select_eventloop *loop) select_eventloop_run, select_eventloop_run_once }; - + (void) mf; (void) memset(loop, 0, sizeof(_getdns_select_eventloop)); loop->loop.vmt = &select_eventloop_vmt; } diff --git a/src/extension/select_eventloop.h b/src/extension/select_eventloop.h index 40dfb549..e830a2ac 100644 --- a/src/extension/select_eventloop.h +++ b/src/extension/select_eventloop.h @@ -53,6 +53,6 @@ typedef struct _getdns_select_eventloop { void -_getdns_select_eventloop_init(_getdns_select_eventloop *loop); +_getdns_select_eventloop_init(struct mem_funcs *mf, _getdns_select_eventloop *loop); #endif From c936f0c51d38d540583822aee6e918c54d27a623 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 10:56:19 +0100 Subject: [PATCH 18/26] Other allocs and frees with custom mem funcs too --- src/extension/poll_eventloop.c | 59 +++++++++++++++++++++++----------- src/extension/poll_eventloop.h | 6 ++-- 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index b5c95c85..d85e254f 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -53,7 +53,8 @@ add_event(struct mem_funcs *mf, _getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { DEBUG_SCHED("poll_eventloop: add_event with id %d\n", id); - _getdns_eventloop_info* myevent = calloc(1, sizeof(_getdns_eventloop_info)); + _getdns_eventloop_info* myevent = GETDNS_MALLOC(*mf, _getdns_eventloop_info); + /* not necessary -- (void) memset(myevent, 0, sizeof(_getdns_eventloop_info)); */ myevent->event = ev->event; myevent->id = id; myevent->timeout_time = ev->timeout_time; @@ -62,11 +63,11 @@ add_event(struct mem_funcs *mf, static void delete_event(struct mem_funcs *mf, - _getdns_eventloop_info** events,_getdns_eventloop_info* ev) + _getdns_eventloop_info** events, _getdns_eventloop_info* ev) { DEBUG_SCHED("poll_eventloop: delete_event with id %d\n", ev->id); HASH_DEL(*events, ev); - free(ev); + GETDNS_FREE(*mf, ev); } static uint64_t get_now_plus(uint64_t amount) @@ -221,6 +222,11 @@ poll_eventloop_cleanup(getdns_eventloop *loop) _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; struct mem_funcs *mf = &poll_loop->mf; + if (poll_loop->pfds) { + GETDNS_FREE(*mf, poll_loop->pfds); + poll_loop->pfds = NULL; + poll_loop->pfds_capacity = 0; + } HASH_CLEAR(hh, poll_loop->fd_events); HASH_CLEAR(hh, poll_loop->timeout_events); } @@ -255,6 +261,17 @@ poll_timeout_cb(int fd, getdns_eventloop_event *event) event->timeout_cb(event->userarg); } +static unsigned long up_pow2(unsigned long v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + return v + 1; +} + static void poll_eventloop_run_once(getdns_eventloop *loop, int blocking) { @@ -264,7 +281,6 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) uint64_t now, timeout = TIMEOUT_FOREVER; size_t i=0; int poll_timeout = 0; - struct pollfd* pfds = NULL; unsigned int num_pfds = 0; _getdns_eventloop_info* timeout_timeout_cbs = NULL; _getdns_eventloop_info* fd_timeout_cbs = NULL; @@ -287,7 +303,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) delete_event(mf, &timeout_timeout_cbs, s); poll_timeout_cb(-1, event); } - // first we count the number of fds that will be active + /* first we count the number of fds that will be active */ HASH_ITER(hh, poll_loop->fd_events, s, tmp) { if (s->event->read_cb || s->event->write_cb) @@ -299,16 +315,22 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if ((timeout == TIMEOUT_FOREVER) && (num_pfds == 0)) return; - pfds = calloc(num_pfds, sizeof(struct pollfd)); + if (num_pfds > poll_loop->pfds_capacity) { + poll_loop->pfds_capacity = up_pow2(num_pfds); + if (poll_loop->pfds) { + poll_loop->pfds = GETDNS_XMALLOC(poll_loop->mf, struct pollfd, poll_loop->pfds_capacity); + } else + poll_loop->pfds = GETDNS_XREALLOC(poll_loop->mf, poll_loop->pfds, struct pollfd, poll_loop->pfds_capacity); + } i = 0; HASH_ITER(hh, poll_loop->fd_events, s, tmp) { if (s->event->read_cb) { - pfds[i].fd = s->id; - pfds[i].events |= POLLIN; + poll_loop->pfds[i].fd = s->id; + poll_loop->pfds[i].events |= POLLIN; } if (s->event->write_cb) { - pfds[i].fd = s->id; - pfds[i].events |= POLLOUT; + poll_loop->pfds[i].fd = s->id; + poll_loop->pfds[i].events |= POLLOUT; } i++; } @@ -322,30 +344,28 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) poll_timeout = (timeout - now) / 1000; /* turn microseconds into milliseconds */ } #ifdef USE_WINSOCK - if (WSAPoll(pfds, num_pfds, poll_timeout) < 0) { + if (WSAPoll(poll_loop->pfds, num_pfds, poll_timeout) < 0) { #else - if (poll(pfds, num_pfds, poll_timeout) < 0) { + if (poll(poll_loop->pfds, num_pfds, poll_timeout) < 0) { #endif perror("poll() failed"); exit(EXIT_FAILURE); } now = get_now_plus(0); for (i = 0; i < num_pfds; i++) { - int fd = pfds[i].fd; + int fd = poll_loop->pfds[i].fd; _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, fd); if (fd_event && fd_event->event) { getdns_eventloop_event* event = fd_event->event; if (event->read_cb && - (pfds[i].revents & POLLIN)) + (poll_loop->pfds[i].revents & POLLIN)) poll_read_cb(fd, event); if (event->write_cb && - (pfds[i].revents & POLLOUT)) + (poll_loop->pfds[i].revents & POLLOUT)) poll_write_cb(fd, event); } } - if (pfds) - free(pfds); HASH_ITER(hh, poll_loop->fd_events, s, tmp) { if (s->event && s->event->timeout_cb && @@ -404,7 +424,6 @@ _getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) poll_eventloop_run_once }; - (void) memset(loop, 0, sizeof(_getdns_poll_eventloop)); loop->loop.vmt = &poll_eventloop_vmt; loop->mf = *mf; @@ -419,4 +438,8 @@ _getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) } #endif loop->timeout_id = 0; + loop->pfds = NULL; + loop->pfds_capacity = 0; + loop->fd_events = NULL; + loop->timeout_events = NULL; } diff --git a/src/extension/poll_eventloop.h b/src/extension/poll_eventloop.h index 9c58b042..8c742e20 100644 --- a/src/extension/poll_eventloop.h +++ b/src/extension/poll_eventloop.h @@ -54,8 +54,10 @@ typedef struct _getdns_poll_eventloop { struct mem_funcs mf; unsigned int max_fds; unsigned int timeout_id; - _getdns_eventloop_info *fd_events; - _getdns_eventloop_info *timeout_events; + struct pollfd *pfds; + unsigned long pfds_capacity; + _getdns_eventloop_info *fd_events; + _getdns_eventloop_info *timeout_events; } _getdns_poll_eventloop; void From 3e8822e0e23f81dc9a65d3fe675f5a460a48cc42 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 11:43:07 +0100 Subject: [PATCH 19/26] Fix uninitialized data error in valgrind check --- src/extension/poll_eventloop.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index d85e254f..1eba706a 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -324,16 +324,18 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) } i = 0; HASH_ITER(hh, poll_loop->fd_events, s, tmp) { - if (s->event->read_cb) { - poll_loop->pfds[i].fd = s->id; + if (!s->event->read_cb && !s->event->write_cb) + continue; + poll_loop->pfds[i].fd = s->id; + poll_loop->pfds[i].events = 0; + poll_loop->pfds[i].revents = 0; /* <-- probably not needed */ + if (s->event->read_cb) poll_loop->pfds[i].events |= POLLIN; - } - if (s->event->write_cb) { - poll_loop->pfds[i].fd = s->id; + if (s->event->write_cb) poll_loop->pfds[i].events |= POLLOUT; - } i++; } + assert(i == num_pfds); if (timeout == TIMEOUT_FOREVER) { poll_timeout = -1; From b7c2e53a82f9f49202854fb9fbc75132a7139b5c Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 12:21:29 +0100 Subject: [PATCH 20/26] Off by one problem? --- src/extension/poll_eventloop.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index 1eba706a..331e5d4b 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -315,12 +315,16 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if ((timeout == TIMEOUT_FOREVER) && (num_pfds == 0)) return; - if (num_pfds > poll_loop->pfds_capacity) { - poll_loop->pfds_capacity = up_pow2(num_pfds); + if (num_pfds >= poll_loop->pfds_capacity) { + poll_loop->pfds_capacity = up_pow2(num_pfds + 1); if (poll_loop->pfds) { poll_loop->pfds = GETDNS_XMALLOC(poll_loop->mf, struct pollfd, poll_loop->pfds_capacity); } else poll_loop->pfds = GETDNS_XREALLOC(poll_loop->mf, poll_loop->pfds, struct pollfd, poll_loop->pfds_capacity); + if (poll_loop->pfds == 0) { + poll_loop->pfds_capacity = 0; + return; + } } i = 0; HASH_ITER(hh, poll_loop->fd_events, s, tmp) { From 840ba8c85d29d52b51cf17e83dadf969f559a8ee Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 12:46:48 +0100 Subject: [PATCH 21/26] Reference fixes jsmn --- src/jsmn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jsmn b/src/jsmn index 49024a6e..868c22e3 160000 --- a/src/jsmn +++ b/src/jsmn @@ -1 +1 @@ -Subproject commit 49024a6e11739c866bce0e9f3617278b98906ad0 +Subproject commit 868c22e35ec223fc26ddefdb9ca83901dc6e2534 From 04f6a2b13b6382575e8351ab7859d611e6946afb Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 12:47:55 +0100 Subject: [PATCH 22/26] Fixed dependencies --- spec/example/Makefile.in | 24 ++- src/Makefile.in | 368 ++++++++++++++++++++++++--------------- src/test/Makefile.in | 71 +++++--- src/tools/Makefile.in | 7 +- 4 files changed, 298 insertions(+), 172 deletions(-) diff --git a/spec/example/Makefile.in b/spec/example/Makefile.in index 7bf5e016..8ff7f2d1 100644 --- a/spec/example/Makefile.in +++ b/spec/example/Makefile.in @@ -149,16 +149,24 @@ depend: # Dependencies for the examples example-all-functions.lo example-all-functions.o: $(srcdir)/example-all-functions.c $(srcdir)/getdns_libevent.h \ - ../../src/config.h ../../src/getdns/getdns.h \ - $(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h -example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h ../../src/config.h \ - ../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ + ../../src/config.h \ + ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ + ../../src/getdns/getdns_extra.h +example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h \ + ../../src/config.h \ + ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/getdns/getdns_extra.h example-simple-answers.lo example-simple-answers.o: $(srcdir)/example-simple-answers.c $(srcdir)/getdns_libevent.h \ - ../../src/config.h ../../src/getdns/getdns.h \ - $(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h + ../../src/config.h \ + ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ + ../../src/getdns/getdns_extra.h example-synchronous.lo example-synchronous.o: $(srcdir)/example-synchronous.c $(srcdir)/getdns_core_only.h \ ../../src/getdns/getdns.h -example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h ../../src/config.h \ - ../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ +example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h \ + ../../src/config.h \ + ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/getdns/getdns_extra.h diff --git a/src/Makefile.in b/src/Makefile.in index 77297c42..33a6c946 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -215,148 +215,236 @@ depend: FORCE: # Dependencies for gldns, utils, the extensions and compat functions -const-info.lo const-info.o: $(srcdir)/const-info.c getdns/getdns.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/const-info.h -context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ - $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h -convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ - $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h \ - $(srcdir)/const-info.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h -dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ - $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h \ - $(srcdir)/gldns/wire2str.h -dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ - $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \ - $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h \ - $(srcdir)/util/val_secalgo.h -general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/getdns.h $(srcdir)/types-internal.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/uthash.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h \ - $(srcdir)/mdns.h -list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ - $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h \ - $(srcdir)/dict.h -mdns.lo mdns.o: $(srcdir)/mdns.c config.h $(srcdir)/debug.h $(srcdir)/context.h getdns/getdns.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ - $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ +const-info.lo const-info.o: $(srcdir)/const-info.c \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/const-info.h +context.lo context.o: $(srcdir)/context.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h \ + $(srcdir)/pubkey-pinning.h +convert.lo convert.o: $(srcdir)/convert.c \ + config.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ + $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ + $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h \ + $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/wire2str.h \ + $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h \ + $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h +dict.lo dict.o: $(srcdir)/dict.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h +dnssec.lo dnssec.o: $(srcdir)/dnssec.c \ + config.h \ + $(srcdir)/debug.h \ + getdns/getdns.h \ + $(srcdir)/context.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ + $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h \ + $(srcdir)/list.h $(srcdir)/util/val_secalgo.h +general.lo general.o: $(srcdir)/general.c \ + config.h \ + $(srcdir)/general.h \ + getdns/getdns.h \ + $(srcdir)/types-internal.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \ + $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ + $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h \ + $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \ + $(srcdir)/dict.h $(srcdir)/mdns.h +list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ + config.h \ + $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ + $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h \ + $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.h +mdns.lo mdns.o: $(srcdir)/mdns.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/context.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/mdns.h -pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \ - $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h -request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \ - getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h \ - $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h -rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/getdns.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/util-internal.h $(srcdir)/context.h getdns/getdns_extra.h getdns/getdns.h \ - $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h -rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h config.h getdns/getdns.h \ +pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \ + config.h \ + $(srcdir)/debug.h \ + getdns/getdns.h \ + $(srcdir)/context.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h +request-internal.lo request-internal.o: $(srcdir)/request-internal.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h +rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \ + config.h \ + getdns/getdns.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/util-internal.h $(srcdir)/context.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h +rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + config.h \ + getdns/getdns.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h -server.lo server.o: $(srcdir)/server.c config.h getdns/getdns_extra.h getdns/getdns.h \ - $(srcdir)/context.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ - $(srcdir)/server.h -stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ - $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h -sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ - $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h -ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h config.h getdns/getdns.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/debug.h -util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getdns.h $(srcdir)/dict.h \ - $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \ - $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h \ - $(srcdir)/gldns/rrdef.h -version.lo version.o: version.c -gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c config.h $(srcdir)/gldns/gbuffer.h -keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c config.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h -parse.lo parse.o: $(srcdir)/gldns/parse.c config.h $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h \ +server.lo server.o: $(srcdir)/server.c \ + config.h \ + getdns/getdns_extra.h \ + getdns/getdns.h \ + $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/debug.h $(srcdir)/server.h +stub.lo stub.o: $(srcdir)/stub.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/stub.h \ + getdns/getdns.h \ + $(srcdir)/types-internal.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h \ + $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ + $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h \ + $(srcdir)/general.h $(srcdir)/pubkey-pinning.h +sync.lo sync.o: $(srcdir)/sync.c \ + getdns/getdns.h \ + config.h \ + $(srcdir)/context.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \ + $(srcdir)/gldns/wire2str.h +ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h \ + config.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/debug.h +util-internal.lo util-internal.o: $(srcdir)/util-internal.c \ + config.h \ + getdns/getdns.h \ + $(srcdir)/dict.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h \ + getdns/getdns_extra.h \ + $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h +gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c \ + config.h \ $(srcdir)/gldns/gbuffer.h -parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c config.h $(srcdir)/gldns/parseutil.h -rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h -str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c config.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h -wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c config.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h \ - $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/keyraw.h -arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c config.h -arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c config.h $(srcdir)/compat/chacha_private.h -arc4random_uniform.lo arc4random_uniform.o: $(srcdir)/compat/arc4random_uniform.c config.h -explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c config.h -getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h -getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c config.h -getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h +keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c \ + config.h \ + $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h +parse.lo parse.o: $(srcdir)/gldns/parse.c \ + config.h \ + $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h +parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c \ + config.h \ + $(srcdir)/gldns/parseutil.h +rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c \ + config.h \ + $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h +str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c \ + config.h \ + $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h +wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c \ + config.h \ + $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/keyraw.h +arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c \ + config.h +arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c \ + config.h \ + $(srcdir)/compat/chacha_private.h +arc4random_uniform.lo arc4random_uniform.o: $(srcdir)/compat/arc4random_uniform.c \ + config.h +explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c \ + config.h +getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c \ + config.h +getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c \ + config.h +getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c \ + config.h getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c -gettimeofday.lo gettimeofday.o: $(srcdir)/compat/gettimeofday.c config.h -inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c config.h -inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c config.h -sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h -strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h -rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/debug.h config.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h -val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \ - $(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h +gettimeofday.lo gettimeofday.o: $(srcdir)/compat/gettimeofday.c \ + config.h +inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c \ + config.h +inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c \ + config.h +sha512.lo sha512.o: $(srcdir)/compat/sha512.c \ + config.h +strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c \ + config.h +rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c \ + config.h \ + $(srcdir)/util/log.h $(srcdir)/debug.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h +val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c \ + config.h \ + $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h $(srcdir)/debug.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h \ + $(srcdir)/gldns/gbuffer.h jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h -libev.lo libev.o: $(srcdir)/extension/libev.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/getdns/getdns_ext_libev.h getdns/getdns_extra.h -libevent.lo libevent.o: $(srcdir)/extension/libevent.c config.h $(srcdir)/types-internal.h \ - getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/getdns/getdns_ext_libevent.h getdns/getdns_extra.h -libuv.lo libuv.o: $(srcdir)/extension/libuv.c config.h $(srcdir)/debug.h config.h $(srcdir)/types-internal.h \ - getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/getdns/getdns_ext_libuv.h getdns/getdns_extra.h -poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util/uthash.h $(srcdir)/debug.h config.h -select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c config.h \ - $(srcdir)/extension/select_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/debug.h config.h $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h +libev.lo libev.o: $(srcdir)/extension/libev.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libev.h +libevent.lo libevent.o: $(srcdir)/extension/libevent.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libevent.h +libuv.lo libuv.o: $(srcdir)/extension/libuv.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h +poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \ + config.h \ + $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/uthash.h $(srcdir)/debug.h +select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c \ + config.h \ + $(srcdir)/extension/select_eventloop.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/debug.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h diff --git a/src/test/Makefile.in b/src/test/Makefile.in index c481fdab..758435c1 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -216,10 +216,13 @@ depend: .PHONY: clean test # Dependencies for the unit tests -check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c ../getdns/getdns.h $(srcdir)/check_getdns_common.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_address.h \ - $(srcdir)/check_getdns_address_sync.h $(srcdir)/check_getdns_cancel_callback.h \ - $(srcdir)/check_getdns_context_create.h $(srcdir)/check_getdns_context_destroy.h \ +check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c \ + ../getdns/getdns.h \ + $(srcdir)/check_getdns_common.h \ + ../getdns/getdns_extra.h \ + $(srcdir)/check_getdns_address.h $(srcdir)/check_getdns_address_sync.h \ + $(srcdir)/check_getdns_cancel_callback.h $(srcdir)/check_getdns_context_create.h \ + $(srcdir)/check_getdns_context_destroy.h \ $(srcdir)/check_getdns_context_set_context_update_callback.h \ $(srcdir)/check_getdns_context_set_dns_transport.h \ $(srcdir)/check_getdns_context_set_timeout.h \ @@ -239,34 +242,58 @@ check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c ../getdns/getdns.h $(sr $(srcdir)/check_getdns_list_get_list.h $(srcdir)/check_getdns_pretty_print_dict.h \ $(srcdir)/check_getdns_service.h $(srcdir)/check_getdns_service_sync.h \ $(srcdir)/check_getdns_transport.h -check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c ../getdns/getdns.h \ - ../config.h $(srcdir)/check_getdns_common.h ../getdns/getdns_extra.h \ +check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c \ + ../getdns/getdns.h \ + ../config.h \ + $(srcdir)/check_getdns_common.h \ + ../getdns/getdns_extra.h \ $(srcdir)/check_getdns_eventloop.h check_getdns_context_set_timeout.lo check_getdns_context_set_timeout.o: $(srcdir)/check_getdns_context_set_timeout.c \ $(srcdir)/check_getdns_context_set_timeout.h $(srcdir)/check_getdns_common.h \ - ../getdns/getdns.h ../getdns/getdns_extra.h + ../getdns/getdns.h \ + ../getdns/getdns_extra.h check_getdns_libev.lo check_getdns_libev.o: $(srcdir)/check_getdns_libev.c $(srcdir)/check_getdns_eventloop.h \ - ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libev.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h + ../config.h \ + ../getdns/getdns.h \ + $(srcdir)/../getdns/getdns_ext_libev.h \ + ../getdns/getdns_extra.h \ + $(srcdir)/check_getdns_common.h check_getdns_libevent.lo check_getdns_libevent.o: $(srcdir)/check_getdns_libevent.c $(srcdir)/check_getdns_eventloop.h \ - ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libevent.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_libevent.h $(srcdir)/check_getdns_common.h + ../config.h \ + ../getdns/getdns.h \ + $(srcdir)/../getdns/getdns_ext_libevent.h \ + ../getdns/getdns_extra.h \ + $(srcdir)/check_getdns_libevent.h $(srcdir)/check_getdns_common.h check_getdns_libuv.lo check_getdns_libuv.o: $(srcdir)/check_getdns_libuv.c $(srcdir)/check_getdns_eventloop.h \ - ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libuv.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h + ../config.h \ + ../getdns/getdns.h \ + $(srcdir)/../getdns/getdns_ext_libuv.h \ + ../getdns/getdns_extra.h \ + $(srcdir)/check_getdns_common.h check_getdns_selectloop.lo check_getdns_selectloop.o: $(srcdir)/check_getdns_selectloop.c \ - $(srcdir)/check_getdns_eventloop.h ../config.h ../getdns/getdns.h \ + $(srcdir)/check_getdns_eventloop.h \ + ../config.h \ + ../getdns/getdns.h \ ../getdns/getdns_extra.h check_getdns_transport.lo check_getdns_transport.o: $(srcdir)/check_getdns_transport.c \ - $(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h ../getdns/getdns.h \ + $(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h \ + ../getdns/getdns.h \ ../getdns/getdns_extra.h -scratchpad.template.lo scratchpad.template.o: scratchpad.template.c ../getdns/getdns.h \ +scratchpad.template.lo scratchpad.template.o: scratchpad.template.c \ + ../getdns/getdns.h \ ../getdns/getdns_extra.h testmessages.lo testmessages.o: $(srcdir)/testmessages.c $(srcdir)/testmessages.h -tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h ../getdns/getdns.h -tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h ../getdns/getdns.h -tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.h ../getdns/getdns.h -tests_stub_async.lo tests_stub_async.o: $(srcdir)/tests_stub_async.c ../config.h $(srcdir)/testmessages.h \ - ../getdns/getdns.h ../getdns/getdns_extra.h -tests_stub_sync.lo tests_stub_sync.o: $(srcdir)/tests_stub_sync.c $(srcdir)/testmessages.h ../getdns/getdns.h \ +tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h +tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h +tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h +tests_stub_async.lo tests_stub_async.o: $(srcdir)/tests_stub_async.c \ + ../config.h \ + $(srcdir)/testmessages.h \ + ../getdns/getdns.h \ + ../getdns/getdns_extra.h +tests_stub_sync.lo tests_stub_sync.o: $(srcdir)/tests_stub_sync.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h \ ../getdns/getdns_extra.h diff --git a/src/tools/Makefile.in b/src/tools/Makefile.in index d98cf437..d066e824 100644 --- a/src/tools/Makefile.in +++ b/src/tools/Makefile.in @@ -113,5 +113,8 @@ depend: .PHONY: clean test # Dependencies for getdns_query -getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \ - ../getdns/getdns.h ../getdns/getdns_extra.h +getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c \ + ../config.h \ + $(srcdir)/../debug.h \ + ../getdns/getdns.h \ + ../getdns/getdns_extra.h From b2fe9673de39bf638f6b8ec64e99ce58952fb07d Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 13:08:47 +0100 Subject: [PATCH 23/26] Fix realloc pfds set error + callback order error --- src/extension/poll_eventloop.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index 331e5d4b..f5e609ab 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -317,7 +317,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if (num_pfds >= poll_loop->pfds_capacity) { poll_loop->pfds_capacity = up_pow2(num_pfds + 1); - if (poll_loop->pfds) { + if (!poll_loop->pfds) { poll_loop->pfds = GETDNS_XMALLOC(poll_loop->mf, struct pollfd, poll_loop->pfds_capacity); } else poll_loop->pfds = GETDNS_XREALLOC(poll_loop->mf, poll_loop->pfds, struct pollfd, poll_loop->pfds_capacity); @@ -363,13 +363,13 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, fd); if (fd_event && fd_event->event) { getdns_eventloop_event* event = fd_event->event; - if (event->read_cb && - (poll_loop->pfds[i].revents & POLLIN)) - poll_read_cb(fd, event); - if (event->write_cb && (poll_loop->pfds[i].revents & POLLOUT)) poll_write_cb(fd, event); + + else if (event->read_cb && + (poll_loop->pfds[i].revents & POLLIN)) + poll_read_cb(fd, event); } } HASH_ITER(hh, poll_loop->fd_events, s, tmp) { From c805d40585b977fb4f20d9ae1a3462e6362540a9 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 14:04:34 +0100 Subject: [PATCH 24/26] Clean in place executed unit tests --- src/test/tpkg/clean.sh | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100755 src/test/tpkg/clean.sh diff --git a/src/test/tpkg/clean.sh b/src/test/tpkg/clean.sh new file mode 100755 index 00000000..b3ebef5e --- /dev/null +++ b/src/test/tpkg/clean.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +export SRCDIR=`dirname $0` +( cd $SRCDIR + ./tpkg clean + rm -fr build build-stub-only build-event-loops install scan-build-reports .tpkg.var.master +) From 7b6b0ff642fdb0c2a735818e2759fac2b77eeca6 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 14:57:30 +0100 Subject: [PATCH 25/26] No helper copy variables --- src/extension/poll_eventloop.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index f5e609ab..65fd17c9 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -49,15 +49,16 @@ find_event(_getdns_eventloop_info** events, int id) } static void -add_event(struct mem_funcs *mf, - _getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) +add_event(struct mem_funcs *mf, _getdns_eventloop_info** events, + int id, getdns_eventloop_event *event, uint64_t timeout_time) { DEBUG_SCHED("poll_eventloop: add_event with id %d\n", id); _getdns_eventloop_info* myevent = GETDNS_MALLOC(*mf, _getdns_eventloop_info); /* not necessary -- (void) memset(myevent, 0, sizeof(_getdns_eventloop_info)); */ - myevent->event = ev->event; + myevent->id = id; - myevent->timeout_time = ev->timeout_time; + myevent->event = event; + myevent->timeout_time = timeout_time; HASH_ADD_INT(*events, id, myevent); } @@ -131,11 +132,8 @@ poll_eventloop_schedule(getdns_eventloop *loop, if (fd_event) { delete_event(mf, &poll_loop->fd_events, fd_event); } - _getdns_eventloop_info fd_ev; event->ev = (void *) (intptr_t) (fd + 1); - fd_ev.event = event; - fd_ev.timeout_time = get_now_plus(timeout); - add_event(mf, &poll_loop->fd_events, fd, &fd_ev); + add_event(mf, &poll_loop->fd_events, fd, event, get_now_plus(timeout)); DEBUG_SCHED( "scheduled read/write at fd %d\n", fd); return GETDNS_RETURN_GOOD; @@ -154,11 +152,8 @@ poll_eventloop_schedule(getdns_eventloop *loop, } for (i = poll_loop->timeout_id + 1; i != poll_loop->timeout_id; i++) { if (find_event(&poll_loop->timeout_events, i) == NULL) { - _getdns_eventloop_info timeout_ev; - timeout_ev.event = event; - timeout_ev.timeout_time = get_now_plus(timeout); - add_event(mf, &poll_loop->timeout_events, i, &timeout_ev); event->ev = (void *) (intptr_t) (i + 1); + add_event(mf, &poll_loop->timeout_events, i, event, get_now_plus(timeout)); DEBUG_SCHED( "scheduled timeout at slot %d\n", (int)i); return GETDNS_RETURN_GOOD; @@ -292,7 +287,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { if (now > s->timeout_time) - add_event(mf, &timeout_timeout_cbs, s->id, s); + add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); else if (s->timeout_time < timeout) timeout = s->timeout_time; } @@ -376,7 +371,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if (s->event && s->event->timeout_cb && now > s->timeout_time) - add_event(mf, &fd_timeout_cbs, s->id, s); + add_event(mf, &fd_timeout_cbs, s->id, s->event, s->timeout_time); } /* this is in case the timeout callback deletes the event and thus messes with the iteration */ @@ -390,7 +385,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if (s->event && s->event->timeout_cb && now > s->timeout_time) - add_event(mf, &timeout_timeout_cbs, s->id, s); + add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); } /* this is in case the timeout callback deletes the event and thus messes with the iteration */ From e4eddca2592c638b42d9457237236c83953a8af1 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 15:10:11 +0100 Subject: [PATCH 26/26] Reference event_info directly --- src/extension/poll_eventloop.c | 53 +++++++++------------------------- 1 file changed, 13 insertions(+), 40 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index 65fd17c9..2f40c30a 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -48,7 +48,7 @@ find_event(_getdns_eventloop_info** events, int id) return ev; } -static void +static _getdns_eventloop_info * add_event(struct mem_funcs *mf, _getdns_eventloop_info** events, int id, getdns_eventloop_event *event, uint64_t timeout_time) { @@ -60,6 +60,7 @@ add_event(struct mem_funcs *mf, _getdns_eventloop_info** events, myevent->event = event; myevent->timeout_time = timeout_time; HASH_ADD_INT(*events, id, myevent); + return myevent; } static void @@ -132,8 +133,7 @@ poll_eventloop_schedule(getdns_eventloop *loop, if (fd_event) { delete_event(mf, &poll_loop->fd_events, fd_event); } - event->ev = (void *) (intptr_t) (fd + 1); - add_event(mf, &poll_loop->fd_events, fd, event, get_now_plus(timeout)); + event->ev = add_event(mf, &poll_loop->fd_events, fd, event, get_now_plus(timeout)); DEBUG_SCHED( "scheduled read/write at fd %d\n", fd); return GETDNS_RETURN_GOOD; @@ -152,8 +152,7 @@ poll_eventloop_schedule(getdns_eventloop *loop, } for (i = poll_loop->timeout_id + 1; i != poll_loop->timeout_id; i++) { if (find_event(&poll_loop->timeout_events, i) == NULL) { - event->ev = (void *) (intptr_t) (i + 1); - add_event(mf, &poll_loop->timeout_events, i, event, get_now_plus(timeout)); + event->ev = add_event(mf, &poll_loop->timeout_events, i, event, get_now_plus(timeout)); DEBUG_SCHED( "scheduled timeout at slot %d\n", (int)i); return GETDNS_RETURN_GOOD; @@ -168,46 +167,20 @@ poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; struct mem_funcs *mf = &poll_loop->mf; - ssize_t i; if (!loop || !event) return GETDNS_RETURN_INVALID_PARAMETER; DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNC__, (void *)loop, (void *)event); - i = (intptr_t)event->ev - 1; - if (i < 0 -#ifdef HAVE_GETRLIMIT - || i > poll_loop->max_fds -#endif - ) { - return GETDNS_RETURN_GENERIC_ERROR; - } - if (event->timeout_cb && !event->read_cb && !event->write_cb) { - _getdns_eventloop_info* timeout_event = find_event(&poll_loop->timeout_events, i); -#if defined(SCHED_DEBUG) && SCHED_DEBUG - if (timeout_event && timeout_event->event != event) - DEBUG_SCHED( "ERROR: Different/wrong event present at " - "timeout slot: %p!\n" - , (void *)timeout_event); + assert(event->ev); -#endif - if (timeout_event) { - delete_event(mf, &poll_loop->timeout_events, timeout_event); - } - } else { - _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, i); -#if defined(SCHED_DEBUG) && SCHED_DEBUG - if (fd_event && fd_event->event != event) - DEBUG_SCHED( "ERROR: Different/wrong event present at " - "fd slot: %p!\n" - , (void *)fd_event); -#endif - if (fd_event) { - delete_event(mf, &poll_loop->fd_events, fd_event); - } - } + delete_event(mf, + ( event->timeout_cb && !event->read_cb && !event->write_cb + ? &poll_loop->timeout_events : &poll_loop->fd_events + ), event->ev); event->ev = NULL; + return GETDNS_RETURN_GOOD; } @@ -287,7 +260,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { if (now > s->timeout_time) - add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); + (void) add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); else if (s->timeout_time < timeout) timeout = s->timeout_time; } @@ -371,7 +344,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if (s->event && s->event->timeout_cb && now > s->timeout_time) - add_event(mf, &fd_timeout_cbs, s->id, s->event, s->timeout_time); + (void) add_event(mf, &fd_timeout_cbs, s->id, s->event, s->timeout_time); } /* this is in case the timeout callback deletes the event and thus messes with the iteration */ @@ -385,7 +358,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if (s->event && s->event->timeout_cb && now > s->timeout_time) - add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); + (void) add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); } /* this is in case the timeout callback deletes the event and thus messes with the iteration */