Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 May 2016 03:28:51 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r300105 - head/sys/dev/hyperv/vmbus
Message-ID:  <201605180328.u4I3SpND003631@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 		}
 	}
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605180328.u4I3SpND003631>