[VIDEOPRT] Protect access to HwResetAdaptersList with spinlock.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 3 Dec 2019 01:08:34 +0000 (02:08 +0100)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 3 Dec 2019 01:46:38 +0000 (02:46 +0100)
win32ss/drivers/videoprt/dispatch.c
win32ss/drivers/videoprt/videoprt.c
win32ss/drivers/videoprt/videoprt.h

index 42f7023..b116cf1 100644 (file)
@@ -74,22 +74,35 @@ IntVideoPortResetDisplayParametersEx(
     _In_ ULONG Rows,
     _In_ BOOLEAN CalledByInbv)
 {
-    BOOLEAN Success = TRUE;
+    BOOLEAN Success = TRUE; // Suppose we don't need to perform a full reset.
+    KIRQL OldIrql;
     PLIST_ENTRY PrevEntry, Entry;
     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
     PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
 
+    /* Check if we are at dispatch level or lower, and acquire the lock */
+    OldIrql = KeGetCurrentIrql();
+    if (OldIrql <= DISPATCH_LEVEL)
+    {
+        /* Loop until the lock is free, then raise IRQL to dispatch level */
+        while (!KeTestSpinLock(&HwResetAdaptersLock));
+        KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+    }
+    KeAcquireSpinLockAtDpcLevel(&HwResetAdaptersLock);
+
+    /* Bail out early if we don't have any resettable adapter */
     if (IsListEmpty(&HwResetAdaptersList))
-        return FALSE;
+    {
+        Success = FALSE; // No adapter found: request HAL to perform a full reset.
+        goto Quit;
+    }
 
+    /*
+     * If we have been unexpectedly called via a callback from
+     * InbvAcquireDisplayOwnership(), start monitoring INBV.
+     */
     if (CalledByInbv)
-    {
-        /*
-         * We have been unexpectedly called via a callback from
-         * InbvAcquireDisplayOwnership(): start monitoring INBV.
-         */
         InbvMonitoring = TRUE;
-    }
 
     for (PrevEntry = &HwResetAdaptersList, Entry = PrevEntry->Flink;
          Entry != &HwResetAdaptersList;
@@ -102,7 +115,10 @@ IntVideoPortResetDisplayParametersEx(
          */
 // #define IS_ALIGNED(addr, align) (((ULONG64)(addr) & (align - 1)) == 0)
         if (((ULONG_PTR)Entry & (sizeof(ULONG_PTR) - 1)) != 0)
-            return FALSE;
+        {
+            Success = FALSE; // We failed: request HAL to perform a full reset.
+            goto Quit;
+        }
 
         DeviceExtension = CONTAINING_RECORD(Entry,
                                             VIDEO_PORT_DEVICE_EXTENSION,
@@ -118,7 +134,10 @@ IntVideoPortResetDisplayParametersEx(
             ASSERT(DriverExtension);
 
             if (DeviceExtension->HwResetListEntry.Blink != PrevEntry)
-                _SEH2_YIELD(return FALSE);
+            {
+                Success = FALSE; // We failed: request HAL to perform a full reset.
+                _SEH2_YIELD(goto Quit);
+            }
 
             if ((DeviceExtension->DeviceOpened >= 1) &&
                 (DriverExtension->InitializationData.HwResetHw != NULL))
@@ -134,6 +153,12 @@ IntVideoPortResetDisplayParametersEx(
         _SEH2_END;
     }
 
+Quit:
+    /* Release the lock and restore the old IRQL if we were at dispatch level or lower */
+    KeReleaseSpinLockFromDpcLevel(&HwResetAdaptersLock);
+    if (OldIrql <= DISPATCH_LEVEL)
+        KeLowerIrql(OldIrql);
+
     return Success;
 }
 
index 6e75d56..b420730 100644 (file)
@@ -33,6 +33,7 @@
 PKPROCESS CsrProcess = NULL;
 ULONG VideoPortDeviceNumber = 0;
 KMUTEX VideoPortInt10Mutex;
+KSPIN_LOCK HwResetAdaptersLock;
 RTL_STATIC_LIST_HEAD(HwResetAdaptersList);
 
 /* PRIVATE FUNCTIONS **********************************************************/
@@ -410,8 +411,9 @@ IntVideoPortFindAdapter(
     InitializeListHead(&DeviceExtension->HwResetListEntry);
     if (DriverExtension->InitializationData.HwResetHw != NULL)
     {
-        InsertTailList(&HwResetAdaptersList,
-                       &DeviceExtension->HwResetListEntry);
+        ExInterlockedInsertTailList(&HwResetAdaptersList,
+                                    &DeviceExtension->HwResetListEntry,
+                                    &HwResetAdaptersLock);
     }
 
     /* Query children of the device. */
@@ -471,14 +473,15 @@ VideoPortInitialize(
     NTSTATUS Status;
     PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
     BOOLEAN PnpDriver = FALSE, LegacyDetection = FALSE;
-    static BOOLEAN Int10MutexInitialized;
+    static BOOLEAN FirstInitialization;
 
     TRACE_(VIDEOPRT, "VideoPortInitialize\n");
 
-    if (!Int10MutexInitialized)
+    if (!FirstInitialization)
     {
         KeInitializeMutex(&VideoPortInt10Mutex, 0);
-        Int10MutexInitialized = TRUE;
+        KeInitializeSpinLock(&HwResetAdaptersLock);
+        FirstInitialization = TRUE;
     }
 
     /* As a first thing do parameter checks. */
index 94289dc..8035278 100644 (file)
@@ -246,6 +246,7 @@ IntVideoPortMapPhysicalMemory(
 extern PKPROCESS CsrProcess;
 extern ULONG VideoPortDeviceNumber;
 extern KMUTEX VideoPortInt10Mutex;
+extern KSPIN_LOCK HwResetAdaptersLock;
 extern LIST_ENTRY HwResetAdaptersList;
 
 VOID FASTCALL