Rework the deferred interrupt loop
authormikeb <mikeb@openbsd.org>
Mon, 26 Jun 2017 18:42:23 +0000 (18:42 +0000)
committermikeb <mikeb@openbsd.org>
Mon, 26 Jun 2017 18:42:23 +0000 (18:42 +0000)
By performing a task_add an interrupt handler can rely on the
taskq_thread to invoke it again with an additional benefit of
being able to sched_pause when required. In the long run more
than 99.8% of calls do not require an additional iteration.

sys/dev/pv/hyperv.c

index 6ba01cd..8754c0a 100644 (file)
@@ -106,6 +106,7 @@ int hv_channel_ring_create(struct hv_channel *, uint32_t);
 void   hv_channel_ring_destroy(struct hv_channel *);
 void   hv_channel_pause(struct hv_channel *);
 uint   hv_channel_unpause(struct hv_channel *);
+uint   hv_channel_ready(struct hv_channel *);
 extern void hv_attach_icdevs(struct hv_softc *);
 int    hv_attach_devices(struct hv_softc *);
 
@@ -1230,22 +1231,14 @@ void
 hv_channel_intr(void *arg)
 {
        struct hv_channel *ch = arg;
-       extern int ticks;
-       int start = ticks;
 
-       do {
+       if (hv_channel_ready(ch))
                ch->ch_handler(ch->ch_ctx);
 
-               if (hv_channel_unpause(ch) == 0)
-                       return;
-
-               hv_channel_pause(ch);
-
-#if (defined(__amd64__) || defined(__i386__))
-               __asm volatile("pause": : : "memory");
-#endif
-       } while (ticks < start + 1);
+       if (hv_channel_unpause(ch) == 0)
+               return;
 
+       hv_channel_pause(ch);
        hv_channel_schedule(ch);
 }
 
@@ -1597,6 +1590,16 @@ hv_channel_unpause(struct hv_channel *ch)
        return (avail);
 }
 
+uint
+hv_channel_ready(struct hv_channel *ch)
+{
+       uint32_t avail;
+
+       hv_ring_avail(&ch->ch_rrd, NULL, &avail);
+
+       return (avail);
+}
+
 /* How many PFNs can be referenced by the header */
 #define HV_NPFNHDR     ((VMBUS_MSG_DSIZE_MAX - \
          sizeof(struct vmbus_chanmsg_gpadl_conn)) / sizeof(uint64_t))