summaryrefslogtreecommitdiffstats
path: root/sys/dev/pv/xen.c
diff options
context:
space:
mode:
authormikeb <mikeb@openbsd.org>2016-08-05 18:31:21 +0000
committermikeb <mikeb@openbsd.org>2016-08-05 18:31:21 +0000
commit30494642db82acd378f52a5034c9b671ff98f9f2 (patch)
tree6917e41e41ff275d0ceb0c73e164552e3355ea73 /sys/dev/pv/xen.c
parentSwitch pending event clearing to an atomic swap operation (diff)
downloadwireguard-openbsd-30494642db82acd378f52a5034c9b671ff98f9f2.tar.xz
wireguard-openbsd-30494642db82acd378f52a5034c9b671ff98f9f2.zip
Switch pending event clearing to an atomic swap operation
Rather than performing an atomic bit clearing for every encountered event bit set we can adjust the code to perform an atomic swap of a single row of the events array and decrease the amount of expensive atomic operations. Same optimization as for Hyper-V. From FreeBSD.
Diffstat (limited to 'sys/dev/pv/xen.c')
-rw-r--r--sys/dev/pv/xen.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/sys/dev/pv/xen.c b/sys/dev/pv/xen.c
index 2ec7c4c7230..f03d7459300 100644
--- a/sys/dev/pv/xen.c
+++ b/sys/dev/pv/xen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xen.c,v 1.60 2016/08/03 17:14:41 mikeb Exp $ */
+/* $OpenBSD: xen.c,v 1.61 2016/08/05 18:31:21 mikeb Exp $ */
/*
* Copyright (c) 2015 Mike Belopuhov
@@ -628,13 +628,14 @@ xen_intr(void)
for (row = 0; selector > 0; selector >>= 1, row++) {
if ((selector & 1) == 0)
continue;
- pending = sc->sc_ipg->evtchn_pending[row] &
- ~(sc->sc_ipg->evtchn_mask[row]);
+ if ((sc->sc_ipg->evtchn_pending[row] &
+ ~(sc->sc_ipg->evtchn_mask[row])) == 0)
+ continue;
+ pending = atomic_swap_ulong(&sc->sc_ipg->evtchn_pending[row],
+ 0) & ~(sc->sc_ipg->evtchn_mask[row]);
for (bit = 0; pending > 0; pending >>= 1, bit++) {
if ((pending & 1) == 0)
continue;
- atomic_clearbit_ptr(&sc->sc_ipg->evtchn_pending[row],
- bit);
port = (row * LONG_BIT) + bit;
if ((xi = xen_lookup_intsrc(sc, port)) == NULL) {
printf("%s: unhandled interrupt on port %u\n",