diff options
author | 2017-07-14 19:09:52 +0000 | |
---|---|---|
committer | 2017-07-14 19:09:52 +0000 | |
commit | e33c817b648b8d87b60f789b366877a5e550c8ce (patch) | |
tree | d93554f86476041dd1ec2b7903cd4da550398498 | |
parent | Because ignore SIGCHLD early, letting signal_del restore it doesn't work (diff) | |
download | wireguard-openbsd-e33c817b648b8d87b60f789b366877a5e550c8ce.tar.xz wireguard-openbsd-e33c817b648b8d87b60f789b366877a5e550c8ce.zip |
Silence the interrupt source until the interrupt task has done its job
This small change significantly improves performance under load and halves
the number of received interrupts.
-rw-r--r-- | sys/dev/pv/xen.c | 63 | ||||
-rw-r--r-- | sys/dev/pv/xenvar.h | 4 |
2 files changed, 48 insertions, 19 deletions
diff --git a/sys/dev/pv/xen.c b/sys/dev/pv/xen.c index 96795da2957..d66293f14a4 100644 --- a/sys/dev/pv/xen.c +++ b/sys/dev/pv/xen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xen.c,v 1.82 2017/06/02 20:25:50 mikeb Exp $ */ +/* $OpenBSD: xen.c,v 1.83 2017/07/14 19:09:52 mikeb Exp $ */ /* * Copyright (c) 2015, 2016, 2017 Mike Belopuhov @@ -71,6 +71,7 @@ int xen_getfeatures(struct xen_softc *); int xen_init_info_page(struct xen_softc *); int xen_init_cbvec(struct xen_softc *); int xen_init_interrupts(struct xen_softc *); +void xen_intr_dispatch(void *); int xen_init_grant_tables(struct xen_softc *); struct xen_gntent * xen_grant_table_grow(struct xen_softc *); @@ -634,6 +635,27 @@ xen_intsrc_remove(struct xen_softc *sc, evtchn_port_t port) return (xi); } +static inline void +xen_intr_mask_acquired(struct xen_softc *sc, struct xen_intsrc *xi) +{ + xi->xi_masked = 1; + set_bit(xi->xi_port, &sc->sc_ipg->evtchn_mask[0]); +} + +static inline int +xen_intr_unmask_release(struct xen_softc *sc, struct xen_intsrc *xi) +{ + struct evtchn_unmask eu; + + xi->xi_masked = 0; + if (!test_bit(xi->xi_port, &sc->sc_ipg->evtchn_mask[0])) + return (0); + eu.port = xi->xi_port; + xen_intsrc_release(sc, xi); + return (xen_evtchn_hypercall(sc, EVTCHNOP_unmask, &eu, + sizeof(eu))); +} + void xen_intr_ack(void) { @@ -678,8 +700,8 @@ xen_intr(void) continue; } xi->xi_evcnt.ec_count++; + xen_intr_mask_acquired(sc, xi); task_add(xi->xi_taskq, &xi->xi_task); - xen_intsrc_release(sc, xi); } } } @@ -690,10 +712,8 @@ xen_intr_schedule(xen_intr_handle_t xih) struct xen_softc *sc = xen_sc; struct xen_intsrc *xi; - if ((xi = xen_intsrc_acquire(sc, (evtchn_port_t)xih)) != NULL) { + if ((xi = xen_intsrc_acquire(sc, (evtchn_port_t)xih)) != NULL) task_add(xi->xi_taskq, &xi->xi_task); - xen_intsrc_release(sc, xi); - } } static void @@ -780,6 +800,9 @@ xen_intr_establish(evtchn_port_t port, xen_intr_handle_t *xih, int domain, xi->xi_port = (evtchn_port_t)*xih; + xi->xi_handler = handler; + xi->xi_ctx = arg; + xi->xi_taskq = taskq_create(name, 1, IPL_NET, TASKQ_MPSAFE); if (!xi->xi_taskq) { printf("%s: failed to create interrupt task for %s\n", @@ -787,7 +810,7 @@ xen_intr_establish(evtchn_port_t port, xen_intr_handle_t *xih, int domain, free(xi, M_DEVBUF, sizeof(*xi)); return (-1); } - task_set(&xi->xi_task, handler, arg); + task_set(&xi->xi_task, xen_intr_dispatch, xi); if (port == 0) { /* We're being asked to allocate a new event port */ @@ -886,6 +909,18 @@ xen_intr_disestablish(xen_intr_handle_t xih) } void +xen_intr_dispatch(void *arg) +{ + struct xen_softc *sc = xen_sc; + struct xen_intsrc *xi = arg; + + if (xi->xi_handler) + xi->xi_handler(xi->xi_ctx); + + xen_intr_unmask_release(sc, xi); +} + +void xen_intr_enable(void) { struct xen_softc *sc = xen_sc; @@ -917,8 +952,7 @@ xen_intr_mask(xen_intr_handle_t xih) struct xen_intsrc *xi; if ((xi = xen_intsrc_acquire(sc, port)) != NULL) { - xi->xi_masked = 1; - set_bit(xi->xi_port, &sc->sc_ipg->evtchn_mask[0]); + xen_intr_mask_acquired(sc, xi); xen_intsrc_release(sc, xi); } } @@ -929,17 +963,10 @@ xen_intr_unmask(xen_intr_handle_t xih) struct xen_softc *sc = xen_sc; evtchn_port_t port = (evtchn_port_t)xih; struct xen_intsrc *xi; - struct evtchn_unmask eu; - if ((xi = xen_intsrc_acquire(sc, port)) != NULL) { - xi->xi_masked = 0; - if (!test_bit(xi->xi_port, &sc->sc_ipg->evtchn_mask[0])) - return (0); - eu.port = xi->xi_port; - xen_intsrc_release(sc, xi); - return (xen_evtchn_hypercall(sc, EVTCHNOP_unmask, &eu, - sizeof(eu))); - } + if ((xi = xen_intsrc_acquire(sc, port)) != NULL) + return (xen_intr_unmask_release(sc, xi)); + return (0); } diff --git a/sys/dev/pv/xenvar.h b/sys/dev/pv/xenvar.h index 61a4dcb920b..dc43698f0cf 100644 --- a/sys/dev/pv/xenvar.h +++ b/sys/dev/pv/xenvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: xenvar.h,v 1.49 2017/02/08 16:15:52 mikeb Exp $ */ +/* $OpenBSD: xenvar.h,v 1.50 2017/07/14 19:09:52 mikeb Exp $ */ /* * Copyright (c) 2015 Mike Belopuhov @@ -49,6 +49,8 @@ struct xen_intsrc { struct refcnt xi_refcnt; struct task xi_task; struct taskq *xi_taskq; + void (*xi_handler)(void *); + void *xi_ctx; }; struct xen_gntent { |