Mercurial > hg > dhcpcd
changeset 2981:17ce5dad11dc draft
Support kqueue(2).
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Wed, 04 Mar 2015 15:47:04 +0000 |
| parents | c66ed22ed0d6 |
| children | b5e381584efe |
| files | configure dhcpcd.c dhcpcd.h eloop.c eloop.h |
| diffstat | 5 files changed, 172 insertions(+), 53 deletions(-) [+] |
line wrap: on
line diff
--- a/configure Wed Mar 04 11:51:55 2015 +0000 +++ b/configure Wed Mar 04 15:47:04 2015 +0000 @@ -790,6 +790,22 @@ fi if [ -z "$POLL" ]; then + printf "Testing for kqueue ... " + cat <<EOF >_kqueue.c +#include <sys/event.h> +int main(void) { + return kqueue(); +} +EOF + if $XCC _kqueue.c -o _kqueue 2>&3; then + POLL=kqueue + echo "yes" + else + echo "no" + fi + rm -f _kqueue.c _kqueue +fi +if [ -z "$POLL" ]; then printf "Testing for epoll ... " cat <<EOF >_epoll.c #ifdef __linux__ @@ -853,6 +869,9 @@ rm -f _pselect.c _pselect fi case "$POLL" in +kqueue) + echo "#define HAVE_KQUEUE" >>$CONFIG_H + ;; epoll) echo "#define HAVE_EPOLL" >>$CONFIG_H ;;
--- a/dhcpcd.c Wed Mar 04 11:51:55 2015 +0000 +++ b/dhcpcd.c Wed Mar 04 15:47:04 2015 +0000 @@ -68,12 +68,12 @@ #ifdef USE_SIGNALS const int dhcpcd_handlesigs[] = { + SIGTERM, + SIGINT, SIGALRM, SIGHUP, - SIGINT, + SIGUSR1, SIGPIPE, - SIGTERM, - SIGUSR1, 0 }; @@ -1060,14 +1060,10 @@ } #ifdef USE_SIGNALS -struct dhcpcd_siginfo { - int signo; - pid_t pid; -} dhcpcd_siginfo; - -#define sigmsg "received signal %s from PID %d, %s" -static void -handle_signal1(void *arg) +struct dhcpcd_siginfo dhcpcd_siginfo; +#define sigmsg "received signal %s, %s" +void +dhcpcd_handle_signal(void *arg) { struct dhcpcd_ctx *ctx; struct dhcpcd_siginfo *si; @@ -1080,19 +1076,19 @@ exit_code = EXIT_FAILURE; switch (si->signo) { case SIGINT: - syslog(LOG_INFO, sigmsg, "INT", (int)si->pid, "stopping"); + syslog(LOG_INFO, sigmsg, "INT", "stopping"); break; case SIGTERM: - syslog(LOG_INFO, sigmsg, "TERM", (int)si->pid, "stopping"); + syslog(LOG_INFO, sigmsg, "TERM", "stopping"); exit_code = EXIT_SUCCESS; break; case SIGALRM: - syslog(LOG_INFO, sigmsg, "ALRM", (int)si->pid, "releasing"); + syslog(LOG_INFO, sigmsg, "ALRM", "releasing"); do_release = 1; exit_code = EXIT_SUCCESS; break; case SIGHUP: - syslog(LOG_INFO, sigmsg, "HUP", (int)si->pid, "rebinding"); + syslog(LOG_INFO, sigmsg, "HUP", "rebinding"); reload_config(ctx); /* Preserve any options passed on the commandline * when we were started. */ @@ -1100,7 +1096,7 @@ ctx->argc - ctx->ifc); return; case SIGUSR1: - syslog(LOG_INFO, sigmsg, "USR1", (int)si->pid, "reconfiguring"); + syslog(LOG_INFO, sigmsg, "USR1", "reconfiguring"); TAILQ_FOREACH(ifp, ctx->ifaces, next) { ipv4_applyaddr(ifp); } @@ -1110,9 +1106,9 @@ return; default: syslog(LOG_ERR, - "received signal %d from PID %d, " + "received signal %d, " "but don't know what to do with it", - si->signo, (int)si->pid); + si->signo); return; } @@ -1121,39 +1117,44 @@ eloop_exit(ctx->eloop, exit_code); } +#ifndef HAVE_KQUEUE static void -handle_signal(int sig, siginfo_t *siginfo, __unused void *context) +handle_signal(int sig, __unused siginfo_t *siginfo, __unused void *context) { /* So that we can operate safely under a signal we instruct * eloop to pass a copy of the siginfo structure to handle_signal1 * as the very first thing to do. */ dhcpcd_siginfo.signo = sig; - dhcpcd_siginfo.pid = siginfo ? siginfo->si_pid : 0; eloop_timeout_add_now(dhcpcd_ctx->eloop, - handle_signal1, &dhcpcd_siginfo); + dhcpcd_handle_signal, &dhcpcd_siginfo); } +#endif static int signal_init(sigset_t *oldset) { - unsigned int i; + sigset_t newset; +#ifndef HAVE_KQUEUE + int i; struct sigaction sa; - sigset_t newset; +#endif sigfillset(&newset); if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1) return -1; +#ifndef HAVE_KQUEUE memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = handle_signal; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); - for (i = 0; dhcpcd_handlesigs[i]; i++) { + for (i = 0; i < dhcpcd_handlesigs[i]; i++) { if (sigaction(dhcpcd_handlesigs[i], &sa, NULL) == -1) return -1; } +#endif return 0; } #endif
--- a/dhcpcd.h Wed Mar 04 11:51:55 2015 +0000 +++ b/dhcpcd.h Wed Mar 04 15:47:04 2015 +0000 @@ -150,7 +150,12 @@ }; #ifdef USE_SIGNALS +struct dhcpcd_siginfo { + int signo; +}; + extern const int dhcpcd_handlesigs[]; +void dhcpcd_handle_signal(void *); #endif int dhcpcd_oneup(struct dhcpcd_ctx *);
--- a/eloop.c Wed Mar 04 11:51:55 2015 +0000 +++ b/eloop.c Wed Mar 04 15:47:04 2015 +0000 @@ -42,7 +42,16 @@ #include "dhcpcd.h" #include "eloop.h" -#if defined(HAVE_EPOLL) +#if defined(HAVE_KQUEUE) +#include <sys/event.h> +#ifdef __NetBSD__ +/* udata is void * except on NetBSD */ +#define UPTR(x) ((intptr_t)(x)) +#else +#define UPTR(x) (x) +#endif +#define eloop_event_setup_fds(ctx) +#elif defined(HAVE_EPOLL) #include <sys/epoll.h> #define eloop_event_setup_fds(ctx) #else @@ -74,7 +83,9 @@ void (*write_cb)(void *), void *write_cb_arg) { struct eloop_event *e; -#ifdef HAVE_EPOLL +#ifdef HAVE_KQUEUE + struct kevent ke[2], *nfds; +#elif HAVE_EPOLL struct epoll_event epe, *nfds; #else struct pollfd *nfds; @@ -99,7 +110,16 @@ e->write_cb = write_cb; e->write_cb_arg = write_cb_arg; } -#ifdef HAVE_EPOLL +#ifdef HAVE_KQUEUE + EV_SET(&ke[0], fd, EVFILT_READ, EV_ADD, 0, 0, UPTR(e)); + if (write_cb) + EV_SET(&ke[1], fd, EVFILT_WRITE, EV_ADD, + 0, 0, UPTR(e)); + if (kevent(ctx->kqueue_fd, ke, write_cb ? 2 : 1, + NULL, 0, NULL) == -1) + goto err; + return 0; +#elif HAVE_EPOLL epe.data.ptr = e; return epoll_ctl(ctx->epoll_fd, EPOLL_CTL_MOD, fd, &epe); @@ -129,7 +149,6 @@ ctx->fds = nfds; } - /* Now populate the structure and add it to the list */ e->fd = fd; e->read_cb = read_cb; @@ -137,7 +156,13 @@ e->write_cb = write_cb; e->write_cb_arg = write_cb_arg; -#ifdef HAVE_EPOLL +#ifdef HAVE_KQUEUE + EV_SET(&ke[0], fd, EVFILT_READ, EV_ADD, 0, 0, UPTR(e)); + if (write_cb) + EV_SET(&ke[1], fd, EVFILT_WRITE, EV_ADD, 0, 0, UPTR(e)); + if (kevent(ctx->kqueue_fd, ke, write_cb ? 2 : 1, NULL, 0, NULL) == -1) + goto err; +#elif HAVE_EPOLL epe.data.ptr = e; if (epoll_ctl(ctx->epoll_fd, EPOLL_CTL_ADD, fd, &epe) == -1) goto err; @@ -166,15 +191,34 @@ eloop_event_delete(struct eloop_ctx *ctx, int fd, int write_only) { struct eloop_event *e; +#ifdef HAVE_KQUEUE + struct kevent ke; +#endif TAILQ_FOREACH(e, &ctx->events, next) { if (e->fd == fd) { if (write_only) { - e->write_cb = NULL; - e->write_cb_arg = NULL; + if (e->write_cb) { + e->write_cb = NULL; + e->write_cb_arg = NULL; +#ifdef HAVE_KQUEUE + EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, + 0, 0, UPTR(NULL)); + kevent(ctx->kqueue_fd, &ke, 1, NULL, 0, + NULL); +#endif + } + } else { TAILQ_REMOVE(&ctx->events, e, next); -#ifdef HAVE_EPOLL +#ifdef HAVE_KQUEUE + EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, + 0, 0, UPTR(NULL)); + kevent(ctx->kqueue_fd, &ke, 1, NULL, 0, NULL); + EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, + 0, 0, UPTR(NULL)); + kevent(ctx->kqueue_fd, &ke, 1, NULL, 0, NULL); +#elif HAVE_EPOLL /* NULL event is safe because we * rely on epoll_pwait which as added * after the delete without event was fixed. */ @@ -299,6 +343,9 @@ { struct eloop_ctx *ctx; struct timespec now; +#ifdef HAVE_KQUEUE + int i; +#endif /* Check we have a working monotonic clock. */ if (get_monotonic(&now) == -1) @@ -311,7 +358,32 @@ TAILQ_INIT(&ctx->timeouts); TAILQ_INIT(&ctx->free_timeouts); ctx->exitcode = EXIT_FAILURE; -#ifdef HAVE_EPOLL +#ifdef HAVE_KQUEUE + if ((ctx->kqueue_fd = kqueue()) == -1) { + free(ctx); + return NULL; + } + /* There is no sigmask parameter to kqueue, instead + * we have to use it's filters. */ + ctx->fds_len = 0; + while ((int)ctx->fds_len < dhcpcd_handlesigs[ctx->fds_len]) + ctx->fds_len++; + ctx->fds = malloc(ctx->fds_len * sizeof(*ctx->fds)); + if (ctx->fds == NULL) { + free(ctx); + return NULL; + } + for (i = 0; i < dhcpcd_handlesigs[i]; i++) + EV_SET(&ctx->fds[i], dhcpcd_handlesigs[i], + EVFILT_SIGNAL, EV_ADD, 0, 0, UPTR(NULL)); + if (kevent(ctx->kqueue_fd, ctx->fds, ctx->fds_len, + NULL, 0, NULL) == -1) + { + free(ctx->fds); + free(ctx); + return NULL; + } +#elif HAVE_EPOLL if ((ctx->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) == -1) { free(ctx); return NULL; @@ -332,6 +404,12 @@ if (ctx == NULL) return; +#ifdef HAVE_KQUEUE + close(ctx->kqueue_fd); +#elif HAVE_EPOLL + close(ctx->epoll_fd); +#endif + while ((e = TAILQ_FIRST(&ctx->events))) { TAILQ_REMOVE(&ctx->events, e, next); free(e); @@ -364,7 +442,7 @@ #if defined(HAVE_EPOLL) || !defined(USE_SIGNALS) int timeout; #endif -#ifdef HAVE_EPOLL +#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) int i; #endif @@ -411,7 +489,10 @@ (tsp->tv_nsec + 999999) / 1000000); #endif -#ifdef HAVE_EPOLL +#ifdef HAVE_KQUEUE + n = kevent(ctx->kqueue_fd, NULL, 0, ctx->fds, ctx->events_len, + tsp); +#elif HAVE_EPOLL #ifdef USE_SIGNALS n = epoll_pwait(ctx->epoll_fd, ctx->fds, (int)ctx->events_len, timeout, &dctx->sigset); @@ -434,27 +515,43 @@ break; } - /* Process any triggered events. */ -#ifdef HAVE_EPOLL + /* Process any triggered events. + * We break after calling each callback incase + * the current event or next event is removed. */ +#ifdef HAVE_KQUEUE + for (i = 0; i < n; i++) { + if (ctx->fds[i].filter == EVFILT_SIGNAL) { + struct dhcpcd_siginfo si; + + si.signo = (int)ctx->fds[i].ident; + dhcpcd_handle_signal(&si); + break; + } + e = (struct eloop_event *)ctx->fds[i].udata; + if (ctx->fds[i].filter == EVFILT_WRITE && + e->write_cb) + { + e->write_cb(e->write_cb_arg); + break; + } + if (ctx->fds[i].filter == EVFILT_READ) { + e->read_cb(e->read_cb_arg); + break; + } + } +#elif HAVE_EPOLL for (i = 0; i < n; i++) { e = (struct eloop_event *)ctx->fds[i].data.ptr; if (ctx->fds[i].events & EPOLLOUT && e->write_cb) { e->write_cb(e->write_cb_arg); - /* We need to break here as the - * callback could destroy the next - * fd to process. */ break; } - if (ctx->fds[i].events && - ctx->fds[i].events & + if (ctx->fds[i].events & (EPOLLIN | EPOLLERR | EPOLLHUP)) { e->read_cb(e->read_cb_arg); - /* We need to break here as the - * callback could destroy the next - * fd to process. */ break; } } @@ -465,16 +562,10 @@ e->write_cb) { e->write_cb(e->write_cb_arg); - /* We need to break here as the - * callback could destroy the next - * fd to process. */ break; } if (e->pollfd->revents) { e->read_cb(e->read_cb_arg); - /* We need to break here as the - * callback could destroy the next - * fd to process. */ break; } }
--- a/eloop.h Wed Mar 04 11:51:55 2015 +0000 +++ b/eloop.h Wed Mar 04 15:47:04 2015 +0000 @@ -47,7 +47,7 @@ void *read_cb_arg; void (*write_cb)(void *); void *write_cb_arg; -#if !defined(HAVE_EPOLL) +#if !defined(HAVE_KQUEUE) && !defined(HAVE_EPOLL) struct pollfd *pollfd; #endif }; @@ -71,7 +71,10 @@ void (*timeout0)(void *); void *timeout0_arg; -#ifdef HAVE_EPOLL +#ifdef HAVE_KQUEUE + int kqueue_fd; + struct kevent *fds; +#elif HAVE_EPOLL int epoll_fd; struct epoll_event *fds; #else
