[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH xenvif 3/5] Use a reader/writer lock in the mac module



Each receiver thread needs to call MacApplyFilters() but the implementation
uses a normal kernel spin lock and hence the threads will all contend the
lock. Switch the mac code to use a reader/writer lock so that
MacApplyFilters() can acquire the lock as a reader and thus avoid causing
the contention.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/xenvif/mac.c | 139 +++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 110 insertions(+), 29 deletions(-)

diff --git a/src/xenvif/mac.c b/src/xenvif/mac.c
index 3110dde..428200a 100644
--- a/src/xenvif/mac.c
+++ b/src/xenvif/mac.c
@@ -49,7 +49,7 @@ typedef struct _XENVIF_MAC_MULTICAST {
 
 struct _XENVIF_MAC {
     PXENVIF_FRONTEND        Frontend;
-    KSPIN_LOCK              Lock;
+    EX_SPIN_LOCK            Lock;
     BOOLEAN                 Connected;
     BOOLEAN                 Enabled;
     ULONG                   MaximumFrameSize;
@@ -214,7 +214,6 @@ MacInitialize(
     if (*Mac == NULL)
         goto fail1;
 
-    KeInitializeSpinLock(&(*Mac)->Lock);
     InitializeListHead(&(*Mac)->MulticastList);
 
     FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
@@ -233,6 +232,52 @@ fail1:
     return status;
 }
 
+static FORCEINLINE VOID
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__MacAcquireLockExclusive(
+    IN  PXENVIF_MAC     Mac
+    )
+{
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+
+    ExAcquireSpinLockExclusiveAtDpcLevel(&Mac->Lock);
+}
+
+static FORCEINLINE VOID
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__MacReleaseLockExclusive(
+    IN  PXENVIF_MAC     Mac
+    )
+{
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+
+#pragma prefast(disable:26110)
+    ExReleaseSpinLockExclusiveFromDpcLevel(&Mac->Lock);
+}
+
+static FORCEINLINE VOID
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__MacAcquireLockShared(
+    IN  PXENVIF_MAC     Mac
+    )
+{
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+
+    ExAcquireSpinLockSharedAtDpcLevel(&Mac->Lock);
+}
+
+static FORCEINLINE VOID
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__MacReleaseLockShared(
+    IN  PXENVIF_MAC     Mac
+    )
+{
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+
+#pragma prefast(disable:26110)
+    ExReleaseSpinLockSharedFromDpcLevel(&Mac->Lock);
+}
+
 static NTSTATUS
 MacDumpAddressTable(
     IN  PXENVIF_MAC     Mac
@@ -250,7 +295,8 @@ MacDumpAddressTable(
 
     Frontend = Mac->Frontend;
 
-    KeAcquireSpinLock(&Mac->Lock, &Irql);
+    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+    __MacAcquireLockShared(Mac);
 
     status  = STATUS_UNSUCCESSFUL;
     if (!Mac->Connected)
@@ -284,7 +330,8 @@ MacDumpAddressTable(
 
     ASSERT3U(Index, ==, Count);
 
-    KeReleaseSpinLock(&Mac->Lock, Irql);
+    __MacReleaseLockShared(Mac);
+    KeLowerIrql(Irql);
 
     (VOID) XENBUS_STORE(Remove,
                         &Mac->StoreInterface,
@@ -328,7 +375,8 @@ fail2:
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    KeReleaseSpinLock(&Mac->Lock, Irql);
+    __MacReleaseLockExclusive(Mac);
+    KeLowerIrql(Irql);
 
     return status;
 }
@@ -344,6 +392,8 @@ MacConnect(
     ULONG64             Mtu;
     NTSTATUS            status;
 
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+
     Frontend = Mac->Frontend;
 
     status = XENBUS_DEBUG(Acquire, &Mac->DebugInterface);
@@ -399,10 +449,12 @@ MacConnect(
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    KeAcquireSpinLockAtDpcLevel(&Mac->Lock);
+    __MacAcquireLockExclusive(Mac);
+
     ASSERT(!Mac->Connected);
     Mac->Connected = TRUE;
-    KeReleaseSpinLockFromDpcLevel(&Mac->Lock);
+
+    __MacReleaseLockExclusive(Mac);
 
     (VOID) MacDumpAddressTable(Mac);
 
@@ -456,7 +508,8 @@ MacEnable(
     Frontend = Mac->Frontend;
 
     ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-    KeAcquireSpinLockAtDpcLevel(&Mac->Lock);
+
+    __MacAcquireLockExclusive(Mac);
 
     Thread = VifGetMacThread(PdoGetVifContext(FrontendGetPdo(Frontend)));
 
@@ -472,7 +525,7 @@ MacEnable(
     ASSERT(!Mac->Enabled);
     Mac->Enabled = TRUE;
 
-    KeReleaseSpinLockFromDpcLevel(&Mac->Lock);
+    __MacReleaseLockExclusive(Mac);
 
     Trace("<====\n");
     return STATUS_SUCCESS;
@@ -480,7 +533,7 @@ MacEnable(
 fail1:
     Error("fail1 (%08x)\n");
 
-    KeReleaseSpinLockFromDpcLevel(&Mac->Lock);
+    __MacReleaseLockExclusive(Mac);
 
     return status;
 }
@@ -497,7 +550,8 @@ MacDisable(
     Frontend = Mac->Frontend;
 
     ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-    KeAcquireSpinLockAtDpcLevel(&Mac->Lock);
+
+    __MacAcquireLockExclusive(Mac);
 
     ASSERT(Mac->Enabled);
     Mac->Enabled = FALSE;
@@ -507,7 +561,7 @@ MacDisable(
                         Mac->Watch);
     Mac->Watch = NULL;
 
-    KeReleaseSpinLockFromDpcLevel(&Mac->Lock);
+    __MacReleaseLockExclusive(Mac);
 
     Trace("<====\n");
 }
@@ -521,10 +575,14 @@ MacDisconnect(
 
     Frontend = Mac->Frontend;
 
-    KeAcquireSpinLockAtDpcLevel(&Mac->Lock);
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+
+    __MacAcquireLockExclusive(Mac);
+
     ASSERT(Mac->Connected);
     Mac->Connected = FALSE;
-    KeReleaseSpinLockFromDpcLevel(&Mac->Lock);
+
+    __MacReleaseLockExclusive(Mac);
 
     XENBUS_DEBUG(Deregister,
                  &Mac->DebugInterface,
@@ -584,7 +642,7 @@ MacTeardown(
     RtlZeroMemory(&Mac->DebugInterface,
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
-    RtlZeroMemory(&Mac->Lock, sizeof (KSPIN_LOCK));
+    Mac->Lock = 0;
 
     ASSERT(IsZeroMemory(Mac, sizeof (XENVIF_MAC)));
     __MacFree(Mac);
@@ -710,10 +768,14 @@ MacAddMulticastAddress(
 
     Multicast->Address = *Address;
 
-    KeAcquireSpinLock(&Mac->Lock, &Irql);
+    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+    __MacAcquireLockExclusive(Mac);
+
     InsertTailList(&Mac->MulticastList, &Multicast->ListEntry);
     Mac->MulticastCount++;
-    KeReleaseSpinLock(&Mac->Lock, Irql);
+
+    __MacReleaseLockExclusive(Mac);
+    KeLowerIrql(Irql);
 
     (VOID) MacDumpAddressTable(Mac);
 
@@ -748,7 +810,8 @@ MacRemoveMulticastAddress(
 
     Frontend = Mac->Frontend;
 
-    KeAcquireSpinLock(&Mac->Lock, &Irql);
+    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+    __MacAcquireLockExclusive(Mac);
 
     for (ListEntry = Mac->MulticastList.Flink;
          ListEntry != &Mac->MulticastList;
@@ -773,7 +836,8 @@ found:
     RemoveEntryList(&Multicast->ListEntry);
     __MacFree(Multicast);
 
-    KeReleaseSpinLock(&Mac->Lock, Irql);
+    __MacReleaseLockExclusive(Mac);
+    KeLowerIrql(Irql);
 
     (VOID) MacDumpAddressTable(Mac);
 
@@ -791,7 +855,8 @@ found:
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    KeReleaseSpinLock(&Mac->Lock, Irql);
+    __MacReleaseLockExclusive(Mac);
+    KeLowerIrql(Irql);
 
     return status;
 }
@@ -807,7 +872,8 @@ MacQueryMulticastAddresses(
     KIRQL                       Irql;
     NTSTATUS                    status;
 
-    KeAcquireSpinLock(&Mac->Lock, &Irql);
+    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+    __MacAcquireLockShared(Mac);
 
     status = STATUS_BUFFER_OVERFLOW;
     if (Address == NULL || *Count < Mac->MulticastCount)
@@ -827,14 +893,16 @@ MacQueryMulticastAddresses(
     }
     ASSERT3U(*Count, ==, Mac->MulticastCount);
 
-    KeReleaseSpinLock(&Mac->Lock, Irql);
+    __MacReleaseLockShared(Mac);
+    KeLowerIrql(Irql);
 
     return STATUS_SUCCESS;
 
 fail1:
     *Count = Mac->MulticastCount;
 
-    KeReleaseSpinLock(&Mac->Lock, Irql);
+    __MacReleaseLockExclusive(Mac);
+    KeLowerIrql(Irql);
 
     return status;
 }
@@ -862,21 +930,25 @@ MacSetFilterLevel(
     if (Type >= ETHERNET_ADDRESS_TYPE_COUNT)
         goto fail1;
 
-    KeAcquireSpinLock(&Mac->Lock, &Irql);
+    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+    __MacAcquireLockExclusive(Mac);
 
     status = STATUS_INVALID_PARAMETER;
     if (Level > XENVIF_MAC_FILTER_ALL || Level < XENVIF_MAC_FILTER_NONE)
         goto fail2;
 
     Mac->FilterLevel[Type] = Level;
-    KeReleaseSpinLock(&Mac->Lock, Irql);
+
+    __MacReleaseLockExclusive(Mac);
+    KeLowerIrql(Irql);
 
     return STATUS_SUCCESS;
 
 fail2:
     Error("fail2\n");
 
-    KeReleaseSpinLock(&Mac->Lock, Irql);
+    __MacReleaseLockExclusive(Mac);
+    KeLowerIrql(Irql);
 
 fail1:
     Error("fail1 (%08x)\n", status);
@@ -891,14 +963,21 @@ MacQueryFilterLevel(
     OUT PXENVIF_MAC_FILTER_LEVEL    Level
     )
 {
+    KIRQL                           Irql;
     NTSTATUS                        status;
 
     status = STATUS_INVALID_PARAMETER;
     if (Type >= ETHERNET_ADDRESS_TYPE_COUNT)
         goto fail1;
 
+    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+    __MacAcquireLockShared(Mac);
+
     *Level = Mac->FilterLevel[Type];
 
+    __MacReleaseLockShared(Mac);
+    KeLowerIrql(Irql);
+
     return STATUS_SUCCESS;
 
 fail1:
@@ -915,12 +994,13 @@ MacApplyFilters(
 {
     ETHERNET_ADDRESS_TYPE   Type;
     BOOLEAN                 Allow;
+    KIRQL                   Irql;
 
     Type = GET_ETHERNET_ADDRESS_TYPE(DestinationAddress);
     Allow = FALSE;
 
-    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-    KeAcquireSpinLockAtDpcLevel(&Mac->Lock);
+    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+    __MacAcquireLockShared(Mac);
 
     switch (Type) {
     case ETHERNET_ADDRESS_UNICAST:
@@ -1014,7 +1094,8 @@ MacApplyFilters(
         break;
     }
 
-    KeReleaseSpinLockFromDpcLevel(&Mac->Lock);
+    __MacReleaseLockShared(Mac);
+    KeLowerIrql(Irql);
 
     return Allow;
 }
-- 
2.5.3


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.