Author: sephe
Date: Wed May 18 03:28:51 2016
New Revision: 300105
URL: https://svnweb.freebsd.org/changeset/base/300105

Log:
  hyperv/vmbus: Use atomic swap and flsl to process event flags
  
  Greatly reduce the locked instructions and reduce number of inner loops.
  
  MFC after:    1 week
  Sponsored by: Microsoft OSTC
  Differential Revision:        https://reviews.freebsd.org/D6404

Modified:
  head/sys/dev/hyperv/vmbus/hv_connection.c

Modified: head/sys/dev/hyperv/vmbus/hv_connection.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_connection.c   Wed May 18 03:23:07 2016        
(r300104)
+++ head/sys/dev/hyperv/vmbus/hv_connection.c   Wed May 18 03:28:51 2016        
(r300105)
@@ -332,32 +332,32 @@ hv_vmbus_on_events(int cpu)
         */
        for (f = 0; f < flag_cnt; f++) {
                uint32_t rel_id_base;
+               unsigned long flags;
                int bit;
 
                if (intr_flags[f] == 0)
                        continue;
 
+               flags = atomic_swap_long(&intr_flags[f], 0);
                rel_id_base = f << HV_CHANNEL_ULONG_SHIFT;
-               for (bit = 0; bit < HV_CHANNEL_ULONG_LEN; bit++) {
-                       if (atomic_testandclear_long(&intr_flags[f], bit)) {
-                               struct hv_vmbus_channel *channel;
-                               uint32_t rel_id;
-
-                               rel_id = rel_id_base + bit;
-                               channel =
-                                   hv_vmbus_g_connection.channels[rel_id];
-
-                               /* if channel is closed or closing */
-                               if (channel == NULL || channel->rxq == NULL)
-                                       continue;
-
-                               if (channel->batched_reading) {
-                                       hv_ring_buffer_read_begin(
-                                           &channel->inbound);
-                               }
-                               taskqueue_enqueue(channel->rxq,
-                                   &channel->channel_task);
-                       }
+
+               while ((bit = ffsl(flags)) != 0) {
+                       struct hv_vmbus_channel *channel;
+                       uint32_t rel_id;
+
+                       --bit;  /* NOTE: ffsl is 1-based */
+                       flags &= ~(1UL << bit);
+
+                       rel_id = rel_id_base + bit;
+                       channel = hv_vmbus_g_connection.channels[rel_id];
+
+                       /* if channel is closed or closing */
+                       if (channel == NULL || channel->rxq == NULL)
+                               continue;
+
+                       if (channel->batched_reading)
+                               hv_ring_buffer_read_begin(&channel->inbound);
+                       taskqueue_enqueue(channel->rxq, &channel->channel_task);
                }
        }
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to